All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/16] MIPS: initial support for the Atheros AR71XX/AR724X/AR913X SoCs
@ 2010-12-22 20:30 Gabor Juhos
  2010-12-22 20:30 ` [PATCH v2 01/16] MIPS: add initial support for the Atheros AR71XX/AR724X/AR931X SoCs Gabor Juhos
                   ` (15 more replies)
  0 siblings, 16 replies; 21+ messages in thread
From: Gabor Juhos @ 2010-12-22 20:30 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: linux-mips, Imre Kaloz, Luis R. Rodriguez, Cliff Holden,
	Kathy Giori, Gabor Juhos

This patch set contains initial support for the 
Atheros AR71XX/AR724X/AR913X SoCs.

Generic changes since v1:
    - rebased against 2.6.37-rc7
    - the 'MIPS: Add generic support for multiple machines within a single kernel' 
      patch has been removed, because that is in the mips-queue tree already
    - the 'input: add input driver for polled GPIO buttons' patch has been removed, 
      because a slightly different version of that driver is present in 2.6.37-rc7 
      already as 'gpio_keys_polled'

Gabor Juhos (16):
  MIPS: add initial support for the Atheros AR71XX/AR724X/AR931X SoCs
  MIPS: ath79: add GPIOLIB support
  MIPS: ath79: utilize the MIPS multi-machine support
  MIPS: ath79: add initial support for the Atheros PB44 reference board
  MIPS: ath79: add common GPIO LEDs device
  watchdog: add driver for the Atheros AR71XX/AR724X/AR913X SoCs
  MIPS: ath79: add common watchdog device
  MIPS: ath79: add common GPIO buttons device
  spi: add SPI controller driver for the Atheros AR71XX/AR724X/AR913X
    SoCs
  MIPS: ath79: add common SPI controller device
  USB: ehci: add workaround for Synopsys HC bug
  USB: ehci: add bus glue for the Atheros AR71XX/AR724X/AR913X SoCs
  USB: ohci: add bus glue for the Atheros AR71XX/AR7240 SoCs
  MIPS: ath79: add common USB Host Controller device
  MIPS: ath79: add initial support for the Atheros AP81 reference board
  MIPS: ath79: add common WMAC device for AR913X based boards

 arch/mips/Kbuild.platforms                         |    1 +
 arch/mips/Kconfig                                  |   17 ++
 arch/mips/ath79/Kconfig                            |   60 ++++
 arch/mips/ath79/Makefile                           |   29 ++
 arch/mips/ath79/Platform                           |    7 +
 arch/mips/ath79/common.c                           |   97 +++++++
 arch/mips/ath79/common.h                           |   30 ++
 arch/mips/ath79/dev-ar913x-wmac.c                  |   60 ++++
 arch/mips/ath79/dev-ar913x-wmac.h                  |   17 ++
 arch/mips/ath79/dev-common.c                       |   69 +++++
 arch/mips/ath79/dev-common.h                       |   18 ++
 arch/mips/ath79/dev-gpio-buttons.c                 |   58 ++++
 arch/mips/ath79/dev-gpio-buttons.h                 |   23 ++
 arch/mips/ath79/dev-leds-gpio.c                    |   56 ++++
 arch/mips/ath79/dev-leds-gpio.h                    |   21 ++
 arch/mips/ath79/dev-spi.c                          |   38 +++
 arch/mips/ath79/dev-spi.h                          |   22 ++
 arch/mips/ath79/dev-usb.c                          |  194 +++++++++++++
 arch/mips/ath79/dev-usb.h                          |   17 ++
 arch/mips/ath79/early_printk.c                     |   36 +++
 arch/mips/ath79/gpio.c                             |  197 +++++++++++++
 arch/mips/ath79/irq.c                              |  187 +++++++++++++
 arch/mips/ath79/mach-ap81.c                        |  100 +++++++
 arch/mips/ath79/mach-pb44.c                        |  120 ++++++++
 arch/mips/ath79/machtypes.h                        |   23 ++
 arch/mips/ath79/prom.c                             |   57 ++++
 arch/mips/ath79/setup.c                            |  279 +++++++++++++++++++
 arch/mips/include/asm/mach-ath79/ar71xx_regs.h     |  253 +++++++++++++++++
 arch/mips/include/asm/mach-ath79/ath79.h           |  100 +++++++
 .../include/asm/mach-ath79/ath79_ehci_platform.h   |   18 ++
 .../include/asm/mach-ath79/ath79_spi_platform.h    |   19 ++
 .../include/asm/mach-ath79/cpu-feature-overrides.h |   56 ++++
 arch/mips/include/asm/mach-ath79/gpio.h            |   26 ++
 arch/mips/include/asm/mach-ath79/irq.h             |   36 +++
 .../include/asm/mach-ath79/kernel-entry-init.h     |   32 +++
 arch/mips/include/asm/mach-ath79/war.h             |   25 ++
 drivers/spi/Kconfig                                |    8 +
 drivers/spi/Makefile                               |    1 +
 drivers/spi/ath79_spi.c                            |  290 +++++++++++++++++++
 drivers/usb/host/Kconfig                           |   16 +
 drivers/usb/host/ehci-ath79.c                      |  176 ++++++++++++
 drivers/usb/host/ehci-hcd.c                        |    5 +
 drivers/usb/host/ehci-q.c                          |    3 +
 drivers/usb/host/ehci.h                            |    1 +
 drivers/usb/host/ohci-ath79.c                      |  162 +++++++++++
 drivers/usb/host/ohci-hcd.c                        |    5 +
 drivers/watchdog/Kconfig                           |    8 +
 drivers/watchdog/Makefile                          |    1 +
 drivers/watchdog/ath79_wdt.c                       |  293 ++++++++++++++++++++
 49 files changed, 3367 insertions(+), 0 deletions(-)
 create mode 100644 arch/mips/ath79/Kconfig
 create mode 100644 arch/mips/ath79/Makefile
 create mode 100644 arch/mips/ath79/Platform
 create mode 100644 arch/mips/ath79/common.c
 create mode 100644 arch/mips/ath79/common.h
 create mode 100644 arch/mips/ath79/dev-ar913x-wmac.c
 create mode 100644 arch/mips/ath79/dev-ar913x-wmac.h
 create mode 100644 arch/mips/ath79/dev-common.c
 create mode 100644 arch/mips/ath79/dev-common.h
 create mode 100644 arch/mips/ath79/dev-gpio-buttons.c
 create mode 100644 arch/mips/ath79/dev-gpio-buttons.h
 create mode 100644 arch/mips/ath79/dev-leds-gpio.c
 create mode 100644 arch/mips/ath79/dev-leds-gpio.h
 create mode 100644 arch/mips/ath79/dev-spi.c
 create mode 100644 arch/mips/ath79/dev-spi.h
 create mode 100644 arch/mips/ath79/dev-usb.c
 create mode 100644 arch/mips/ath79/dev-usb.h
 create mode 100644 arch/mips/ath79/early_printk.c
 create mode 100644 arch/mips/ath79/gpio.c
 create mode 100644 arch/mips/ath79/irq.c
 create mode 100644 arch/mips/ath79/mach-ap81.c
 create mode 100644 arch/mips/ath79/mach-pb44.c
 create mode 100644 arch/mips/ath79/machtypes.h
 create mode 100644 arch/mips/ath79/prom.c
 create mode 100644 arch/mips/ath79/setup.c
 create mode 100644 arch/mips/include/asm/mach-ath79/ar71xx_regs.h
 create mode 100644 arch/mips/include/asm/mach-ath79/ath79.h
 create mode 100644 arch/mips/include/asm/mach-ath79/ath79_ehci_platform.h
 create mode 100644 arch/mips/include/asm/mach-ath79/ath79_spi_platform.h
 create mode 100644 arch/mips/include/asm/mach-ath79/cpu-feature-overrides.h
 create mode 100644 arch/mips/include/asm/mach-ath79/gpio.h
 create mode 100644 arch/mips/include/asm/mach-ath79/irq.h
 create mode 100644 arch/mips/include/asm/mach-ath79/kernel-entry-init.h
 create mode 100644 arch/mips/include/asm/mach-ath79/war.h
 create mode 100644 drivers/spi/ath79_spi.c
 create mode 100644 drivers/usb/host/ehci-ath79.c
 create mode 100644 drivers/usb/host/ohci-ath79.c
 create mode 100644 drivers/watchdog/ath79_wdt.c

-- 
1.7.2.1

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v2 01/16] MIPS: add initial support for the Atheros AR71XX/AR724X/AR931X SoCs
  2010-12-22 20:30 [PATCH v2 00/16] MIPS: initial support for the Atheros AR71XX/AR724X/AR913X SoCs Gabor Juhos
@ 2010-12-22 20:30 ` Gabor Juhos
  2010-12-22 20:30 ` [PATCH v2 02/16] MIPS: ath79: add GPIOLIB support Gabor Juhos
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 21+ messages in thread
From: Gabor Juhos @ 2010-12-22 20:30 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: linux-mips, Imre Kaloz, Luis R. Rodriguez, Cliff Holden,
	Kathy Giori, Gabor Juhos

This patch adds initial support for various Atheros SoCs based on the
MIPS 24Kc core. The following models are supported at the moment:

  - AR7130
  - AR7141
  - AR7161
  - AR9130
  - AR9132
  - AR7240
  - AR7241
  - AR7242

The current patch contains minimal support only, but the resulting
kernel can boot into user-space with using of an initramfs image on
various boards which are using these SoCs. Support for more built-in
devices and individual boards will be implemented in further patches.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Signed-off-by: Imre Kaloz <kaloz@openwrt.org>
---

Changes since RFC:
    - the ATH79_DEV_UART Kconfig option is removed, and the URT platform
      code has been moved into dev-common[ch]

Changes since v1:
    - ath79_device_{start,stop} has been renamed to ath79_device_reset_{set,clear}
      to to reflect the purpose of these functions better
    - some definitions has been moved from 'arch/mips/ath79/common.h' to 
      'arch/mips/include/asm/mach-ath79/ath79.h' to make them available for 
      future drivers
    - rebased against 2.6.37-rc7

 arch/mips/Kbuild.platforms                         |    1 +
 arch/mips/Kconfig                                  |   15 ++
 arch/mips/ath79/Kconfig                            |   12 +
 arch/mips/ath79/Makefile                           |   18 ++
 arch/mips/ath79/Platform                           |    7 +
 arch/mips/ath79/common.c                           |   97 +++++++
 arch/mips/ath79/common.h                           |   25 ++
 arch/mips/ath79/dev-common.c                       |   59 +++++
 arch/mips/ath79/dev-common.h                       |   17 ++
 arch/mips/ath79/early_printk.c                     |   36 +++
 arch/mips/ath79/irq.c                              |  187 ++++++++++++++
 arch/mips/ath79/prom.c                             |   57 +++++
 arch/mips/ath79/setup.c                            |  263 ++++++++++++++++++++
 arch/mips/include/asm/mach-ath79/ar71xx_regs.h     |  207 +++++++++++++++
 arch/mips/include/asm/mach-ath79/ath79.h           |  100 ++++++++
 .../include/asm/mach-ath79/cpu-feature-overrides.h |   56 ++++
 arch/mips/include/asm/mach-ath79/irq.h             |   36 +++
 .../include/asm/mach-ath79/kernel-entry-init.h     |   32 +++
 arch/mips/include/asm/mach-ath79/war.h             |   25 ++
 19 files changed, 1250 insertions(+), 0 deletions(-)
 create mode 100644 arch/mips/ath79/Kconfig
 create mode 100644 arch/mips/ath79/Makefile
 create mode 100644 arch/mips/ath79/Platform
 create mode 100644 arch/mips/ath79/common.c
 create mode 100644 arch/mips/ath79/common.h
 create mode 100644 arch/mips/ath79/dev-common.c
 create mode 100644 arch/mips/ath79/dev-common.h
 create mode 100644 arch/mips/ath79/early_printk.c
 create mode 100644 arch/mips/ath79/irq.c
 create mode 100644 arch/mips/ath79/prom.c
 create mode 100644 arch/mips/ath79/setup.c
 create mode 100644 arch/mips/include/asm/mach-ath79/ar71xx_regs.h
 create mode 100644 arch/mips/include/asm/mach-ath79/ath79.h
 create mode 100644 arch/mips/include/asm/mach-ath79/cpu-feature-overrides.h
 create mode 100644 arch/mips/include/asm/mach-ath79/irq.h
 create mode 100644 arch/mips/include/asm/mach-ath79/kernel-entry-init.h
 create mode 100644 arch/mips/include/asm/mach-ath79/war.h

diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms
index 78439b8..7ff9b54 100644
--- a/arch/mips/Kbuild.platforms
+++ b/arch/mips/Kbuild.platforms
@@ -2,6 +2,7 @@
 
 platforms += alchemy
 platforms += ar7
+platforms += ath79
 platforms += bcm47xx
 platforms += bcm63xx
 platforms += cavium-octeon
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 913d50d..c0511d6 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -65,6 +65,20 @@ config AR7
 	  Support for the Texas Instruments AR7 System-on-a-Chip
 	  family: TNETD7100, 7200 and 7300.
 
+config ATH79
+	bool "Atheros AR71XX/AR724X/AR913X based boards"
+	select BOOT_RAW
+	select CEVT_R4K
+	select CSRC_R4K
+	select DMA_NONCOHERENT
+	select IRQ_CPU
+	select SYS_HAS_CPU_MIPS32_R2
+	select SYS_HAS_EARLY_PRINTK
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_BIG_ENDIAN
+	help
+	  Support for the Atheros AR71XX/AR724X/AR913X SoCs.
+
 config BCM47XX
 	bool "Broadcom BCM47XX based boards"
 	select CEVT_R4K
@@ -717,6 +731,7 @@ config CAVIUM_OCTEON_REFERENCE_BOARD
 endchoice
 
 source "arch/mips/alchemy/Kconfig"
+source "arch/mips/ath79/Kconfig"
 source "arch/mips/bcm63xx/Kconfig"
 source "arch/mips/jazz/Kconfig"
 source "arch/mips/jz4740/Kconfig"
diff --git a/arch/mips/ath79/Kconfig b/arch/mips/ath79/Kconfig
new file mode 100644
index 0000000..50b9334
--- /dev/null
+++ b/arch/mips/ath79/Kconfig
@@ -0,0 +1,12 @@
+if ATH79
+
+config SOC_AR71XX
+	def_bool n
+
+config SOC_AR724X
+	def_bool n
+
+config SOC_AR913X
+	def_bool n
+
+endif
diff --git a/arch/mips/ath79/Makefile b/arch/mips/ath79/Makefile
new file mode 100644
index 0000000..b4ec9c2
--- /dev/null
+++ b/arch/mips/ath79/Makefile
@@ -0,0 +1,18 @@
+#
+# Makefile for the Atheros AR71XX/AR724X/AR913X specific parts of the kernel
+#
+# Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+# Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 as published
+# by the Free Software Foundation.
+
+obj-y	:= prom.o setup.o irq.o common.o
+
+obj-$(CONFIG_EARLY_PRINTK)		+= early_printk.o
+
+#
+# Devices
+#
+obj-y					+= dev-common.o
diff --git a/arch/mips/ath79/Platform b/arch/mips/ath79/Platform
new file mode 100644
index 0000000..2bd6636
--- /dev/null
+++ b/arch/mips/ath79/Platform
@@ -0,0 +1,7 @@
+#
+# Atheros AR71xx/AR724x/AR913x
+#
+
+platform-$(CONFIG_ATH79)	+= ath79/
+cflags-$(CONFIG_ATH79)		+= -I$(srctree)/arch/mips/include/asm/mach-ath79
+load-$(CONFIG_ATH79)		= 0xffffffff80060000
diff --git a/arch/mips/ath79/common.c b/arch/mips/ath79/common.c
new file mode 100644
index 0000000..58f60e7
--- /dev/null
+++ b/arch/mips/ath79/common.c
@@ -0,0 +1,97 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X common routines
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/spinlock.h>
+
+#include <asm/mach-ath79/ath79.h>
+#include <asm/mach-ath79/ar71xx_regs.h>
+#include "common.h"
+
+static DEFINE_SPINLOCK(ath79_device_reset_lock);
+
+u32 ath79_cpu_freq;
+EXPORT_SYMBOL_GPL(ath79_cpu_freq);
+
+u32 ath79_ahb_freq;
+EXPORT_SYMBOL_GPL(ath79_ahb_freq);
+
+u32 ath79_ddr_freq;
+EXPORT_SYMBOL_GPL(ath79_ddr_freq);
+
+enum ath79_soc_type ath79_soc;
+
+void __iomem *ath79_pll_base;
+void __iomem *ath79_reset_base;
+EXPORT_SYMBOL_GPL(ath79_reset_base);
+void __iomem *ath79_ddr_base;
+
+void ath79_ddr_wb_flush(u32 reg)
+{
+	void __iomem *flush_reg = ath79_ddr_base + reg;
+
+	/* Flush the DDR write buffer. */
+	__raw_writel(0x1, flush_reg);
+	while (__raw_readl(flush_reg) & 0x1)
+		;
+
+	/* It must be run twice. */
+	__raw_writel(0x1, flush_reg);
+	while (__raw_readl(flush_reg) & 0x1)
+		;
+}
+EXPORT_SYMBOL_GPL(ath79_ddr_wb_flush);
+
+void ath79_device_reset_set(u32 mask)
+{
+	unsigned long flags;
+	u32 reg;
+	u32 t;
+
+	if (soc_is_ar71xx())
+		reg = AR71XX_RESET_REG_RESET_MODULE;
+	else if (soc_is_ar724x())
+		reg = AR724X_RESET_REG_RESET_MODULE;
+	else if (soc_is_ar913x())
+		reg = AR913X_RESET_REG_RESET_MODULE;
+	else
+		BUG();
+
+	spin_lock_irqsave(&ath79_device_reset_lock, flags);
+	t = ath79_reset_rr(reg);
+	ath79_reset_wr(reg, t | mask);
+	spin_unlock_irqrestore(&ath79_device_reset_lock, flags);
+}
+EXPORT_SYMBOL_GPL(ath79_device_reset_set);
+
+void ath79_device_reset_clear(u32 mask)
+{
+	unsigned long flags;
+	u32 reg;
+	u32 t;
+
+	if (soc_is_ar71xx())
+		reg = AR71XX_RESET_REG_RESET_MODULE;
+	else if (soc_is_ar724x())
+		reg = AR724X_RESET_REG_RESET_MODULE;
+	else if (soc_is_ar913x())
+		reg = AR913X_RESET_REG_RESET_MODULE;
+	else
+		BUG();
+
+	spin_lock_irqsave(&ath79_device_reset_lock, flags);
+	t = ath79_reset_rr(reg);
+	ath79_reset_wr(reg, t & ~mask);
+	spin_unlock_irqrestore(&ath79_device_reset_lock, flags);
+}
+EXPORT_SYMBOL_GPL(ath79_device_reset_clear);
diff --git a/arch/mips/ath79/common.h b/arch/mips/ath79/common.h
new file mode 100644
index 0000000..a1bcdbb
--- /dev/null
+++ b/arch/mips/ath79/common.h
@@ -0,0 +1,25 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X common definitions
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  Parts of this file are based on Atheros' 2.6.15 BSP
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#ifndef __ATH79_COMMON_H
+#define __ATH79_COMMON_H
+
+#include <linux/types.h>
+#include <linux/init.h>
+
+#define ATH79_MEM_SIZE_MIN	(2 * 1024 * 1024)
+#define ATH79_MEM_SIZE_MAX	(128 * 1024 * 1024)
+
+void ath79_ddr_wb_flush(unsigned int reg);
+
+#endif /* __ATH79_COMMON_H */
diff --git a/arch/mips/ath79/dev-common.c b/arch/mips/ath79/dev-common.c
new file mode 100644
index 0000000..897522c
--- /dev/null
+++ b/arch/mips/ath79/dev-common.c
@@ -0,0 +1,59 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X common devices
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  Parts of this file are based on Atheros' 2.6.15 BSP
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+
+#include <asm/mach-ath79/ath79.h>
+#include <asm/mach-ath79/ar71xx_regs.h>
+#include "common.h"
+#include "dev-common.h"
+
+static struct resource ath79_uart_resources[] = {
+	{
+		.start	= AR71XX_UART_BASE,
+		.end	= AR71XX_UART_BASE + AR71XX_UART_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+#define AR71XX_UART_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP)
+static struct plat_serial8250_port ath79_uart_data[] = {
+	{
+		.mapbase	= AR71XX_UART_BASE,
+		.irq		= ATH79_MISC_IRQ_UART,
+		.flags		= AR71XX_UART_FLAGS,
+		.iotype		= UPIO_MEM32,
+		.regshift	= 2,
+	}, {
+		/* terminating entry */
+	}
+};
+
+static struct platform_device ath79_uart_device = {
+	.name		= "serial8250",
+	.id		= PLAT8250_DEV_PLATFORM,
+	.resource	= ath79_uart_resources,
+	.num_resources	= ARRAY_SIZE(ath79_uart_resources),
+	.dev = {
+		.platform_data	= ath79_uart_data
+	},
+};
+
+void __init ath79_register_uart(void)
+{
+	ath79_uart_data[0].uartclk = ath79_ahb_freq;
+	platform_device_register(&ath79_uart_device);
+}
diff --git a/arch/mips/ath79/dev-common.h b/arch/mips/ath79/dev-common.h
new file mode 100644
index 0000000..1cec894
--- /dev/null
+++ b/arch/mips/ath79/dev-common.h
@@ -0,0 +1,17 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X common devices
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#ifndef _ATH79_DEV_COMMON_H
+#define _ATH79_DEV_COMMON_H
+
+void ath79_register_uart(void) __init;
+
+#endif /* _ATH79_DEV_COMMON_H */
diff --git a/arch/mips/ath79/early_printk.c b/arch/mips/ath79/early_printk.c
new file mode 100644
index 0000000..7499b0e
--- /dev/null
+++ b/arch/mips/ath79/early_printk.c
@@ -0,0 +1,36 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X SoC early printk support
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#include <linux/io.h>
+#include <linux/serial_reg.h>
+#include <asm/addrspace.h>
+
+#include <asm/mach-ath79/ar71xx_regs.h>
+
+static inline void prom_wait_thre(void __iomem *base)
+{
+	u32 lsr;
+
+	do {
+		lsr = __raw_readl(base + UART_LSR * 4);
+		if (lsr & UART_LSR_THRE)
+			break;
+	} while (1);
+}
+
+void prom_putchar(unsigned char ch)
+{
+	void __iomem *base = (void __iomem *)(KSEG1ADDR(AR71XX_UART_BASE));
+
+	prom_wait_thre(base);
+	__raw_writel(ch, base + UART_TX * 4);
+	prom_wait_thre(base);
+}
diff --git a/arch/mips/ath79/irq.c b/arch/mips/ath79/irq.c
new file mode 100644
index 0000000..1bf7f71
--- /dev/null
+++ b/arch/mips/ath79/irq.c
@@ -0,0 +1,187 @@
+/*
+ *  Atheros AR71xx/AR724x/AR913x specific interrupt handling
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  Parts of this file are based on Atheros' 2.6.15 BSP
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
+#include <asm/irq_cpu.h>
+#include <asm/mipsregs.h>
+
+#include <asm/mach-ath79/ath79.h>
+#include <asm/mach-ath79/ar71xx_regs.h>
+#include "common.h"
+
+static unsigned int ath79_ip2_flush_reg;
+static unsigned int ath79_ip3_flush_reg;
+
+static void ath79_misc_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	void __iomem *base = ath79_reset_base;
+	u32 pending;
+
+	pending = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS) &
+		  __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
+
+	if (pending & MISC_INT_UART)
+		generic_handle_irq(ATH79_MISC_IRQ_UART);
+
+	else if (pending & MISC_INT_DMA)
+		generic_handle_irq(ATH79_MISC_IRQ_DMA);
+
+	else if (pending & MISC_INT_PERFC)
+		generic_handle_irq(ATH79_MISC_IRQ_PERFC);
+
+	else if (pending & MISC_INT_TIMER)
+		generic_handle_irq(ATH79_MISC_IRQ_TIMER);
+
+	else if (pending & MISC_INT_OHCI)
+		generic_handle_irq(ATH79_MISC_IRQ_OHCI);
+
+	else if (pending & MISC_INT_ERROR)
+		generic_handle_irq(ATH79_MISC_IRQ_ERROR);
+
+	else if (pending & MISC_INT_GPIO)
+		generic_handle_irq(ATH79_MISC_IRQ_GPIO);
+
+	else if (pending & MISC_INT_WDOG)
+		generic_handle_irq(ATH79_MISC_IRQ_WDOG);
+
+	else
+		spurious_interrupt();
+}
+
+static void ar71xx_misc_irq_unmask(unsigned int irq)
+{
+	void __iomem *base = ath79_reset_base;
+	u32 t;
+
+	irq -= ATH79_MISC_IRQ_BASE;
+
+	t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
+	__raw_writel(t | (1 << irq), base + AR71XX_RESET_REG_MISC_INT_ENABLE);
+
+	/* flush write */
+	__raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
+}
+
+static void ar71xx_misc_irq_mask(unsigned int irq)
+{
+	void __iomem *base = ath79_reset_base;
+	u32 t;
+
+	irq -= ATH79_MISC_IRQ_BASE;
+
+	t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
+	__raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_MISC_INT_ENABLE);
+
+	/* flush write */
+	__raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
+}
+
+static void ar724x_misc_irq_ack(unsigned int irq)
+{
+	void __iomem *base = ath79_reset_base;
+	u32 t;
+
+	irq -= ATH79_MISC_IRQ_BASE;
+
+	t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS);
+	__raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_MISC_INT_STATUS);
+
+	/* flush write */
+	__raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS);
+}
+
+static struct irq_chip ath79_misc_irq_chip = {
+	.name		= "MISC",
+	.unmask		= ar71xx_misc_irq_unmask,
+	.mask		= ar71xx_misc_irq_mask,
+};
+
+static void __init ath79_misc_irq_init(void)
+{
+	void __iomem *base = ath79_reset_base;
+	int i;
+
+	__raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_ENABLE);
+	__raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_STATUS);
+
+	if (soc_is_ar71xx() || soc_is_ar913x())
+		ath79_misc_irq_chip.mask_ack = ar71xx_misc_irq_mask;
+	else if (soc_is_ar724x())
+		ath79_misc_irq_chip.ack = ar724x_misc_irq_ack;
+	else
+		BUG();
+
+	for (i = ATH79_MISC_IRQ_BASE;
+	     i < ATH79_MISC_IRQ_BASE + ATH79_MISC_IRQ_COUNT; i++) {
+		irq_desc[i].status = IRQ_DISABLED;
+		set_irq_chip_and_handler(i, &ath79_misc_irq_chip,
+					 handle_level_irq);
+	}
+
+	set_irq_chained_handler(ATH79_CPU_IRQ_MISC, ath79_misc_irq_handler);
+}
+
+asmlinkage void plat_irq_dispatch(void)
+{
+	unsigned long pending;
+
+	pending = read_c0_status() & read_c0_cause() & ST0_IM;
+
+	if (pending & STATUSF_IP7)
+		do_IRQ(ATH79_CPU_IRQ_TIMER);
+
+	else if (pending & STATUSF_IP2) {
+		ath79_ddr_wb_flush(ath79_ip2_flush_reg);
+		do_IRQ(ATH79_CPU_IRQ_IP2);
+	}
+
+	else if (pending & STATUSF_IP4)
+		do_IRQ(ATH79_CPU_IRQ_GE0);
+
+	else if (pending & STATUSF_IP5)
+		do_IRQ(ATH79_CPU_IRQ_GE1);
+
+	else if (pending & STATUSF_IP3) {
+		ath79_ddr_wb_flush(ath79_ip3_flush_reg);
+		do_IRQ(ATH79_CPU_IRQ_USB);
+	}
+
+	else if (pending & STATUSF_IP6)
+		do_IRQ(ATH79_CPU_IRQ_MISC);
+
+	else
+		spurious_interrupt();
+}
+
+void __init arch_init_irq(void)
+{
+	if (soc_is_ar71xx()) {
+		ath79_ip2_flush_reg = AR71XX_DDR_REG_FLUSH_PCI;
+		ath79_ip3_flush_reg = AR71XX_DDR_REG_FLUSH_USB;
+	} else if (soc_is_ar724x()) {
+		ath79_ip2_flush_reg = AR724X_DDR_REG_FLUSH_PCIE;
+		ath79_ip3_flush_reg = AR724X_DDR_REG_FLUSH_USB;
+	} else if (soc_is_ar913x()) {
+		ath79_ip2_flush_reg = AR913X_DDR_REG_FLUSH_WMAC;
+		ath79_ip3_flush_reg = AR913X_DDR_REG_FLUSH_USB;
+	} else
+		BUG();
+
+	cp0_perfcount_irq = ATH79_MISC_IRQ_PERFC;
+	mips_cpu_irq_init();
+	ath79_misc_irq_init();
+}
diff --git a/arch/mips/ath79/prom.c b/arch/mips/ath79/prom.c
new file mode 100644
index 0000000..e9cbd7c
--- /dev/null
+++ b/arch/mips/ath79/prom.c
@@ -0,0 +1,57 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X specific prom routines
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/string.h>
+
+#include <asm/bootinfo.h>
+#include <asm/addrspace.h>
+
+#include "common.h"
+
+static inline int is_valid_ram_addr(void *addr)
+{
+	if (((u32) addr > KSEG0) &&
+	    ((u32) addr < (KSEG0 + ATH79_MEM_SIZE_MAX)))
+		return 1;
+
+	if (((u32) addr > KSEG1) &&
+	    ((u32) addr < (KSEG1 + ATH79_MEM_SIZE_MAX)))
+		return 1;
+
+	return 0;
+}
+
+static __init void ath79_prom_init_cmdline(int argc, char **argv)
+{
+	int i;
+
+	if (!is_valid_ram_addr(argv))
+		return;
+
+	for (i = 0; i < argc; i++)
+		if (is_valid_ram_addr(argv[i])) {
+			strlcat(arcs_cmdline, " ", sizeof(arcs_cmdline));
+			strlcat(arcs_cmdline, argv[i], sizeof(arcs_cmdline));
+		}
+}
+
+void __init prom_init(void)
+{
+	ath79_prom_init_cmdline(fw_arg0, (char **)fw_arg1);
+}
+
+void __init prom_free_prom_memory(void)
+{
+	/* We do not have to prom memory to free */
+}
diff --git a/arch/mips/ath79/setup.c b/arch/mips/ath79/setup.c
new file mode 100644
index 0000000..4157ddc
--- /dev/null
+++ b/arch/mips/ath79/setup.c
@@ -0,0 +1,263 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X specific setup
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  Parts of this file are based on Atheros' 2.6.15 BSP
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+
+#include <asm/bootinfo.h>
+#include <asm/time.h>		/* for mips_hpt_frequency */
+#include <asm/reboot.h>		/* for _machine_{restart,halt} */
+
+#include <asm/mach-ath79/ath79.h>
+#include <asm/mach-ath79/ar71xx_regs.h>
+#include "common.h"
+#include "dev-common.h"
+
+#define ATH79_SYS_TYPE_LEN	64
+
+#define AR71XX_BASE_FREQ	40000000
+#define AR724X_BASE_FREQ	5000000
+#define AR913X_BASE_FREQ	5000000
+
+static char ath79_sys_type[ATH79_SYS_TYPE_LEN];
+
+static void ath79_restart(char *command)
+{
+	ath79_device_reset_set(AR71XX_RESET_FULL_CHIP);
+	for (;;)
+		if (cpu_wait)
+			cpu_wait();
+}
+
+static void ath79_halt(void)
+{
+	while (1)
+		cpu_wait();
+}
+
+static void __init ath79_detect_mem_size(void)
+{
+	unsigned long size;
+
+	for (size = ATH79_MEM_SIZE_MIN; size < ATH79_MEM_SIZE_MAX;
+	     size <<= 1) {
+		if (!memcmp(ath79_detect_mem_size,
+			    ath79_detect_mem_size + size, 1024))
+			break;
+	}
+
+	add_memory_region(0, size, BOOT_MEM_RAM);
+}
+
+static void __init ath79_detect_sys_type(void)
+{
+	char *chip = "????";
+	u32 id;
+	u32 major;
+	u32 minor;
+	u32 rev = 0;
+
+	id = ath79_reset_rr(AR71XX_RESET_REG_REV_ID);
+	major = id & REV_ID_MAJOR_MASK;
+
+	switch (major) {
+	case REV_ID_MAJOR_AR71XX:
+		minor = id & AR71XX_REV_ID_MINOR_MASK;
+		rev = id >> AR71XX_REV_ID_REVISION_SHIFT;
+		rev &= AR71XX_REV_ID_REVISION_MASK;
+		switch (minor) {
+		case AR71XX_REV_ID_MINOR_AR7130:
+			ath79_soc = ATH79_SOC_AR7130;
+			chip = "7130";
+			break;
+
+		case AR71XX_REV_ID_MINOR_AR7141:
+			ath79_soc = ATH79_SOC_AR7141;
+			chip = "7141";
+			break;
+
+		case AR71XX_REV_ID_MINOR_AR7161:
+			ath79_soc = ATH79_SOC_AR7161;
+			chip = "7161";
+			break;
+		}
+		break;
+
+	case REV_ID_MAJOR_AR7240:
+		ath79_soc = ATH79_SOC_AR7240;
+		chip = "7240";
+		rev = (id & AR724X_REV_ID_REVISION_MASK);
+		break;
+
+	case REV_ID_MAJOR_AR7241:
+		ath79_soc = ATH79_SOC_AR7241;
+		chip = "7241";
+		rev = (id & AR724X_REV_ID_REVISION_MASK);
+		break;
+
+	case REV_ID_MAJOR_AR7242:
+		ath79_soc = ATH79_SOC_AR7242;
+		chip = "7242";
+		rev = (id & AR724X_REV_ID_REVISION_MASK);
+		break;
+
+	case REV_ID_MAJOR_AR913X:
+		minor = id & AR913X_REV_ID_MINOR_MASK;
+		rev = id >> AR913X_REV_ID_REVISION_SHIFT;
+		rev &= AR913X_REV_ID_REVISION_MASK;
+		switch (minor) {
+		case AR913X_REV_ID_MINOR_AR9130:
+			ath79_soc = ATH79_SOC_AR9130;
+			chip = "9130";
+			break;
+
+		case AR913X_REV_ID_MINOR_AR9132:
+			ath79_soc = ATH79_SOC_AR9132;
+			chip = "9132";
+			break;
+		}
+		break;
+
+	default:
+		panic("ath79: unknown SoC, id:0x%08x\n", id);
+	}
+
+	sprintf(ath79_sys_type, "Atheros AR%s rev %u", chip, rev);
+}
+
+static void __init ar71xx_detect_sys_frequency(void)
+{
+	u32 pll;
+	u32 freq;
+	u32 div;
+
+	pll = ath79_pll_rr(AR71XX_PLL_REG_CPU_CONFIG);
+
+	div = ((pll >> AR71XX_PLL_DIV_SHIFT) & AR71XX_PLL_DIV_MASK) + 1;
+	freq = div * AR71XX_BASE_FREQ;
+
+	div = ((pll >> AR71XX_CPU_DIV_SHIFT) & AR71XX_CPU_DIV_MASK) + 1;
+	ath79_cpu_freq = freq / div;
+
+	div = ((pll >> AR71XX_DDR_DIV_SHIFT) & AR71XX_DDR_DIV_MASK) + 1;
+	ath79_ddr_freq = freq / div;
+
+	div = (((pll >> AR71XX_AHB_DIV_SHIFT) & AR71XX_AHB_DIV_MASK) + 1) * 2;
+	ath79_ahb_freq = ath79_cpu_freq / div;
+}
+
+static void __init ar724x_detect_sys_frequency(void)
+{
+	u32 pll;
+	u32 freq;
+	u32 div;
+
+	pll = ath79_pll_rr(AR724X_PLL_REG_CPU_CONFIG);
+
+	div = ((pll >> AR724X_PLL_DIV_SHIFT) & AR724X_PLL_DIV_MASK);
+	freq = div * AR724X_BASE_FREQ;
+
+	div = ((pll >> AR724X_PLL_REF_DIV_SHIFT) & AR724X_PLL_REF_DIV_MASK);
+	freq *= div;
+
+	ath79_cpu_freq = freq;
+
+	div = ((pll >> AR724X_DDR_DIV_SHIFT) & AR724X_DDR_DIV_MASK) + 1;
+	ath79_ddr_freq = freq / div;
+
+	div = (((pll >> AR724X_AHB_DIV_SHIFT) & AR724X_AHB_DIV_MASK) + 1) * 2;
+	ath79_ahb_freq = ath79_cpu_freq / div;
+}
+
+static void __init ar913x_detect_sys_frequency(void)
+{
+	u32 pll;
+	u32 freq;
+	u32 div;
+
+	pll = ath79_pll_rr(AR913X_PLL_REG_CPU_CONFIG);
+
+	div = ((pll >> AR913X_PLL_DIV_SHIFT) & AR913X_PLL_DIV_MASK);
+	freq = div * AR913X_BASE_FREQ;
+
+	ath79_cpu_freq = freq;
+
+	div = ((pll >> AR913X_DDR_DIV_SHIFT) & AR913X_DDR_DIV_MASK) + 1;
+	ath79_ddr_freq = freq / div;
+
+	div = (((pll >> AR913X_AHB_DIV_SHIFT) & AR913X_AHB_DIV_MASK) + 1) * 2;
+	ath79_ahb_freq = ath79_cpu_freq / div;
+}
+
+static void __init ath79_detect_sys_frequency(void)
+{
+	if (soc_is_ar71xx())
+		ar71xx_detect_sys_frequency();
+	else if (soc_is_ar724x())
+		ar724x_detect_sys_frequency();
+	else if (soc_is_ar913x())
+		ar913x_detect_sys_frequency();
+	else
+		BUG();
+}
+
+const char *get_system_type(void)
+{
+	return ath79_sys_type;
+}
+
+unsigned int __cpuinit get_c0_compare_int(void)
+{
+	return CP0_LEGACY_COMPARE_IRQ;
+}
+
+void __init plat_mem_setup(void)
+{
+	set_io_port_base(KSEG1);
+
+	ath79_reset_base = ioremap_nocache(AR71XX_RESET_BASE,
+					   AR71XX_RESET_SIZE);
+	ath79_pll_base = ioremap_nocache(AR71XX_PLL_BASE,
+					 AR71XX_PLL_SIZE);
+
+	ath79_ddr_base = ioremap_nocache(AR71XX_DDR_CTRL_BASE,
+					 AR71XX_DDR_CTRL_SIZE);
+
+	ath79_detect_sys_type();
+	ath79_detect_mem_size();
+	ath79_detect_sys_frequency();
+
+	pr_info("SoC: %s, CPU:%u.%03u MHz, DDR:%u.%03u MHz, AHB:%u.%03u MHz\n",
+		ath79_sys_type,
+		ath79_cpu_freq / 1000000, (ath79_cpu_freq / 1000) % 1000,
+		ath79_ddr_freq / 1000000, (ath79_ddr_freq / 1000) % 1000,
+		ath79_ahb_freq / 1000000, (ath79_ahb_freq / 1000) % 1000);
+
+	_machine_restart = ath79_restart;
+	_machine_halt = ath79_halt;
+	pm_power_off = ath79_halt;
+}
+
+void __init plat_time_init(void)
+{
+	mips_hpt_frequency = ath79_cpu_freq / 2;
+}
+
+static int __init ath79_setup(void)
+{
+	ath79_register_uart();
+	return 0;
+}
+
+arch_initcall(ath79_setup);
diff --git a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
new file mode 100644
index 0000000..5a9e5e1
--- /dev/null
+++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
@@ -0,0 +1,207 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X SoC register definitions
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  Parts of this file are based on Atheros' 2.6.15 BSP
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#ifndef __ASM_MACH_AR71XX_REGS_H
+#define __ASM_MACH_AR71XX_REGS_H
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/bitops.h>
+
+#define AR71XX_APB_BASE		0x18000000
+
+#define AR71XX_DDR_CTRL_BASE	(AR71XX_APB_BASE + 0x00000000)
+#define AR71XX_DDR_CTRL_SIZE	0x100
+#define AR71XX_UART_BASE	(AR71XX_APB_BASE + 0x00020000)
+#define AR71XX_UART_SIZE	0x100
+#define AR71XX_PLL_BASE		(AR71XX_APB_BASE + 0x00050000)
+#define AR71XX_PLL_SIZE		0x100
+#define AR71XX_RESET_BASE	(AR71XX_APB_BASE + 0x00060000)
+#define AR71XX_RESET_SIZE	0x100
+
+/*
+ * DDR_CTRL block
+ */
+#define AR71XX_DDR_REG_PCI_WIN0		0x7c
+#define AR71XX_DDR_REG_PCI_WIN1		0x80
+#define AR71XX_DDR_REG_PCI_WIN2		0x84
+#define AR71XX_DDR_REG_PCI_WIN3		0x88
+#define AR71XX_DDR_REG_PCI_WIN4		0x8c
+#define AR71XX_DDR_REG_PCI_WIN5		0x90
+#define AR71XX_DDR_REG_PCI_WIN6		0x94
+#define AR71XX_DDR_REG_PCI_WIN7		0x98
+#define AR71XX_DDR_REG_FLUSH_GE0	0x9c
+#define AR71XX_DDR_REG_FLUSH_GE1	0xa0
+#define AR71XX_DDR_REG_FLUSH_USB	0xa4
+#define AR71XX_DDR_REG_FLUSH_PCI	0xa8
+
+#define AR724X_DDR_REG_FLUSH_GE0	0x7c
+#define AR724X_DDR_REG_FLUSH_GE1	0x80
+#define AR724X_DDR_REG_FLUSH_USB	0x84
+#define AR724X_DDR_REG_FLUSH_PCIE	0x88
+
+#define AR913X_DDR_REG_FLUSH_GE0	0x7c
+#define AR913X_DDR_REG_FLUSH_GE1	0x80
+#define AR913X_DDR_REG_FLUSH_USB	0x84
+#define AR913X_DDR_REG_FLUSH_WMAC	0x88
+
+/*
+ * PLL block
+ */
+#define AR71XX_PLL_REG_CPU_CONFIG	0x00
+#define AR71XX_PLL_REG_SEC_CONFIG	0x04
+#define AR71XX_PLL_REG_ETH0_INT_CLOCK	0x10
+#define AR71XX_PLL_REG_ETH1_INT_CLOCK	0x14
+
+#define AR71XX_PLL_DIV_SHIFT		3
+#define AR71XX_PLL_DIV_MASK		0x1f
+#define AR71XX_CPU_DIV_SHIFT		16
+#define AR71XX_CPU_DIV_MASK		0x3
+#define AR71XX_DDR_DIV_SHIFT		18
+#define AR71XX_DDR_DIV_MASK		0x3
+#define AR71XX_AHB_DIV_SHIFT		20
+#define AR71XX_AHB_DIV_MASK		0x7
+
+#define AR724X_PLL_REG_CPU_CONFIG	0x00
+#define AR724X_PLL_REG_PCIE_CONFIG	0x18
+
+#define AR724X_PLL_DIV_SHIFT		0
+#define AR724X_PLL_DIV_MASK		0x3ff
+#define AR724X_PLL_REF_DIV_SHIFT	10
+#define AR724X_PLL_REF_DIV_MASK		0xf
+#define AR724X_AHB_DIV_SHIFT		19
+#define AR724X_AHB_DIV_MASK		0x1
+#define AR724X_DDR_DIV_SHIFT		22
+#define AR724X_DDR_DIV_MASK		0x3
+
+#define AR913X_PLL_REG_CPU_CONFIG	0x00
+#define AR913X_PLL_REG_ETH_CONFIG	0x04
+#define AR913X_PLL_REG_ETH0_INT_CLOCK	0x14
+#define AR913X_PLL_REG_ETH1_INT_CLOCK	0x18
+
+#define AR913X_PLL_DIV_SHIFT		0
+#define AR913X_PLL_DIV_MASK		0x3ff
+#define AR913X_DDR_DIV_SHIFT		22
+#define AR913X_DDR_DIV_MASK		0x3
+#define AR913X_AHB_DIV_SHIFT		19
+#define AR913X_AHB_DIV_MASK		0x1
+
+/*
+ * RESET block
+ */
+#define AR71XX_RESET_REG_TIMER			0x00
+#define AR71XX_RESET_REG_TIMER_RELOAD		0x04
+#define AR71XX_RESET_REG_WDOG_CTRL		0x08
+#define AR71XX_RESET_REG_WDOG			0x0c
+#define AR71XX_RESET_REG_MISC_INT_STATUS	0x10
+#define AR71XX_RESET_REG_MISC_INT_ENABLE	0x14
+#define AR71XX_RESET_REG_PCI_INT_STATUS		0x18
+#define AR71XX_RESET_REG_PCI_INT_ENABLE		0x1c
+#define AR71XX_RESET_REG_GLOBAL_INT_STATUS	0x20
+#define AR71XX_RESET_REG_RESET_MODULE		0x24
+#define AR71XX_RESET_REG_PERFC_CTRL		0x2c
+#define AR71XX_RESET_REG_PERFC0			0x30
+#define AR71XX_RESET_REG_PERFC1			0x34
+#define AR71XX_RESET_REG_REV_ID			0x90
+
+#define AR913X_RESET_REG_GLOBAL_INT_STATUS	0x18
+#define AR913X_RESET_REG_RESET_MODULE		0x1c
+#define AR913X_RESET_REG_PERF_CTRL		0x20
+#define AR913X_RESET_REG_PERFC0			0x24
+#define AR913X_RESET_REG_PERFC1			0x28
+
+#define AR724X_RESET_REG_RESET_MODULE		0x1c
+
+#define MISC_INT_DMA			BIT(7)
+#define MISC_INT_OHCI			BIT(6)
+#define MISC_INT_PERFC			BIT(5)
+#define MISC_INT_WDOG			BIT(4)
+#define MISC_INT_UART			BIT(3)
+#define MISC_INT_GPIO			BIT(2)
+#define MISC_INT_ERROR			BIT(1)
+#define MISC_INT_TIMER			BIT(0)
+
+#define AR71XX_RESET_EXTERNAL		BIT(28)
+#define AR71XX_RESET_FULL_CHIP		BIT(24)
+#define AR71XX_RESET_CPU_NMI		BIT(21)
+#define AR71XX_RESET_CPU_COLD		BIT(20)
+#define AR71XX_RESET_DMA		BIT(19)
+#define AR71XX_RESET_SLIC		BIT(18)
+#define AR71XX_RESET_STEREO		BIT(17)
+#define AR71XX_RESET_DDR		BIT(16)
+#define AR71XX_RESET_GE1_MAC		BIT(13)
+#define AR71XX_RESET_GE1_PHY		BIT(12)
+#define AR71XX_RESET_USBSUS_OVERRIDE	BIT(10)
+#define AR71XX_RESET_GE0_MAC		BIT(9)
+#define AR71XX_RESET_GE0_PHY		BIT(8)
+#define AR71XX_RESET_USB_OHCI_DLL	BIT(6)
+#define AR71XX_RESET_USB_HOST		BIT(5)
+#define AR71XX_RESET_USB_PHY		BIT(4)
+#define AR71XX_RESET_PCI_BUS		BIT(1)
+#define AR71XX_RESET_PCI_CORE		BIT(0)
+
+#define AR724X_RESET_GE1_MDIO		BIT(23)
+#define AR724X_RESET_GE0_MDIO		BIT(22)
+#define AR724X_RESET_PCIE_PHY_SERIAL	BIT(10)
+#define AR724X_RESET_PCIE_PHY		BIT(7)
+#define AR724X_RESET_PCIE		BIT(6)
+#define AR724X_RESET_OHCI_DLL		BIT(3)
+
+#define AR913X_RESET_AMBA2WMAC		BIT(22)
+
+#define REV_ID_MAJOR_MASK		0xfff0
+#define REV_ID_MAJOR_AR71XX		0x00a0
+#define REV_ID_MAJOR_AR913X		0x00b0
+#define REV_ID_MAJOR_AR7240		0x00c0
+#define REV_ID_MAJOR_AR7241		0x0100
+#define REV_ID_MAJOR_AR7242		0x1100
+
+#define AR71XX_REV_ID_MINOR_MASK	0x3
+#define AR71XX_REV_ID_MINOR_AR7130	0x0
+#define AR71XX_REV_ID_MINOR_AR7141	0x1
+#define AR71XX_REV_ID_MINOR_AR7161	0x2
+#define AR71XX_REV_ID_REVISION_MASK	0x3
+#define AR71XX_REV_ID_REVISION_SHIFT	2
+
+#define AR913X_REV_ID_MINOR_MASK	0x3
+#define AR913X_REV_ID_MINOR_AR9130	0x0
+#define AR913X_REV_ID_MINOR_AR9132	0x1
+#define AR913X_REV_ID_REVISION_MASK	0x3
+#define AR913X_REV_ID_REVISION_SHIFT	2
+
+#define AR724X_REV_ID_REVISION_MASK	0x3
+
+/*
+ * SPI block
+ */
+#define AR71XX_SPI_REG_FS	0x00	/* Function Select */
+#define AR71XX_SPI_REG_CTRL	0x04	/* SPI Control */
+#define AR71XX_SPI_REG_IOC	0x08	/* SPI I/O Control */
+#define AR71XX_SPI_REG_RDS	0x0c	/* Read Data Shift */
+
+#define AR71XX_SPI_FS_GPIO	BIT(0)	/* Enable GPIO mode */
+
+#define AR71XX_SPI_CTRL_RD	BIT(6)	/* Remap Disable */
+#define AR71XX_SPI_CTRL_DIV_MASK 0x3f
+
+#define AR71XX_SPI_IOC_DO	BIT(0)	/* Data Out pin */
+#define AR71XX_SPI_IOC_CLK	BIT(8)	/* CLK pin */
+#define AR71XX_SPI_IOC_CS(n)	BIT(16 + (n))
+#define AR71XX_SPI_IOC_CS0	AR71XX_SPI_IOC_CS(0)
+#define AR71XX_SPI_IOC_CS1	AR71XX_SPI_IOC_CS(1)
+#define AR71XX_SPI_IOC_CS2	AR71XX_SPI_IOC_CS(2)
+#define AR71XX_SPI_IOC_CS_ALL	(AR71XX_SPI_IOC_CS0 | AR71XX_SPI_IOC_CS1 | \
+				 AR71XX_SPI_IOC_CS2)
+
+#endif /* __ASM_MACH_AR71XX_REGS_H */
diff --git a/arch/mips/include/asm/mach-ath79/ath79.h b/arch/mips/include/asm/mach-ath79/ath79.h
new file mode 100644
index 0000000..34fa294
--- /dev/null
+++ b/arch/mips/include/asm/mach-ath79/ath79.h
@@ -0,0 +1,100 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X common definitions
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  Parts of this file are based on Atheros' 2.6.15 BSP
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#ifndef __ASM_MACH_ATH79_H
+#define __ASM_MACH_ATH79_H
+
+#include <linux/types.h>
+#include <linux/io.h>
+
+extern u32 ath79_ahb_freq;
+extern u32 ath79_cpu_freq;
+extern u32 ath79_ddr_freq;
+
+enum ath79_soc_type {
+	ATH79_SOC_UNKNOWN,
+	ATH79_SOC_AR7130,
+	ATH79_SOC_AR7141,
+	ATH79_SOC_AR7161,
+	ATH79_SOC_AR7240,
+	ATH79_SOC_AR7241,
+	ATH79_SOC_AR7242,
+	ATH79_SOC_AR9130,
+	ATH79_SOC_AR9132
+};
+
+extern enum ath79_soc_type ath79_soc;
+
+static inline int soc_is_ar71xx(void)
+{
+	return (ath79_soc == ATH79_SOC_AR7130 ||
+		ath79_soc == ATH79_SOC_AR7141 ||
+		ath79_soc == ATH79_SOC_AR7161);
+}
+
+static inline int soc_is_ar724x(void)
+{
+	return (ath79_soc == ATH79_SOC_AR7240 ||
+		ath79_soc == ATH79_SOC_AR7241 ||
+		ath79_soc == ATH79_SOC_AR7242);
+}
+
+static inline int soc_is_ar7240(void)
+{
+	return (ath79_soc == ATH79_SOC_AR7240);
+}
+
+static inline int soc_is_ar7241(void)
+{
+	return (ath79_soc == ATH79_SOC_AR7241);
+}
+
+static inline int soc_is_ar7242(void)
+{
+	return (ath79_soc == ATH79_SOC_AR7242);
+}
+
+static inline int soc_is_ar913x(void)
+{
+	return (ath79_soc == ATH79_SOC_AR9130 ||
+		ath79_soc == ATH79_SOC_AR9132);
+}
+
+extern void __iomem *ath79_ddr_base;
+extern void __iomem *ath79_pll_base;
+extern void __iomem *ath79_reset_base;
+
+static inline void ath79_pll_wr(unsigned reg, u32 val)
+{
+	__raw_writel(val, ath79_pll_base + reg);
+}
+
+static inline u32 ath79_pll_rr(unsigned reg)
+{
+	return __raw_readl(ath79_pll_base + reg);
+}
+
+static inline void ath79_reset_wr(unsigned reg, u32 val)
+{
+	__raw_writel(val, ath79_reset_base + reg);
+}
+
+static inline u32 ath79_reset_rr(unsigned reg)
+{
+	return __raw_readl(ath79_reset_base + reg);
+}
+
+void ath79_device_reset_set(u32 mask);
+void ath79_device_reset_clear(u32 mask);
+
+#endif /* __ASM_MACH_ATH79_H */
diff --git a/arch/mips/include/asm/mach-ath79/cpu-feature-overrides.h b/arch/mips/include/asm/mach-ath79/cpu-feature-overrides.h
new file mode 100644
index 0000000..4476fa0
--- /dev/null
+++ b/arch/mips/include/asm/mach-ath79/cpu-feature-overrides.h
@@ -0,0 +1,56 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X specific CPU feature overrides
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  This file was derived from: include/asm-mips/cpu-features.h
+ *	Copyright (C) 2003, 2004 Ralf Baechle
+ *	Copyright (C) 2004 Maciej W. Rozycki
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ *
+ */
+#ifndef __ASM_MACH_ATH79_CPU_FEATURE_OVERRIDES_H
+#define __ASM_MACH_ATH79_CPU_FEATURE_OVERRIDES_H
+
+#define cpu_has_tlb		1
+#define cpu_has_4kex		1
+#define cpu_has_3k_cache	0
+#define cpu_has_4k_cache	1
+#define cpu_has_tx39_cache	0
+#define cpu_has_sb1_cache	0
+#define cpu_has_fpu		0
+#define cpu_has_32fpr		0
+#define cpu_has_counter		1
+#define cpu_has_watch		1
+#define cpu_has_divec		1
+
+#define cpu_has_prefetch	1
+#define cpu_has_ejtag		1
+#define cpu_has_llsc		1
+
+#define cpu_has_mips16		1
+#define cpu_has_mdmx		0
+#define cpu_has_mips3d		0
+#define cpu_has_smartmips	0
+
+#define cpu_has_mips32r1	1
+#define cpu_has_mips32r2	1
+#define cpu_has_mips64r1	0
+#define cpu_has_mips64r2	0
+
+#define cpu_has_dsp		0
+#define cpu_has_mipsmt		0
+
+#define cpu_has_64bits		0
+#define cpu_has_64bit_zero_reg	0
+#define cpu_has_64bit_gp_regs	0
+#define cpu_has_64bit_addresses	0
+
+#define cpu_dcache_line_size()	32
+#define cpu_icache_line_size()	32
+
+#endif /* __ASM_MACH_ATH79_CPU_FEATURE_OVERRIDES_H */
diff --git a/arch/mips/include/asm/mach-ath79/irq.h b/arch/mips/include/asm/mach-ath79/irq.h
new file mode 100644
index 0000000..189bc6e
--- /dev/null
+++ b/arch/mips/include/asm/mach-ath79/irq.h
@@ -0,0 +1,36 @@
+/*
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+#ifndef __ASM_MACH_ATH79_IRQ_H
+#define __ASM_MACH_ATH79_IRQ_H
+
+#define MIPS_CPU_IRQ_BASE	0
+#define NR_IRQS			16
+
+#define ATH79_MISC_IRQ_BASE	8
+#define ATH79_MISC_IRQ_COUNT	8
+
+#define ATH79_CPU_IRQ_IP2	(MIPS_CPU_IRQ_BASE + 2)
+#define ATH79_CPU_IRQ_USB	(MIPS_CPU_IRQ_BASE + 3)
+#define ATH79_CPU_IRQ_GE0	(MIPS_CPU_IRQ_BASE + 4)
+#define ATH79_CPU_IRQ_GE1	(MIPS_CPU_IRQ_BASE + 5)
+#define ATH79_CPU_IRQ_MISC	(MIPS_CPU_IRQ_BASE + 6)
+#define ATH79_CPU_IRQ_TIMER	(MIPS_CPU_IRQ_BASE + 7)
+
+#define ATH79_MISC_IRQ_TIMER	(ATH79_MISC_IRQ_BASE + 0)
+#define ATH79_MISC_IRQ_ERROR	(ATH79_MISC_IRQ_BASE + 1)
+#define ATH79_MISC_IRQ_GPIO	(ATH79_MISC_IRQ_BASE + 2)
+#define ATH79_MISC_IRQ_UART	(ATH79_MISC_IRQ_BASE + 3)
+#define ATH79_MISC_IRQ_WDOG	(ATH79_MISC_IRQ_BASE + 4)
+#define ATH79_MISC_IRQ_PERFC	(ATH79_MISC_IRQ_BASE + 5)
+#define ATH79_MISC_IRQ_OHCI	(ATH79_MISC_IRQ_BASE + 6)
+#define ATH79_MISC_IRQ_DMA	(ATH79_MISC_IRQ_BASE + 7)
+
+#include_next <irq.h>
+
+#endif /* __ASM_MACH_ATH79_IRQ_H */
diff --git a/arch/mips/include/asm/mach-ath79/kernel-entry-init.h b/arch/mips/include/asm/mach-ath79/kernel-entry-init.h
new file mode 100644
index 0000000..d8d046b
--- /dev/null
+++ b/arch/mips/include/asm/mach-ath79/kernel-entry-init.h
@@ -0,0 +1,32 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X specific kernel entry setup
+ *
+ *  Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ *
+ */
+#ifndef __ASM_MACH_ATH79_KERNEL_ENTRY_H
+#define __ASM_MACH_ATH79_KERNEL_ENTRY_H
+
+	/*
+	 * Some bootloaders set the 'Kseg0 coherency algorithm' to
+	 * 'Cacheable, noncoherent, write-through, no write allocate'
+	 * and this cause performance issues. Let's go and change it to
+	 * 'Cacheable, noncoherent, write-back, write allocate'
+	 */
+	.macro	kernel_entry_setup
+	mfc0	t0, CP0_CONFIG
+	li	t1, ~CONF_CM_CMASK
+	and	t0, t1
+	ori	t0, CONF_CM_CACHABLE_NONCOHERENT
+	mtc0	t0, CP0_CONFIG
+	nop
+	.endm
+
+	.macro	smp_slave_setup
+	.endm
+
+#endif /* __ASM_MACH_ATH79_KERNEL_ENTRY_H */
diff --git a/arch/mips/include/asm/mach-ath79/war.h b/arch/mips/include/asm/mach-ath79/war.h
new file mode 100644
index 0000000..323d9f1
--- /dev/null
+++ b/arch/mips/include/asm/mach-ath79/war.h
@@ -0,0 +1,25 @@
+/*
+ * 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) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org>
+ */
+#ifndef __ASM_MACH_ATH79_WAR_H
+#define __ASM_MACH_ATH79_WAR_H
+
+#define R4600_V1_INDEX_ICACHEOP_WAR	0
+#define R4600_V1_HIT_CACHEOP_WAR	0
+#define R4600_V2_HIT_CACHEOP_WAR	0
+#define R5432_CP0_INTERRUPT_WAR		0
+#define BCM1250_M3_WAR			0
+#define SIBYTE_1956_WAR			0
+#define MIPS4K_ICACHE_REFILL_WAR	0
+#define MIPS_CACHE_SYNC_WAR		0
+#define TX49XX_ICACHE_INDEX_INV_WAR	0
+#define RM9000_CDEX_SMP_WAR		0
+#define ICACHE_REFILLS_WORKAROUND_WAR	0
+#define R10000_LLSC_WAR			0
+#define MIPS34K_MISSED_ITLB_WAR		0
+
+#endif /* __ASM_MACH_ATH79_WAR_H */
-- 
1.7.2.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v2 02/16] MIPS: ath79: add GPIOLIB support
  2010-12-22 20:30 [PATCH v2 00/16] MIPS: initial support for the Atheros AR71XX/AR724X/AR913X SoCs Gabor Juhos
  2010-12-22 20:30 ` [PATCH v2 01/16] MIPS: add initial support for the Atheros AR71XX/AR724X/AR931X SoCs Gabor Juhos
@ 2010-12-22 20:30 ` Gabor Juhos
  2010-12-22 20:30 ` [PATCH v2 03/16] MIPS: ath79: utilize the MIPS multi-machine support Gabor Juhos
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 21+ messages in thread
From: Gabor Juhos @ 2010-12-22 20:30 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: linux-mips, Imre Kaloz, Luis R. Rodriguez, Cliff Holden,
	Kathy Giori, Gabor Juhos, David Brownell

This patch implements generic GPIO routines for the built-in
GPIO controllers of the Atheros AR71XX/AR724X/AR913X SoCs.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Signed-off-by: Imre Kaloz <kaloz@openwrt.org>
Cc: David Brownell <dbrownell@users.sourceforge.net>
---

Changes since RFC: ---

Changes since v1:
    - rebased against 2.6.37-rc7

 arch/mips/Kconfig                              |    1 +
 arch/mips/ath79/Makefile                       |    2 +-
 arch/mips/ath79/common.h                       |    5 +
 arch/mips/ath79/gpio.c                         |  197 ++++++++++++++++++++++++
 arch/mips/ath79/setup.c                        |    2 +-
 arch/mips/include/asm/mach-ath79/ar71xx_regs.h |   21 +++
 arch/mips/include/asm/mach-ath79/gpio.h        |   26 +++
 7 files changed, 252 insertions(+), 2 deletions(-)
 create mode 100644 arch/mips/ath79/gpio.c
 create mode 100644 arch/mips/include/asm/mach-ath79/gpio.h

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index c0511d6..c3270a4 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -67,6 +67,7 @@ config AR7
 
 config ATH79
 	bool "Atheros AR71XX/AR724X/AR913X based boards"
+	select ARCH_REQUIRE_GPIOLIB
 	select BOOT_RAW
 	select CEVT_R4K
 	select CSRC_R4K
diff --git a/arch/mips/ath79/Makefile b/arch/mips/ath79/Makefile
index b4ec9c2..facbb70 100644
--- a/arch/mips/ath79/Makefile
+++ b/arch/mips/ath79/Makefile
@@ -8,7 +8,7 @@
 # under the terms of the GNU General Public License version 2 as published
 # by the Free Software Foundation.
 
-obj-y	:= prom.o setup.o irq.o common.o
+obj-y	:= prom.o setup.o irq.o common.o gpio.o
 
 obj-$(CONFIG_EARLY_PRINTK)		+= early_printk.o
 
diff --git a/arch/mips/ath79/common.h b/arch/mips/ath79/common.h
index a1bcdbb..cb2f3e8 100644
--- a/arch/mips/ath79/common.h
+++ b/arch/mips/ath79/common.h
@@ -22,4 +22,9 @@
 
 void ath79_ddr_wb_flush(unsigned int reg);
 
+void ath79_gpio_function_enable(u32 mask);
+void ath79_gpio_function_disable(u32 mask);
+void ath79_gpio_function_setup(u32 set, u32 clear);
+void ath79_gpio_init(void) __init;
+
 #endif /* __ATH79_COMMON_H */
diff --git a/arch/mips/ath79/gpio.c b/arch/mips/ath79/gpio.c
new file mode 100644
index 0000000..a0c426b
--- /dev/null
+++ b/arch/mips/ath79/gpio.c
@@ -0,0 +1,197 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X GPIO API support
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/gpio.h>
+
+#include <asm/mach-ath79/ar71xx_regs.h>
+#include <asm/mach-ath79/ath79.h>
+#include "common.h"
+
+static void __iomem *ath79_gpio_base;
+static unsigned long ath79_gpio_count;
+static DEFINE_SPINLOCK(ath79_gpio_lock);
+
+static void __ath79_gpio_set_value(unsigned gpio, int value)
+{
+	void __iomem *base = ath79_gpio_base;
+
+	if (value)
+		__raw_writel(1 << gpio, base + AR71XX_GPIO_REG_SET);
+	else
+		__raw_writel(1 << gpio, base + AR71XX_GPIO_REG_CLEAR);
+}
+
+static int __ath79_gpio_get_value(unsigned gpio)
+{
+	return (__raw_readl(ath79_gpio_base + AR71XX_GPIO_REG_IN) >> gpio) & 1;
+}
+
+static int ath79_gpio_get_value(struct gpio_chip *chip, unsigned offset)
+{
+	return __ath79_gpio_get_value(offset);
+}
+
+static void ath79_gpio_set_value(struct gpio_chip *chip,
+				  unsigned offset, int value)
+{
+	__ath79_gpio_set_value(offset, value);
+}
+
+static int ath79_gpio_direction_input(struct gpio_chip *chip,
+				       unsigned offset)
+{
+	void __iomem *base = ath79_gpio_base;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ath79_gpio_lock, flags);
+
+	__raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) & ~(1 << offset),
+		     base + AR71XX_GPIO_REG_OE);
+
+	spin_unlock_irqrestore(&ath79_gpio_lock, flags);
+
+	return 0;
+}
+
+static int ath79_gpio_direction_output(struct gpio_chip *chip,
+					unsigned offset, int value)
+{
+	void __iomem *base = ath79_gpio_base;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ath79_gpio_lock, flags);
+
+	if (value)
+		__raw_writel(1 << offset, base + AR71XX_GPIO_REG_SET);
+	else
+		__raw_writel(1 << offset, base + AR71XX_GPIO_REG_CLEAR);
+
+	__raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) | (1 << offset),
+		     base + AR71XX_GPIO_REG_OE);
+
+	spin_unlock_irqrestore(&ath79_gpio_lock, flags);
+
+	return 0;
+}
+
+static struct gpio_chip ath79_gpio_chip = {
+	.label			= "ath79",
+	.get			= ath79_gpio_get_value,
+	.set			= ath79_gpio_set_value,
+	.direction_input	= ath79_gpio_direction_input,
+	.direction_output	= ath79_gpio_direction_output,
+	.base			= 0,
+};
+
+void ath79_gpio_function_enable(u32 mask)
+{
+	void __iomem *base = ath79_gpio_base;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ath79_gpio_lock, flags);
+
+	__raw_writel(__raw_readl(base + AR71XX_GPIO_REG_FUNC) | mask,
+		     base + AR71XX_GPIO_REG_FUNC);
+	/* flush write */
+	__raw_readl(base + AR71XX_GPIO_REG_FUNC);
+
+	spin_unlock_irqrestore(&ath79_gpio_lock, flags);
+}
+
+void ath79_gpio_function_disable(u32 mask)
+{
+	void __iomem *base = ath79_gpio_base;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ath79_gpio_lock, flags);
+
+	__raw_writel(__raw_readl(base + AR71XX_GPIO_REG_FUNC) & ~mask,
+		     base + AR71XX_GPIO_REG_FUNC);
+	/* flush write */
+	__raw_readl(base + AR71XX_GPIO_REG_FUNC);
+
+	spin_unlock_irqrestore(&ath79_gpio_lock, flags);
+}
+
+void ath79_gpio_function_setup(u32 set, u32 clear)
+{
+	void __iomem *base = ath79_gpio_base;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ath79_gpio_lock, flags);
+
+	__raw_writel((__raw_readl(base + AR71XX_GPIO_REG_FUNC) & ~clear) | set,
+		     base + AR71XX_GPIO_REG_FUNC);
+	/* flush write */
+	__raw_readl(base + AR71XX_GPIO_REG_FUNC);
+
+	spin_unlock_irqrestore(&ath79_gpio_lock, flags);
+}
+
+void __init ath79_gpio_init(void)
+{
+	int err;
+
+	if (soc_is_ar71xx())
+		ath79_gpio_count = AR71XX_GPIO_COUNT;
+	else if (soc_is_ar724x())
+		ath79_gpio_count = AR724X_GPIO_COUNT;
+	else if (soc_is_ar913x())
+		ath79_gpio_count = AR913X_GPIO_COUNT;
+	else
+		BUG();
+
+	ath79_gpio_base = ioremap_nocache(AR71XX_GPIO_BASE, AR71XX_GPIO_SIZE);
+	ath79_gpio_chip.ngpio = ath79_gpio_count;
+
+	err = gpiochip_add(&ath79_gpio_chip);
+	if (err)
+		panic("cannot add AR71xx GPIO chip, error=%d", err);
+}
+
+int gpio_get_value(unsigned gpio)
+{
+	if (gpio < ath79_gpio_count)
+		return __ath79_gpio_get_value(gpio);
+
+	return __gpio_get_value(gpio);
+}
+EXPORT_SYMBOL(gpio_get_value);
+
+void gpio_set_value(unsigned gpio, int value)
+{
+	if (gpio < ath79_gpio_count)
+		__ath79_gpio_set_value(gpio, value);
+	else
+		__gpio_set_value(gpio, value);
+}
+EXPORT_SYMBOL(gpio_set_value);
+
+int gpio_to_irq(unsigned gpio)
+{
+	/* FIXME */
+	return -EINVAL;
+}
+EXPORT_SYMBOL(gpio_to_irq);
+
+int irq_to_gpio(unsigned irq)
+{
+	/* FIXME */
+	return -EINVAL;
+}
+EXPORT_SYMBOL(irq_to_gpio);
diff --git a/arch/mips/ath79/setup.c b/arch/mips/ath79/setup.c
index 4157ddc..83dd855 100644
--- a/arch/mips/ath79/setup.c
+++ b/arch/mips/ath79/setup.c
@@ -230,7 +230,6 @@ void __init plat_mem_setup(void)
 					   AR71XX_RESET_SIZE);
 	ath79_pll_base = ioremap_nocache(AR71XX_PLL_BASE,
 					 AR71XX_PLL_SIZE);
-
 	ath79_ddr_base = ioremap_nocache(AR71XX_DDR_CTRL_BASE,
 					 AR71XX_DDR_CTRL_SIZE);
 
@@ -256,6 +255,7 @@ void __init plat_time_init(void)
 
 static int __init ath79_setup(void)
 {
+	ath79_gpio_init();
 	ath79_register_uart();
 	return 0;
 }
diff --git a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
index 5a9e5e1..7f2933d 100644
--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
+++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
@@ -25,6 +25,8 @@
 #define AR71XX_DDR_CTRL_SIZE	0x100
 #define AR71XX_UART_BASE	(AR71XX_APB_BASE + 0x00020000)
 #define AR71XX_UART_SIZE	0x100
+#define AR71XX_GPIO_BASE        (AR71XX_APB_BASE + 0x00040000)
+#define AR71XX_GPIO_SIZE        0x100
 #define AR71XX_PLL_BASE		(AR71XX_APB_BASE + 0x00050000)
 #define AR71XX_PLL_SIZE		0x100
 #define AR71XX_RESET_BASE	(AR71XX_APB_BASE + 0x00060000)
@@ -204,4 +206,23 @@
 #define AR71XX_SPI_IOC_CS_ALL	(AR71XX_SPI_IOC_CS0 | AR71XX_SPI_IOC_CS1 | \
 				 AR71XX_SPI_IOC_CS2)
 
+/*
+ * GPIO block
+ */
+#define AR71XX_GPIO_REG_OE		0x00
+#define AR71XX_GPIO_REG_IN		0x04
+#define AR71XX_GPIO_REG_OUT		0x08
+#define AR71XX_GPIO_REG_SET		0x0c
+#define AR71XX_GPIO_REG_CLEAR		0x10
+#define AR71XX_GPIO_REG_INT_MODE	0x14
+#define AR71XX_GPIO_REG_INT_TYPE	0x18
+#define AR71XX_GPIO_REG_INT_POLARITY	0x1c
+#define AR71XX_GPIO_REG_INT_PENDING	0x20
+#define AR71XX_GPIO_REG_INT_ENABLE	0x24
+#define AR71XX_GPIO_REG_FUNC		0x28
+
+#define AR71XX_GPIO_COUNT		16
+#define AR724X_GPIO_COUNT		18
+#define AR913X_GPIO_COUNT		22
+
 #endif /* __ASM_MACH_AR71XX_REGS_H */
diff --git a/arch/mips/include/asm/mach-ath79/gpio.h b/arch/mips/include/asm/mach-ath79/gpio.h
new file mode 100644
index 0000000..60dcb62
--- /dev/null
+++ b/arch/mips/include/asm/mach-ath79/gpio.h
@@ -0,0 +1,26 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X GPIO API definitions
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ *
+ */
+
+#ifndef __ASM_MACH_ATH79_GPIO_H
+#define __ASM_MACH_ATH79_GPIO_H
+
+#define ARCH_NR_GPIOS	64
+#include <asm-generic/gpio.h>
+
+int gpio_to_irq(unsigned gpio);
+int irq_to_gpio(unsigned irq);
+int gpio_get_value(unsigned gpio);
+void gpio_set_value(unsigned gpio, int value);
+
+#define gpio_cansleep	__gpio_cansleep
+
+#endif /* __ASM_MACH_ATH79_GPIO_H */
-- 
1.7.2.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v2 03/16] MIPS: ath79: utilize the MIPS multi-machine support
  2010-12-22 20:30 [PATCH v2 00/16] MIPS: initial support for the Atheros AR71XX/AR724X/AR913X SoCs Gabor Juhos
  2010-12-22 20:30 ` [PATCH v2 01/16] MIPS: add initial support for the Atheros AR71XX/AR724X/AR931X SoCs Gabor Juhos
  2010-12-22 20:30 ` [PATCH v2 02/16] MIPS: ath79: add GPIOLIB support Gabor Juhos
@ 2010-12-22 20:30 ` Gabor Juhos
  2010-12-22 20:30 ` [PATCH v2 04/16] MIPS: ath79: add initial support for the Atheros PB44 reference board Gabor Juhos
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 21+ messages in thread
From: Gabor Juhos @ 2010-12-22 20:30 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: linux-mips, Imre Kaloz, Luis R. Rodriguez, Cliff Holden,
	Kathy Giori, Gabor Juhos

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---

Changes since RFC: ---

Changes since v1:
    - rebased against 2.6.37-rc7

 arch/mips/Kconfig           |    1 +
 arch/mips/ath79/machtypes.h |   21 +++++++++++++++++++++
 arch/mips/ath79/setup.c     |   15 +++++++++++++++
 3 files changed, 37 insertions(+), 0 deletions(-)
 create mode 100644 arch/mips/ath79/machtypes.h

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index c3270a4..feb8de4 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -73,6 +73,7 @@ config ATH79
 	select CSRC_R4K
 	select DMA_NONCOHERENT
 	select IRQ_CPU
+	select MIPS_MACHINE
 	select SYS_HAS_CPU_MIPS32_R2
 	select SYS_HAS_EARLY_PRINTK
 	select SYS_SUPPORTS_32BIT_KERNEL
diff --git a/arch/mips/ath79/machtypes.h b/arch/mips/ath79/machtypes.h
new file mode 100644
index 0000000..fac0e26
--- /dev/null
+++ b/arch/mips/ath79/machtypes.h
@@ -0,0 +1,21 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X machine type definitions
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#ifndef _ATH79_MACHTYPE_H
+#define _ATH79_MACHTYPE_H
+
+#include <asm/mips_machine.h>
+
+enum ath79_mach_type {
+	ATH79_MACH_GENERIC = 0,
+};
+
+#endif /* _ATH79_MACHTYPE_H */
diff --git a/arch/mips/ath79/setup.c b/arch/mips/ath79/setup.c
index 83dd855..5f2b6de 100644
--- a/arch/mips/ath79/setup.c
+++ b/arch/mips/ath79/setup.c
@@ -18,11 +18,13 @@
 #include <asm/bootinfo.h>
 #include <asm/time.h>		/* for mips_hpt_frequency */
 #include <asm/reboot.h>		/* for _machine_{restart,halt} */
+#include <asm/mips_machine.h>
 
 #include <asm/mach-ath79/ath79.h>
 #include <asm/mach-ath79/ar71xx_regs.h>
 #include "common.h"
 #include "dev-common.h"
+#include "machtypes.h"
 
 #define ATH79_SYS_TYPE_LEN	64
 
@@ -257,7 +259,20 @@ static int __init ath79_setup(void)
 {
 	ath79_gpio_init();
 	ath79_register_uart();
+
+	mips_machine_setup();
+
 	return 0;
 }
 
 arch_initcall(ath79_setup);
+
+static void __init ath79_generic_init(void)
+{
+	/* Nothing to do */
+}
+
+MIPS_MACHINE(ATH79_MACH_GENERIC,
+	     "Generic",
+	     "Generic AR71XX/AR724X/AR913X based board",
+	     ath79_generic_init);
-- 
1.7.2.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v2 04/16] MIPS: ath79: add initial support for the Atheros PB44 reference board
  2010-12-22 20:30 [PATCH v2 00/16] MIPS: initial support for the Atheros AR71XX/AR724X/AR913X SoCs Gabor Juhos
                   ` (2 preceding siblings ...)
  2010-12-22 20:30 ` [PATCH v2 03/16] MIPS: ath79: utilize the MIPS multi-machine support Gabor Juhos
@ 2010-12-22 20:30 ` Gabor Juhos
  2010-12-22 20:30 ` [PATCH v2 05/16] MIPS: ath79: add common GPIO LEDs device Gabor Juhos
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 21+ messages in thread
From: Gabor Juhos @ 2010-12-22 20:30 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: linux-mips, Imre Kaloz, Luis R. Rodriguez, Cliff Holden,
	Kathy Giori, Gabor Juhos

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---

Changes since RFC:
    - don't use 'default n' for the ATH79_MACH_PB44 Kconfig option

Changes since v1:
    - rebased against 2.6.37-rc7
    
 arch/mips/ath79/Kconfig     |   11 ++++++++
 arch/mips/ath79/Makefile    |    5 ++++
 arch/mips/ath79/mach-pb44.c |   56 +++++++++++++++++++++++++++++++++++++++++++
 arch/mips/ath79/machtypes.h |    1 +
 4 files changed, 73 insertions(+), 0 deletions(-)
 create mode 100644 arch/mips/ath79/mach-pb44.c

diff --git a/arch/mips/ath79/Kconfig b/arch/mips/ath79/Kconfig
index 50b9334..fabb2b0 100644
--- a/arch/mips/ath79/Kconfig
+++ b/arch/mips/ath79/Kconfig
@@ -1,5 +1,16 @@
 if ATH79
 
+menu "Atheros AR71XX/AR724X/AR913X machine selection"
+
+config ATH79_MACH_PB44
+	bool "Atheros PB44 reference board"
+	select SOC_AR71XX
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Atheros PB44 reference board.
+
+endmenu
+
 config SOC_AR71XX
 	def_bool n
 
diff --git a/arch/mips/ath79/Makefile b/arch/mips/ath79/Makefile
index facbb70..a9ba120 100644
--- a/arch/mips/ath79/Makefile
+++ b/arch/mips/ath79/Makefile
@@ -16,3 +16,8 @@ obj-$(CONFIG_EARLY_PRINTK)		+= early_printk.o
 # Devices
 #
 obj-y					+= dev-common.o
+
+#
+# Machines
+#
+obj-$(CONFIG_ATH79_MACH_PB44)		+= mach-pb44.o
diff --git a/arch/mips/ath79/mach-pb44.c b/arch/mips/ath79/mach-pb44.c
new file mode 100644
index 0000000..ffc24d7
--- /dev/null
+++ b/arch/mips/ath79/mach-pb44.c
@@ -0,0 +1,56 @@
+/*
+ *  Atheros PB44 reference board support
+ *
+ *  Copyright (C) 2009-2010 Gabor Juhos <juhosg@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/i2c-gpio.h>
+#include <linux/i2c/pcf857x.h>
+
+#include "machtypes.h"
+
+#define PB44_GPIO_I2C_SCL	0
+#define PB44_GPIO_I2C_SDA	1
+
+#define PB44_GPIO_EXP_BASE	16
+
+static struct i2c_gpio_platform_data pb44_i2c_gpio_data = {
+	.sda_pin        = PB44_GPIO_I2C_SDA,
+	.scl_pin        = PB44_GPIO_I2C_SCL,
+};
+
+static struct platform_device pb44_i2c_gpio_device = {
+	.name		= "i2c-gpio",
+	.id		= 0,
+	.dev = {
+		.platform_data	= &pb44_i2c_gpio_data,
+	}
+};
+
+static struct pcf857x_platform_data pb44_pcf857x_data = {
+	.gpio_base	= PB44_GPIO_EXP_BASE,
+};
+
+static struct i2c_board_info pb44_i2c_board_info[] __initdata = {
+	{
+		I2C_BOARD_INFO("pcf8575", 0x20),
+		.platform_data  = &pb44_pcf857x_data,
+	},
+};
+
+static void __init pb44_init(void)
+{
+	i2c_register_board_info(0, pb44_i2c_board_info,
+				ARRAY_SIZE(pb44_i2c_board_info));
+	platform_device_register(&pb44_i2c_gpio_device);
+}
+
+MIPS_MACHINE(ATH79_MACH_PB44, "PB44", "Atheros PB44 reference board",
+	     pb44_init);
diff --git a/arch/mips/ath79/machtypes.h b/arch/mips/ath79/machtypes.h
index fac0e26..a796fa3 100644
--- a/arch/mips/ath79/machtypes.h
+++ b/arch/mips/ath79/machtypes.h
@@ -16,6 +16,7 @@
 
 enum ath79_mach_type {
 	ATH79_MACH_GENERIC = 0,
+	ATH79_MACH_PB44,		/* Atheros PB44 reference board */
 };
 
 #endif /* _ATH79_MACHTYPE_H */
-- 
1.7.2.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v2 05/16] MIPS: ath79: add common GPIO LEDs device
  2010-12-22 20:30 [PATCH v2 00/16] MIPS: initial support for the Atheros AR71XX/AR724X/AR913X SoCs Gabor Juhos
                   ` (3 preceding siblings ...)
  2010-12-22 20:30 ` [PATCH v2 04/16] MIPS: ath79: add initial support for the Atheros PB44 reference board Gabor Juhos
@ 2010-12-22 20:30 ` Gabor Juhos
  2010-12-22 20:30 ` [PATCH v2 06/16] watchdog: add driver for the Atheros AR71XX/AR724X/AR913X SoCs Gabor Juhos
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 21+ messages in thread
From: Gabor Juhos @ 2010-12-22 20:30 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: linux-mips, Imre Kaloz, Luis R. Rodriguez, Cliff Holden,
	Kathy Giori, Gabor Juhos

Almost all boards have one or more LEDs connected to GPIO lines. This
patch adds common code to register a platform_device for them.

The patch also adds support for the LEDs on the PB44 board.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Signed-off-by: Imre Kaloz <kaloz@openwrt.org>
---

Changes since RFC: ---

Changes since v1:
    - rebased against 2.6.37-rc7

 arch/mips/ath79/Kconfig         |    4 +++
 arch/mips/ath79/Makefile        |    1 +
 arch/mips/ath79/dev-leds-gpio.c |   56 +++++++++++++++++++++++++++++++++++++++
 arch/mips/ath79/dev-leds-gpio.h |   21 ++++++++++++++
 arch/mips/ath79/mach-pb44.c     |   18 ++++++++++++
 5 files changed, 100 insertions(+), 0 deletions(-)
 create mode 100644 arch/mips/ath79/dev-leds-gpio.c
 create mode 100644 arch/mips/ath79/dev-leds-gpio.h

diff --git a/arch/mips/ath79/Kconfig b/arch/mips/ath79/Kconfig
index fabb2b0..5bc480e 100644
--- a/arch/mips/ath79/Kconfig
+++ b/arch/mips/ath79/Kconfig
@@ -5,6 +5,7 @@ menu "Atheros AR71XX/AR724X/AR913X machine selection"
 config ATH79_MACH_PB44
 	bool "Atheros PB44 reference board"
 	select SOC_AR71XX
+	select ATH79_DEV_LEDS_GPIO
 	help
 	  Say 'Y' here if you want your kernel to support the
 	  Atheros PB44 reference board.
@@ -20,4 +21,7 @@ config SOC_AR724X
 config SOC_AR913X
 	def_bool n
 
+config ATH79_DEV_LEDS_GPIO
+	def_bool n
+
 endif
diff --git a/arch/mips/ath79/Makefile b/arch/mips/ath79/Makefile
index a9ba120..d14b597 100644
--- a/arch/mips/ath79/Makefile
+++ b/arch/mips/ath79/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_EARLY_PRINTK)		+= early_printk.o
 # Devices
 #
 obj-y					+= dev-common.o
+obj-$(CONFIG_ATH79_DEV_LEDS_GPIO)	+= dev-leds-gpio.o
 
 #
 # Machines
diff --git a/arch/mips/ath79/dev-leds-gpio.c b/arch/mips/ath79/dev-leds-gpio.c
new file mode 100644
index 0000000..cdade68
--- /dev/null
+++ b/arch/mips/ath79/dev-leds-gpio.c
@@ -0,0 +1,56 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X common GPIO LEDs support
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+
+#include "dev-leds-gpio.h"
+
+void __init ath79_register_leds_gpio(int id,
+				     unsigned num_leds,
+				     struct gpio_led *leds)
+{
+	struct platform_device *pdev;
+	struct gpio_led_platform_data pdata;
+	struct gpio_led *p;
+	int err;
+
+	p = kmalloc(num_leds * sizeof(*p), GFP_KERNEL);
+	if (!p)
+		return;
+
+	memcpy(p, leds, num_leds * sizeof(*p));
+
+	pdev = platform_device_alloc("leds-gpio", id);
+	if (!pdev)
+		goto err_free_leds;
+
+	memset(&pdata, 0, sizeof(pdata));
+	pdata.num_leds = num_leds;
+	pdata.leds = p;
+
+	err = platform_device_add_data(pdev, &pdata, sizeof(pdata));
+	if (err)
+		goto err_put_pdev;
+
+	err = platform_device_add(pdev);
+	if (err)
+		goto err_put_pdev;
+
+	return;
+
+err_put_pdev:
+	platform_device_put(pdev);
+
+err_free_leds:
+	kfree(p);
+}
diff --git a/arch/mips/ath79/dev-leds-gpio.h b/arch/mips/ath79/dev-leds-gpio.h
new file mode 100644
index 0000000..0fb0ed1
--- /dev/null
+++ b/arch/mips/ath79/dev-leds-gpio.h
@@ -0,0 +1,21 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X common GPIO LEDs support
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#ifndef _ATH79_DEV_LEDS_GPIO_H
+#define _ATH79_DEV_LEDS_GPIO_H
+
+#include <linux/leds.h>
+
+void ath79_register_leds_gpio(int id,
+			      unsigned num_leds,
+			      struct gpio_led *leds) __init;
+
+#endif /* _ATH79_DEV_LEDS_GPIO_H */
diff --git a/arch/mips/ath79/mach-pb44.c b/arch/mips/ath79/mach-pb44.c
index ffc24d7..e176779 100644
--- a/arch/mips/ath79/mach-pb44.c
+++ b/arch/mips/ath79/mach-pb44.c
@@ -15,11 +15,14 @@
 #include <linux/i2c/pcf857x.h>
 
 #include "machtypes.h"
+#include "dev-leds-gpio.h"
 
 #define PB44_GPIO_I2C_SCL	0
 #define PB44_GPIO_I2C_SDA	1
 
 #define PB44_GPIO_EXP_BASE	16
+#define PB44_GPIO_LED_JUMP1	(PB44_GPIO_EXP_BASE + 9)
+#define PB44_GPIO_LED_JUMP2	(PB44_GPIO_EXP_BASE + 10)
 
 static struct i2c_gpio_platform_data pb44_i2c_gpio_data = {
 	.sda_pin        = PB44_GPIO_I2C_SDA,
@@ -45,11 +48,26 @@ static struct i2c_board_info pb44_i2c_board_info[] __initdata = {
 	},
 };
 
+static struct gpio_led pb44_leds_gpio[] __initdata = {
+	{
+		.name		= "pb44:amber:jump1",
+		.gpio		= PB44_GPIO_LED_JUMP1,
+		.active_low	= 1,
+	}, {
+		.name		= "pb44:green:jump2",
+		.gpio		= PB44_GPIO_LED_JUMP2,
+		.active_low	= 1,
+	},
+};
+
 static void __init pb44_init(void)
 {
 	i2c_register_board_info(0, pb44_i2c_board_info,
 				ARRAY_SIZE(pb44_i2c_board_info));
 	platform_device_register(&pb44_i2c_gpio_device);
+
+	ath79_register_leds_gpio(-1, ARRAY_SIZE(pb44_leds_gpio),
+				 pb44_leds_gpio);
 }
 
 MIPS_MACHINE(ATH79_MACH_PB44, "PB44", "Atheros PB44 reference board",
-- 
1.7.2.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v2 06/16] watchdog: add driver for the Atheros AR71XX/AR724X/AR913X SoCs
  2010-12-22 20:30 [PATCH v2 00/16] MIPS: initial support for the Atheros AR71XX/AR724X/AR913X SoCs Gabor Juhos
                   ` (4 preceding siblings ...)
  2010-12-22 20:30 ` [PATCH v2 05/16] MIPS: ath79: add common GPIO LEDs device Gabor Juhos
@ 2010-12-22 20:30 ` Gabor Juhos
  2010-12-22 20:30 ` [PATCH v2 07/16] MIPS: ath79: add common watchdog device Gabor Juhos
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 21+ messages in thread
From: Gabor Juhos @ 2010-12-22 20:30 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: linux-mips, Imre Kaloz, Luis R. Rodriguez, Cliff Holden,
	Kathy Giori, Gabor Juhos, Wim Van Sebroeck, linux-watchdog

This patch adds a driver for the built-in hardware watchdog device
of the Atheros AR71XX/AR724X/AR913X SoCs.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Signed-off-by: Imre Kaloz <kaloz@openwrt.org>
Cc: Wim Van Sebroeck <wim@iguana.be>
Cc: linux-watchdog@vger.kernel.org
---

Changes since RFC: ---

Changes since v1:
    - rebased against 2.6.37-rc7

 drivers/watchdog/Kconfig     |    8 +
 drivers/watchdog/Makefile    |    1 +
 drivers/watchdog/ath79_wdt.c |  293 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 302 insertions(+), 0 deletions(-)
 create mode 100644 drivers/watchdog/ath79_wdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index a5ad77e..7833e44 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -930,6 +930,14 @@ config BCM63XX_WDT
 	  To compile this driver as a loadable module, choose M here.
 	  The module will be called bcm63xx_wdt.
 
+config ATH79_WDT
+	tristate "Atheros AR71XX/AR724X/AR913X hardware watchdog"
+	depends on ATH79
+	help
+	  Hardware driver for the built-in watchdog timer on the Atheros
+	  AR71XX/AR724X/AR913X SoCs.
+
+
 # PARISC Architecture
 
 # POWERPC Architecture
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 4b0ef38..6d7af07 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -117,6 +117,7 @@ obj-$(CONFIG_PNX833X_WDT) += pnx833x_wdt.o
 obj-$(CONFIG_SIBYTE_WDOG) += sb_wdog.o
 obj-$(CONFIG_AR7_WDT) += ar7_wdt.o
 obj-$(CONFIG_TXX9_WDT) += txx9wdt.o
+obj-$(CONFIG_ATH79_WDT) += ath79_wdt.o
 obj-$(CONFIG_OCTEON_WDT) += octeon-wdt.o
 octeon-wdt-y := octeon-wdt-main.o octeon-wdt-nmi.o
 
diff --git a/drivers/watchdog/ath79_wdt.c b/drivers/watchdog/ath79_wdt.c
new file mode 100644
index 0000000..f8e027b
--- /dev/null
+++ b/drivers/watchdog/ath79_wdt.c
@@ -0,0 +1,293 @@
+/*
+ * Atheros AR71XX/AR724X/AR913X built-in hardware watchdog timer.
+ *
+ * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ * This driver was based on: drivers/watchdog/ixp4xx_wdt.c
+ *	Author: Deepak Saxena <dsaxena@plexity.net>
+ *	Copyright 2004 (c) MontaVista, Software, Inc.
+ *
+ * which again was based on sa1100 driver,
+ *	Copyright (C) 2000 Oleg Drokin <green@crimea.edu>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ */
+
+#include <linux/bitops.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+#include <linux/reboot.h>
+#include <linux/watchdog.h>
+
+#include <asm/mach-ath79/ath79.h>
+#include <asm/mach-ath79/ar71xx_regs.h>
+
+#define DRIVER_NAME	"ath79-wdt"
+#define DRIVER_DESC	"Atheros AR71XX/AR724X/AR913X hardware watchdog driver"
+
+#define WDT_TIMEOUT	15	/* seconds */
+
+#define WDOG_CTRL_LAST_RESET	BIT(31)
+#define WDOG_CTRL_ACTION_MASK	3
+#define WDOG_CTRL_ACTION_NONE	0	/* no action */
+#define WDOG_CTRL_ACTION_GPI	1	/* general purpose interrupt */
+#define WDOG_CTRL_ACTION_NMI	2	/* NMI */
+#define WDOG_CTRL_ACTION_FCR	3	/* full chip reset */
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
+			   "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+#endif
+
+static unsigned long wdt_flags;
+
+#define WDT_FLAGS_BUSY		0
+#define WDT_FLAGS_EXPECT_CLOSE	1
+
+static int wdt_timeout = WDT_TIMEOUT;
+static int boot_status;
+static int max_timeout;
+
+static inline void ath79_wdt_keepalive(void)
+{
+	ath79_reset_wr(AR71XX_RESET_REG_WDOG, ath79_ahb_freq * wdt_timeout);
+}
+
+static inline void ath79_wdt_enable(void)
+{
+	ath79_wdt_keepalive();
+	ath79_reset_wr(AR71XX_RESET_REG_WDOG_CTRL, WDOG_CTRL_ACTION_FCR);
+}
+
+static inline void ath79_wdt_disable(void)
+{
+	ath79_reset_wr(AR71XX_RESET_REG_WDOG_CTRL, WDOG_CTRL_ACTION_NONE);
+}
+
+static int ath79_wdt_set_timeout(int val)
+{
+	if (val < 1 || val > max_timeout)
+		return -EINVAL;
+
+	wdt_timeout = val;
+	ath79_wdt_keepalive();
+
+	return 0;
+}
+
+static int ath79_wdt_open(struct inode *inode, struct file *file)
+{
+	if (test_and_set_bit(WDT_FLAGS_BUSY, &wdt_flags))
+		return -EBUSY;
+
+	clear_bit(WDT_FLAGS_EXPECT_CLOSE, &wdt_flags);
+	ath79_wdt_enable();
+
+	return nonseekable_open(inode, file);
+}
+
+static int ath79_wdt_release(struct inode *inode, struct file *file)
+{
+	if (test_bit(WDT_FLAGS_EXPECT_CLOSE, &wdt_flags))
+		ath79_wdt_disable();
+	else
+		pr_crit(DRIVER_NAME ": device closed unexpectedly, "
+			"watchdog timer will not stop!\n");
+
+	clear_bit(WDT_FLAGS_BUSY, &wdt_flags);
+	clear_bit(WDT_FLAGS_EXPECT_CLOSE, &wdt_flags);
+
+	return 0;
+}
+
+static ssize_t ath79_wdt_write(struct file *file, const char *data,
+				size_t len, loff_t *ppos)
+{
+	if (len) {
+		if (!nowayout) {
+			size_t i;
+
+			clear_bit(WDT_FLAGS_EXPECT_CLOSE, &wdt_flags);
+
+			for (i = 0; i != len; i++) {
+				char c;
+
+				if (get_user(c, data + i))
+					return -EFAULT;
+
+				if (c == 'V')
+					set_bit(WDT_FLAGS_EXPECT_CLOSE,
+						&wdt_flags);
+			}
+		}
+
+		ath79_wdt_keepalive();
+	}
+
+	return len;
+}
+
+static const struct watchdog_info ath79_wdt_info = {
+	.options		= WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
+				  WDIOF_MAGICCLOSE | WDIOF_CARDRESET,
+	.firmware_version	= 0,
+	.identity		= "ATH79 watchdog",
+};
+
+static long ath79_wdt_ioctl(struct file *file, unsigned int cmd,
+			    unsigned long arg)
+{
+	void __user *argp = (void __user *)arg;
+	int __user *p = argp;
+	int err;
+	int t;
+
+	switch (cmd) {
+	case WDIOC_GETSUPPORT:
+		err = copy_to_user(argp, &ath79_wdt_info,
+				   sizeof(ath79_wdt_info)) ? -EFAULT : 0;
+		break;
+
+	case WDIOC_GETSTATUS:
+		err = put_user(0, p);
+		break;
+
+	case WDIOC_GETBOOTSTATUS:
+		err = put_user(boot_status, p);
+		break;
+
+	case WDIOC_KEEPALIVE:
+		ath79_wdt_keepalive();
+		err = 0;
+		break;
+
+	case WDIOC_SETTIMEOUT:
+		err = get_user(t, p);
+		if (err)
+			break;
+
+		err = ath79_wdt_set_timeout(t);
+		if (err)
+			break;
+
+		/* fallthrough */
+	case WDIOC_GETTIMEOUT:
+		err = put_user(wdt_timeout, p);
+		break;
+
+	default:
+		err = -ENOTTY;
+		break;
+	}
+
+	return err;
+}
+
+static const struct file_operations ath79_wdt_fops = {
+	.owner		= THIS_MODULE,
+	.llseek		= no_llseek,
+	.write		= ath79_wdt_write,
+	.unlocked_ioctl	= ath79_wdt_ioctl,
+	.open		= ath79_wdt_open,
+	.release	= ath79_wdt_release,
+};
+
+static int ath79_wdt_notify_sys(struct notifier_block *this,
+				unsigned long code, void *unused)
+{
+	if (code == SYS_DOWN || code == SYS_HALT)
+		ath79_wdt_disable();
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block ath79_wdt_notifier = {
+	.notifier_call = ath79_wdt_notify_sys,
+};
+
+static struct miscdevice ath79_wdt_miscdev = {
+	.minor = WATCHDOG_MINOR,
+	.name = "watchdog",
+	.fops = &ath79_wdt_fops,
+};
+
+static int __init ath79_wdt_probe(struct platform_device *pdev)
+{
+	u32 ctrl;
+	int err;
+
+	max_timeout = (0xfffffffful / ath79_ahb_freq);
+	wdt_timeout = (max_timeout < WDT_TIMEOUT) ? max_timeout : WDT_TIMEOUT;
+
+	ctrl = ath79_reset_rr(AR71XX_RESET_REG_WDOG_CTRL);
+	boot_status = (ctrl & WDOG_CTRL_LAST_RESET) ? WDIOF_CARDRESET : 0;
+
+	err = register_reboot_notifier(&ath79_wdt_notifier);
+	if (err) {
+		dev_err(&pdev->dev,
+			"unable to register reboot notifier, err=%d\n", err);
+		goto err;
+	}
+
+	err = misc_register(&ath79_wdt_miscdev);
+	if (err) {
+		dev_err(&pdev->dev,
+			"unable to register misc device, err=%d\n", err);
+		goto err_unregister;
+	}
+
+	return 0;
+
+err_unregister:
+	unregister_reboot_notifier(&ath79_wdt_notifier);
+
+err:
+	return err;
+}
+
+static int __exit ath79_wdt_remove(struct platform_device *pdev)
+{
+	misc_deregister(&ath79_wdt_miscdev);
+	return 0;
+}
+
+static struct platform_driver ath79_wdt_driver = {
+	.remove		= __exit_p(ath79_wdt_remove),
+	.driver		= {
+		.name	= DRIVER_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init ath79_wdt_init(void)
+{
+	return platform_driver_probe(&ath79_wdt_driver, ath79_wdt_probe);
+}
+module_init(ath79_wdt_init);
+
+static void __exit ath79_wdt_exit(void)
+{
+	platform_driver_unregister(&ath79_wdt_driver);
+}
+module_exit(ath79_wdt_exit);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org");
+MODULE_AUTHOR("Imre Kaloz <kaloz@openwrt.org");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRIVER_NAME);
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
-- 
1.7.2.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v2 07/16] MIPS: ath79: add common watchdog device
  2010-12-22 20:30 [PATCH v2 00/16] MIPS: initial support for the Atheros AR71XX/AR724X/AR913X SoCs Gabor Juhos
                   ` (5 preceding siblings ...)
  2010-12-22 20:30 ` [PATCH v2 06/16] watchdog: add driver for the Atheros AR71XX/AR724X/AR913X SoCs Gabor Juhos
@ 2010-12-22 20:30 ` Gabor Juhos
  2010-12-23 10:41   ` Sergei Shtylyov
  2010-12-22 20:30 ` [PATCH v2 08/16] MIPS: ath79: add common GPIO buttons device Gabor Juhos
                   ` (8 subsequent siblings)
  15 siblings, 1 reply; 21+ messages in thread
From: Gabor Juhos @ 2010-12-22 20:30 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: linux-mips, Imre Kaloz, Luis R. Rodriguez, Cliff Holden,
	Kathy Giori, Gabor Juhos

All supported SoCs have a built-in hardware watchdog driver. This patch
registers a platform_device for that to make it usable.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Signed-off-by: Imre Kaloz <kaloz@openwrt.org>
---

Changes since RFC:
    - remove the ATH79_DEV_WDT Kconfig option, and move the watchdog platform
      code into dev-common.[ch]

Changes since v1:
    - rebased against 2.6.37-rc7

 arch/mips/ath79/dev-common.c |   10 ++++++++++
 arch/mips/ath79/dev-common.h |    1 +
 arch/mips/ath79/setup.c      |    1 +
 3 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/arch/mips/ath79/dev-common.c b/arch/mips/ath79/dev-common.c
index 897522c..74b1e3b 100644
--- a/arch/mips/ath79/dev-common.c
+++ b/arch/mips/ath79/dev-common.c
@@ -57,3 +57,13 @@ void __init ath79_register_uart(void)
 	ath79_uart_data[0].uartclk = ath79_ahb_freq;
 	platform_device_register(&ath79_uart_device);
 }
+
+static struct platform_device ath79_wdt_device = {
+	.name		= "ath79-wdt",
+	.id		= -1,
+};
+
+void __init ath79_register_wdt(void)
+{
+	platform_device_register(&ath79_wdt_device);
+}
diff --git a/arch/mips/ath79/dev-common.h b/arch/mips/ath79/dev-common.h
index 1cec894..65bf400 100644
--- a/arch/mips/ath79/dev-common.h
+++ b/arch/mips/ath79/dev-common.h
@@ -13,5 +13,6 @@
 #define _ATH79_DEV_COMMON_H
 
 void ath79_register_uart(void) __init;
+void ath79_register_wdt(void) __init;
 
 #endif /* _ATH79_DEV_COMMON_H */
diff --git a/arch/mips/ath79/setup.c b/arch/mips/ath79/setup.c
index 5f2b6de..ef4207f 100644
--- a/arch/mips/ath79/setup.c
+++ b/arch/mips/ath79/setup.c
@@ -259,6 +259,7 @@ static int __init ath79_setup(void)
 {
 	ath79_gpio_init();
 	ath79_register_uart();
+	ath79_register_wdt();
 
 	mips_machine_setup();
 
-- 
1.7.2.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v2 08/16] MIPS: ath79: add common GPIO buttons device
  2010-12-22 20:30 [PATCH v2 00/16] MIPS: initial support for the Atheros AR71XX/AR724X/AR913X SoCs Gabor Juhos
                   ` (6 preceding siblings ...)
  2010-12-22 20:30 ` [PATCH v2 07/16] MIPS: ath79: add common watchdog device Gabor Juhos
@ 2010-12-22 20:30 ` Gabor Juhos
  2010-12-22 20:30   ` Gabor Juhos
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 21+ messages in thread
From: Gabor Juhos @ 2010-12-22 20:30 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: linux-mips, Imre Kaloz, Luis R. Rodriguez, Cliff Holden,
	Kathy Giori, Gabor Juhos

Almost all boards have one or more push buttons connected to GPIO lines.
This patch adds common code to register a platform_device for them.

The patch also adds support for the buttons on the PB44 board.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Signed-off-by: Imre Kaloz <kaloz@openwrt.org>
---

Changes since RFC: ---

Changes since v1:
    - converted to use the gpio_keys_polled driver
    - rebased against 2.6.37-rc7


 arch/mips/ath79/Kconfig            |    4 ++
 arch/mips/ath79/Makefile           |    1 +
 arch/mips/ath79/dev-gpio-buttons.c |   58 ++++++++++++++++++++++++++++++++++++
 arch/mips/ath79/dev-gpio-buttons.h |   23 ++++++++++++++
 arch/mips/ath79/mach-pb44.c        |   27 ++++++++++++++++
 5 files changed, 113 insertions(+), 0 deletions(-)
 create mode 100644 arch/mips/ath79/dev-gpio-buttons.c
 create mode 100644 arch/mips/ath79/dev-gpio-buttons.h

diff --git a/arch/mips/ath79/Kconfig b/arch/mips/ath79/Kconfig
index 5bc480e..185a8d6 100644
--- a/arch/mips/ath79/Kconfig
+++ b/arch/mips/ath79/Kconfig
@@ -5,6 +5,7 @@ menu "Atheros AR71XX/AR724X/AR913X machine selection"
 config ATH79_MACH_PB44
 	bool "Atheros PB44 reference board"
 	select SOC_AR71XX
+	select ATH79_DEV_GPIO_BUTTONS
 	select ATH79_DEV_LEDS_GPIO
 	help
 	  Say 'Y' here if you want your kernel to support the
@@ -21,6 +22,9 @@ config SOC_AR724X
 config SOC_AR913X
 	def_bool n
 
+config ATH79_DEV_GPIO_BUTTONS
+	def_bool n
+
 config ATH79_DEV_LEDS_GPIO
 	def_bool n
 
diff --git a/arch/mips/ath79/Makefile b/arch/mips/ath79/Makefile
index d14b597..0ceb45e 100644
--- a/arch/mips/ath79/Makefile
+++ b/arch/mips/ath79/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_EARLY_PRINTK)		+= early_printk.o
 # Devices
 #
 obj-y					+= dev-common.o
+obj-$(CONFIG_ATH79_DEV_GPIO_BUTTONS)	+= dev-gpio-buttons.o
 obj-$(CONFIG_ATH79_DEV_LEDS_GPIO)	+= dev-leds-gpio.o
 
 #
diff --git a/arch/mips/ath79/dev-gpio-buttons.c b/arch/mips/ath79/dev-gpio-buttons.c
new file mode 100644
index 0000000..4b0168a
--- /dev/null
+++ b/arch/mips/ath79/dev-gpio-buttons.c
@@ -0,0 +1,58 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X GPIO button support
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#include "linux/init.h"
+#include "linux/slab.h"
+#include <linux/platform_device.h>
+
+#include "dev-gpio-buttons.h"
+
+void __init ath79_register_gpio_keys_polled(int id,
+					    unsigned poll_interval,
+					    unsigned nbuttons,
+					    struct gpio_keys_button *buttons)
+{
+	struct platform_device *pdev;
+	struct gpio_keys_platform_data pdata;
+	struct gpio_keys_button *p;
+	int err;
+
+	p = kmalloc(nbuttons * sizeof(*p), GFP_KERNEL);
+	if (!p)
+		return;
+
+	memcpy(p, buttons, nbuttons * sizeof(*p));
+
+	pdev = platform_device_alloc("gpio-keys-polled", id);
+	if (!pdev)
+		goto err_free_buttons;
+
+	memset(&pdata, 0, sizeof(pdata));
+	pdata.poll_interval = poll_interval;
+	pdata.nbuttons = nbuttons;
+	pdata.buttons = p;
+
+	err = platform_device_add_data(pdev, &pdata, sizeof(pdata));
+	if (err)
+		goto err_put_pdev;
+
+	err = platform_device_add(pdev);
+	if (err)
+		goto err_put_pdev;
+
+	return;
+
+err_put_pdev:
+	platform_device_put(pdev);
+
+err_free_buttons:
+	kfree(p);
+}
diff --git a/arch/mips/ath79/dev-gpio-buttons.h b/arch/mips/ath79/dev-gpio-buttons.h
new file mode 100644
index 0000000..51783af
--- /dev/null
+++ b/arch/mips/ath79/dev-gpio-buttons.h
@@ -0,0 +1,23 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X GPIO button support
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#ifndef _ATH79_DEV_GPIO_BUTTONS_H
+#define _ATH79_DEV_GPIO_BUTTONS_H
+
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
+
+void ath79_register_gpio_keys_polled(int id,
+				     unsigned poll_interval,
+				     unsigned nbuttons,
+				     struct gpio_keys_button *buttons) __init;
+
+#endif /* _ATH79_DEV_GPIO_BUTTONS_H */
diff --git a/arch/mips/ath79/mach-pb44.c b/arch/mips/ath79/mach-pb44.c
index e176779..3dc5080 100644
--- a/arch/mips/ath79/mach-pb44.c
+++ b/arch/mips/ath79/mach-pb44.c
@@ -15,15 +15,21 @@
 #include <linux/i2c/pcf857x.h>
 
 #include "machtypes.h"
+#include "dev-gpio-buttons.h"
 #include "dev-leds-gpio.h"
 
 #define PB44_GPIO_I2C_SCL	0
 #define PB44_GPIO_I2C_SDA	1
 
 #define PB44_GPIO_EXP_BASE	16
+#define PB44_GPIO_SW_RESET	(PB44_GPIO_EXP_BASE + 6)
+#define PB44_GPIO_SW_JUMP	(PB44_GPIO_EXP_BASE + 8)
 #define PB44_GPIO_LED_JUMP1	(PB44_GPIO_EXP_BASE + 9)
 #define PB44_GPIO_LED_JUMP2	(PB44_GPIO_EXP_BASE + 10)
 
+#define PB44_KEYS_POLL_INTERVAL		20	/* msecs */
+#define PB44_KEYS_DEBOUNCE_INTERVAL	(3 * PB44_KEYS_POLL_INTERVAL)
+
 static struct i2c_gpio_platform_data pb44_i2c_gpio_data = {
 	.sda_pin        = PB44_GPIO_I2C_SDA,
 	.scl_pin        = PB44_GPIO_I2C_SCL,
@@ -60,6 +66,24 @@ static struct gpio_led pb44_leds_gpio[] __initdata = {
 	},
 };
 
+static struct gpio_keys_button pb44_gpio_keys[] __initdata = {
+	{
+		.desc		= "soft_reset",
+		.type		= EV_KEY,
+		.code		= KEY_RESTART,
+		.debounce_interval = PB44_KEYS_DEBOUNCE_INTERVAL,
+		.gpio		= PB44_GPIO_SW_RESET,
+		.active_low	= 1,
+	} , {
+		.desc		= "jumpstart",
+		.type		= EV_KEY,
+		.code		= KEY_WPS_BUTTON,
+		.debounce_interval = PB44_KEYS_DEBOUNCE_INTERVAL,
+		.gpio		= PB44_GPIO_SW_JUMP,
+		.active_low	= 1,
+	}
+};
+
 static void __init pb44_init(void)
 {
 	i2c_register_board_info(0, pb44_i2c_board_info,
@@ -68,6 +92,9 @@ static void __init pb44_init(void)
 
 	ath79_register_leds_gpio(-1, ARRAY_SIZE(pb44_leds_gpio),
 				 pb44_leds_gpio);
+	ath79_register_gpio_keys_polled(-1, PB44_KEYS_POLL_INTERVAL,
+					ARRAY_SIZE(pb44_gpio_keys),
+					pb44_gpio_keys);
 }
 
 MIPS_MACHINE(ATH79_MACH_PB44, "PB44", "Atheros PB44 reference board",
-- 
1.7.2.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v2 09/16] spi: add SPI controller driver for the Atheros AR71XX/AR724X/AR913X SoCs
@ 2010-12-22 20:30   ` Gabor Juhos
  0 siblings, 0 replies; 21+ messages in thread
From: Gabor Juhos @ 2010-12-22 20:30 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: linux-mips, Imre Kaloz, Luis R. Rodriguez, Cliff Holden,
	Kathy Giori, Gabor Juhos, David Brownell, spi-devel-general

The Atheros AR71XX/AR724X/AR913X SoCs have a built-in SPI controller. This
patch implements a driver for that.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Cc: David Brownell <dbrownell@users.sourceforge.net>
Cc: spi-devel-general@lists.sourceforge.net
---

Changes since RFC:
    - remove DRV_DESC definition and use its previous value directly in the
      MODULE_DESCRIPTION() macro,
    - use io{read,write}32 accesors instead of __raw_{read,write}l,
    - use __dev{init,exit,exit_p} annotations where in the appropriate places,
    - initialize 'master->bus_num' field to -1 if no platform data specified,
      so that a bus number can be dynamically assigned,
    - rename ath79_spi_drv to ath79_spi_driver to avoid section mismatch 
      warnings

Changes since v1:
    - rebased against 2.6.37-rc7

 .../include/asm/mach-ath79/ath79_spi_platform.h    |   19 ++
 drivers/spi/Kconfig                                |    8 +
 drivers/spi/Makefile                               |    1 +
 drivers/spi/ath79_spi.c                            |  290 ++++++++++++++++++++
 4 files changed, 318 insertions(+), 0 deletions(-)
 create mode 100644 arch/mips/include/asm/mach-ath79/ath79_spi_platform.h
 create mode 100644 drivers/spi/ath79_spi.c

diff --git a/arch/mips/include/asm/mach-ath79/ath79_spi_platform.h b/arch/mips/include/asm/mach-ath79/ath79_spi_platform.h
new file mode 100644
index 0000000..aa71216
--- /dev/null
+++ b/arch/mips/include/asm/mach-ath79/ath79_spi_platform.h
@@ -0,0 +1,19 @@
+/*
+ *  Platform data definition for Atheros AR71XX/AR724X/AR913X SPI controller
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#ifndef _ATH79_SPI_PLATFORM_H
+#define _ATH79_SPI_PLATFORM_H
+
+struct ath79_spi_platform_data {
+	unsigned	bus_num;
+	unsigned	num_chipselect;
+};
+
+#endif /* _ATH79_SPI_PLATFORM_H */
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 78f9fd0..f2093e1 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -53,6 +53,14 @@ if SPI_MASTER
 
 comment "SPI Master Controller Drivers"
 
+config SPI_ATH79
+	tristate "Atheros AR71XX/AR724X/AR913X SPI controller driver"
+	depends on ATH79 && GENERIC_GPIO
+	select SPI_BITBANG
+	help
+	  This enables support for the SPI controller present on the
+	  Atheros AR71XX/AR724X/AR913X SoCs.
+
 config SPI_ATMEL
 	tristate "Atmel SPI Controller"
 	depends on (ARCH_AT91 || AVR32)
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 8bc1a5a..875bc3d 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_SPI_MASTER)		+= spi.o
 
 # SPI master controller drivers (bus)
 obj-$(CONFIG_SPI_ATMEL)			+= atmel_spi.o
+obj-$(CONFIG_SPI_ATH79)			+= ath79_spi.o
 obj-$(CONFIG_SPI_BFIN)			+= spi_bfin5xx.o
 obj-$(CONFIG_SPI_BITBANG)		+= spi_bitbang.o
 obj-$(CONFIG_SPI_AU1550)		+= au1550_spi.o
diff --git a/drivers/spi/ath79_spi.c b/drivers/spi/ath79_spi.c
new file mode 100644
index 0000000..96f169a
--- /dev/null
+++ b/drivers/spi/ath79_spi.c
@@ -0,0 +1,290 @@
+/*
+ * SPI controller driver for the Atheros AR71XX/AR724X/AR913X SoCs
+ *
+ * Copyright (C) 2009-2010 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * This driver has been based on the spi-gpio.c:
+ *	Copyright (C) 2006,2008 David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+#include <linux/bitops.h>
+#include <linux/gpio.h>
+
+#include <asm/mach-ath79/ar71xx_regs.h>
+#include <asm/mach-ath79/ath79_spi_platform.h>
+
+#define DRV_NAME	"ath79-spi"
+
+struct ath79_spi {
+	struct	spi_bitbang	bitbang;
+	u32			ioc_base;
+	u32			reg_ctrl;
+
+	void __iomem		*base;
+
+	struct platform_device	*pdev;
+};
+
+static inline u32 ath79_spi_rr(struct ath79_spi *sp, unsigned reg)
+{
+	return ioread32(sp->base + reg);
+}
+
+static inline void ath79_spi_wr(struct ath79_spi *sp, unsigned reg, u32 val)
+{
+	iowrite32(val, sp->base + reg);
+}
+
+static inline struct ath79_spi *spidev_to_sp(struct spi_device *spi)
+{
+	return spi_master_get_devdata(spi->master);
+}
+
+static void ath79_spi_chipselect(struct spi_device *spi, int is_active)
+{
+	struct ath79_spi *sp = spidev_to_sp(spi);
+	int cs_high = (spi->mode & SPI_CS_HIGH) ? is_active : !is_active;
+
+	if (is_active) {
+		/* set initial clock polarity */
+		if (spi->mode & SPI_CPOL)
+			sp->ioc_base |= AR71XX_SPI_IOC_CLK;
+		else
+			sp->ioc_base &= ~AR71XX_SPI_IOC_CLK;
+
+		ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
+	}
+
+	if (spi->chip_select) {
+		unsigned long gpio = (unsigned long) spi->controller_data;
+
+		/* SPI is normally active-low */
+		gpio_set_value(gpio, cs_high);
+	} else {
+		if (cs_high)
+			sp->ioc_base |= AR71XX_SPI_IOC_CS0;
+		else
+			sp->ioc_base &= ~AR71XX_SPI_IOC_CS0;
+
+		ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
+	}
+
+}
+
+static int ath79_spi_setup_cs(struct spi_device *spi)
+{
+	struct ath79_spi *sp = spidev_to_sp(spi);
+
+	/* enable GPIO mode */
+	ath79_spi_wr(sp, AR71XX_SPI_REG_FS, AR71XX_SPI_FS_GPIO);
+
+	/* save CTRL register */
+	sp->reg_ctrl = ath79_spi_rr(sp, AR71XX_SPI_REG_CTRL);
+	sp->ioc_base = ath79_spi_rr(sp, AR71XX_SPI_REG_IOC);
+
+	/* TODO: setup speed? */
+	ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, 0x43);
+
+	if (spi->chip_select) {
+		unsigned long gpio = (unsigned long) spi->controller_data;
+		int status = 0;
+
+		status = gpio_request(gpio, dev_name(&spi->dev));
+		if (status)
+			return status;
+
+		status = gpio_direction_output(gpio, spi->mode & SPI_CS_HIGH);
+		if (status) {
+			gpio_free(gpio);
+			return status;
+		}
+	} else {
+		if (spi->mode & SPI_CS_HIGH)
+			sp->ioc_base |= AR71XX_SPI_IOC_CS0;
+		else
+			sp->ioc_base &= ~AR71XX_SPI_IOC_CS0;
+		ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
+	}
+
+	return 0;
+}
+
+static void ath79_spi_cleanup_cs(struct spi_device *spi)
+{
+	struct ath79_spi *sp = spidev_to_sp(spi);
+
+	if (spi->chip_select) {
+		unsigned long gpio = (unsigned long) spi->controller_data;
+		gpio_free(gpio);
+	}
+
+	/* restore CTRL register */
+	ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, sp->reg_ctrl);
+	/* disable GPIO mode */
+	ath79_spi_wr(sp, AR71XX_SPI_REG_FS, 0);
+}
+
+static int ath79_spi_setup(struct spi_device *spi)
+{
+	int status = 0;
+
+	if (spi->bits_per_word > 32)
+		return -EINVAL;
+
+	if (!spi->controller_state) {
+		status = ath79_spi_setup_cs(spi);
+		if (status)
+			return status;
+	}
+
+	status = spi_bitbang_setup(spi);
+	if (status && !spi->controller_state)
+		ath79_spi_cleanup_cs(spi);
+
+	return status;
+}
+
+static void ath79_spi_cleanup(struct spi_device *spi)
+{
+	ath79_spi_cleanup_cs(spi);
+	spi_bitbang_cleanup(spi);
+}
+
+static u32 ath79_spi_txrx_mode0(struct spi_device *spi, unsigned nsecs,
+			       u32 word, u8 bits)
+{
+	struct ath79_spi *sp = spidev_to_sp(spi);
+	u32 ioc = sp->ioc_base;
+
+	/* clock starts at inactive polarity */
+	for (word <<= (32 - bits); likely(bits); bits--) {
+		u32 out;
+
+		if (word & (1 << 31))
+			out = ioc | AR71XX_SPI_IOC_DO;
+		else
+			out = ioc & ~AR71XX_SPI_IOC_DO;
+
+		/* setup MSB (to slave) on trailing edge */
+		ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out);
+		ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out | AR71XX_SPI_IOC_CLK);
+
+		word <<= 1;
+	}
+
+	return ath79_spi_rr(sp, AR71XX_SPI_REG_RDS);
+}
+
+static __devinit int ath79_spi_probe(struct platform_device *pdev)
+{
+	struct spi_master *master;
+	struct ath79_spi *sp;
+	struct ath79_spi_platform_data *pdata;
+	struct resource	*r;
+	int ret;
+
+	master = spi_alloc_master(&pdev->dev, sizeof(*sp));
+	if (master == NULL) {
+		dev_err(&pdev->dev, "failed to allocate spi master\n");
+		return -ENOMEM;
+	}
+
+	sp = spi_master_get_devdata(master);
+	platform_set_drvdata(pdev, sp);
+
+	pdata = pdev->dev.platform_data;
+
+	master->setup = ath79_spi_setup;
+	master->cleanup = ath79_spi_cleanup;
+	if (pdata) {
+		master->bus_num = pdata->bus_num;
+		master->num_chipselect = pdata->num_chipselect;
+	} else {
+		master->bus_num = -1;
+		master->num_chipselect = 1;
+	}
+
+	sp->bitbang.master = spi_master_get(master);
+	sp->bitbang.chipselect = ath79_spi_chipselect;
+	sp->bitbang.txrx_word[SPI_MODE_0] = ath79_spi_txrx_mode0;
+	sp->bitbang.setup_transfer = spi_bitbang_setup_transfer;
+	sp->bitbang.flags = SPI_CS_HIGH;
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (r == NULL) {
+		ret = -ENOENT;
+		goto err_put_master;
+	}
+
+	sp->base = ioremap(r->start, r->end - r->start + 1);
+	if (!sp->base) {
+		ret = -ENXIO;
+		goto err_put_master;
+	}
+
+	ret = spi_bitbang_start(&sp->bitbang);
+	if (ret)
+		goto err_unmap;
+
+	return 0;
+
+err_unmap:
+	iounmap(sp->base);
+err_put_master:
+	platform_set_drvdata(pdev, NULL);
+	spi_master_put(sp->bitbang.master);
+
+	return ret;
+}
+
+static __devexit int ath79_spi_remove(struct platform_device *pdev)
+{
+	struct ath79_spi *sp = platform_get_drvdata(pdev);
+
+	spi_bitbang_stop(&sp->bitbang);
+	iounmap(sp->base);
+	platform_set_drvdata(pdev, NULL);
+	spi_master_put(sp->bitbang.master);
+
+	return 0;
+}
+
+static struct platform_driver ath79_spi_driver = {
+	.probe		= ath79_spi_probe,
+	.remove		= __devexit_p(ath79_spi_remove),
+	.driver		= {
+		.name	= DRV_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+static __init int ath79_spi_init(void)
+{
+	return platform_driver_register(&ath79_spi_driver);
+}
+module_init(ath79_spi_init);
+
+static __exit void ath79_spi_exit(void)
+{
+	platform_driver_unregister(&ath79_spi_driver);
+}
+module_exit(ath79_spi_exit);
+
+MODULE_DESCRIPTION("SPI controller driver for Atheros AR71XX/AR724X/AR91X");
+MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
-- 
1.7.2.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v2 09/16] spi: add SPI controller driver for the Atheros AR71XX/AR724X/AR913X SoCs
@ 2010-12-22 20:30   ` Gabor Juhos
  0 siblings, 0 replies; 21+ messages in thread
From: Gabor Juhos @ 2010-12-22 20:30 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: linux-mips-6z/3iImG2C8G8FEW9MqTrA, David Brownell,
	Luis R. Rodriguez, Cliff Holden, Gabor Juhos, Kathy Giori,
	spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, Imre Kaloz

The Atheros AR71XX/AR724X/AR913X SoCs have a built-in SPI controller. This
patch implements a driver for that.

Signed-off-by: Gabor Juhos <juhosg-p3rKhJxN3npAfugRpC6u6w@public.gmane.org>
Cc: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
---

Changes since RFC:
    - remove DRV_DESC definition and use its previous value directly in the
      MODULE_DESCRIPTION() macro,
    - use io{read,write}32 accesors instead of __raw_{read,write}l,
    - use __dev{init,exit,exit_p} annotations where in the appropriate places,
    - initialize 'master->bus_num' field to -1 if no platform data specified,
      so that a bus number can be dynamically assigned,
    - rename ath79_spi_drv to ath79_spi_driver to avoid section mismatch 
      warnings

Changes since v1:
    - rebased against 2.6.37-rc7

 .../include/asm/mach-ath79/ath79_spi_platform.h    |   19 ++
 drivers/spi/Kconfig                                |    8 +
 drivers/spi/Makefile                               |    1 +
 drivers/spi/ath79_spi.c                            |  290 ++++++++++++++++++++
 4 files changed, 318 insertions(+), 0 deletions(-)
 create mode 100644 arch/mips/include/asm/mach-ath79/ath79_spi_platform.h
 create mode 100644 drivers/spi/ath79_spi.c

diff --git a/arch/mips/include/asm/mach-ath79/ath79_spi_platform.h b/arch/mips/include/asm/mach-ath79/ath79_spi_platform.h
new file mode 100644
index 0000000..aa71216
--- /dev/null
+++ b/arch/mips/include/asm/mach-ath79/ath79_spi_platform.h
@@ -0,0 +1,19 @@
+/*
+ *  Platform data definition for Atheros AR71XX/AR724X/AR913X SPI controller
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg-p3rKhJxN3npAfugRpC6u6w@public.gmane.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#ifndef _ATH79_SPI_PLATFORM_H
+#define _ATH79_SPI_PLATFORM_H
+
+struct ath79_spi_platform_data {
+	unsigned	bus_num;
+	unsigned	num_chipselect;
+};
+
+#endif /* _ATH79_SPI_PLATFORM_H */
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 78f9fd0..f2093e1 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -53,6 +53,14 @@ if SPI_MASTER
 
 comment "SPI Master Controller Drivers"
 
+config SPI_ATH79
+	tristate "Atheros AR71XX/AR724X/AR913X SPI controller driver"
+	depends on ATH79 && GENERIC_GPIO
+	select SPI_BITBANG
+	help
+	  This enables support for the SPI controller present on the
+	  Atheros AR71XX/AR724X/AR913X SoCs.
+
 config SPI_ATMEL
 	tristate "Atmel SPI Controller"
 	depends on (ARCH_AT91 || AVR32)
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 8bc1a5a..875bc3d 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_SPI_MASTER)		+= spi.o
 
 # SPI master controller drivers (bus)
 obj-$(CONFIG_SPI_ATMEL)			+= atmel_spi.o
+obj-$(CONFIG_SPI_ATH79)			+= ath79_spi.o
 obj-$(CONFIG_SPI_BFIN)			+= spi_bfin5xx.o
 obj-$(CONFIG_SPI_BITBANG)		+= spi_bitbang.o
 obj-$(CONFIG_SPI_AU1550)		+= au1550_spi.o
diff --git a/drivers/spi/ath79_spi.c b/drivers/spi/ath79_spi.c
new file mode 100644
index 0000000..96f169a
--- /dev/null
+++ b/drivers/spi/ath79_spi.c
@@ -0,0 +1,290 @@
+/*
+ * SPI controller driver for the Atheros AR71XX/AR724X/AR913X SoCs
+ *
+ * Copyright (C) 2009-2010 Gabor Juhos <juhosg-p3rKhJxN3npAfugRpC6u6w@public.gmane.org>
+ *
+ * This driver has been based on the spi-gpio.c:
+ *	Copyright (C) 2006,2008 David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+#include <linux/bitops.h>
+#include <linux/gpio.h>
+
+#include <asm/mach-ath79/ar71xx_regs.h>
+#include <asm/mach-ath79/ath79_spi_platform.h>
+
+#define DRV_NAME	"ath79-spi"
+
+struct ath79_spi {
+	struct	spi_bitbang	bitbang;
+	u32			ioc_base;
+	u32			reg_ctrl;
+
+	void __iomem		*base;
+
+	struct platform_device	*pdev;
+};
+
+static inline u32 ath79_spi_rr(struct ath79_spi *sp, unsigned reg)
+{
+	return ioread32(sp->base + reg);
+}
+
+static inline void ath79_spi_wr(struct ath79_spi *sp, unsigned reg, u32 val)
+{
+	iowrite32(val, sp->base + reg);
+}
+
+static inline struct ath79_spi *spidev_to_sp(struct spi_device *spi)
+{
+	return spi_master_get_devdata(spi->master);
+}
+
+static void ath79_spi_chipselect(struct spi_device *spi, int is_active)
+{
+	struct ath79_spi *sp = spidev_to_sp(spi);
+	int cs_high = (spi->mode & SPI_CS_HIGH) ? is_active : !is_active;
+
+	if (is_active) {
+		/* set initial clock polarity */
+		if (spi->mode & SPI_CPOL)
+			sp->ioc_base |= AR71XX_SPI_IOC_CLK;
+		else
+			sp->ioc_base &= ~AR71XX_SPI_IOC_CLK;
+
+		ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
+	}
+
+	if (spi->chip_select) {
+		unsigned long gpio = (unsigned long) spi->controller_data;
+
+		/* SPI is normally active-low */
+		gpio_set_value(gpio, cs_high);
+	} else {
+		if (cs_high)
+			sp->ioc_base |= AR71XX_SPI_IOC_CS0;
+		else
+			sp->ioc_base &= ~AR71XX_SPI_IOC_CS0;
+
+		ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
+	}
+
+}
+
+static int ath79_spi_setup_cs(struct spi_device *spi)
+{
+	struct ath79_spi *sp = spidev_to_sp(spi);
+
+	/* enable GPIO mode */
+	ath79_spi_wr(sp, AR71XX_SPI_REG_FS, AR71XX_SPI_FS_GPIO);
+
+	/* save CTRL register */
+	sp->reg_ctrl = ath79_spi_rr(sp, AR71XX_SPI_REG_CTRL);
+	sp->ioc_base = ath79_spi_rr(sp, AR71XX_SPI_REG_IOC);
+
+	/* TODO: setup speed? */
+	ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, 0x43);
+
+	if (spi->chip_select) {
+		unsigned long gpio = (unsigned long) spi->controller_data;
+		int status = 0;
+
+		status = gpio_request(gpio, dev_name(&spi->dev));
+		if (status)
+			return status;
+
+		status = gpio_direction_output(gpio, spi->mode & SPI_CS_HIGH);
+		if (status) {
+			gpio_free(gpio);
+			return status;
+		}
+	} else {
+		if (spi->mode & SPI_CS_HIGH)
+			sp->ioc_base |= AR71XX_SPI_IOC_CS0;
+		else
+			sp->ioc_base &= ~AR71XX_SPI_IOC_CS0;
+		ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
+	}
+
+	return 0;
+}
+
+static void ath79_spi_cleanup_cs(struct spi_device *spi)
+{
+	struct ath79_spi *sp = spidev_to_sp(spi);
+
+	if (spi->chip_select) {
+		unsigned long gpio = (unsigned long) spi->controller_data;
+		gpio_free(gpio);
+	}
+
+	/* restore CTRL register */
+	ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, sp->reg_ctrl);
+	/* disable GPIO mode */
+	ath79_spi_wr(sp, AR71XX_SPI_REG_FS, 0);
+}
+
+static int ath79_spi_setup(struct spi_device *spi)
+{
+	int status = 0;
+
+	if (spi->bits_per_word > 32)
+		return -EINVAL;
+
+	if (!spi->controller_state) {
+		status = ath79_spi_setup_cs(spi);
+		if (status)
+			return status;
+	}
+
+	status = spi_bitbang_setup(spi);
+	if (status && !spi->controller_state)
+		ath79_spi_cleanup_cs(spi);
+
+	return status;
+}
+
+static void ath79_spi_cleanup(struct spi_device *spi)
+{
+	ath79_spi_cleanup_cs(spi);
+	spi_bitbang_cleanup(spi);
+}
+
+static u32 ath79_spi_txrx_mode0(struct spi_device *spi, unsigned nsecs,
+			       u32 word, u8 bits)
+{
+	struct ath79_spi *sp = spidev_to_sp(spi);
+	u32 ioc = sp->ioc_base;
+
+	/* clock starts at inactive polarity */
+	for (word <<= (32 - bits); likely(bits); bits--) {
+		u32 out;
+
+		if (word & (1 << 31))
+			out = ioc | AR71XX_SPI_IOC_DO;
+		else
+			out = ioc & ~AR71XX_SPI_IOC_DO;
+
+		/* setup MSB (to slave) on trailing edge */
+		ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out);
+		ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out | AR71XX_SPI_IOC_CLK);
+
+		word <<= 1;
+	}
+
+	return ath79_spi_rr(sp, AR71XX_SPI_REG_RDS);
+}
+
+static __devinit int ath79_spi_probe(struct platform_device *pdev)
+{
+	struct spi_master *master;
+	struct ath79_spi *sp;
+	struct ath79_spi_platform_data *pdata;
+	struct resource	*r;
+	int ret;
+
+	master = spi_alloc_master(&pdev->dev, sizeof(*sp));
+	if (master == NULL) {
+		dev_err(&pdev->dev, "failed to allocate spi master\n");
+		return -ENOMEM;
+	}
+
+	sp = spi_master_get_devdata(master);
+	platform_set_drvdata(pdev, sp);
+
+	pdata = pdev->dev.platform_data;
+
+	master->setup = ath79_spi_setup;
+	master->cleanup = ath79_spi_cleanup;
+	if (pdata) {
+		master->bus_num = pdata->bus_num;
+		master->num_chipselect = pdata->num_chipselect;
+	} else {
+		master->bus_num = -1;
+		master->num_chipselect = 1;
+	}
+
+	sp->bitbang.master = spi_master_get(master);
+	sp->bitbang.chipselect = ath79_spi_chipselect;
+	sp->bitbang.txrx_word[SPI_MODE_0] = ath79_spi_txrx_mode0;
+	sp->bitbang.setup_transfer = spi_bitbang_setup_transfer;
+	sp->bitbang.flags = SPI_CS_HIGH;
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (r == NULL) {
+		ret = -ENOENT;
+		goto err_put_master;
+	}
+
+	sp->base = ioremap(r->start, r->end - r->start + 1);
+	if (!sp->base) {
+		ret = -ENXIO;
+		goto err_put_master;
+	}
+
+	ret = spi_bitbang_start(&sp->bitbang);
+	if (ret)
+		goto err_unmap;
+
+	return 0;
+
+err_unmap:
+	iounmap(sp->base);
+err_put_master:
+	platform_set_drvdata(pdev, NULL);
+	spi_master_put(sp->bitbang.master);
+
+	return ret;
+}
+
+static __devexit int ath79_spi_remove(struct platform_device *pdev)
+{
+	struct ath79_spi *sp = platform_get_drvdata(pdev);
+
+	spi_bitbang_stop(&sp->bitbang);
+	iounmap(sp->base);
+	platform_set_drvdata(pdev, NULL);
+	spi_master_put(sp->bitbang.master);
+
+	return 0;
+}
+
+static struct platform_driver ath79_spi_driver = {
+	.probe		= ath79_spi_probe,
+	.remove		= __devexit_p(ath79_spi_remove),
+	.driver		= {
+		.name	= DRV_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+static __init int ath79_spi_init(void)
+{
+	return platform_driver_register(&ath79_spi_driver);
+}
+module_init(ath79_spi_init);
+
+static __exit void ath79_spi_exit(void)
+{
+	platform_driver_unregister(&ath79_spi_driver);
+}
+module_exit(ath79_spi_exit);
+
+MODULE_DESCRIPTION("SPI controller driver for Atheros AR71XX/AR724X/AR91X");
+MODULE_AUTHOR("Gabor Juhos <juhosg-p3rKhJxN3npAfugRpC6u6w@public.gmane.org>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
-- 
1.7.2.1


------------------------------------------------------------------------------
Learn how Oracle Real Application Clusters (RAC) One Node allows customers
to consolidate database storage, standardize their database environment, and, 
should the need arise, upgrade to a full multi-node Oracle RAC database 
without downtime or disruption
http://p.sf.net/sfu/oracle-sfdevnl

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v2 10/16] MIPS: ath79: add common SPI controller device
  2010-12-22 20:30 [PATCH v2 00/16] MIPS: initial support for the Atheros AR71XX/AR724X/AR913X SoCs Gabor Juhos
                   ` (8 preceding siblings ...)
  2010-12-22 20:30   ` Gabor Juhos
@ 2010-12-22 20:30 ` Gabor Juhos
  2010-12-22 20:30 ` [PATCH v2 11/16] USB: ehci: add workaround for Synopsys HC bug Gabor Juhos
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 21+ messages in thread
From: Gabor Juhos @ 2010-12-22 20:30 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: linux-mips, Imre Kaloz, Luis R. Rodriguez, Cliff Holden,
	Kathy Giori, Gabor Juhos

Several boards are using the built-in SPI controller of the
AR71XX/AR724X/AR913X SoCs. This patch adds common platform_device
and helper code to register it. Additionally, the patch registers
the SPI bus on the PB44 board.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---

Changes since RFC: ---

Changes since v1:
    - rebased against 2.6.37-rc7

 arch/mips/ath79/Kconfig                        |    4 ++
 arch/mips/ath79/Makefile                       |    1 +
 arch/mips/ath79/dev-spi.c                      |   38 ++++++++++++++++++++++++
 arch/mips/ath79/dev-spi.h                      |   22 ++++++++++++++
 arch/mips/ath79/mach-pb44.c                    |   17 ++++++++++
 arch/mips/include/asm/mach-ath79/ar71xx_regs.h |    2 +
 6 files changed, 84 insertions(+), 0 deletions(-)
 create mode 100644 arch/mips/ath79/dev-spi.c
 create mode 100644 arch/mips/ath79/dev-spi.h

diff --git a/arch/mips/ath79/Kconfig b/arch/mips/ath79/Kconfig
index 185a8d6..cd6c738 100644
--- a/arch/mips/ath79/Kconfig
+++ b/arch/mips/ath79/Kconfig
@@ -7,6 +7,7 @@ config ATH79_MACH_PB44
 	select SOC_AR71XX
 	select ATH79_DEV_GPIO_BUTTONS
 	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_SPI
 	help
 	  Say 'Y' here if you want your kernel to support the
 	  Atheros PB44 reference board.
@@ -28,4 +29,7 @@ config ATH79_DEV_GPIO_BUTTONS
 config ATH79_DEV_LEDS_GPIO
 	def_bool n
 
+config ATH79_DEV_SPI
+	def_bool n
+
 endif
diff --git a/arch/mips/ath79/Makefile b/arch/mips/ath79/Makefile
index 0ceb45e..a8de078 100644
--- a/arch/mips/ath79/Makefile
+++ b/arch/mips/ath79/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_EARLY_PRINTK)		+= early_printk.o
 obj-y					+= dev-common.o
 obj-$(CONFIG_ATH79_DEV_GPIO_BUTTONS)	+= dev-gpio-buttons.o
 obj-$(CONFIG_ATH79_DEV_LEDS_GPIO)	+= dev-leds-gpio.o
+obj-$(CONFIG_ATH79_DEV_SPI)		+= dev-spi.o
 
 #
 # Machines
diff --git a/arch/mips/ath79/dev-spi.c b/arch/mips/ath79/dev-spi.c
new file mode 100644
index 0000000..aa30163
--- /dev/null
+++ b/arch/mips/ath79/dev-spi.c
@@ -0,0 +1,38 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X SPI controller device
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#include <linux/platform_device.h>
+#include <asm/mach-ath79/ar71xx_regs.h>
+#include "dev-spi.h"
+
+static struct resource ath79_spi_resources[] = {
+	{
+		.start	= AR71XX_SPI_BASE,
+		.end	= AR71XX_SPI_BASE + AR71XX_SPI_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device ath79_spi_device = {
+	.name		= "ath79-spi",
+	.id		= -1,
+	.resource	= ath79_spi_resources,
+	.num_resources	= ARRAY_SIZE(ath79_spi_resources),
+};
+
+void __init ath79_register_spi(struct ath79_spi_platform_data *pdata,
+			       struct spi_board_info const *info,
+			       unsigned n)
+{
+	spi_register_board_info(info, n);
+	ath79_spi_device.dev.platform_data = pdata;
+	platform_device_register(&ath79_spi_device);
+}
diff --git a/arch/mips/ath79/dev-spi.h b/arch/mips/ath79/dev-spi.h
new file mode 100644
index 0000000..9a98333
--- /dev/null
+++ b/arch/mips/ath79/dev-spi.h
@@ -0,0 +1,22 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X SPI controller device
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#ifndef _ATH79_DEV_SPI_H
+#define _ATH79_DEV_SPI_H
+
+#include <linux/spi/spi.h>
+#include <asm/mach-ath79/ath79_spi_platform.h>
+
+void __init ath79_register_spi(struct ath79_spi_platform_data *pdata,
+			       struct spi_board_info const *info,
+			       unsigned n);
+
+#endif /* _ATH79_DEV_SPI_H */
diff --git a/arch/mips/ath79/mach-pb44.c b/arch/mips/ath79/mach-pb44.c
index 3dc5080..ec7b7a1 100644
--- a/arch/mips/ath79/mach-pb44.c
+++ b/arch/mips/ath79/mach-pb44.c
@@ -17,6 +17,7 @@
 #include "machtypes.h"
 #include "dev-gpio-buttons.h"
 #include "dev-leds-gpio.h"
+#include "dev-spi.h"
 
 #define PB44_GPIO_I2C_SCL	0
 #define PB44_GPIO_I2C_SDA	1
@@ -84,6 +85,20 @@ static struct gpio_keys_button pb44_gpio_keys[] __initdata = {
 	}
 };
 
+static struct spi_board_info pb44_spi_info[] = {
+	{
+		.bus_num	= 0,
+		.chip_select	= 0,
+		.max_speed_hz	= 25000000,
+		.modalias	= "m25p64",
+	},
+};
+
+static struct ath79_spi_platform_data pb44_spi_data = {
+	.bus_num		= 0,
+	.num_chipselect		= 1,
+};
+
 static void __init pb44_init(void)
 {
 	i2c_register_board_info(0, pb44_i2c_board_info,
@@ -95,6 +110,8 @@ static void __init pb44_init(void)
 	ath79_register_gpio_keys_polled(-1, PB44_KEYS_POLL_INTERVAL,
 					ARRAY_SIZE(pb44_gpio_keys),
 					pb44_gpio_keys);
+	ath79_register_spi(&pb44_spi_data, pb44_spi_info,
+			   ARRAY_SIZE(pb44_spi_info));
 }
 
 MIPS_MACHINE(ATH79_MACH_PB44, "PB44", "Atheros PB44 reference board",
diff --git a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
index 7f2933d..4f2b621 100644
--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
+++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
@@ -20,6 +20,8 @@
 #include <linux/bitops.h>
 
 #define AR71XX_APB_BASE		0x18000000
+#define AR71XX_SPI_BASE		0x1f000000
+#define AR71XX_SPI_SIZE		0x01000000
 
 #define AR71XX_DDR_CTRL_BASE	(AR71XX_APB_BASE + 0x00000000)
 #define AR71XX_DDR_CTRL_SIZE	0x100
-- 
1.7.2.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v2 11/16] USB: ehci: add workaround for Synopsys HC bug
  2010-12-22 20:30 [PATCH v2 00/16] MIPS: initial support for the Atheros AR71XX/AR724X/AR913X SoCs Gabor Juhos
                   ` (9 preceding siblings ...)
  2010-12-22 20:30 ` [PATCH v2 10/16] MIPS: ath79: add common SPI controller device Gabor Juhos
@ 2010-12-22 20:30 ` Gabor Juhos
  2010-12-23  0:30   ` Greg KH
  2010-12-22 20:30 ` [PATCH v2 12/16] USB: ehci: add bus glue for the Atheros AR71XX/AR724X/AR913X SoCs Gabor Juhos
                   ` (4 subsequent siblings)
  15 siblings, 1 reply; 21+ messages in thread
From: Gabor Juhos @ 2010-12-22 20:30 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: linux-mips, Imre Kaloz, Luis R. Rodriguez, Cliff Holden,
	Kathy Giori, Gabor Juhos, David Brownell, Greg Kroah-Hartman,
	linux-usb

A Synopsys USB core used in various SoCs has a bug which might cause
that the host controller not issuing ping.

When software uses the Doorbell mechanism to remove queue heads, the
host controller still has references to the removed queue head even
after indicating an Interrupt on Async Advance. This happens if the last
executed queue head's Next Link queue head is removed.

Consequences of the defect:
The Host controller fetches the removed queue head, using memory that
would otherwise be deallocated.This results in incorrect transactions on
both the USB and system memory. This may result in undefined behavior.

Workarounds:

1) If no queue head is active (no Status field's Active bit is set)
after removing the queue heads, the software can write one of the valid
queue head addresses to the ASYNCLISTADDR register and deallocate the
removed queue head's memory after 2 microframes.

If one or more of the queue heads is active (the Active bit is set in
the Status field) after removing the queue heads, the software can delay
memory deallocation after time X, where X is the time required for the
Host Controller to go through all the queue heads once. X varies with
the number of queue heads and the time required to process periodic
transactions: if more periodic transactions must be performed, the Host
Controller has less time to process asynchronous transaction processing.

2) Do not use the Doorbell mechanism to remove the queue heads. Disable
the Asynchronous Schedule Enable bit instead.

The bug has been discussed on the linux-usb-devel mailing-list
four years ago, the original thread can be found here:
http://www.mail-archive.com/linux-usb-devel@lists.sourceforge.net/msg45345.html

This patch implements the first workaround as suggested by David Brownell.
The built-in USB host controller of the Atheros AR7130/AR7141/AR7161 SoCs
requires this to work properly.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Cc: David Brownell <dbrownell@users.sourceforge.net>
Cc: Greg Kroah-Hartman <gregkh@suse.de>
Cc: linux-usb@vger.kernel.org
---

Changes since RFC: ---

Changes since v1:
    - rebased against 2.6.37-rc7

 drivers/usb/host/ehci-q.c |    3 +++
 drivers/usb/host/ehci.h   |    1 +
 2 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index 233c288..343b8de 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -1193,6 +1193,9 @@ static void end_unlink_async (struct ehci_hcd *ehci)
 		ehci->reclaim = NULL;
 		start_unlink_async (ehci, next);
 	}
+
+	if (ehci->has_synopsys_hc_bug)
+		writel((u32)ehci->async->qh_dma, &ehci->regs->async_next);
 }
 
 /* makes sure the async qh will become idle */
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index ba8eab3..6da85b2 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -133,6 +133,7 @@ struct ehci_hcd {			/* one per controller */
 	unsigned		broken_periodic:1;
 	unsigned		fs_i_thresh:1;	/* Intel iso scheduling */
 	unsigned		use_dummy_qh:1;	/* AMD Frame List table quirk*/
+	unsigned		has_synopsys_hc_bug:1; /* Synopsys HC */
 
 	/* required for usb32 quirk */
 	#define OHCI_CTRL_HCFS          (3 << 6)
-- 
1.7.2.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v2 12/16] USB: ehci: add bus glue for the Atheros AR71XX/AR724X/AR913X SoCs
  2010-12-22 20:30 [PATCH v2 00/16] MIPS: initial support for the Atheros AR71XX/AR724X/AR913X SoCs Gabor Juhos
                   ` (10 preceding siblings ...)
  2010-12-22 20:30 ` [PATCH v2 11/16] USB: ehci: add workaround for Synopsys HC bug Gabor Juhos
@ 2010-12-22 20:30 ` Gabor Juhos
  2010-12-22 20:30 ` [PATCH v2 13/16] USB: ohci: add bus glue for the Atheros AR71XX/AR7240 SoCs Gabor Juhos
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 21+ messages in thread
From: Gabor Juhos @ 2010-12-22 20:30 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: linux-mips, Imre Kaloz, Luis R. Rodriguez, Cliff Holden,
	Kathy Giori, Gabor Juhos, David Brownell, Greg Kroah-Hartman,
	linux-usb

The Atheros AR71XX/AR724X/AR913X SoCs have a built-in EHCI controller.
This patch adds the necessary glue code to make the generic EHCI driver
usable for them.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Signed-off-by: Imre Kaloz <kaloz@openwrt.org>
Cc: David Brownell <dbrownell@users.sourceforge.net>
Cc: Greg Kroah-Hartman <gregkh@suse.de>
Cc: linux-usb@vger.kernel.org
---

Changes since RFC:
    - don't use 'default y if SOC_*', select USB_ARCH_HAS_EHCI option in the
      platform specific Kconfig file instead
    - add missing 'ath79_ehci_platform.h' file

Changes since v1:
    - rebased against 2.6.37-rc7

 arch/mips/ath79/Kconfig                            |    3 +
 .../include/asm/mach-ath79/ath79_ehci_platform.h   |   18 ++
 drivers/usb/host/Kconfig                           |    8 +
 drivers/usb/host/ehci-ath79.c                      |  176 ++++++++++++++++++++
 drivers/usb/host/ehci-hcd.c                        |    5 +
 5 files changed, 210 insertions(+), 0 deletions(-)
 create mode 100644 arch/mips/include/asm/mach-ath79/ath79_ehci_platform.h
 create mode 100644 drivers/usb/host/ehci-ath79.c

diff --git a/arch/mips/ath79/Kconfig b/arch/mips/ath79/Kconfig
index cd6c738..647f535 100644
--- a/arch/mips/ath79/Kconfig
+++ b/arch/mips/ath79/Kconfig
@@ -15,12 +15,15 @@ config ATH79_MACH_PB44
 endmenu
 
 config SOC_AR71XX
+	select USB_ARCH_HAS_EHCI
 	def_bool n
 
 config SOC_AR724X
+	select USB_ARCH_HAS_EHCI
 	def_bool n
 
 config SOC_AR913X
+	select USB_ARCH_HAS_EHCI
 	def_bool n
 
 config ATH79_DEV_GPIO_BUTTONS
diff --git a/arch/mips/include/asm/mach-ath79/ath79_ehci_platform.h b/arch/mips/include/asm/mach-ath79/ath79_ehci_platform.h
new file mode 100644
index 0000000..6ee075f
--- /dev/null
+++ b/arch/mips/include/asm/mach-ath79/ath79_ehci_platform.h
@@ -0,0 +1,18 @@
+/*
+ *  Platform data definition for Atheros AR71XX/AR913X EHCI controller
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#ifndef _ATH79_EHCI_PLATFORM_H
+#define _ATH79_EHCI_PLATFORM_H
+
+struct ath79_ehci_platform_data {
+	u8	is_ar913x;
+};
+
+#endif /* _ATH79_EHCI_PLATFORM_H */
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 6f4f8e6..3a2667a 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -147,6 +147,14 @@ config USB_W90X900_EHCI
 	---help---
 		Enables support for the W90X900 USB controller
 
+config USB_EHCI_ATH79
+	bool "EHCI support for AR71XX/AR724X/AR913X SoCs"
+	depends on USB_EHCI_HCD && ATH79
+	select USB_EHCI_ROOT_HUB_TT
+	---help---
+	  Enables support for the built-in EHCI controller present
+	  on the Atheros AR71XX/AR724X/AR913X SoCs.
+
 config USB_OXU210HP_HCD
 	tristate "OXU210HP HCD support"
 	depends on USB
diff --git a/drivers/usb/host/ehci-ath79.c b/drivers/usb/host/ehci-ath79.c
new file mode 100644
index 0000000..43a728f
--- /dev/null
+++ b/drivers/usb/host/ehci-ath79.c
@@ -0,0 +1,176 @@
+/*
+ *  Bus Glue for Atheros AR71XX/AR913X built-in EHCI controller.
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  Parts of this file are based on Atheros' 2.6.15 BSP
+ *	Copyright (C) 2007 Atheros Communications, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#include <linux/platform_device.h>
+#include <asm/mach-ath79/ath79_ehci_platform.h>
+
+static int ehci_ath79_init(struct usb_hcd *hcd)
+{
+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+	struct ath79_ehci_platform_data *pdata;
+	int ret;
+
+	pdata = hcd->self.controller->platform_data;
+
+	if (pdata->is_ar913x) {
+		hcd->has_tt = 1;
+
+		ehci->caps = hcd->regs + 0x100;
+		ehci->regs = hcd->regs + 0x100 +
+			HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
+	} else {
+		ehci->has_synopsys_hc_bug = 1;
+
+		ehci->caps = hcd->regs;
+		ehci->regs = hcd->regs +
+			HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
+	}
+
+	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+	ehci->sbrn = 0x20;
+
+	ehci_reset(ehci);
+
+	ret = ehci_init(hcd);
+	if (ret)
+		return ret;
+
+	ehci_port_power(ehci, 0);
+
+	return 0;
+}
+
+static const struct hc_driver ehci_ath79_hc_driver = {
+	.description		= hcd_name,
+	.product_desc		= "Atheros built-in EHCI controller",
+	.hcd_priv_size		= sizeof(struct ehci_hcd),
+	.irq			= ehci_irq,
+	.flags			= HCD_MEMORY | HCD_USB2,
+
+	.reset			= ehci_ath79_init,
+	.start			= ehci_run,
+	.stop			= ehci_stop,
+	.shutdown		= ehci_shutdown,
+
+	.urb_enqueue		= ehci_urb_enqueue,
+	.urb_dequeue		= ehci_urb_dequeue,
+	.endpoint_disable	= ehci_endpoint_disable,
+	.endpoint_reset		= ehci_endpoint_reset,
+
+	.get_frame_number	= ehci_get_frame,
+
+	.hub_status_data	= ehci_hub_status_data,
+	.hub_control		= ehci_hub_control,
+#ifdef CONFIG_PM
+	.hub_suspend		= ehci_hub_suspend,
+	.hub_resume		= ehci_hub_resume,
+#endif
+	.relinquish_port	= ehci_relinquish_port,
+	.port_handed_over	= ehci_port_handed_over,
+
+	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
+};
+
+static int ehci_ath79_probe(struct platform_device *pdev)
+{
+	struct ath79_ehci_platform_data *pdata;
+	struct usb_hcd *hcd;
+	struct resource *res;
+	int irq;
+	int ret;
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	pdata = pdev->dev.platform_data;
+	if (!pdata) {
+		dev_dbg(&pdev->dev, "no platform data specified for %s\n",
+			dev_name(&pdev->dev));
+		return -EINVAL;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res) {
+		dev_dbg(&pdev->dev, "no IRQ specified for %s\n",
+			dev_name(&pdev->dev));
+		return -ENODEV;
+	}
+	irq = res->start;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_dbg(&pdev->dev, "no base address specified for %s\n",
+			dev_name(&pdev->dev));
+		return -ENODEV;
+	}
+
+	hcd = usb_create_hcd(&ehci_ath79_hc_driver, &pdev->dev,
+			     dev_name(&pdev->dev));
+	if (!hcd)
+		return -ENOMEM;
+
+	hcd->rsrc_start	= res->start;
+	hcd->rsrc_len	= res->end - res->start + 1;
+
+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+		dev_dbg(&pdev->dev, "controller already in use\n");
+		ret = -EBUSY;
+		goto err_put_hcd;
+	}
+
+	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+	if (!hcd->regs) {
+		dev_dbg(&pdev->dev, "error mapping memory\n");
+		ret = -EFAULT;
+		goto err_release_region;
+	}
+
+	ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
+	if (ret)
+		goto err_iounmap;
+
+	return 0;
+
+err_iounmap:
+	iounmap(hcd->regs);
+
+err_release_region:
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+err_put_hcd:
+	usb_put_hcd(hcd);
+	return ret;
+}
+
+static int ehci_ath79_remove(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+
+	usb_remove_hcd(hcd);
+	iounmap(hcd->regs);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	usb_put_hcd(hcd);
+
+	return 0;
+}
+
+static struct platform_driver ehci_ath79_driver = {
+	.probe		= ehci_ath79_probe,
+	.remove		= ehci_ath79_remove,
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "ath79-ehci",
+	}
+};
+
+MODULE_ALIAS("platform:ath79-ehci");
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index e906280..b1313af 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1216,6 +1216,11 @@ MODULE_LICENSE ("GPL");
 #define PLATFORM_DRIVER		ehci_octeon_driver
 #endif
 
+#ifdef CONFIG_USB_EHCI_ATH79
+#include "ehci-ath79.c"
+#define PLATFORM_DRIVER		ehci_ath79_driver
+#endif
+
 #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
     !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \
     !defined(XILINX_OF_PLATFORM_DRIVER)
-- 
1.7.2.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v2 13/16] USB: ohci: add bus glue for the Atheros AR71XX/AR7240 SoCs
  2010-12-22 20:30 [PATCH v2 00/16] MIPS: initial support for the Atheros AR71XX/AR724X/AR913X SoCs Gabor Juhos
                   ` (11 preceding siblings ...)
  2010-12-22 20:30 ` [PATCH v2 12/16] USB: ehci: add bus glue for the Atheros AR71XX/AR724X/AR913X SoCs Gabor Juhos
@ 2010-12-22 20:30 ` Gabor Juhos
  2010-12-22 20:30 ` [PATCH v2 14/16] MIPS: ath79: add common USB Host Controller device Gabor Juhos
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 21+ messages in thread
From: Gabor Juhos @ 2010-12-22 20:30 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: linux-mips, Imre Kaloz, Luis R. Rodriguez, Cliff Holden,
	Kathy Giori, Gabor Juhos, David Brownell, Greg Kroah-Hartman,
	linux-usb

The Atheros AR71XX/AR7240 SoCs have a built-in OHCI controller.
This patch adds the necessary glue code to make the generic OHCI
driver usable for them.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Signed-off-by: Imre Kaloz <kaloz@openwrt.org>
Cc: David Brownell <dbrownell@users.sourceforge.net>
Cc: Greg Kroah-Hartman <gregkh@suse.de>
Cc: linux-usb@vger.kernel.org
---

Changes since RFC:
    - don't use 'defauly y if SOC_*', select the USB_ARCH_HAS_OHCI option
      in the platform specific Kconfig file instead
    - remove ath79_ehci_platform.h, it belongs to the EHCI patch

Changes since v1:
    - rebased against 2.6.37-rc7

 arch/mips/ath79/Kconfig       |    2 +
 drivers/usb/host/Kconfig      |    8 ++
 drivers/usb/host/ohci-ath79.c |  162 +++++++++++++++++++++++++++++++++++++++++
 drivers/usb/host/ohci-hcd.c   |    5 +
 4 files changed, 177 insertions(+), 0 deletions(-)
 create mode 100644 drivers/usb/host/ohci-ath79.c

diff --git a/arch/mips/ath79/Kconfig b/arch/mips/ath79/Kconfig
index 647f535..d4456ce 100644
--- a/arch/mips/ath79/Kconfig
+++ b/arch/mips/ath79/Kconfig
@@ -16,10 +16,12 @@ endmenu
 
 config SOC_AR71XX
 	select USB_ARCH_HAS_EHCI
+	select USB_ARCH_HAS_OHCI
 	def_bool n
 
 config SOC_AR724X
 	select USB_ARCH_HAS_EHCI
+	select USB_ARCH_HAS_OHCI
 	def_bool n
 
 config SOC_AR913X
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 3a2667a..39ed353 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -240,6 +240,14 @@ config USB_OHCI_HCD_OMAP3
 	  Enables support for the on-chip OHCI controller on
 	  OMAP3 and later chips.
 
+config USB_OHCI_ATH79
+	bool "USB OHCI support for the Atheros AR71XX/AR724X SoCs"
+	depends on USB_OHCI_HCD && (SOC_AR71XX || SOC_AR724X)
+	default y
+	help
+	  Enables support for the uilt-in OHCI controller present on the
+	  Atheros AR71XX/AR724X SoCs.
+
 config USB_OHCI_HCD_PPC_SOC
 	bool "OHCI support for on-chip PPC USB controller"
 	depends on USB_OHCI_HCD && (STB03xxx || PPC_MPC52xx)
diff --git a/drivers/usb/host/ohci-ath79.c b/drivers/usb/host/ohci-ath79.c
new file mode 100644
index 0000000..6e864bf
--- /dev/null
+++ b/drivers/usb/host/ohci-ath79.c
@@ -0,0 +1,162 @@
+/*
+ *  OHCI HCD (Host Controller Driver) for USB.
+ *
+ *  Bus Glue for Atheros AR71XX/AR724X built-in OHCI controller.
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  Parts of this file are based on Atheros' 2.6.15 BSP
+ *	Copyright (C) 2007 Atheros Communications, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#include <linux/platform_device.h>
+
+static int usb_hcd_ath79_probe(const struct hc_driver *driver,
+			       struct platform_device *pdev)
+{
+	struct usb_hcd *hcd;
+	struct resource *res;
+	int irq;
+	int ret;
+
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res) {
+		dev_dbg(&pdev->dev, "no IRQ specified for %s\n",
+			dev_name(&pdev->dev));
+		return -ENODEV;
+	}
+	irq = res->start;
+
+	hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
+	if (!hcd)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_dbg(&pdev->dev, "no base address specified for %s\n",
+			dev_name(&pdev->dev));
+		ret = -ENODEV;
+		goto err_put_hcd;
+	}
+	hcd->rsrc_start	= res->start;
+	hcd->rsrc_len	= res->end - res->start + 1;
+
+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+		dev_dbg(&pdev->dev, "controller already in use\n");
+		ret = -EBUSY;
+		goto err_put_hcd;
+	}
+
+	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+	if (!hcd->regs) {
+		dev_dbg(&pdev->dev, "error mapping memory\n");
+		ret = -EFAULT;
+		goto err_release_region;
+	}
+
+	ohci_hcd_init(hcd_to_ohci(hcd));
+
+	ret = usb_add_hcd(hcd, irq, IRQF_DISABLED);
+	if (ret)
+		goto err_stop_hcd;
+
+	return 0;
+
+err_stop_hcd:
+	iounmap(hcd->regs);
+err_release_region:
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+err_put_hcd:
+	usb_put_hcd(hcd);
+	return ret;
+}
+
+void usb_hcd_ath79_remove(struct usb_hcd *hcd, struct platform_device *pdev)
+{
+	usb_remove_hcd(hcd);
+	iounmap(hcd->regs);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	usb_put_hcd(hcd);
+}
+
+static int __devinit ohci_ath79_start(struct usb_hcd *hcd)
+{
+	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
+	int ret;
+
+	ret = ohci_init(ohci);
+	if (ret < 0)
+		return ret;
+
+	ret = ohci_run(ohci);
+	if (ret < 0)
+		goto err;
+
+	return 0;
+
+err:
+	ohci_stop(hcd);
+	return ret;
+}
+
+static const struct hc_driver ohci_ath79_hc_driver = {
+	.description		= hcd_name,
+	.product_desc		= "Atheros built-in OHCI controller",
+	.hcd_priv_size		= sizeof(struct ohci_hcd),
+
+	.irq			= ohci_irq,
+	.flags			= HCD_USB11 | HCD_MEMORY,
+
+	.start			= ohci_ath79_start,
+	.stop			= ohci_stop,
+	.shutdown		= ohci_shutdown,
+
+	.urb_enqueue		= ohci_urb_enqueue,
+	.urb_dequeue		= ohci_urb_dequeue,
+	.endpoint_disable	= ohci_endpoint_disable,
+
+	/*
+	 * scheduling support
+	 */
+	.get_frame_number	= ohci_get_frame,
+
+	/*
+	 * root hub support
+	 */
+	.hub_status_data	= ohci_hub_status_data,
+	.hub_control		= ohci_hub_control,
+	.start_port_reset	= ohci_start_port_reset,
+};
+
+static int ohci_hcd_ath79_drv_probe(struct platform_device *pdev)
+{
+	if (usb_disabled())
+		return -ENODEV;
+
+	return usb_hcd_ath79_probe(&ohci_ath79_hc_driver, pdev);
+}
+
+static int ohci_hcd_ath79_drv_remove(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+
+	usb_hcd_ath79_remove(hcd, pdev);
+	return 0;
+}
+
+static struct platform_driver ohci_hcd_ath79_driver = {
+	.probe		= ohci_hcd_ath79_drv_probe,
+	.remove		= ohci_hcd_ath79_drv_remove,
+	.shutdown	= usb_hcd_platform_shutdown,
+	.driver		= {
+		.name	= "ath79-ohci",
+		.owner	= THIS_MODULE,
+	},
+};
+
+MODULE_ALIAS("platform:ath79-ohci");
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 5179acb..6daeb68 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -1111,6 +1111,11 @@ MODULE_LICENSE ("GPL");
 #define PLATFORM_DRIVER		ohci_octeon_driver
 #endif
 
+#ifdef CONFIG_USB_OHCI_ATH79
+#include "ohci-ath79.c"
+#define PLATFORM_DRIVER		ohci_hcd_ath79_driver
+#endif
+
 #if	!defined(PCI_DRIVER) &&		\
 	!defined(PLATFORM_DRIVER) &&	\
 	!defined(OMAP1_PLATFORM_DRIVER) &&	\
-- 
1.7.2.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v2 14/16] MIPS: ath79: add common USB Host Controller device
  2010-12-22 20:30 [PATCH v2 00/16] MIPS: initial support for the Atheros AR71XX/AR724X/AR913X SoCs Gabor Juhos
                   ` (12 preceding siblings ...)
  2010-12-22 20:30 ` [PATCH v2 13/16] USB: ohci: add bus glue for the Atheros AR71XX/AR7240 SoCs Gabor Juhos
@ 2010-12-22 20:30 ` Gabor Juhos
  2010-12-22 20:31 ` [PATCH v2 15/16] MIPS: ath79: add initial support for the Atheros AP81 reference board Gabor Juhos
  2010-12-22 20:31 ` [PATCH v2 16/16] MIPS: ath79: add common WMAC device for AR913X based boards Gabor Juhos
  15 siblings, 0 replies; 21+ messages in thread
From: Gabor Juhos @ 2010-12-22 20:30 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: linux-mips, Imre Kaloz, Luis R. Rodriguez, Cliff Holden,
	Kathy Giori, Gabor Juhos

Add common platform_device and helper code to make the registration of
the built-in USB controllers easier on the board which are using them.
Also register the USB controller on the PB44 board.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Signed-off-by: Imre Kaloz <kaloz@openwrt.org>
---

Changes since RFC: ---

Changes since v1:
    - rebased against 2.6.37-rc7

 arch/mips/ath79/Kconfig                        |    4 +
 arch/mips/ath79/Makefile                       |    1 +
 arch/mips/ath79/dev-usb.c                      |  194 ++++++++++++++++++++++++
 arch/mips/ath79/dev-usb.h                      |   17 ++
 arch/mips/ath79/mach-pb44.c                    |    2 +
 arch/mips/include/asm/mach-ath79/ar71xx_regs.h |   22 +++-
 6 files changed, 239 insertions(+), 1 deletions(-)
 create mode 100644 arch/mips/ath79/dev-usb.c
 create mode 100644 arch/mips/ath79/dev-usb.h

diff --git a/arch/mips/ath79/Kconfig b/arch/mips/ath79/Kconfig
index d4456ce..5d67942 100644
--- a/arch/mips/ath79/Kconfig
+++ b/arch/mips/ath79/Kconfig
@@ -8,6 +8,7 @@ config ATH79_MACH_PB44
 	select ATH79_DEV_GPIO_BUTTONS
 	select ATH79_DEV_LEDS_GPIO
 	select ATH79_DEV_SPI
+	select ATH79_DEV_USB
 	help
 	  Say 'Y' here if you want your kernel to support the
 	  Atheros PB44 reference board.
@@ -37,4 +38,7 @@ config ATH79_DEV_LEDS_GPIO
 config ATH79_DEV_SPI
 	def_bool n
 
+config ATH79_DEV_USB
+	def_bool n
+
 endif
diff --git a/arch/mips/ath79/Makefile b/arch/mips/ath79/Makefile
index a8de078..494d106 100644
--- a/arch/mips/ath79/Makefile
+++ b/arch/mips/ath79/Makefile
@@ -19,6 +19,7 @@ obj-y					+= dev-common.o
 obj-$(CONFIG_ATH79_DEV_GPIO_BUTTONS)	+= dev-gpio-buttons.o
 obj-$(CONFIG_ATH79_DEV_LEDS_GPIO)	+= dev-leds-gpio.o
 obj-$(CONFIG_ATH79_DEV_SPI)		+= dev-spi.o
+obj-$(CONFIG_ATH79_DEV_USB)		+= dev-usb.o
 
 #
 # Machines
diff --git a/arch/mips/ath79/dev-usb.c b/arch/mips/ath79/dev-usb.c
new file mode 100644
index 0000000..fb7033f
--- /dev/null
+++ b/arch/mips/ath79/dev-usb.c
@@ -0,0 +1,194 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X USB Host Controller support
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  Parts of this file are based on Atheros' 2.6.15 BSP
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach-ath79/ath79.h>
+#include <asm/mach-ath79/ar71xx_regs.h>
+#include <asm/mach-ath79/ath79_ehci_platform.h>
+#include "common.h"
+#include "dev-usb.h"
+
+static void __iomem *ath79_usb_ctrl_base;
+
+static struct resource ar71xx_ohci_resources[] = {
+	[0] = {
+		.start	= AR71XX_OHCI_BASE,
+		.end	= AR71XX_OHCI_BASE + AR71XX_OHCI_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= ATH79_MISC_IRQ_OHCI,
+		.end	= ATH79_MISC_IRQ_OHCI,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource ar724x_usb_resources[] = {
+	[0] = {
+		.start	= AR7240_OHCI_BASE,
+		.end	= AR7240_OHCI_BASE + AR7240_OHCI_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= ATH79_CPU_IRQ_USB,
+		.end	= ATH79_CPU_IRQ_USB,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static u64 ath79_ohci_dmamask = DMA_BIT_MASK(32);
+static struct platform_device ath79_ohci_device = {
+	.name		= "ath79-ohci",
+	.id		= -1,
+	.resource	= ar71xx_ohci_resources,
+	.num_resources	= ARRAY_SIZE(ar71xx_ohci_resources),
+	.dev = {
+		.dma_mask		= &ath79_ohci_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
+static struct resource ar71xx_ehci_resources[] = {
+	[0] = {
+		.start	= AR71XX_EHCI_BASE,
+		.end	= AR71XX_EHCI_BASE + AR71XX_EHCI_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= ATH79_CPU_IRQ_USB,
+		.end	= ATH79_CPU_IRQ_USB,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static u64 ath79_ehci_dmamask = DMA_BIT_MASK(32);
+static struct ath79_ehci_platform_data ath79_ehci_data;
+
+static struct platform_device ath79_ehci_device = {
+	.name		= "ath79-ehci",
+	.id		= -1,
+	.resource	= ar71xx_ehci_resources,
+	.num_resources	= ARRAY_SIZE(ar71xx_ehci_resources),
+	.dev = {
+		.dma_mask		= &ath79_ehci_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+		.platform_data		= &ath79_ehci_data,
+	},
+};
+
+#define AR71XX_USB_RESET_MASK	(AR71XX_RESET_USB_HOST | \
+				 AR71XX_RESET_USB_PHY | \
+				 AR71XX_RESET_USB_OHCI_DLL)
+
+static void __init ar71xx_usb_setup(void)
+{
+	ath79_device_reset_set(AR71XX_USB_RESET_MASK);
+	mdelay(1000);
+	ath79_device_reset_clear(AR71XX_USB_RESET_MASK);
+
+	/* Turning on the Buff and Desc swap bits */
+	__raw_writel(0xf0000, ath79_usb_ctrl_base + AR71XX_USB_CTRL_REG_CONFIG);
+
+	/* WAR for HW bug. Here it adjusts the duration between two SOFS */
+	__raw_writel(0x20c00, ath79_usb_ctrl_base + AR71XX_USB_CTRL_REG_FLADJ);
+
+	mdelay(900);
+
+	platform_device_register(&ath79_ohci_device);
+	platform_device_register(&ath79_ehci_device);
+}
+
+static void __init ar7240_usb_setup(void)
+{
+	ath79_device_reset_clear(AR7240_RESET_OHCI_DLL);
+	ath79_device_reset_set(AR7240_RESET_USB_HOST);
+	mdelay(1000);
+	ath79_device_reset_set(AR7240_RESET_OHCI_DLL);
+	ath79_device_reset_clear(AR7240_RESET_USB_HOST);
+
+	/* WAR for HW bug. Here it adjusts the duration between two SOFS */
+	__raw_writel(0x3, ath79_usb_ctrl_base + AR71XX_USB_CTRL_REG_FLADJ);
+
+	ath79_ohci_device.resource = ar724x_usb_resources;
+	ath79_ohci_device.num_resources = ARRAY_SIZE(ar724x_usb_resources);
+	platform_device_register(&ath79_ohci_device);
+}
+
+static void __init ar724x_usb_setup(void)
+{
+	ath79_device_reset_set(AR724X_RESET_USBSUS_OVERRIDE);
+	mdelay(10);
+
+	ath79_device_reset_clear(AR724X_RESET_USB_HOST);
+	mdelay(10);
+
+	ath79_device_reset_clear(AR724X_RESET_USB_PHY);
+	mdelay(10);
+
+	ath79_ehci_data.is_ar913x = 1;
+	ath79_ehci_device.resource = ar724x_usb_resources;
+	ath79_ehci_device.num_resources = ARRAY_SIZE(ar724x_usb_resources);
+	platform_device_register(&ath79_ehci_device);
+}
+
+static void __init ar913x_usb_setup(void)
+{
+	ath79_device_reset_set(AR71XX_RESET_USBSUS_OVERRIDE);
+	mdelay(10);
+
+	ath79_device_reset_clear(AR71XX_RESET_USB_HOST);
+	mdelay(10);
+
+	ath79_device_reset_clear(AR71XX_RESET_USB_PHY);
+	mdelay(10);
+
+	ath79_ehci_data.is_ar913x = 1;
+	platform_device_register(&ath79_ehci_device);
+}
+
+void __init ath79_register_usb(void)
+{
+	ath79_usb_ctrl_base = ioremap(AR71XX_USB_CTRL_BASE,
+				      AR71XX_USB_CTRL_SIZE);
+
+	switch (ath79_soc) {
+	case ATH79_SOC_AR7130:
+	case ATH79_SOC_AR7141:
+	case ATH79_SOC_AR7161:
+		ar71xx_usb_setup();
+		break;
+
+	case ATH79_SOC_AR7240:
+		ar7240_usb_setup();
+		break;
+
+	case ATH79_SOC_AR7241:
+	case ATH79_SOC_AR7242:
+		ar724x_usb_setup();
+		break;
+
+	case ATH79_SOC_AR9130:
+	case ATH79_SOC_AR9132:
+		ar913x_usb_setup();
+		break;
+
+	default:
+		BUG();
+	}
+}
diff --git a/arch/mips/ath79/dev-usb.h b/arch/mips/ath79/dev-usb.h
new file mode 100644
index 0000000..dbe6d3d
--- /dev/null
+++ b/arch/mips/ath79/dev-usb.h
@@ -0,0 +1,17 @@
+/*
+ *  Atheros AR71XX/AR724X/AR913X USB Host Controller support
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#ifndef _ATH79_DEV_USB_H
+#define _ATH79_DEV_USB_H
+
+void ath79_register_usb(void) __init;
+
+#endif /* _ATH79_DEV_USB_H */
diff --git a/arch/mips/ath79/mach-pb44.c b/arch/mips/ath79/mach-pb44.c
index ec7b7a1..fe9701a 100644
--- a/arch/mips/ath79/mach-pb44.c
+++ b/arch/mips/ath79/mach-pb44.c
@@ -18,6 +18,7 @@
 #include "dev-gpio-buttons.h"
 #include "dev-leds-gpio.h"
 #include "dev-spi.h"
+#include "dev-usb.h"
 
 #define PB44_GPIO_I2C_SCL	0
 #define PB44_GPIO_I2C_SDA	1
@@ -112,6 +113,7 @@ static void __init pb44_init(void)
 					pb44_gpio_keys);
 	ath79_register_spi(&pb44_spi_data, pb44_spi_info,
 			   ARRAY_SIZE(pb44_spi_info));
+	ath79_register_usb();
 }
 
 MIPS_MACHINE(ATH79_MACH_PB44, "PB44", "Atheros PB44 reference board",
diff --git a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
index 4f2b621..f125f1e 100644
--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
+++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
@@ -20,6 +20,10 @@
 #include <linux/bitops.h>
 
 #define AR71XX_APB_BASE		0x18000000
+#define AR71XX_EHCI_BASE	0x1b000000
+#define AR71XX_EHCI_SIZE	0x1000
+#define AR71XX_OHCI_BASE	0x1c000000
+#define AR71XX_OHCI_SIZE	0x1000
 #define AR71XX_SPI_BASE		0x1f000000
 #define AR71XX_SPI_SIZE		0x01000000
 
@@ -27,6 +31,8 @@
 #define AR71XX_DDR_CTRL_SIZE	0x100
 #define AR71XX_UART_BASE	(AR71XX_APB_BASE + 0x00020000)
 #define AR71XX_UART_SIZE	0x100
+#define AR71XX_USB_CTRL_BASE	(AR71XX_APB_BASE + 0x00030000)
+#define AR71XX_USB_CTRL_SIZE	0x100
 #define AR71XX_GPIO_BASE        (AR71XX_APB_BASE + 0x00040000)
 #define AR71XX_GPIO_SIZE        0x100
 #define AR71XX_PLL_BASE		(AR71XX_APB_BASE + 0x00050000)
@@ -34,6 +40,9 @@
 #define AR71XX_RESET_BASE	(AR71XX_APB_BASE + 0x00060000)
 #define AR71XX_RESET_SIZE	0x100
 
+#define AR7240_OHCI_BASE	0x1b000000
+#define AR7240_OHCI_SIZE	0x1000
+
 /*
  * DDR_CTRL block
  */
@@ -102,6 +111,12 @@
 #define AR913X_AHB_DIV_MASK		0x1
 
 /*
+ * USB_CONFIG block
+ */
+#define AR71XX_USB_CTRL_REG_FLADJ	0x00
+#define AR71XX_USB_CTRL_REG_CONFIG	0x04
+
+/*
  * RESET block
  */
 #define AR71XX_RESET_REG_TIMER			0x00
@@ -155,12 +170,17 @@
 #define AR71XX_RESET_PCI_BUS		BIT(1)
 #define AR71XX_RESET_PCI_CORE		BIT(0)
 
+#define AR7240_RESET_USB_HOST		BIT(5)
+#define AR7240_RESET_OHCI_DLL		BIT(3)
+
 #define AR724X_RESET_GE1_MDIO		BIT(23)
 #define AR724X_RESET_GE0_MDIO		BIT(22)
 #define AR724X_RESET_PCIE_PHY_SERIAL	BIT(10)
 #define AR724X_RESET_PCIE_PHY		BIT(7)
 #define AR724X_RESET_PCIE		BIT(6)
-#define AR724X_RESET_OHCI_DLL		BIT(3)
+#define AR724X_RESET_USB_HOST		BIT(5)
+#define AR724X_RESET_USB_PHY		BIT(4)
+#define AR724X_RESET_USBSUS_OVERRIDE	BIT(3)
 
 #define AR913X_RESET_AMBA2WMAC		BIT(22)
 
-- 
1.7.2.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v2 15/16] MIPS: ath79: add initial support for the Atheros AP81 reference board
  2010-12-22 20:30 [PATCH v2 00/16] MIPS: initial support for the Atheros AR71XX/AR724X/AR913X SoCs Gabor Juhos
                   ` (13 preceding siblings ...)
  2010-12-22 20:30 ` [PATCH v2 14/16] MIPS: ath79: add common USB Host Controller device Gabor Juhos
@ 2010-12-22 20:31 ` Gabor Juhos
  2010-12-22 20:31 ` [PATCH v2 16/16] MIPS: ath79: add common WMAC device for AR913X based boards Gabor Juhos
  15 siblings, 0 replies; 21+ messages in thread
From: Gabor Juhos @ 2010-12-22 20:31 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: linux-mips, Imre Kaloz, Luis R. Rodriguez, Cliff Holden,
	Kathy Giori, Gabor Juhos

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Signed-off-by: Imre Kaloz <kaloz@openwrt.org>
---

Changes since RFC:
    - don't use 'default n' for the ATH79_MACH_AP81 Kconfig option

Changes since v1:
    - rebased against 2.6.37-rc7

 arch/mips/ath79/Kconfig     |   11 +++++
 arch/mips/ath79/Makefile    |    1 +
 arch/mips/ath79/mach-ap81.c |   94 +++++++++++++++++++++++++++++++++++++++++++
 arch/mips/ath79/machtypes.h |    1 +
 4 files changed, 107 insertions(+), 0 deletions(-)
 create mode 100644 arch/mips/ath79/mach-ap81.c

diff --git a/arch/mips/ath79/Kconfig b/arch/mips/ath79/Kconfig
index 5d67942..1912d54 100644
--- a/arch/mips/ath79/Kconfig
+++ b/arch/mips/ath79/Kconfig
@@ -2,6 +2,17 @@ if ATH79
 
 menu "Atheros AR71XX/AR724X/AR913X machine selection"
 
+config ATH79_MACH_AP81
+	bool "Atheros AP81 reference board"
+	select SOC_AR913X
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_SPI
+	select ATH79_DEV_USB
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Atheros AP81 reference board.
+
 config ATH79_MACH_PB44
 	bool "Atheros PB44 reference board"
 	select SOC_AR71XX
diff --git a/arch/mips/ath79/Makefile b/arch/mips/ath79/Makefile
index 494d106..1b111d8 100644
--- a/arch/mips/ath79/Makefile
+++ b/arch/mips/ath79/Makefile
@@ -24,4 +24,5 @@ obj-$(CONFIG_ATH79_DEV_USB)		+= dev-usb.o
 #
 # Machines
 #
+obj-$(CONFIG_ATH79_MACH_AP81)		+= mach-ap81.o
 obj-$(CONFIG_ATH79_MACH_PB44)		+= mach-pb44.o
diff --git a/arch/mips/ath79/mach-ap81.c b/arch/mips/ath79/mach-ap81.c
new file mode 100644
index 0000000..909ca5d
--- /dev/null
+++ b/arch/mips/ath79/mach-ap81.c
@@ -0,0 +1,94 @@
+/*
+ *  Atheros AP81 board support
+ *
+ *  Copyright (C) 2009-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2009 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#include "machtypes.h"
+#include "dev-gpio-buttons.h"
+#include "dev-leds-gpio.h"
+#include "dev-spi.h"
+#include "dev-usb.h"
+
+#define AP81_GPIO_LED_STATUS	1
+#define AP81_GPIO_LED_AOSS	3
+#define AP81_GPIO_LED_WLAN	6
+#define AP81_GPIO_LED_POWER	14
+
+#define AP81_GPIO_BTN_SW4	12
+#define AP81_GPIO_BTN_SW1	21
+
+#define AP81_KEYS_POLL_INTERVAL		20	/* msecs */
+#define AP81_KEYS_DEBOUNCE_INTERVAL	(3 * AP81_KEYS_POLL_INTERVAL)
+
+static struct gpio_led ap81_leds_gpio[] __initdata = {
+	{
+		.name		= "ap81:green:status",
+		.gpio		= AP81_GPIO_LED_STATUS,
+		.active_low	= 1,
+	}, {
+		.name		= "ap81:amber:aoss",
+		.gpio		= AP81_GPIO_LED_AOSS,
+		.active_low	= 1,
+	}, {
+		.name		= "ap81:green:wlan",
+		.gpio		= AP81_GPIO_LED_WLAN,
+		.active_low	= 1,
+	}, {
+		.name		= "ap81:green:power",
+		.gpio		= AP81_GPIO_LED_POWER,
+		.active_low	= 1,
+	}
+};
+
+static struct gpio_keys_button ap81_gpio_keys[] __initdata = {
+	{
+		.desc		= "sw1",
+		.type		= EV_KEY,
+		.code		= BTN_0,
+		.debounce_interval = AP81_KEYS_DEBOUNCE_INTERVAL,
+		.gpio		= AP81_GPIO_BTN_SW1,
+		.active_low	= 1,
+	} , {
+		.desc		= "sw4",
+		.type		= EV_KEY,
+		.code		= BTN_1,
+		.debounce_interval = AP81_KEYS_DEBOUNCE_INTERVAL,
+		.gpio		= AP81_GPIO_BTN_SW4,
+		.active_low	= 1,
+	}
+};
+
+static struct spi_board_info ap81_spi_info[] = {
+	{
+		.bus_num	= 0,
+		.chip_select	= 0,
+		.max_speed_hz	= 25000000,
+		.modalias	= "m25p64",
+	}
+};
+
+static struct ath79_spi_platform_data ap81_spi_data = {
+	.bus_num	= 0,
+	.num_chipselect	= 1,
+};
+
+static void __init ap81_setup(void)
+{
+	ath79_register_leds_gpio(-1, ARRAY_SIZE(ap81_leds_gpio),
+				 ap81_leds_gpio);
+	ath79_register_gpio_keys_polled(-1, AP81_KEYS_POLL_INTERVAL,
+					ARRAY_SIZE(ap81_gpio_keys),
+					ap81_gpio_keys);
+	ath79_register_spi(&ap81_spi_data, ap81_spi_info,
+			   ARRAY_SIZE(ap81_spi_info));
+	ath79_register_usb();
+}
+
+MIPS_MACHINE(ATH79_MACH_AP81, "AP81", "Atheros AP81 reference board",
+	     ap81_setup);
diff --git a/arch/mips/ath79/machtypes.h b/arch/mips/ath79/machtypes.h
index a796fa3..3940fe4 100644
--- a/arch/mips/ath79/machtypes.h
+++ b/arch/mips/ath79/machtypes.h
@@ -16,6 +16,7 @@
 
 enum ath79_mach_type {
 	ATH79_MACH_GENERIC = 0,
+	ATH79_MACH_AP81,		/* Atheros AP81 reference board */
 	ATH79_MACH_PB44,		/* Atheros PB44 reference board */
 };
 
-- 
1.7.2.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v2 16/16] MIPS: ath79: add common WMAC device for AR913X based boards
  2010-12-22 20:30 [PATCH v2 00/16] MIPS: initial support for the Atheros AR71XX/AR724X/AR913X SoCs Gabor Juhos
                   ` (14 preceding siblings ...)
  2010-12-22 20:31 ` [PATCH v2 15/16] MIPS: ath79: add initial support for the Atheros AP81 reference board Gabor Juhos
@ 2010-12-22 20:31 ` Gabor Juhos
  15 siblings, 0 replies; 21+ messages in thread
From: Gabor Juhos @ 2010-12-22 20:31 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: linux-mips, Imre Kaloz, Luis R. Rodriguez, Cliff Holden,
	Kathy Giori, Gabor Juhos

Add common platform_device and helper code to make the registration
of the built-in wireless MAC easier on the Atheros AR9130/AR9132
based boards. Also register the WMAC device on the AR81 board.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---

Changes since RFC: ---

Changes since v1:
    - rebased against 2.6.37-rc7

 arch/mips/ath79/Kconfig                        |    5 ++
 arch/mips/ath79/Makefile                       |    1 +
 arch/mips/ath79/dev-ar913x-wmac.c              |   60 ++++++++++++++++++++++++
 arch/mips/ath79/dev-ar913x-wmac.h              |   17 +++++++
 arch/mips/ath79/mach-ap81.c                    |    6 ++
 arch/mips/include/asm/mach-ath79/ar71xx_regs.h |    3 +
 6 files changed, 92 insertions(+), 0 deletions(-)
 create mode 100644 arch/mips/ath79/dev-ar913x-wmac.c
 create mode 100644 arch/mips/ath79/dev-ar913x-wmac.h

diff --git a/arch/mips/ath79/Kconfig b/arch/mips/ath79/Kconfig
index 1912d54..af01669 100644
--- a/arch/mips/ath79/Kconfig
+++ b/arch/mips/ath79/Kconfig
@@ -5,6 +5,7 @@ menu "Atheros AR71XX/AR724X/AR913X machine selection"
 config ATH79_MACH_AP81
 	bool "Atheros AP81 reference board"
 	select SOC_AR913X
+	select ATH79_DEV_AR913X_WMAC
 	select ATH79_DEV_GPIO_BUTTONS
 	select ATH79_DEV_LEDS_GPIO
 	select ATH79_DEV_SPI
@@ -40,6 +41,10 @@ config SOC_AR913X
 	select USB_ARCH_HAS_EHCI
 	def_bool n
 
+config ATH79_DEV_AR913X_WMAC
+	depends on SOC_AR913X
+	def_bool n
+
 config ATH79_DEV_GPIO_BUTTONS
 	def_bool n
 
diff --git a/arch/mips/ath79/Makefile b/arch/mips/ath79/Makefile
index 1b111d8..48398561 100644
--- a/arch/mips/ath79/Makefile
+++ b/arch/mips/ath79/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_EARLY_PRINTK)		+= early_printk.o
 # Devices
 #
 obj-y					+= dev-common.o
+obj-$(CONFIG_ATH79_DEV_AR913X_WMAC)	+= dev-ar913x-wmac.o
 obj-$(CONFIG_ATH79_DEV_GPIO_BUTTONS)	+= dev-gpio-buttons.o
 obj-$(CONFIG_ATH79_DEV_LEDS_GPIO)	+= dev-leds-gpio.o
 obj-$(CONFIG_ATH79_DEV_SPI)		+= dev-spi.o
diff --git a/arch/mips/ath79/dev-ar913x-wmac.c b/arch/mips/ath79/dev-ar913x-wmac.c
new file mode 100644
index 0000000..48f425a
--- /dev/null
+++ b/arch/mips/ath79/dev-ar913x-wmac.c
@@ -0,0 +1,60 @@
+/*
+ *  Atheros AR913X SoC built-in WMAC device support
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/ath9k_platform.h>
+
+#include <asm/mach-ath79/ath79.h>
+#include <asm/mach-ath79/ar71xx_regs.h>
+#include "dev-ar913x-wmac.h"
+
+static struct ath9k_platform_data ar913x_wmac_data;
+
+static struct resource ar913x_wmac_resources[] = {
+	{
+		.start	= AR913X_WMAC_BASE,
+		.end	= AR913X_WMAC_BASE + AR913X_WMAC_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= ATH79_CPU_IRQ_IP2,
+		.end	= ATH79_CPU_IRQ_IP2,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device ar913x_wmac_device = {
+	.name		= "ath9k",
+	.id		= -1,
+	.resource	= ar913x_wmac_resources,
+	.num_resources	= ARRAY_SIZE(ar913x_wmac_resources),
+	.dev = {
+		.platform_data = &ar913x_wmac_data,
+	},
+};
+
+void __init ath79_register_ar913x_wmac(u8 *cal_data)
+{
+	if (cal_data)
+		memcpy(ar913x_wmac_data.eeprom_data, cal_data,
+		       sizeof(ar913x_wmac_data.eeprom_data));
+
+	/* reset the WMAC */
+	ath79_device_reset_set(AR913X_RESET_AMBA2WMAC);
+	mdelay(10);
+
+	ath79_device_reset_clear(AR913X_RESET_AMBA2WMAC);
+	mdelay(10);
+
+	platform_device_register(&ar913x_wmac_device);
+}
diff --git a/arch/mips/ath79/dev-ar913x-wmac.h b/arch/mips/ath79/dev-ar913x-wmac.h
new file mode 100644
index 0000000..5df653f
--- /dev/null
+++ b/arch/mips/ath79/dev-ar913x-wmac.h
@@ -0,0 +1,17 @@
+/*
+ *  Atheros AR913X SoC built-in WMAC device support
+ *
+ *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#ifndef _ATH79_DEV_AR913X_WMAC_H
+#define _ATH79_DEV_AR913X_WMAC_H
+
+void ath79_register_ar913x_wmac(u8 *cal_data) __init;
+
+#endif /* _ATH79_DEV_AR913X_WMAC_H */
diff --git a/arch/mips/ath79/mach-ap81.c b/arch/mips/ath79/mach-ap81.c
index 909ca5d..03719b8 100644
--- a/arch/mips/ath79/mach-ap81.c
+++ b/arch/mips/ath79/mach-ap81.c
@@ -10,6 +10,7 @@
  */
 
 #include "machtypes.h"
+#include "dev-ar913x-wmac.h"
 #include "dev-gpio-buttons.h"
 #include "dev-leds-gpio.h"
 #include "dev-spi.h"
@@ -26,6 +27,8 @@
 #define AP81_KEYS_POLL_INTERVAL		20	/* msecs */
 #define AP81_KEYS_DEBOUNCE_INTERVAL	(3 * AP81_KEYS_POLL_INTERVAL)
 
+#define AP81_CAL_DATA_ADDR	0x1fff1000
+
 static struct gpio_led ap81_leds_gpio[] __initdata = {
 	{
 		.name		= "ap81:green:status",
@@ -80,6 +83,8 @@ static struct ath79_spi_platform_data ap81_spi_data = {
 
 static void __init ap81_setup(void)
 {
+	u8 *cal_data = (u8 *) KSEG1ADDR(AP81_CAL_DATA_ADDR);
+
 	ath79_register_leds_gpio(-1, ARRAY_SIZE(ap81_leds_gpio),
 				 ap81_leds_gpio);
 	ath79_register_gpio_keys_polled(-1, AP81_KEYS_POLL_INTERVAL,
@@ -88,6 +93,7 @@ static void __init ap81_setup(void)
 	ath79_register_spi(&ap81_spi_data, ap81_spi_info,
 			   ARRAY_SIZE(ap81_spi_info));
 	ath79_register_usb();
+	ath79_register_ar913x_wmac(cal_data);
 }
 
 MIPS_MACHINE(ATH79_MACH_AP81, "AP81", "Atheros AP81 reference board",
diff --git a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
index f125f1e..9beb073 100644
--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
+++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
@@ -43,6 +43,9 @@
 #define AR7240_OHCI_BASE	0x1b000000
 #define AR7240_OHCI_SIZE	0x1000
 
+#define AR913X_WMAC_BASE	(AR71XX_APB_BASE + 0x000C0000)
+#define AR913X_WMAC_SIZE	0x30000
+
 /*
  * DDR_CTRL block
  */
-- 
1.7.2.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [PATCH v2 11/16] USB: ehci: add workaround for Synopsys HC bug
  2010-12-22 20:30 ` [PATCH v2 11/16] USB: ehci: add workaround for Synopsys HC bug Gabor Juhos
@ 2010-12-23  0:30   ` Greg KH
  2010-12-23  8:29     ` Gabor Juhos
  0 siblings, 1 reply; 21+ messages in thread
From: Greg KH @ 2010-12-23  0:30 UTC (permalink / raw)
  To: Gabor Juhos
  Cc: Ralf Baechle, linux-mips, Imre Kaloz, Luis R. Rodriguez,
	Cliff Holden, Kathy Giori, David Brownell, linux-usb

On Wed, Dec 22, 2010 at 09:30:56PM +0100, Gabor Juhos wrote:
> A Synopsys USB core used in various SoCs has a bug which might cause
> that the host controller not issuing ping.
> 
> When software uses the Doorbell mechanism to remove queue heads, the
> host controller still has references to the removed queue head even
> after indicating an Interrupt on Async Advance. This happens if the last
> executed queue head's Next Link queue head is removed.
> 
> Consequences of the defect:
> The Host controller fetches the removed queue head, using memory that
> would otherwise be deallocated.This results in incorrect transactions on
> both the USB and system memory. This may result in undefined behavior.
> 
> Workarounds:
> 
> 1) If no queue head is active (no Status field's Active bit is set)
> after removing the queue heads, the software can write one of the valid
> queue head addresses to the ASYNCLISTADDR register and deallocate the
> removed queue head's memory after 2 microframes.
> 
> If one or more of the queue heads is active (the Active bit is set in
> the Status field) after removing the queue heads, the software can delay
> memory deallocation after time X, where X is the time required for the
> Host Controller to go through all the queue heads once. X varies with
> the number of queue heads and the time required to process periodic
> transactions: if more periodic transactions must be performed, the Host
> Controller has less time to process asynchronous transaction processing.
> 
> 2) Do not use the Doorbell mechanism to remove the queue heads. Disable
> the Asynchronous Schedule Enable bit instead.
> 
> The bug has been discussed on the linux-usb-devel mailing-list
> four years ago, the original thread can be found here:
> http://www.mail-archive.com/linux-usb-devel@lists.sourceforge.net/msg45345.html
> 
> This patch implements the first workaround as suggested by David Brownell.
> The built-in USB host controller of the Atheros AR7130/AR7141/AR7161 SoCs
> requires this to work properly.
> 
> Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
> Cc: David Brownell <dbrownell@users.sourceforge.net>
> Cc: Greg Kroah-Hartman <gregkh@suse.de>
> Cc: linux-usb@vger.kernel.org
> ---
> 
> Changes since RFC: ---
> 
> Changes since v1:
>     - rebased against 2.6.37-rc7
> 
>  drivers/usb/host/ehci-q.c |    3 +++
>  drivers/usb/host/ehci.h   |    1 +
>  2 files changed, 4 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
> index 233c288..343b8de 100644
> --- a/drivers/usb/host/ehci-q.c
> +++ b/drivers/usb/host/ehci-q.c
> @@ -1193,6 +1193,9 @@ static void end_unlink_async (struct ehci_hcd *ehci)
>  		ehci->reclaim = NULL;
>  		start_unlink_async (ehci, next);
>  	}
> +
> +	if (ehci->has_synopsys_hc_bug)
> +		writel((u32)ehci->async->qh_dma, &ehci->regs->async_next);
>  }
>  
>  /* makes sure the async qh will become idle */
> diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
> index ba8eab3..6da85b2 100644
> --- a/drivers/usb/host/ehci.h
> +++ b/drivers/usb/host/ehci.h
> @@ -133,6 +133,7 @@ struct ehci_hcd {			/* one per controller */
>  	unsigned		broken_periodic:1;
>  	unsigned		fs_i_thresh:1;	/* Intel iso scheduling */
>  	unsigned		use_dummy_qh:1;	/* AMD Frame List table quirk*/
> +	unsigned		has_synopsys_hc_bug:1; /* Synopsys HC */

That's fine, but who sets this value to 1?  I don't see any code that
does that, so why add this at all?  :)

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v2 11/16] USB: ehci: add workaround for Synopsys HC bug
  2010-12-23  0:30   ` Greg KH
@ 2010-12-23  8:29     ` Gabor Juhos
  0 siblings, 0 replies; 21+ messages in thread
From: Gabor Juhos @ 2010-12-23  8:29 UTC (permalink / raw)
  To: Greg KH
  Cc: Ralf Baechle, linux-mips, Imre Kaloz, Luis R. Rodriguez,
	Cliff Holden, Kathy Giori, David Brownell, linux-usb

Hi Greg,

<...>
>> diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
>> index 233c288..343b8de 100644
>> --- a/drivers/usb/host/ehci-q.c
>> +++ b/drivers/usb/host/ehci-q.c
>> @@ -1193,6 +1193,9 @@ static void end_unlink_async (struct ehci_hcd *ehci)
>>  		ehci->reclaim = NULL;
>>  		start_unlink_async (ehci, next);
>>  	}
>> +
>> +	if (ehci->has_synopsys_hc_bug)
>> +		writel((u32)ehci->async->qh_dma, &ehci->regs->async_next);
>>  }
>>  
>>  /* makes sure the async qh will become idle */
>> diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
>> index ba8eab3..6da85b2 100644
>> --- a/drivers/usb/host/ehci.h
>> +++ b/drivers/usb/host/ehci.h
>> @@ -133,6 +133,7 @@ struct ehci_hcd {			/* one per controller */
>>  	unsigned		broken_periodic:1;
>>  	unsigned		fs_i_thresh:1;	/* Intel iso scheduling */
>>  	unsigned		use_dummy_qh:1;	/* AMD Frame List table quirk*/
>> +	unsigned		has_synopsys_hc_bug:1; /* Synopsys HC */
> 
> That's fine, but who sets this value to 1?  I don't see any code that
> does that, so why add this at all?  :)

It will be set to 1 by ehci_ath79_init which is in the next patch [1] of this
series.

-Gabor

1. http://marc.info/?l=linux-usb&m=129304988827418&w=2

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v2 07/16] MIPS: ath79: add common watchdog device
  2010-12-22 20:30 ` [PATCH v2 07/16] MIPS: ath79: add common watchdog device Gabor Juhos
@ 2010-12-23 10:41   ` Sergei Shtylyov
  0 siblings, 0 replies; 21+ messages in thread
From: Sergei Shtylyov @ 2010-12-23 10:41 UTC (permalink / raw)
  To: Gabor Juhos
  Cc: Ralf Baechle, linux-mips, Imre Kaloz, Luis R. Rodriguez,
	Cliff Holden, Kathy Giori

Hello.

On 22-12-2010 23:30, Gabor Juhos wrote:

> All supported SoCs have a built-in hardware watchdog driver. This patch
> registers a platform_device for that to make it usable.

> Signed-off-by: Gabor Juhos<juhosg@openwrt.org>
> Signed-off-by: Imre Kaloz<kaloz@openwrt.org>
[...]

> diff --git a/arch/mips/ath79/dev-common.h b/arch/mips/ath79/dev-common.h
> index 1cec894..65bf400 100644
> --- a/arch/mips/ath79/dev-common.h
> +++ b/arch/mips/ath79/dev-common.h
> @@ -13,5 +13,6 @@
>   #define _ATH79_DEV_COMMON_H
>
>  void ath79_register_uart(void) __init;
> +void ath79_register_wdt(void) __init;

    '__init' not needed with declarations.

WBR, Sergei

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2010-12-23 10:42 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-12-22 20:30 [PATCH v2 00/16] MIPS: initial support for the Atheros AR71XX/AR724X/AR913X SoCs Gabor Juhos
2010-12-22 20:30 ` [PATCH v2 01/16] MIPS: add initial support for the Atheros AR71XX/AR724X/AR931X SoCs Gabor Juhos
2010-12-22 20:30 ` [PATCH v2 02/16] MIPS: ath79: add GPIOLIB support Gabor Juhos
2010-12-22 20:30 ` [PATCH v2 03/16] MIPS: ath79: utilize the MIPS multi-machine support Gabor Juhos
2010-12-22 20:30 ` [PATCH v2 04/16] MIPS: ath79: add initial support for the Atheros PB44 reference board Gabor Juhos
2010-12-22 20:30 ` [PATCH v2 05/16] MIPS: ath79: add common GPIO LEDs device Gabor Juhos
2010-12-22 20:30 ` [PATCH v2 06/16] watchdog: add driver for the Atheros AR71XX/AR724X/AR913X SoCs Gabor Juhos
2010-12-22 20:30 ` [PATCH v2 07/16] MIPS: ath79: add common watchdog device Gabor Juhos
2010-12-23 10:41   ` Sergei Shtylyov
2010-12-22 20:30 ` [PATCH v2 08/16] MIPS: ath79: add common GPIO buttons device Gabor Juhos
2010-12-22 20:30 ` [PATCH v2 09/16] spi: add SPI controller driver for the Atheros AR71XX/AR724X/AR913X SoCs Gabor Juhos
2010-12-22 20:30   ` Gabor Juhos
2010-12-22 20:30 ` [PATCH v2 10/16] MIPS: ath79: add common SPI controller device Gabor Juhos
2010-12-22 20:30 ` [PATCH v2 11/16] USB: ehci: add workaround for Synopsys HC bug Gabor Juhos
2010-12-23  0:30   ` Greg KH
2010-12-23  8:29     ` Gabor Juhos
2010-12-22 20:30 ` [PATCH v2 12/16] USB: ehci: add bus glue for the Atheros AR71XX/AR724X/AR913X SoCs Gabor Juhos
2010-12-22 20:30 ` [PATCH v2 13/16] USB: ohci: add bus glue for the Atheros AR71XX/AR7240 SoCs Gabor Juhos
2010-12-22 20:30 ` [PATCH v2 14/16] MIPS: ath79: add common USB Host Controller device Gabor Juhos
2010-12-22 20:31 ` [PATCH v2 15/16] MIPS: ath79: add initial support for the Atheros AP81 reference board Gabor Juhos
2010-12-22 20:31 ` [PATCH v2 16/16] MIPS: ath79: add common WMAC device for AR913X based boards Gabor Juhos

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.