Discussion:
[PATCH v2 00/13] MIPS: support for the Atheros AR231X SoCs
Sergey Ryazanov
2014-10-21 23:03:38 UTC
Permalink
This patch set contains initial support for the following Atheros SoCs: AR5312,
AR2312, AR2313, AR2315, AR2316, AR2317, AR2318.

- Patches 1 through 10 and patch 13 add support for different parts of AR231x
SoCs.
- Patch 11 recover ath5k AHB bus support
- Patch 12 updates ath5k dependecies

The code was successfully tested with AR2313, AR2315 and AR2317 SoCs.

This code has been written by OpenWRT developers and it resided in OpenWRT's
tree for a long time. My work was to cleanup the code and its rebase on the
latest linux-mips tree.

Changes since RFC:
- use dynamic IRQ numbers allocation
- group ath5 related changes in one patch
- group devices registration in separate patch

Changes since v1:
- rename MIPS machine ar231x -> ath25
- drop the GPIO and Watchdog drivers, since they need more work
- add patch which recover ath5k AHB bus support
- rebased on top of 3.18-rc1

Sergey Ryazanov (13):
MIPS: ath25: add common parts
MIPS: ath25: add basic AR5312 SoC support
MIPS: ath25: add basic AR2315 SoC support
MIPS: ath25: add interrupts handling routines
MIPS: ath25: add early printk support
MIPS: ath25: add UART support
MIPS: ath25: add board configuration detection
MIPS: ath25: add SoC type detection
MIPS: ath25: register various chip devices
MIPS: ath25: add AR2315 PCI host controller driver
ath5k: revert AHB bus support removing
ath5k: update dependencies
MIPS: ath25: add Wireless device support

arch/mips/Kbuild.platforms | 1 +
arch/mips/Kconfig | 15 +
arch/mips/ath25/Kconfig | 18 +
arch/mips/ath25/Makefile | 16 +
arch/mips/ath25/Platform | 6 +
arch/mips/ath25/ar2315.c | 367 +++++++++++++
arch/mips/ath25/ar2315.h | 24 +
arch/mips/ath25/ar5312.c | 374 +++++++++++++
arch/mips/ath25/ar5312.h | 24 +
arch/mips/ath25/board.c | 228 ++++++++
arch/mips/ath25/devices.c | 125 +++++
arch/mips/ath25/devices.h | 39 ++
arch/mips/ath25/early_printk.c | 45 ++
arch/mips/ath25/prom.c | 34 ++
arch/mips/include/asm/mach-ath25/ar2315_regs.h | 580 +++++++++++++++++++++
arch/mips/include/asm/mach-ath25/ar5312_regs.h | 215 ++++++++
arch/mips/include/asm/mach-ath25/ath25.h | 31 ++
arch/mips/include/asm/mach-ath25/ath25_platform.h | 73 +++
.../include/asm/mach-ath25/cpu-feature-overrides.h | 84 +++
arch/mips/include/asm/mach-ath25/dma-coherence.h | 76 +++
arch/mips/include/asm/mach-ath25/gpio.h | 16 +
arch/mips/include/asm/mach-ath25/war.h | 25 +
arch/mips/pci/Makefile | 1 +
arch/mips/pci/pci-ar2315.c | 352 +++++++++++++
drivers/net/wireless/ath/ath5k/Kconfig | 14 +-
drivers/net/wireless/ath/ath5k/Makefile | 1 +
drivers/net/wireless/ath/ath5k/ahb.c | 234 +++++++++
drivers/net/wireless/ath/ath5k/ath5k.h | 28 +
drivers/net/wireless/ath/ath5k/base.c | 14 +
drivers/net/wireless/ath/ath5k/led.c | 6 +
30 files changed, 3063 insertions(+), 3 deletions(-)
create mode 100644 arch/mips/ath25/Kconfig
create mode 100644 arch/mips/ath25/Makefile
create mode 100644 arch/mips/ath25/Platform
create mode 100644 arch/mips/ath25/ar2315.c
create mode 100644 arch/mips/ath25/ar2315.h
create mode 100644 arch/mips/ath25/ar5312.c
create mode 100644 arch/mips/ath25/ar5312.h
create mode 100644 arch/mips/ath25/board.c
create mode 100644 arch/mips/ath25/devices.c
create mode 100644 arch/mips/ath25/devices.h
create mode 100644 arch/mips/ath25/early_printk.c
create mode 100644 arch/mips/ath25/prom.c
create mode 100644 arch/mips/include/asm/mach-ath25/ar2315_regs.h
create mode 100644 arch/mips/include/asm/mach-ath25/ar5312_regs.h
create mode 100644 arch/mips/include/asm/mach-ath25/ath25.h
create mode 100644 arch/mips/include/asm/mach-ath25/ath25_platform.h
create mode 100644 arch/mips/include/asm/mach-ath25/cpu-feature-overrides.h
create mode 100644 arch/mips/include/asm/mach-ath25/dma-coherence.h
create mode 100644 arch/mips/include/asm/mach-ath25/gpio.h
create mode 100644 arch/mips/include/asm/mach-ath25/war.h
create mode 100644 arch/mips/pci/pci-ar2315.c
create mode 100644 drivers/net/wireless/ath/ath5k/ahb.c
--
1.8.5.5
Sergey Ryazanov
2014-10-21 23:03:50 UTC
Permalink
- Use config symbol defined in the driver instead of arch specific one for
conditional compilation.
- Rename the ATHEROS_AR231X config symbol to ATH25.
- Fix include (ar231x_platform.h -> ath25_platform.h).
- Some of AR231x SoCs (e.g. AR2315) have PCI bus support, so remove !PCI
dependency, which block AHB support build.

Signed-off-by: Sergey Ryazanov <ryazanov.s.a-***@public.gmane.org>
Cc: Jiri Slaby <jirislaby-***@public.gmane.org>
Cc: Nick Kossifidis <mickflemm-***@public.gmane.org>
Cc: "Luis R. Rodriguez" <mcgrof-***@public.gmane.org>
Cc: linux-wireless-***@public.gmane.org
Cc: ath5k-devel-***@public.gmane.org
---

Changes since RFC:
- merge together patches that update ath5k dependencies

Changes since v1:
- rename config symbol AR231X -> ATH25
- rename arch header ar231x_platform.h -> ath25_platform.h

drivers/net/wireless/ath/ath5k/Kconfig | 10 +++++-----
drivers/net/wireless/ath/ath5k/ahb.c | 2 +-
drivers/net/wireless/ath/ath5k/ath5k.h | 2 +-
drivers/net/wireless/ath/ath5k/base.c | 4 ++--
drivers/net/wireless/ath/ath5k/led.c | 4 ++--
5 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/net/wireless/ath/ath5k/Kconfig b/drivers/net/wireless/ath/ath5k/Kconfig
index c9f81a3..2399a39 100644
--- a/drivers/net/wireless/ath/ath5k/Kconfig
+++ b/drivers/net/wireless/ath/ath5k/Kconfig
@@ -1,13 +1,13 @@
config ATH5K
tristate "Atheros 5xxx wireless cards support"
- depends on (PCI || ATHEROS_AR231X) && MAC80211
+ depends on (PCI || ATH25) && MAC80211
select ATH_COMMON
select MAC80211_LEDS
select LEDS_CLASS
select NEW_LEDS
select AVERAGE
- select ATH5K_AHB if (ATHEROS_AR231X && !PCI)
- select ATH5K_PCI if (!ATHEROS_AR231X && PCI)
+ select ATH5K_AHB if ATH25
+ select ATH5K_PCI if !ATH25
---help---
This module adds support for wireless adapters based on
Atheros 5xxx chipset.
@@ -54,14 +54,14 @@ config ATH5K_TRACER

config ATH5K_AHB
bool "Atheros 5xxx AHB bus support"
- depends on (ATHEROS_AR231X && !PCI)
+ depends on ATH25
---help---
This adds support for WiSoC type chipsets of the 5xxx Atheros
family.

config ATH5K_PCI
bool "Atheros 5xxx PCI bus support"
- depends on (!ATHEROS_AR231X && PCI)
+ depends on (!ATH25 && PCI)
---help---
This adds support for PCI type chipsets of the 5xxx Atheros
family.
diff --git a/drivers/net/wireless/ath/ath5k/ahb.c b/drivers/net/wireless/ath/ath5k/ahb.c
index 79bffe1..8f387cf 100644
--- a/drivers/net/wireless/ath/ath5k/ahb.c
+++ b/drivers/net/wireless/ath/ath5k/ahb.c
@@ -20,7 +20,7 @@
#include <linux/platform_device.h>
#include <linux/etherdevice.h>
#include <linux/export.h>
-#include <ar231x_platform.h>
+#include <ath25_platform.h>
#include "ath5k.h"
#include "debug.h"
#include "base.h"
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
index 85316bb..1ed7a88 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -1647,7 +1647,7 @@ static inline struct ath_regulatory *ath5k_hw_regulatory(struct ath5k_hw *ah)
return &(ath5k_hw_common(ah)->regulatory);
}

-#ifdef CONFIG_ATHEROS_AR231X
+#ifdef CONFIG_ATH5K_AHB
#define AR5K_AR2315_PCI_BASE ((void __iomem *)0xb0100000)

static inline void __iomem *ath5k_ahb_reg(struct ath5k_hw *ah, u16 reg)
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 59a8724..bc9cb35 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -99,7 +99,7 @@ static int ath5k_reset(struct ath5k_hw *ah, struct ieee80211_channel *chan,

/* Known SREVs */
static const struct ath5k_srev_name srev_names[] = {
-#ifdef CONFIG_ATHEROS_AR231X
+#ifdef CONFIG_ATH5K_AHB
{ "5312", AR5K_VERSION_MAC, AR5K_SREV_AR5312_R2 },
{ "5312", AR5K_VERSION_MAC, AR5K_SREV_AR5312_R7 },
{ "2313", AR5K_VERSION_MAC, AR5K_SREV_AR2313_R8 },
@@ -142,7 +142,7 @@ static const struct ath5k_srev_name srev_names[] = {
{ "5413", AR5K_VERSION_RAD, AR5K_SREV_RAD_5413 },
{ "5424", AR5K_VERSION_RAD, AR5K_SREV_RAD_5424 },
{ "5133", AR5K_VERSION_RAD, AR5K_SREV_RAD_5133 },
-#ifdef CONFIG_ATHEROS_AR231X
+#ifdef CONFIG_ATH5K_AHB
{ "2316", AR5K_VERSION_RAD, AR5K_SREV_RAD_2316 },
{ "2317", AR5K_VERSION_RAD, AR5K_SREV_RAD_2317 },
#endif
diff --git a/drivers/net/wireless/ath/ath5k/led.c b/drivers/net/wireless/ath/ath5k/led.c
index 2062d11..ca4b7cc 100644
--- a/drivers/net/wireless/ath/ath5k/led.c
+++ b/drivers/net/wireless/ath/ath5k/led.c
@@ -163,7 +163,7 @@ int ath5k_init_leds(struct ath5k_hw *ah)
{
int ret = 0;
struct ieee80211_hw *hw = ah->hw;
-#ifndef CONFIG_ATHEROS_AR231X
+#ifndef CONFIG_ATH5K_AHB
struct pci_dev *pdev = ah->pdev;
#endif
char name[ATH5K_LED_MAX_NAME_LEN + 1];
@@ -172,7 +172,7 @@ int ath5k_init_leds(struct ath5k_hw *ah)
if (!ah->pdev)
return 0;

-#ifdef CONFIG_ATHEROS_AR231X
+#ifdef CONFIG_ATH5K_AHB
match = NULL;
#else
match = pci_match_id(&ath5k_led_devices[0], pdev);
--
1.8.5.5

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-***@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Sergey Ryazanov
2014-10-21 23:03:49 UTC
Permalink
This reverts commit 093ec3c5337434f40d77c1af06c139da3e5ba6dc.

AHB bus code has been removed, since we did not have support Atheros
AR231x SoC, required for building the AHB version of ath5k. Now that
support WiSoC chips added we can restore functionality back.

Singed-off-by: Sergey Ryazanov <ryazanov.s.a-***@public.gmane.org>
Cc: Jiri Slaby <jirislaby-***@public.gmane.org>
Cc: Nick Kossifidis <mickflemm-***@public.gmane.org>
Cc: "Luis R. Rodriguez" <mcgrof-***@public.gmane.org>
Cc: linux-wireless-***@public.gmane.org
Cc: ath5k-devel-***@public.gmane.org
---
drivers/net/wireless/ath/ath5k/Kconfig | 14 +-
drivers/net/wireless/ath/ath5k/Makefile | 1 +
drivers/net/wireless/ath/ath5k/ahb.c | 234 ++++++++++++++++++++++++++++++++
drivers/net/wireless/ath/ath5k/ath5k.h | 28 ++++
drivers/net/wireless/ath/ath5k/base.c | 14 ++
drivers/net/wireless/ath/ath5k/led.c | 6 +
6 files changed, 294 insertions(+), 3 deletions(-)
create mode 100644 drivers/net/wireless/ath/ath5k/ahb.c

diff --git a/drivers/net/wireless/ath/ath5k/Kconfig b/drivers/net/wireless/ath/ath5k/Kconfig
index 93caf8e68..c9f81a3 100644
--- a/drivers/net/wireless/ath/ath5k/Kconfig
+++ b/drivers/net/wireless/ath/ath5k/Kconfig
@@ -1,12 +1,13 @@
config ATH5K
tristate "Atheros 5xxx wireless cards support"
- depends on PCI && MAC80211
+ depends on (PCI || ATHEROS_AR231X) && MAC80211
select ATH_COMMON
select MAC80211_LEDS
select LEDS_CLASS
select NEW_LEDS
select AVERAGE
- select ATH5K_PCI
+ select ATH5K_AHB if (ATHEROS_AR231X && !PCI)
+ select ATH5K_PCI if (!ATHEROS_AR231X && PCI)
---help---
This module adds support for wireless adapters based on
Atheros 5xxx chipset.
@@ -51,9 +52,16 @@ config ATH5K_TRACER

If unsure, say N.

+config ATH5K_AHB
+ bool "Atheros 5xxx AHB bus support"
+ depends on (ATHEROS_AR231X && !PCI)
+ ---help---
+ This adds support for WiSoC type chipsets of the 5xxx Atheros
+ family.
+
config ATH5K_PCI
bool "Atheros 5xxx PCI bus support"
- depends on PCI
+ depends on (!ATHEROS_AR231X && PCI)
---help---
This adds support for PCI type chipsets of the 5xxx Atheros
family.
diff --git a/drivers/net/wireless/ath/ath5k/Makefile b/drivers/net/wireless/ath/ath5k/Makefile
index 51e2d86..1b3a34f 100644
--- a/drivers/net/wireless/ath/ath5k/Makefile
+++ b/drivers/net/wireless/ath/ath5k/Makefile
@@ -17,5 +17,6 @@ ath5k-y += ani.o
ath5k-y += sysfs.o
ath5k-y += mac80211-ops.o
ath5k-$(CONFIG_ATH5K_DEBUG) += debug.o
+ath5k-$(CONFIG_ATH5K_AHB) += ahb.o
ath5k-$(CONFIG_ATH5K_PCI) += pci.o
obj-$(CONFIG_ATH5K) += ath5k.o
diff --git a/drivers/net/wireless/ath/ath5k/ahb.c b/drivers/net/wireless/ath/ath5k/ahb.c
new file mode 100644
index 0000000..79bffe1
--- /dev/null
+++ b/drivers/net/wireless/ath/ath5k/ahb.c
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ * Copyright (c) 2009 Gabor Juhos <juhosg-***@public.gmane.org>
+ * Copyright (c) 2009 Imre Kaloz <kaloz-***@public.gmane.org>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/nl80211.h>
+#include <linux/platform_device.h>
+#include <linux/etherdevice.h>
+#include <linux/export.h>
+#include <ar231x_platform.h>
+#include "ath5k.h"
+#include "debug.h"
+#include "base.h"
+#include "reg.h"
+
+/* return bus cachesize in 4B word units */
+static void ath5k_ahb_read_cachesize(struct ath_common *common, int *csz)
+{
+ *csz = L1_CACHE_BYTES >> 2;
+}
+
+static bool
+ath5k_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
+{
+ struct ath5k_hw *ah = common->priv;
+ struct platform_device *pdev = to_platform_device(ah->dev);
+ struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
+ u16 *eeprom, *eeprom_end;
+
+ eeprom = (u16 *) bcfg->radio;
+ eeprom_end = ((void *) bcfg->config) + BOARD_CONFIG_BUFSZ;
+
+ eeprom += off;
+ if (eeprom > eeprom_end)
+ return false;
+
+ *data = *eeprom;
+ return true;
+}
+
+int ath5k_hw_read_srev(struct ath5k_hw *ah)
+{
+ struct platform_device *pdev = to_platform_device(ah->dev);
+ struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
+ ah->ah_mac_srev = bcfg->devid;
+ return 0;
+}
+
+static int ath5k_ahb_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
+{
+ struct platform_device *pdev = to_platform_device(ah->dev);
+ struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
+ u8 *cfg_mac;
+
+ if (to_platform_device(ah->dev)->id == 0)
+ cfg_mac = bcfg->config->wlan0_mac;
+ else
+ cfg_mac = bcfg->config->wlan1_mac;
+
+ memcpy(mac, cfg_mac, ETH_ALEN);
+ return 0;
+}
+
+static const struct ath_bus_ops ath_ahb_bus_ops = {
+ .ath_bus_type = ATH_AHB,
+ .read_cachesize = ath5k_ahb_read_cachesize,
+ .eeprom_read = ath5k_ahb_eeprom_read,
+ .eeprom_read_mac = ath5k_ahb_eeprom_read_mac,
+};
+
+/*Initialization*/
+static int ath_ahb_probe(struct platform_device *pdev)
+{
+ struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
+ struct ath5k_hw *ah;
+ struct ieee80211_hw *hw;
+ struct resource *res;
+ void __iomem *mem;
+ int irq;
+ int ret = 0;
+ u32 reg;
+
+ if (!dev_get_platdata(&pdev->dev)) {
+ dev_err(&pdev->dev, "no platform data specified\n");
+ ret = -EINVAL;
+ goto err_out;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res == NULL) {
+ dev_err(&pdev->dev, "no memory resource found\n");
+ ret = -ENXIO;
+ goto err_out;
+ }
+
+ mem = ioremap_nocache(res->start, resource_size(res));
+ if (mem == NULL) {
+ dev_err(&pdev->dev, "ioremap failed\n");
+ ret = -ENOMEM;
+ goto err_out;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (res == NULL) {
+ dev_err(&pdev->dev, "no IRQ resource found\n");
+ ret = -ENXIO;
+ goto err_iounmap;
+ }
+
+ irq = res->start;
+
+ hw = ieee80211_alloc_hw(sizeof(struct ath5k_hw), &ath5k_hw_ops);
+ if (hw == NULL) {
+ dev_err(&pdev->dev, "no memory for ieee80211_hw\n");
+ ret = -ENOMEM;
+ goto err_iounmap;
+ }
+
+ ah = hw->priv;
+ ah->hw = hw;
+ ah->dev = &pdev->dev;
+ ah->iobase = mem;
+ ah->irq = irq;
+ ah->devid = bcfg->devid;
+
+ if (bcfg->devid >= AR5K_SREV_AR2315_R6) {
+ /* Enable WMAC AHB arbitration */
+ reg = ioread32((void __iomem *) AR5K_AR2315_AHB_ARB_CTL);
+ reg |= AR5K_AR2315_AHB_ARB_CTL_WLAN;
+ iowrite32(reg, (void __iomem *) AR5K_AR2315_AHB_ARB_CTL);
+
+ /* Enable global WMAC swapping */
+ reg = ioread32((void __iomem *) AR5K_AR2315_BYTESWAP);
+ reg |= AR5K_AR2315_BYTESWAP_WMAC;
+ iowrite32(reg, (void __iomem *) AR5K_AR2315_BYTESWAP);
+ } else {
+ /* Enable WMAC DMA access (assuming 5312 or 231x*/
+ /* TODO: check other platforms */
+ reg = ioread32((void __iomem *) AR5K_AR5312_ENABLE);
+ if (to_platform_device(ah->dev)->id == 0)
+ reg |= AR5K_AR5312_ENABLE_WLAN0;
+ else
+ reg |= AR5K_AR5312_ENABLE_WLAN1;
+ iowrite32(reg, (void __iomem *) AR5K_AR5312_ENABLE);
+
+ /*
+ * On a dual-band AR5312, the multiband radio is only
+ * used as pass-through. Disable 2 GHz support in the
+ * driver for it
+ */
+ if (to_platform_device(ah->dev)->id == 0 &&
+ (bcfg->config->flags & (BD_WLAN0 | BD_WLAN1)) ==
+ (BD_WLAN1 | BD_WLAN0))
+ ah->ah_capabilities.cap_needs_2GHz_ovr = true;
+ else
+ ah->ah_capabilities.cap_needs_2GHz_ovr = false;
+ }
+
+ ret = ath5k_init_ah(ah, &ath_ahb_bus_ops);
+ if (ret != 0) {
+ dev_err(&pdev->dev, "failed to attach device, err=%d\n", ret);
+ ret = -ENODEV;
+ goto err_free_hw;
+ }
+
+ platform_set_drvdata(pdev, hw);
+
+ return 0;
+
+ err_free_hw:
+ ieee80211_free_hw(hw);
+ err_iounmap:
+ iounmap(mem);
+ err_out:
+ return ret;
+}
+
+static int ath_ahb_remove(struct platform_device *pdev)
+{
+ struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
+ struct ieee80211_hw *hw = platform_get_drvdata(pdev);
+ struct ath5k_hw *ah;
+ u32 reg;
+
+ if (!hw)
+ return 0;
+
+ ah = hw->priv;
+
+ if (bcfg->devid >= AR5K_SREV_AR2315_R6) {
+ /* Disable WMAC AHB arbitration */
+ reg = ioread32((void __iomem *) AR5K_AR2315_AHB_ARB_CTL);
+ reg &= ~AR5K_AR2315_AHB_ARB_CTL_WLAN;
+ iowrite32(reg, (void __iomem *) AR5K_AR2315_AHB_ARB_CTL);
+ } else {
+ /*Stop DMA access */
+ reg = ioread32((void __iomem *) AR5K_AR5312_ENABLE);
+ if (to_platform_device(ah->dev)->id == 0)
+ reg &= ~AR5K_AR5312_ENABLE_WLAN0;
+ else
+ reg &= ~AR5K_AR5312_ENABLE_WLAN1;
+ iowrite32(reg, (void __iomem *) AR5K_AR5312_ENABLE);
+ }
+
+ ath5k_deinit_ah(ah);
+ iounmap(ah->iobase);
+ ieee80211_free_hw(hw);
+
+ return 0;
+}
+
+static struct platform_driver ath_ahb_driver = {
+ .probe = ath_ahb_probe,
+ .remove = ath_ahb_remove,
+ .driver = {
+ .name = "ar231x-wmac",
+ .owner = THIS_MODULE,
+ },
+};
+
+module_platform_driver(ath_ahb_driver);
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
index ed24682..85316bb 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -1647,6 +1647,32 @@ static inline struct ath_regulatory *ath5k_hw_regulatory(struct ath5k_hw *ah)
return &(ath5k_hw_common(ah)->regulatory);
}

+#ifdef CONFIG_ATHEROS_AR231X
+#define AR5K_AR2315_PCI_BASE ((void __iomem *)0xb0100000)
+
+static inline void __iomem *ath5k_ahb_reg(struct ath5k_hw *ah, u16 reg)
+{
+ /* On AR2315 and AR2317 the PCI clock domain registers
+ * are outside of the WMAC register space */
+ if (unlikely((reg >= 0x4000) && (reg < 0x5000) &&
+ (ah->ah_mac_srev >= AR5K_SREV_AR2315_R6)))
+ return AR5K_AR2315_PCI_BASE + reg;
+
+ return ah->iobase + reg;
+}
+
+static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg)
+{
+ return ioread32(ath5k_ahb_reg(ah, reg));
+}
+
+static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg)
+{
+ iowrite32(val, ath5k_ahb_reg(ah, reg));
+}
+
+#else
+
static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg)
{
return ioread32(ah->iobase + reg);
@@ -1657,6 +1683,8 @@ static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg)
iowrite32(val, ah->iobase + reg);
}

+#endif
+
static inline enum ath_bus_type ath5k_get_bus_type(struct ath5k_hw *ah)
{
return ath5k_hw_common(ah)->bus_ops->ath_bus_type;
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index a4a09bb..59a8724 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -99,6 +99,15 @@ static int ath5k_reset(struct ath5k_hw *ah, struct ieee80211_channel *chan,

/* Known SREVs */
static const struct ath5k_srev_name srev_names[] = {
+#ifdef CONFIG_ATHEROS_AR231X
+ { "5312", AR5K_VERSION_MAC, AR5K_SREV_AR5312_R2 },
+ { "5312", AR5K_VERSION_MAC, AR5K_SREV_AR5312_R7 },
+ { "2313", AR5K_VERSION_MAC, AR5K_SREV_AR2313_R8 },
+ { "2315", AR5K_VERSION_MAC, AR5K_SREV_AR2315_R6 },
+ { "2315", AR5K_VERSION_MAC, AR5K_SREV_AR2315_R7 },
+ { "2317", AR5K_VERSION_MAC, AR5K_SREV_AR2317_R1 },
+ { "2317", AR5K_VERSION_MAC, AR5K_SREV_AR2317_R2 },
+#else
{ "5210", AR5K_VERSION_MAC, AR5K_SREV_AR5210 },
{ "5311", AR5K_VERSION_MAC, AR5K_SREV_AR5311 },
{ "5311A", AR5K_VERSION_MAC, AR5K_SREV_AR5311A },
@@ -117,6 +126,7 @@ static const struct ath5k_srev_name srev_names[] = {
{ "5418", AR5K_VERSION_MAC, AR5K_SREV_AR5418 },
{ "2425", AR5K_VERSION_MAC, AR5K_SREV_AR2425 },
{ "2417", AR5K_VERSION_MAC, AR5K_SREV_AR2417 },
+#endif
{ "xxxxx", AR5K_VERSION_MAC, AR5K_SREV_UNKNOWN },
{ "5110", AR5K_VERSION_RAD, AR5K_SREV_RAD_5110 },
{ "5111", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111 },
@@ -132,6 +142,10 @@ static const struct ath5k_srev_name srev_names[] = {
{ "5413", AR5K_VERSION_RAD, AR5K_SREV_RAD_5413 },
{ "5424", AR5K_VERSION_RAD, AR5K_SREV_RAD_5424 },
{ "5133", AR5K_VERSION_RAD, AR5K_SREV_RAD_5133 },
+#ifdef CONFIG_ATHEROS_AR231X
+ { "2316", AR5K_VERSION_RAD, AR5K_SREV_RAD_2316 },
+ { "2317", AR5K_VERSION_RAD, AR5K_SREV_RAD_2317 },
+#endif
{ "xxxxx", AR5K_VERSION_RAD, AR5K_SREV_UNKNOWN },
};

diff --git a/drivers/net/wireless/ath/ath5k/led.c b/drivers/net/wireless/ath/ath5k/led.c
index 0beb7e7..2062d11 100644
--- a/drivers/net/wireless/ath/ath5k/led.c
+++ b/drivers/net/wireless/ath/ath5k/led.c
@@ -163,14 +163,20 @@ int ath5k_init_leds(struct ath5k_hw *ah)
{
int ret = 0;
struct ieee80211_hw *hw = ah->hw;
+#ifndef CONFIG_ATHEROS_AR231X
struct pci_dev *pdev = ah->pdev;
+#endif
char name[ATH5K_LED_MAX_NAME_LEN + 1];
const struct pci_device_id *match;

if (!ah->pdev)
return 0;

+#ifdef CONFIG_ATHEROS_AR231X
+ match = NULL;
+#else
match = pci_match_id(&ath5k_led_devices[0], pdev);
+#endif
if (match) {
__set_bit(ATH_STAT_LEDSOFT, ah->status);
ah->led_pin = ATH_PIN(match->driver_data);
--
1.8.5.5

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-***@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Bob Copeland
2014-10-22 12:18:24 UTC
Permalink
Post by Sergey Ryazanov
This reverts commit 093ec3c5337434f40d77c1af06c139da3e5ba6dc.
AHB bus code has been removed, since we did not have support Atheros
AR231x SoC, required for building the AHB version of ath5k. Now that
support WiSoC chips added we can restore functionality back.
^^^^^^

Please keep the patches away from the stove! (SCNR)
--
Bob Copeland %% www.bobcopeland.com
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-***@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Sergey Ryazanov
2014-10-22 12:37:46 UTC
Permalink
Post by Bob Copeland
Post by Sergey Ryazanov
This reverts commit 093ec3c5337434f40d77c1af06c139da3e5ba6dc.
AHB bus code has been removed, since we did not have support Atheros
AR231x SoC, required for building the AHB version of ath5k. Now that
support WiSoC chips added we can restore functionality back.
^^^^^^
Please keep the patches away from the stove! (SCNR)
I will send the healthy patch in v3!
--
BR,
Sergey
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-***@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Sergey Ryazanov
2014-10-21 23:03:39 UTC
Permalink
Add common code for Atheros AR5312 and Atheros AR2315 SoCs families.

Signed-off-by: Sergey Ryazanov <***@gmail.com>
---

Changes since v1:
- rename MIPS machine ar231x -> ath25

arch/mips/Kbuild.platforms | 1 +
arch/mips/Kconfig | 13 ++++
arch/mips/ath25/Makefile | 11 ++++
arch/mips/ath25/Platform | 6 ++
arch/mips/ath25/board.c | 53 +++++++++++++++
arch/mips/ath25/devices.c | 11 ++++
arch/mips/ath25/devices.h | 16 +++++
arch/mips/ath25/prom.c | 26 ++++++++
arch/mips/include/asm/mach-ath25/ath25.h | 29 +++++++++
.../include/asm/mach-ath25/cpu-feature-overrides.h | 76 ++++++++++++++++++++++
arch/mips/include/asm/mach-ath25/dma-coherence.h | 64 ++++++++++++++++++
arch/mips/include/asm/mach-ath25/gpio.h | 16 +++++
arch/mips/include/asm/mach-ath25/war.h | 25 +++++++
13 files changed, 347 insertions(+)
create mode 100644 arch/mips/ath25/Makefile
create mode 100644 arch/mips/ath25/Platform
create mode 100644 arch/mips/ath25/board.c
create mode 100644 arch/mips/ath25/devices.c
create mode 100644 arch/mips/ath25/devices.h
create mode 100644 arch/mips/ath25/prom.c
create mode 100644 arch/mips/include/asm/mach-ath25/ath25.h
create mode 100644 arch/mips/include/asm/mach-ath25/cpu-feature-overrides.h
create mode 100644 arch/mips/include/asm/mach-ath25/dma-coherence.h
create mode 100644 arch/mips/include/asm/mach-ath25/gpio.h
create mode 100644 arch/mips/include/asm/mach-ath25/war.h

diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms
index f5e18bf..1780c74 100644
--- a/arch/mips/Kbuild.platforms
+++ b/arch/mips/Kbuild.platforms
@@ -2,6 +2,7 @@

platforms += alchemy
platforms += ar7
+platforms += ath25
platforms += ath79
platforms += bcm47xx
platforms += bcm63xx
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 652bd79..54abb9a 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -96,6 +96,19 @@ config AR7
Support for the Texas Instruments AR7 System-on-a-Chip
family: TNETD7100, 7200 and 7300.

+config ATH25
+ bool "Atheros AR231x/AR531x SoC support"
+ select CEVT_R4K
+ select CSRC_R4K
+ select DMA_NONCOHERENT
+ select IRQ_CPU
+ select SYS_HAS_CPU_MIPS32_R1
+ select SYS_SUPPORTS_BIG_ENDIAN
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select ARCH_REQUIRE_GPIOLIB
+ help
+ Support for Atheros AR231x and Atheros AR531x based boards
+
config ATH79
bool "Atheros AR71XX/AR724X/AR913X based boards"
select ARCH_REQUIRE_GPIOLIB
diff --git a/arch/mips/ath25/Makefile b/arch/mips/ath25/Makefile
new file mode 100644
index 0000000..9199fa1
--- /dev/null
+++ b/arch/mips/ath25/Makefile
@@ -0,0 +1,11 @@
+#
+# 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) 2006 FON Technology, SL.
+# Copyright (C) 2006 Imre Kaloz <***@openwrt.org>
+# Copyright (C) 2006-2009 Felix Fietkau <***@openwrt.org>
+#
+
+obj-y += board.o prom.o devices.o
diff --git a/arch/mips/ath25/Platform b/arch/mips/ath25/Platform
new file mode 100644
index 0000000..ef3f81f
--- /dev/null
+++ b/arch/mips/ath25/Platform
@@ -0,0 +1,6 @@
+#
+# Atheros AR531X/AR231X WiSoC
+#
+platform-$(CONFIG_ATH25) += ath25/
+cflags-$(CONFIG_ATH25) += -I$(srctree)/arch/mips/include/asm/mach-ath25
+load-$(CONFIG_ATH25) += 0xffffffff80041000
diff --git a/arch/mips/ath25/board.c b/arch/mips/ath25/board.c
new file mode 100644
index 0000000..cbc6d7b
--- /dev/null
+++ b/arch/mips/ath25/board.c
@@ -0,0 +1,53 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 Atheros Communications, Inc., All Rights Reserved.
+ * Copyright (C) 2006 FON Technology, SL.
+ * Copyright (C) 2006 Imre Kaloz <***@openwrt.org>
+ * Copyright (C) 2006-2009 Felix Fietkau <***@openwrt.org>
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <asm/irq_cpu.h>
+#include <asm/reboot.h>
+#include <asm/bootinfo.h>
+#include <asm/time.h>
+
+static void ath25_halt(void)
+{
+ local_irq_disable();
+ while (1)
+ ;
+}
+
+void __init plat_mem_setup(void)
+{
+ _machine_halt = ath25_halt;
+ pm_power_off = ath25_halt;
+
+ /* Disable data watchpoints */
+ write_c0_watchlo0(0);
+}
+
+asmlinkage void plat_irq_dispatch(void)
+{
+}
+
+void __init plat_time_init(void)
+{
+}
+
+unsigned int __cpuinit get_c0_compare_int(void)
+{
+ return CP0_LEGACY_COMPARE_IRQ;
+}
+
+void __init arch_init_irq(void)
+{
+ clear_c0_status(ST0_IM);
+ mips_cpu_irq_init();
+}
+
diff --git a/arch/mips/ath25/devices.c b/arch/mips/ath25/devices.c
new file mode 100644
index 0000000..e30afbc
--- /dev/null
+++ b/arch/mips/ath25/devices.c
@@ -0,0 +1,11 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <asm/bootinfo.h>
+
+#include "devices.h"
+
+const char *get_system_type(void)
+{
+ return "Atheros (unknown)";
+}
+
diff --git a/arch/mips/ath25/devices.h b/arch/mips/ath25/devices.h
new file mode 100644
index 0000000..edda636
--- /dev/null
+++ b/arch/mips/ath25/devices.h
@@ -0,0 +1,16 @@
+#ifndef __ATH25_DEVICES_H
+#define __ATH25_DEVICES_H
+
+#include <linux/cpu.h>
+
+static inline bool is_ar2315(void)
+{
+ return (current_cpu_data.cputype == CPU_4KEC);
+}
+
+static inline bool is_ar5312(void)
+{
+ return !is_ar2315();
+}
+
+#endif
diff --git a/arch/mips/ath25/prom.c b/arch/mips/ath25/prom.c
new file mode 100644
index 0000000..edf82be
--- /dev/null
+++ b/arch/mips/ath25/prom.c
@@ -0,0 +1,26 @@
+/*
+ * 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 MontaVista Software Inc
+ * Copyright (C) 2003 Atheros Communications, Inc., All Rights Reserved.
+ * Copyright (C) 2006 FON Technology, SL.
+ * Copyright (C) 2006 Imre Kaloz <***@openwrt.org>
+ * Copyright (C) 2006 Felix Fietkau <***@openwrt.org>
+ */
+
+/*
+ * Prom setup file for AR5312/AR231x SoCs
+ */
+
+#include <linux/init.h>
+#include <asm/bootinfo.h>
+
+void __init prom_init(void)
+{
+}
+
+void __init prom_free_prom_memory(void)
+{
+}
diff --git a/arch/mips/include/asm/mach-ath25/ath25.h b/arch/mips/include/asm/mach-ath25/ath25.h
new file mode 100644
index 0000000..bd66ce7
--- /dev/null
+++ b/arch/mips/include/asm/mach-ath25/ath25.h
@@ -0,0 +1,29 @@
+#ifndef __ASM_MACH_ATH25_H
+#define __ASM_MACH_ATH25_H
+
+#include <linux/io.h>
+
+#define ATH25_REG_MS(_val, _field) (((_val) & _field##_M) >> _field##_S)
+
+static inline u32 ath25_read_reg(u32 reg)
+{
+ return __raw_readl((void __iomem *)KSEG1ADDR(reg));
+}
+
+static inline void ath25_write_reg(u32 reg, u32 val)
+{
+ __raw_writel(val, (void __iomem *)KSEG1ADDR(reg));
+}
+
+static inline u32 ath25_mask_reg(u32 reg, u32 mask, u32 val)
+{
+ u32 ret = ath25_read_reg(reg);
+
+ ret &= ~mask;
+ ret |= val;
+ ath25_write_reg(reg, ret);
+
+ return ret;
+}
+
+#endif /* __ASM_MACH_ATH25_H */
diff --git a/arch/mips/include/asm/mach-ath25/cpu-feature-overrides.h b/arch/mips/include/asm/mach-ath25/cpu-feature-overrides.h
new file mode 100644
index 0000000..c1aebdc
--- /dev/null
+++ b/arch/mips/include/asm/mach-ath25/cpu-feature-overrides.h
@@ -0,0 +1,76 @@
+/*
+ * Atheros AR231x/AR531x SoC specific CPU feature overrides
+ *
+ * Copyright (C) 2008 Gabor Juhos <***@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_ATH25_CPU_FEATURE_OVERRIDES_H
+#define __ASM_MACH_ATH25_CPU_FEATURE_OVERRIDES_H
+
+/*
+ * The Atheros AR531x/AR231x SoCs have MIPS 4Kc/4KEc core.
+ */
+#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 ? */
+/* #define cpu_has_divec ? */
+/* #define cpu_has_vce ? */
+/* #define cpu_has_cache_cdex_p ? */
+/* #define cpu_has_cache_cdex_s ? */
+/* #define cpu_has_prefetch ? */
+/* #define cpu_has_mcheck ? */
+#define cpu_has_ejtag 1
+
+/*
+ * The MIPS 4Kc V0.9 core in the AR5312/AR2312 have problems with the
+ * ll/sc instructions.
+ */
+#define cpu_has_llsc 0
+
+#define cpu_has_mips16 0
+#define cpu_has_mdmx 0
+#define cpu_has_mips3d 0
+#define cpu_has_smartmips 0
+
+/* #define cpu_has_vtag_icache ? */
+/* #define cpu_has_dc_aliases ? */
+/* #define cpu_has_ic_fills_f_dc ? */
+/* #define cpu_has_pindexed_dcache ? */
+
+/* #define cpu_icache_snoops_remote_store ? */
+
+#define cpu_has_mips32r1 1
+
+#define cpu_has_mips64r1 0
+#define cpu_has_mips64r2 0
+
+#define cpu_has_dsp 0
+#define cpu_has_mipsmt 0
+
+/* #define cpu_has_nofpuex ? */
+#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_has_inclusive_pcaches ? */
+
+/* #define cpu_dcache_line_size() ? */
+/* #define cpu_icache_line_size() ? */
+
+#endif /* __ASM_MACH_ATH25_CPU_FEATURE_OVERRIDES_H */
diff --git a/arch/mips/include/asm/mach-ath25/dma-coherence.h b/arch/mips/include/asm/mach-ath25/dma-coherence.h
new file mode 100644
index 0000000..8b3d0cc
--- /dev/null
+++ b/arch/mips/include/asm/mach-ath25/dma-coherence.h
@@ -0,0 +1,64 @@
+/*
+ * 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) 2006 Ralf Baechle <***@linux-mips.org>
+ * Copyright (C) 2007 Felix Fietkau <***@openwrt.org>
+ *
+ */
+#ifndef __ASM_MACH_ATH25_DMA_COHERENCE_H
+#define __ASM_MACH_ATH25_DMA_COHERENCE_H
+
+#include <linux/device.h>
+
+static inline dma_addr_t
+plat_map_dma_mem(struct device *dev, void *addr, size_t size)
+{
+ return virt_to_phys(addr);
+}
+
+static inline dma_addr_t
+plat_map_dma_mem_page(struct device *dev, struct page *page)
+{
+ return page_to_phys(page);
+}
+
+static inline unsigned long
+plat_dma_addr_to_phys(struct device *dev, dma_addr_t dma_addr)
+{
+ return dma_addr;
+}
+
+static inline void
+plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr, size_t size,
+ enum dma_data_direction direction)
+{
+}
+
+static inline int plat_dma_supported(struct device *dev, u64 mask)
+{
+ return 1;
+}
+
+static inline void plat_extra_sync_for_device(struct device *dev)
+{
+}
+
+static inline int plat_dma_mapping_error(struct device *dev,
+ dma_addr_t dma_addr)
+{
+ return 0;
+}
+
+static inline int plat_device_is_coherent(struct device *dev)
+{
+#ifdef CONFIG_DMA_COHERENT
+ return 1;
+#endif
+#ifdef CONFIG_DMA_NONCOHERENT
+ return 0;
+#endif
+}
+
+#endif /* __ASM_MACH_ATH25_DMA_COHERENCE_H */
diff --git a/arch/mips/include/asm/mach-ath25/gpio.h b/arch/mips/include/asm/mach-ath25/gpio.h
new file mode 100644
index 0000000..713564b
--- /dev/null
+++ b/arch/mips/include/asm/mach-ath25/gpio.h
@@ -0,0 +1,16 @@
+#ifndef __ASM_MACH_ATH25_GPIO_H
+#define __ASM_MACH_ATH25_GPIO_H
+
+#include <asm-generic/gpio.h>
+
+#define gpio_get_value __gpio_get_value
+#define gpio_set_value __gpio_set_value
+#define gpio_cansleep __gpio_cansleep
+#define gpio_to_irq __gpio_to_irq
+
+static inline int irq_to_gpio(unsigned irq)
+{
+ return -EINVAL;
+}
+
+#endif /* __ASM_MACH_ATH25_GPIO_H */
diff --git a/arch/mips/include/asm/mach-ath25/war.h b/arch/mips/include/asm/mach-ath25/war.h
new file mode 100644
index 0000000..e3a5250
--- /dev/null
+++ b/arch/mips/include/asm/mach-ath25/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) 2008 Felix Fietkau <***@openwrt.org>
+ */
+#ifndef __ASM_MACH_ATH25_WAR_H
+#define __ASM_MACH_ATH25_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_ATH25_WAR_H */
--
1.8.5.5
John Crispin
2014-10-21 23:36:25 UTC
Permalink
Hi Sergey,

Thanks for the patches, a few comments inline
Post by Sergey Ryazanov
Add common code for Atheros AR5312 and Atheros AR2315 SoCs families.
---
- rename MIPS machine ar231x -> ath25
arch/mips/Kbuild.platforms | 1 +
arch/mips/Kconfig | 13 ++++
arch/mips/ath25/Makefile | 11 ++++
arch/mips/ath25/Platform | 6 ++
arch/mips/ath25/board.c | 53 +++++++++++++++
arch/mips/ath25/devices.c | 11 ++++
arch/mips/ath25/devices.h | 16 +++++
arch/mips/ath25/prom.c | 26 ++++++++
arch/mips/include/asm/mach-ath25/ath25.h | 29 +++++++++
.../include/asm/mach-ath25/cpu-feature-overrides.h | 76 ++++++++++++++++++++++
arch/mips/include/asm/mach-ath25/dma-coherence.h | 64 ++++++++++++++++++
arch/mips/include/asm/mach-ath25/gpio.h | 16 +++++
arch/mips/include/asm/mach-ath25/war.h | 25 +++++++
13 files changed, 347 insertions(+)
create mode 100644 arch/mips/ath25/Makefile
create mode 100644 arch/mips/ath25/Platform
create mode 100644 arch/mips/ath25/board.c
create mode 100644 arch/mips/ath25/devices.c
create mode 100644 arch/mips/ath25/devices.h
create mode 100644 arch/mips/ath25/prom.c
create mode 100644 arch/mips/include/asm/mach-ath25/ath25.h
create mode 100644 arch/mips/include/asm/mach-ath25/cpu-feature-overrides.h
create mode 100644 arch/mips/include/asm/mach-ath25/dma-coherence.h
create mode 100644 arch/mips/include/asm/mach-ath25/gpio.h
create mode 100644 arch/mips/include/asm/mach-ath25/war.h
diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms
index f5e18bf..1780c74 100644
--- a/arch/mips/Kbuild.platforms
+++ b/arch/mips/Kbuild.platforms
@@ -2,6 +2,7 @@
platforms += alchemy
platforms += ar7
+platforms += ath25
platforms += ath79
platforms += bcm47xx
platforms += bcm63xx
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 652bd79..54abb9a 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -96,6 +96,19 @@ config AR7
Support for the Texas Instruments AR7 System-on-a-Chip
family: TNETD7100, 7200 and 7300.
+config ATH25
+ bool "Atheros AR231x/AR531x SoC support"
+ select CEVT_R4K
+ select CSRC_R4K
+ select DMA_NONCOHERENT
+ select IRQ_CPU
+ select SYS_HAS_CPU_MIPS32_R1
+ select SYS_SUPPORTS_BIG_ENDIAN
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select ARCH_REQUIRE_GPIOLIB
you probably do not want to select GPIOLIB since the driver is dropped
from the series.

[snip]
Post by Sergey Ryazanov
diff --git a/arch/mips/ath25/board.c b/arch/mips/ath25/board.c
new file mode 100644
index 0000000..cbc6d7b
--- /dev/null
+++ b/arch/mips/ath25/board.c
@@ -0,0 +1,53 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 Atheros Communications, Inc., All Rights Reserved.
+ * Copyright (C) 2006 FON Technology, SL.
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <asm/irq_cpu.h>
+#include <asm/reboot.h>
+#include <asm/bootinfo.h>
+#include <asm/time.h>
+
+static void ath25_halt(void)
+{
+ local_irq_disable();
+ while (1)
+ ;
please use unreachable() macro here from include/linux/compiler.h

[snip]
Post by Sergey Ryazanov
diff --git a/arch/mips/include/asm/mach-ath25/cpu-feature-overrides.h b/arch/mips/include/asm/mach-ath25/cpu-feature-overrides.h
new file mode 100644
index 0000000..c1aebdc
--- /dev/null
+++ b/arch/mips/include/asm/mach-ath25/cpu-feature-overrides.h
@@ -0,0 +1,76 @@
+/*
+ * Atheros AR231x/AR531x SoC specific CPU feature overrides
+ *
+ *
+ * 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_ATH25_CPU_FEATURE_OVERRIDES_H
+#define __ASM_MACH_ATH25_CPU_FEATURE_OVERRIDES_H
+
+/*
+ * The Atheros AR531x/AR231x SoCs have MIPS 4Kc/4KEc core.
+ */
+#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 ? */
+/* #define cpu_has_divec ? */
+/* #define cpu_has_vce ? */
+/* #define cpu_has_cache_cdex_p ? */
+/* #define cpu_has_cache_cdex_s ? */
+/* #define cpu_has_prefetch ? */
+/* #define cpu_has_mcheck ? */
+#define cpu_has_ejtag 1
+
+/*
+ * The MIPS 4Kc V0.9 core in the AR5312/AR2312 have problems with the
+ * ll/sc instructions.
+ */
+#define cpu_has_llsc 0
+
+#define cpu_has_mips16 0
+#define cpu_has_mdmx 0
+#define cpu_has_mips3d 0
+#define cpu_has_smartmips 0
+
+/* #define cpu_has_vtag_icache ? */
+/* #define cpu_has_dc_aliases ? */
+/* #define cpu_has_ic_fills_f_dc ? */
+/* #define cpu_has_pindexed_dcache ? */
+
+/* #define cpu_icache_snoops_remote_store ? */
please drop the ones with a "?"
Post by Sergey Ryazanov
+
+#define cpu_has_mips32r1 1
+
+#define cpu_has_mips64r1 0
+#define cpu_has_mips64r2 0
+
+#define cpu_has_dsp 0
+#define cpu_has_mipsmt 0
+
+/* #define cpu_has_nofpuex ? */
+#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_has_inclusive_pcaches ? */
+
+/* #define cpu_dcache_line_size() ? */
+/* #define cpu_icache_line_size() ? */
same here
Post by Sergey Ryazanov
+
+#endif /* __ASM_MACH_ATH25_CPU_FEATURE_OVERRIDES_H */
diff --git a/arch/mips/include/asm/mach-ath25/dma-coherence.h b/arch/mips/include/asm/mach-ath25/dma-coherence.h
new file mode 100644
index 0000000..8b3d0cc
--- /dev/null
+++ b/arch/mips/include/asm/mach-ath25/dma-coherence.h
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ *
+ *
+ */
+#ifndef __ASM_MACH_ATH25_DMA_COHERENCE_H
+#define __ASM_MACH_ATH25_DMA_COHERENCE_H
+
+#include <linux/device.h>
+
+static inline dma_addr_t
+plat_map_dma_mem(struct device *dev, void *addr, size_t size)
+{
+ return virt_to_phys(addr);
+}
+
+static inline dma_addr_t
+plat_map_dma_mem_page(struct device *dev, struct page *page)
+{
+ return page_to_phys(page);
+}
+
+static inline unsigned long
+plat_dma_addr_to_phys(struct device *dev, dma_addr_t dma_addr)
+{
+ return dma_addr;
+}
+
+static inline void
+plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr, size_t size,
+ enum dma_data_direction direction)
+{
+}
+
+static inline int plat_dma_supported(struct device *dev, u64 mask)
+{
+ return 1;
+}
+
+static inline void plat_extra_sync_for_device(struct device *dev)
+{
+}
+
+static inline int plat_dma_mapping_error(struct device *dev,
+ dma_addr_t dma_addr)
+{
+ return 0;
+}
+
+static inline int plat_device_is_coherent(struct device *dev)
+{
+#ifdef CONFIG_DMA_COHERENT
+ return 1;
+#endif
+#ifdef CONFIG_DMA_NONCOHERENT
+ return 0;
+#endif
+}
+
+#endif /* __ASM_MACH_ATH25_DMA_COHERENCE_H */
diff --git a/arch/mips/include/asm/mach-ath25/gpio.h b/arch/mips/include/asm/mach-ath25/gpio.h
new file mode 100644
index 0000000..713564b
--- /dev/null
+++ b/arch/mips/include/asm/mach-ath25/gpio.h
@@ -0,0 +1,16 @@
+#ifndef __ASM_MACH_ATH25_GPIO_H
+#define __ASM_MACH_ATH25_GPIO_H
+
+#include <asm-generic/gpio.h>
+
+#define gpio_get_value __gpio_get_value
+#define gpio_set_value __gpio_set_value
+#define gpio_cansleep __gpio_cansleep
+#define gpio_to_irq __gpio_to_irq
+
+static inline int irq_to_gpio(unsigned irq)
+{
+ return -EINVAL;
+}
+
+#endif /* __ASM_MACH_ATH25_GPIO_H */
diff --git a/arch/mips/include/asm/mach-ath25/war.h b/arch/mips/include/asm/mach-ath25/war.h
new file mode 100644
index 0000000..e3a5250
--- /dev/null
+++ b/arch/mips/include/asm/mach-ath25/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.
+ *
+ */
+#ifndef __ASM_MACH_ATH25_WAR_H
+#define __ASM_MACH_ATH25_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_ATH25_WAR_H */
Sergey Ryazanov
2014-10-22 12:40:58 UTC
Permalink
Post by John Crispin
Hi Sergey,
Thanks for the patches, a few comments inline
Thank you for detailed review!
Post by John Crispin
Post by Sergey Ryazanov
Add common code for Atheros AR5312 and Atheros AR2315 SoCs families.
---
- rename MIPS machine ar231x -> ath25
arch/mips/Kbuild.platforms | 1 +
arch/mips/Kconfig | 13 ++++
arch/mips/ath25/Makefile | 11 ++++
arch/mips/ath25/Platform | 6 ++
arch/mips/ath25/board.c | 53 +++++++++++=
++++
Post by John Crispin
Post by Sergey Ryazanov
arch/mips/ath25/devices.c | 11 ++++
arch/mips/ath25/devices.h | 16 +++++
arch/mips/ath25/prom.c | 26 ++++++++
arch/mips/include/asm/mach-ath25/ath25.h | 29 +++++++++
.../include/asm/mach-ath25/cpu-feature-overrides.h | 76 +++++++++++=
+++++++++++
Post by John Crispin
Post by Sergey Ryazanov
arch/mips/include/asm/mach-ath25/dma-coherence.h | 64 +++++++++++=
+++++++
Post by John Crispin
Post by Sergey Ryazanov
arch/mips/include/asm/mach-ath25/gpio.h | 16 +++++
arch/mips/include/asm/mach-ath25/war.h | 25 +++++++
13 files changed, 347 insertions(+)
create mode 100644 arch/mips/ath25/Makefile
create mode 100644 arch/mips/ath25/Platform
create mode 100644 arch/mips/ath25/board.c
create mode 100644 arch/mips/ath25/devices.c
create mode 100644 arch/mips/ath25/devices.h
create mode 100644 arch/mips/ath25/prom.c
create mode 100644 arch/mips/include/asm/mach-ath25/ath25.h
create mode 100644 arch/mips/include/asm/mach-ath25/cpu-feature-ove=
rrides.h
Post by John Crispin
Post by Sergey Ryazanov
create mode 100644 arch/mips/include/asm/mach-ath25/dma-coherence.h
create mode 100644 arch/mips/include/asm/mach-ath25/gpio.h
create mode 100644 arch/mips/include/asm/mach-ath25/war.h
diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms
index f5e18bf..1780c74 100644
--- a/arch/mips/Kbuild.platforms
+++ b/arch/mips/Kbuild.platforms
@@ -2,6 +2,7 @@
platforms +=3D alchemy
platforms +=3D ar7
+platforms +=3D ath25
platforms +=3D ath79
platforms +=3D bcm47xx
platforms +=3D bcm63xx
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 652bd79..54abb9a 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -96,6 +96,19 @@ config AR7
Support for the Texas Instruments AR7 System-on-a-Chip
family: TNETD7100, 7200 and 7300.
+config ATH25
+ bool "Atheros AR231x/AR531x SoC support"
+ select CEVT_R4K
+ select CSRC_R4K
+ select DMA_NONCOHERENT
+ select IRQ_CPU
+ select SYS_HAS_CPU_MIPS32_R1
+ select SYS_SUPPORTS_BIG_ENDIAN
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select ARCH_REQUIRE_GPIOLIB
you probably do not want to select GPIOLIB since the driver is droppe=
d
Post by John Crispin
from the series.
Yep, sure.
Post by John Crispin
[snip]
Post by Sergey Ryazanov
diff --git a/arch/mips/ath25/board.c b/arch/mips/ath25/board.c
new file mode 100644
index 0000000..cbc6d7b
--- /dev/null
+++ b/arch/mips/ath25/board.c
@@ -0,0 +1,53 @@
+/*
+ * This file is subject to the terms and conditions of the GNU Gene=
ral Public
Post by John Crispin
Post by Sergey Ryazanov
+ * License. See the file "COPYING" in the main directory of this a=
rchive
Post by John Crispin
Post by Sergey Ryazanov
+ * for more details.
+ *
+ * Copyright (C) 2003 Atheros Communications, Inc., All Rights Res=
erved.
Post by John Crispin
Post by Sergey Ryazanov
+ * Copyright (C) 2006 FON Technology, SL.
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <asm/irq_cpu.h>
+#include <asm/reboot.h>
+#include <asm/bootinfo.h>
+#include <asm/time.h>
+
+static void ath25_halt(void)
+{
+ local_irq_disable();
+ while (1)
+ ;
please use unreachable() macro here from include/linux/compiler.h
will do
Post by John Crispin
[snip]
Post by Sergey Ryazanov
diff --git a/arch/mips/include/asm/mach-ath25/cpu-feature-overrides.=
h b/arch/mips/include/asm/mach-ath25/cpu-feature-overrides.h
Post by John Crispin
Post by Sergey Ryazanov
new file mode 100644
index 0000000..c1aebdc
--- /dev/null
+++ b/arch/mips/include/asm/mach-ath25/cpu-feature-overrides.h
@@ -0,0 +1,76 @@
+/*
+ * Atheros AR231x/AR531x SoC specific CPU feature overrides
+ *
+ *
+ * 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 m=
odify it
Post by John Crispin
Post by Sergey Ryazanov
+ * under the terms of the GNU General Public License version 2 as =
published
Post by John Crispin
Post by Sergey Ryazanov
+ * by the Free Software Foundation.
+ *
+ */
+#ifndef __ASM_MACH_ATH25_CPU_FEATURE_OVERRIDES_H
+#define __ASM_MACH_ATH25_CPU_FEATURE_OVERRIDES_H
+
+/*
+ * The Atheros AR531x/AR231x SoCs have MIPS 4Kc/4KEc core.
+ */
+#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 ? */
+/* #define cpu_has_divec ? */
+/* #define cpu_has_vce ? */
+/* #define cpu_has_cache_cdex_p ? */
+/* #define cpu_has_cache_cdex_s ? */
+/* #define cpu_has_prefetch ? */
+/* #define cpu_has_mcheck ? */
+#define cpu_has_ejtag 1
+
+/*
+ * The MIPS 4Kc V0.9 core in the AR5312/AR2312 have problems with t=
he
Post by John Crispin
Post by Sergey Ryazanov
+ * ll/sc instructions.
+ */
+#define cpu_has_llsc 0
+
+#define cpu_has_mips16 0
+#define cpu_has_mdmx 0
+#define cpu_has_mips3d 0
+#define cpu_has_smartmips 0
+
+/* #define cpu_has_vtag_icache ? */
+/* #define cpu_has_dc_aliases ? */
+/* #define cpu_has_ic_fills_f_dc ? */
+/* #define cpu_has_pindexed_dcache ? */
+
+/* #define cpu_icache_snoops_remote_store ? */
please drop the ones with a "?"
Ok
Post by John Crispin
Post by Sergey Ryazanov
+
+#define cpu_has_mips32r1 1
+
+#define cpu_has_mips64r1 0
+#define cpu_has_mips64r2 0
+
+#define cpu_has_dsp 0
+#define cpu_has_mipsmt 0
+
+/* #define cpu_has_nofpuex ? */
+#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_has_inclusive_pcaches ? */
+
+/* #define cpu_dcache_line_size() ? */
+/* #define cpu_icache_line_size() ? */
same here
Post by Sergey Ryazanov
+
+#endif /* __ASM_MACH_ATH25_CPU_FEATURE_OVERRIDES_H */
diff --git a/arch/mips/include/asm/mach-ath25/dma-coherence.h b/arch=
/mips/include/asm/mach-ath25/dma-coherence.h
Post by John Crispin
Post by Sergey Ryazanov
new file mode 100644
index 0000000..8b3d0cc
--- /dev/null
+++ b/arch/mips/include/asm/mach-ath25/dma-coherence.h
@@ -0,0 +1,64 @@
+/*
+ * This file is subject to the terms and conditions of the GNU Gene=
ral Public
Post by John Crispin
Post by Sergey Ryazanov
+ * License. See the file "COPYING" in the main directory of this a=
rchive
Post by John Crispin
Post by Sergey Ryazanov
+ * for more details.
+ *
+ *
+ */
+#ifndef __ASM_MACH_ATH25_DMA_COHERENCE_H
+#define __ASM_MACH_ATH25_DMA_COHERENCE_H
+
+#include <linux/device.h>
+
+static inline dma_addr_t
+plat_map_dma_mem(struct device *dev, void *addr, size_t size)
+{
+ return virt_to_phys(addr);
+}
+
+static inline dma_addr_t
+plat_map_dma_mem_page(struct device *dev, struct page *page)
+{
+ return page_to_phys(page);
+}
+
+static inline unsigned long
+plat_dma_addr_to_phys(struct device *dev, dma_addr_t dma_addr)
+{
+ return dma_addr;
+}
+
+static inline void
+plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr, size_t =
size,
Post by John Crispin
Post by Sergey Ryazanov
+ enum dma_data_direction direction)
+{
+}
+
+static inline int plat_dma_supported(struct device *dev, u64 mask)
+{
+ return 1;
+}
+
+static inline void plat_extra_sync_for_device(struct device *dev)
+{
+}
+
+static inline int plat_dma_mapping_error(struct device *dev,
+ dma_addr_t dma_addr)
+{
+ return 0;
+}
+
+static inline int plat_device_is_coherent(struct device *dev)
+{
+#ifdef CONFIG_DMA_COHERENT
+ return 1;
+#endif
+#ifdef CONFIG_DMA_NONCOHERENT
+ return 0;
+#endif
+}
+
+#endif /* __ASM_MACH_ATH25_DMA_COHERENCE_H */
diff --git a/arch/mips/include/asm/mach-ath25/gpio.h b/arch/mips/inc=
lude/asm/mach-ath25/gpio.h
Post by John Crispin
Post by Sergey Ryazanov
new file mode 100644
index 0000000..713564b
--- /dev/null
+++ b/arch/mips/include/asm/mach-ath25/gpio.h
@@ -0,0 +1,16 @@
+#ifndef __ASM_MACH_ATH25_GPIO_H
+#define __ASM_MACH_ATH25_GPIO_H
+
+#include <asm-generic/gpio.h>
+
+#define gpio_get_value __gpio_get_value
+#define gpio_set_value __gpio_set_value
+#define gpio_cansleep __gpio_cansleep
+#define gpio_to_irq __gpio_to_irq
+
+static inline int irq_to_gpio(unsigned irq)
+{
+ return -EINVAL;
+}
+
+#endif /* __ASM_MACH_ATH25_GPIO_H */
diff --git a/arch/mips/include/asm/mach-ath25/war.h b/arch/mips/incl=
ude/asm/mach-ath25/war.h
Post by John Crispin
Post by Sergey Ryazanov
new file mode 100644
index 0000000..e3a5250
--- /dev/null
+++ b/arch/mips/include/asm/mach-ath25/war.h
@@ -0,0 +1,25 @@
+/*
+ * This file is subject to the terms and conditions of the GNU Gene=
ral Public
Post by John Crispin
Post by Sergey Ryazanov
+ * License. See the file "COPYING" in the main directory of this a=
rchive
Post by John Crispin
Post by Sergey Ryazanov
+ * for more details.
+ *
+ */
+#ifndef __ASM_MACH_ATH25_WAR_H
+#define __ASM_MACH_ATH25_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_ATH25_WAR_H */
--=20
BR,
Sergey

=F3 =CE=C1=C9=CC=D5=DE=DB=C9=CD=C9 =D0=CF=D6=C5=CC=C1=CE=C9=D1=CD=C9
=F2=D1=DA=C1=CE=CF=D7 =F3=C5=D2=C7=C5=CA
John Crispin
2014-10-22 08:31:57 UTC
Permalink
Post by Sergey Ryazanov
Add common code for Atheros AR5312 and Atheros AR2315 SoCs families.
---
- rename MIPS machine ar231x -> ath25
arch/mips/Kbuild.platforms | 1 +
arch/mips/Kconfig | 13 ++++
arch/mips/ath25/Makefile | 11 ++++
arch/mips/ath25/Platform | 6 ++
arch/mips/ath25/board.c | 53 +++++++++++++++
arch/mips/ath25/devices.c | 11 ++++
arch/mips/ath25/devices.h | 16 +++++
arch/mips/ath25/prom.c | 26 ++++++++
arch/mips/include/asm/mach-ath25/ath25.h | 29 +++++++++
.../include/asm/mach-ath25/cpu-feature-overrides.h | 76 ++++++++++++++++++++++
arch/mips/include/asm/mach-ath25/dma-coherence.h | 64 ++++++++++++++++++
arch/mips/include/asm/mach-ath25/gpio.h | 16 +++++
arch/mips/include/asm/mach-ath25/war.h | 25 +++++++
13 files changed, 347 insertions(+)
create mode 100644 arch/mips/ath25/Makefile
create mode 100644 arch/mips/ath25/Platform
create mode 100644 arch/mips/ath25/board.c
create mode 100644 arch/mips/ath25/devices.c
create mode 100644 arch/mips/ath25/devices.h
create mode 100644 arch/mips/ath25/prom.c
create mode 100644 arch/mips/include/asm/mach-ath25/ath25.h
create mode 100644 arch/mips/include/asm/mach-ath25/cpu-feature-overrides.h
create mode 100644 arch/mips/include/asm/mach-ath25/dma-coherence.h
create mode 100644 arch/mips/include/asm/mach-ath25/gpio.h
create mode 100644 arch/mips/include/asm/mach-ath25/war.h
diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms
index f5e18bf..1780c74 100644
--- a/arch/mips/Kbuild.platforms
+++ b/arch/mips/Kbuild.platforms
@@ -2,6 +2,7 @@
platforms += alchemy
platforms += ar7
+platforms += ath25
platforms += ath79
platforms += bcm47xx
platforms += bcm63xx
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 652bd79..54abb9a 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -96,6 +96,19 @@ config AR7
Support for the Texas Instruments AR7 System-on-a-Chip
family: TNETD7100, 7200 and 7300.
+config ATH25
+ bool "Atheros AR231x/AR531x SoC support"
+ select CEVT_R4K
+ select CSRC_R4K
+ select DMA_NONCOHERENT
+ select IRQ_CPU
+ select SYS_HAS_CPU_MIPS32_R1
+ select SYS_SUPPORTS_BIG_ENDIAN
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select ARCH_REQUIRE_GPIOLIB
+ help
+ Support for Atheros AR231x and Atheros AR531x based boards
+
config ATH79
bool "Atheros AR71XX/AR724X/AR913X based boards"
select ARCH_REQUIRE_GPIOLIB
diff --git a/arch/mips/ath25/Makefile b/arch/mips/ath25/Makefile
new file mode 100644
index 0000000..9199fa1
--- /dev/null
+++ b/arch/mips/ath25/Makefile
@@ -0,0 +1,11 @@
+#
+# 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) 2006 FON Technology, SL.
+#
+
+obj-y += board.o prom.o devices.o
diff --git a/arch/mips/ath25/Platform b/arch/mips/ath25/Platform
new file mode 100644
index 0000000..ef3f81f
--- /dev/null
+++ b/arch/mips/ath25/Platform
@@ -0,0 +1,6 @@
+#
+# Atheros AR531X/AR231X WiSoC
+#
+platform-$(CONFIG_ATH25) += ath25/
+cflags-$(CONFIG_ATH25) += -I$(srctree)/arch/mips/include/asm/mach-ath25
+load-$(CONFIG_ATH25) += 0xffffffff80041000
diff --git a/arch/mips/ath25/board.c b/arch/mips/ath25/board.c
new file mode 100644
index 0000000..cbc6d7b
--- /dev/null
+++ b/arch/mips/ath25/board.c
@@ -0,0 +1,53 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 Atheros Communications, Inc., All Rights Reserved.
+ * Copyright (C) 2006 FON Technology, SL.
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <asm/irq_cpu.h>
+#include <asm/reboot.h>
+#include <asm/bootinfo.h>
+#include <asm/time.h>
+
+static void ath25_halt(void)
+{
+ local_irq_disable();
+ while (1)
+ ;
+}
+
+void __init plat_mem_setup(void)
+{
+ _machine_halt = ath25_halt;
+ pm_power_off = ath25_halt;
+
+ /* Disable data watchpoints */
+ write_c0_watchlo0(0);
+}
+
+asmlinkage void plat_irq_dispatch(void)
+{
+}
+
+void __init plat_time_init(void)
+{
+}
+
+unsigned int __cpuinit get_c0_compare_int(void)
+{
+ return CP0_LEGACY_COMPARE_IRQ;
+}
+
+void __init arch_init_irq(void)
+{
+ clear_c0_status(ST0_IM);
+ mips_cpu_irq_init();
+}
+
diff --git a/arch/mips/ath25/devices.c b/arch/mips/ath25/devices.c
new file mode 100644
index 0000000..e30afbc
--- /dev/null
+++ b/arch/mips/ath25/devices.c
@@ -0,0 +1,11 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <asm/bootinfo.h>
+
+#include "devices.h"
+
+const char *get_system_type(void)
+{
+ return "Atheros (unknown)";
+}
+
diff --git a/arch/mips/ath25/devices.h b/arch/mips/ath25/devices.h
new file mode 100644
index 0000000..edda636
--- /dev/null
+++ b/arch/mips/ath25/devices.h
@@ -0,0 +1,16 @@
+#ifndef __ATH25_DEVICES_H
+#define __ATH25_DEVICES_H
+
+#include <linux/cpu.h>
+
+static inline bool is_ar2315(void)
+{
+ return (current_cpu_data.cputype == CPU_4KEC);
+}
+
+static inline bool is_ar5312(void)
+{
+ return !is_ar2315();
+}
+
+#endif
diff --git a/arch/mips/ath25/prom.c b/arch/mips/ath25/prom.c
new file mode 100644
index 0000000..edf82be
--- /dev/null
+++ b/arch/mips/ath25/prom.c
@@ -0,0 +1,26 @@
+/*
+ * 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 MontaVista Software Inc
+ * Copyright (C) 2003 Atheros Communications, Inc., All Rights Reserved.
+ * Copyright (C) 2006 FON Technology, SL.
+ */
+
+/*
+ * Prom setup file for AR5312/AR231x SoCs
+ */
+
+#include <linux/init.h>
+#include <asm/bootinfo.h>
+
+void __init prom_init(void)
+{
+}
+
+void __init prom_free_prom_memory(void)
+{
+}
diff --git a/arch/mips/include/asm/mach-ath25/ath25.h b/arch/mips/include/asm/mach-ath25/ath25.h
new file mode 100644
index 0000000..bd66ce7
--- /dev/null
+++ b/arch/mips/include/asm/mach-ath25/ath25.h
@@ -0,0 +1,29 @@
+#ifndef __ASM_MACH_ATH25_H
+#define __ASM_MACH_ATH25_H
+
+#include <linux/io.h>
+
+#define ATH25_REG_MS(_val, _field) (((_val) & _field##_M) >> _field##_S)
+
+static inline u32 ath25_read_reg(u32 reg)
+{
+ return __raw_readl((void __iomem *)KSEG1ADDR(reg));
+}
+
+static inline void ath25_write_reg(u32 reg, u32 val)
+{
+ __raw_writel(val, (void __iomem *)KSEG1ADDR(reg));
+}
+
using KSEG1ADDR is a bad idea. EVA will obselete these. please use
ioremap() to get a void __iomem pointer and then use this as a
register base. the current code will also lead to a addr cast with
every call of the functions.
Post by Sergey Ryazanov
+static inline u32 ath25_mask_reg(u32 reg, u32 mask, u32 val)
+{
+ u32 ret = ath25_read_reg(reg);
+
+ ret &= ~mask;
+ ret |= val;
+ ath25_write_reg(reg, ret);
+
+ return ret;
+}
+
+#endif /* __ASM_MACH_ATH25_H */
diff --git a/arch/mips/include/asm/mach-ath25/cpu-feature-overrides.h b/arch/mips/include/asm/mach-ath25/cpu-feature-overrides.h
new file mode 100644
index 0000000..c1aebdc
--- /dev/null
+++ b/arch/mips/include/asm/mach-ath25/cpu-feature-overrides.h
@@ -0,0 +1,76 @@
+/*
+ * Atheros AR231x/AR531x SoC specific CPU feature overrides
+ *
+ *
+ * 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_ATH25_CPU_FEATURE_OVERRIDES_H
+#define __ASM_MACH_ATH25_CPU_FEATURE_OVERRIDES_H
+
+/*
+ * The Atheros AR531x/AR231x SoCs have MIPS 4Kc/4KEc core.
+ */
+#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 ? */
+/* #define cpu_has_divec ? */
+/* #define cpu_has_vce ? */
+/* #define cpu_has_cache_cdex_p ? */
+/* #define cpu_has_cache_cdex_s ? */
+/* #define cpu_has_prefetch ? */
+/* #define cpu_has_mcheck ? */
+#define cpu_has_ejtag 1
+
+/*
+ * The MIPS 4Kc V0.9 core in the AR5312/AR2312 have problems with the
+ * ll/sc instructions.
+ */
+#define cpu_has_llsc 0
+
+#define cpu_has_mips16 0
+#define cpu_has_mdmx 0
+#define cpu_has_mips3d 0
+#define cpu_has_smartmips 0
+
+/* #define cpu_has_vtag_icache ? */
+/* #define cpu_has_dc_aliases ? */
+/* #define cpu_has_ic_fills_f_dc ? */
+/* #define cpu_has_pindexed_dcache ? */
+
+/* #define cpu_icache_snoops_remote_store ? */
+
+#define cpu_has_mips32r1 1
+
+#define cpu_has_mips64r1 0
+#define cpu_has_mips64r2 0
+
+#define cpu_has_dsp 0
+#define cpu_has_mipsmt 0
+
+/* #define cpu_has_nofpuex ? */
+#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_has_inclusive_pcaches ? */
+
+/* #define cpu_dcache_line_size() ? */
+/* #define cpu_icache_line_size() ? */
+
+#endif /* __ASM_MACH_ATH25_CPU_FEATURE_OVERRIDES_H */
diff --git a/arch/mips/include/asm/mach-ath25/dma-coherence.h b/arch/mips/include/asm/mach-ath25/dma-coherence.h
new file mode 100644
index 0000000..8b3d0cc
--- /dev/null
+++ b/arch/mips/include/asm/mach-ath25/dma-coherence.h
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ *
+ *
+ */
+#ifndef __ASM_MACH_ATH25_DMA_COHERENCE_H
+#define __ASM_MACH_ATH25_DMA_COHERENCE_H
+
+#include <linux/device.h>
+
+static inline dma_addr_t
+plat_map_dma_mem(struct device *dev, void *addr, size_t size)
+{
+ return virt_to_phys(addr);
+}
+
+static inline dma_addr_t
+plat_map_dma_mem_page(struct device *dev, struct page *page)
+{
+ return page_to_phys(page);
+}
+
+static inline unsigned long
+plat_dma_addr_to_phys(struct device *dev, dma_addr_t dma_addr)
+{
+ return dma_addr;
+}
+
+static inline void
+plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr, size_t size,
+ enum dma_data_direction direction)
+{
+}
+
+static inline int plat_dma_supported(struct device *dev, u64 mask)
+{
+ return 1;
+}
+
+static inline void plat_extra_sync_for_device(struct device *dev)
+{
+}
+
+static inline int plat_dma_mapping_error(struct device *dev,
+ dma_addr_t dma_addr)
+{
+ return 0;
+}
+
+static inline int plat_device_is_coherent(struct device *dev)
+{
+#ifdef CONFIG_DMA_COHERENT
+ return 1;
+#endif
+#ifdef CONFIG_DMA_NONCOHERENT
+ return 0;
+#endif
+}
+
+#endif /* __ASM_MACH_ATH25_DMA_COHERENCE_H */
diff --git a/arch/mips/include/asm/mach-ath25/gpio.h b/arch/mips/include/asm/mach-ath25/gpio.h
new file mode 100644
index 0000000..713564b
--- /dev/null
+++ b/arch/mips/include/asm/mach-ath25/gpio.h
@@ -0,0 +1,16 @@
+#ifndef __ASM_MACH_ATH25_GPIO_H
+#define __ASM_MACH_ATH25_GPIO_H
+
+#include <asm-generic/gpio.h>
+
+#define gpio_get_value __gpio_get_value
+#define gpio_set_value __gpio_set_value
+#define gpio_cansleep __gpio_cansleep
+#define gpio_to_irq __gpio_to_irq
+
+static inline int irq_to_gpio(unsigned irq)
+{
+ return -EINVAL;
+}
+
+#endif /* __ASM_MACH_ATH25_GPIO_H */
diff --git a/arch/mips/include/asm/mach-ath25/war.h b/arch/mips/include/asm/mach-ath25/war.h
new file mode 100644
index 0000000..e3a5250
--- /dev/null
+++ b/arch/mips/include/asm/mach-ath25/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.
+ *
+ */
+#ifndef __ASM_MACH_ATH25_WAR_H
+#define __ASM_MACH_ATH25_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_ATH25_WAR_H */
Sergey Ryazanov
2014-10-22 13:06:08 UTC
Permalink
Post by John Crispin
Post by Sergey Ryazanov
Add common code for Atheros AR5312 and Atheros AR2315 SoCs families.
---
- rename MIPS machine ar231x -> ath25
arch/mips/Kbuild.platforms | 1 +
arch/mips/Kconfig | 13 ++++
arch/mips/ath25/Makefile | 11 ++++
arch/mips/ath25/Platform | 6 ++
arch/mips/ath25/board.c | 53 +++++++++++++++
arch/mips/ath25/devices.c | 11 ++++
arch/mips/ath25/devices.h | 16 +++++
arch/mips/ath25/prom.c | 26 ++++++++
arch/mips/include/asm/mach-ath25/ath25.h | 29 +++++++++
.../include/asm/mach-ath25/cpu-feature-overrides.h | 76 ++++++++++++++++++++++
arch/mips/include/asm/mach-ath25/dma-coherence.h | 64 ++++++++++++++++++
arch/mips/include/asm/mach-ath25/gpio.h | 16 +++++
arch/mips/include/asm/mach-ath25/war.h | 25 +++++++
13 files changed, 347 insertions(+)
create mode 100644 arch/mips/ath25/Makefile
create mode 100644 arch/mips/ath25/Platform
create mode 100644 arch/mips/ath25/board.c
create mode 100644 arch/mips/ath25/devices.c
create mode 100644 arch/mips/ath25/devices.h
create mode 100644 arch/mips/ath25/prom.c
create mode 100644 arch/mips/include/asm/mach-ath25/ath25.h
create mode 100644 arch/mips/include/asm/mach-ath25/cpu-feature-overrides.h
create mode 100644 arch/mips/include/asm/mach-ath25/dma-coherence.h
create mode 100644 arch/mips/include/asm/mach-ath25/gpio.h
create mode 100644 arch/mips/include/asm/mach-ath25/war.h
diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms
index f5e18bf..1780c74 100644
--- a/arch/mips/Kbuild.platforms
+++ b/arch/mips/Kbuild.platforms
@@ -2,6 +2,7 @@
platforms += alchemy
platforms += ar7
+platforms += ath25
platforms += ath79
platforms += bcm47xx
platforms += bcm63xx
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 652bd79..54abb9a 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -96,6 +96,19 @@ config AR7
Support for the Texas Instruments AR7 System-on-a-Chip
family: TNETD7100, 7200 and 7300.
+config ATH25
+ bool "Atheros AR231x/AR531x SoC support"
+ select CEVT_R4K
+ select CSRC_R4K
+ select DMA_NONCOHERENT
+ select IRQ_CPU
+ select SYS_HAS_CPU_MIPS32_R1
+ select SYS_SUPPORTS_BIG_ENDIAN
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select ARCH_REQUIRE_GPIOLIB
+ help
+ Support for Atheros AR231x and Atheros AR531x based boards
+
config ATH79
bool "Atheros AR71XX/AR724X/AR913X based boards"
select ARCH_REQUIRE_GPIOLIB
diff --git a/arch/mips/ath25/Makefile b/arch/mips/ath25/Makefile
new file mode 100644
index 0000000..9199fa1
--- /dev/null
+++ b/arch/mips/ath25/Makefile
@@ -0,0 +1,11 @@
+#
+# 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) 2006 FON Technology, SL.
+#
+
+obj-y += board.o prom.o devices.o
diff --git a/arch/mips/ath25/Platform b/arch/mips/ath25/Platform
new file mode 100644
index 0000000..ef3f81f
--- /dev/null
+++ b/arch/mips/ath25/Platform
@@ -0,0 +1,6 @@
+#
+# Atheros AR531X/AR231X WiSoC
+#
+platform-$(CONFIG_ATH25) += ath25/
+cflags-$(CONFIG_ATH25) += -I$(srctree)/arch/mips/include/asm/mach-ath25
+load-$(CONFIG_ATH25) += 0xffffffff80041000
diff --git a/arch/mips/ath25/board.c b/arch/mips/ath25/board.c
new file mode 100644
index 0000000..cbc6d7b
--- /dev/null
+++ b/arch/mips/ath25/board.c
@@ -0,0 +1,53 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 Atheros Communications, Inc., All Rights Reserved.
+ * Copyright (C) 2006 FON Technology, SL.
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <asm/irq_cpu.h>
+#include <asm/reboot.h>
+#include <asm/bootinfo.h>
+#include <asm/time.h>
+
+static void ath25_halt(void)
+{
+ local_irq_disable();
+ while (1)
+ ;
+}
+
+void __init plat_mem_setup(void)
+{
+ _machine_halt = ath25_halt;
+ pm_power_off = ath25_halt;
+
+ /* Disable data watchpoints */
+ write_c0_watchlo0(0);
+}
+
+asmlinkage void plat_irq_dispatch(void)
+{
+}
+
+void __init plat_time_init(void)
+{
+}
+
+unsigned int __cpuinit get_c0_compare_int(void)
+{
+ return CP0_LEGACY_COMPARE_IRQ;
+}
+
+void __init arch_init_irq(void)
+{
+ clear_c0_status(ST0_IM);
+ mips_cpu_irq_init();
+}
+
diff --git a/arch/mips/ath25/devices.c b/arch/mips/ath25/devices.c
new file mode 100644
index 0000000..e30afbc
--- /dev/null
+++ b/arch/mips/ath25/devices.c
@@ -0,0 +1,11 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <asm/bootinfo.h>
+
+#include "devices.h"
+
+const char *get_system_type(void)
+{
+ return "Atheros (unknown)";
+}
+
diff --git a/arch/mips/ath25/devices.h b/arch/mips/ath25/devices.h
new file mode 100644
index 0000000..edda636
--- /dev/null
+++ b/arch/mips/ath25/devices.h
@@ -0,0 +1,16 @@
+#ifndef __ATH25_DEVICES_H
+#define __ATH25_DEVICES_H
+
+#include <linux/cpu.h>
+
+static inline bool is_ar2315(void)
+{
+ return (current_cpu_data.cputype == CPU_4KEC);
+}
+
+static inline bool is_ar5312(void)
+{
+ return !is_ar2315();
+}
+
+#endif
diff --git a/arch/mips/ath25/prom.c b/arch/mips/ath25/prom.c
new file mode 100644
index 0000000..edf82be
--- /dev/null
+++ b/arch/mips/ath25/prom.c
@@ -0,0 +1,26 @@
+/*
+ * 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 MontaVista Software Inc
+ * Copyright (C) 2003 Atheros Communications, Inc., All Rights Reserved.
+ * Copyright (C) 2006 FON Technology, SL.
+ */
+
+/*
+ * Prom setup file for AR5312/AR231x SoCs
+ */
+
+#include <linux/init.h>
+#include <asm/bootinfo.h>
+
+void __init prom_init(void)
+{
+}
+
+void __init prom_free_prom_memory(void)
+{
+}
diff --git a/arch/mips/include/asm/mach-ath25/ath25.h b/arch/mips/include/asm/mach-ath25/ath25.h
new file mode 100644
index 0000000..bd66ce7
--- /dev/null
+++ b/arch/mips/include/asm/mach-ath25/ath25.h
@@ -0,0 +1,29 @@
+#ifndef __ASM_MACH_ATH25_H
+#define __ASM_MACH_ATH25_H
+
+#include <linux/io.h>
+
+#define ATH25_REG_MS(_val, _field) (((_val) & _field##_M) >> _field##_S)
+
+static inline u32 ath25_read_reg(u32 reg)
+{
+ return __raw_readl((void __iomem *)KSEG1ADDR(reg));
+}
+
+static inline void ath25_write_reg(u32 reg, u32 val)
+{
+ __raw_writel(val, (void __iomem *)KSEG1ADDR(reg));
+}
+
using KSEG1ADDR is a bad idea. EVA will obselete these. please use
ioremap() to get a void __iomem pointer and then use this as a
register base. the current code will also lead to a addr cast with
every call of the functions.
I will investigate that.

And BTW, what the EVA is?
--
BR,
Sergey
John Crispin
2014-10-22 13:09:15 UTC
Permalink
Post by Sergey Ryazanov
Post by John Crispin
Post by Sergey Ryazanov
Add common code for Atheros AR5312 and Atheros AR2315 SoCs
families.
Changes since v1: - rename MIPS machine ar231x -> ath25
arch/mips/Kbuild.platforms | 1 +
arch/mips/Kconfig | 13 ++++
arch/mips/ath25/Makefile | 11 ++++
arch/mips/ath25/Platform | 6 ++
arch/mips/ath25/board.c | 53
+++++++++++++++ arch/mips/ath25/devices.c
| 11 ++++ arch/mips/ath25/devices.h |
16 +++++ arch/mips/ath25/prom.c |
26 ++++++++ arch/mips/include/asm/mach-ath25/ath25.h
| 29 +++++++++
.../include/asm/mach-ath25/cpu-feature-overrides.h | 76
++++++++++++++++++++++
arch/mips/include/asm/mach-ath25/dma-coherence.h | 64
++++++++++++++++++ arch/mips/include/asm/mach-ath25/gpio.h
| 16 +++++ arch/mips/include/asm/mach-ath25/war.h |
25 +++++++ 13 files changed, 347 insertions(+) create mode
100644 arch/mips/ath25/Makefile create mode 100644
arch/mips/ath25/Platform create mode 100644
arch/mips/ath25/board.c create mode 100644
arch/mips/ath25/devices.c create mode 100644
arch/mips/ath25/devices.h create mode 100644
arch/mips/ath25/prom.c create mode 100644
arch/mips/include/asm/mach-ath25/ath25.h create mode 100644
arch/mips/include/asm/mach-ath25/cpu-feature-overrides.h create
mode 100644 arch/mips/include/asm/mach-ath25/dma-coherence.h
create mode 100644 arch/mips/include/asm/mach-ath25/gpio.h
create mode 100644 arch/mips/include/asm/mach-ath25/war.h
diff --git a/arch/mips/Kbuild.platforms
b/arch/mips/Kbuild.platforms index f5e18bf..1780c74 100644 ---
a/arch/mips/Kbuild.platforms +++ b/arch/mips/Kbuild.platforms
@@ -2,6 +2,7 @@
platforms += alchemy platforms += ar7 +platforms += ath25
platforms += ath79 platforms += bcm47xx platforms += bcm63xx
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index
652bd79..54abb9a 100644 --- a/arch/mips/Kconfig +++
the Texas Instruments AR7 System-on-a-Chip family: TNETD7100,
7200 and 7300.
+config ATH25 + bool "Atheros AR231x/AR531x SoC support" +
select CEVT_R4K + select CSRC_R4K + select
DMA_NONCOHERENT + select IRQ_CPU + select
SYS_HAS_CPU_MIPS32_R1 + select SYS_SUPPORTS_BIG_ENDIAN +
select SYS_SUPPORTS_32BIT_KERNEL + select
ARCH_REQUIRE_GPIOLIB + help + Support for Atheros
AR231x and Atheros AR531x based boards + config ATH79 bool
"Atheros AR71XX/AR724X/AR913X based boards" select
ARCH_REQUIRE_GPIOLIB diff --git a/arch/mips/ath25/Makefile
b/arch/mips/ath25/Makefile new file mode 100644 index
0000000..9199fa1 --- /dev/null +++ b/arch/mips/ath25/Makefile
@@ -0,0 +1,11 @@ +# +# 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) 2006 FON Technology, SL. +#
board.o prom.o devices.o diff --git a/arch/mips/ath25/Platform
b/arch/mips/ath25/Platform new file mode 100644 index
0000000..ef3f81f --- /dev/null +++ b/arch/mips/ath25/Platform
@@ -0,0 +1,6 @@ +# +# Atheros AR531X/AR231X WiSoC +#
+platform-$(CONFIG_ATH25) += ath25/ +cflags-$(CONFIG_ATH25)
+= -I$(srctree)/arch/mips/include/asm/mach-ath25
+load-$(CONFIG_ATH25) += 0xffffffff80041000 diff --git
a/arch/mips/ath25/board.c b/arch/mips/ath25/board.c new file
mode 100644 index 0000000..cbc6d7b --- /dev/null +++
subject to the terms and conditions of the GNU General Public +
* License. See the file "COPYING" in the main directory of
this archive + * for more details. + * + * Copyright (C) 2003
Atheros Communications, Inc., All Rights Reserved. + *
Copyright (C) 2006 FON Technology, SL. + * Copyright (C) 2006
<linux/init.h> +#include <linux/interrupt.h> +#include
<asm/irq_cpu.h> +#include <asm/reboot.h> +#include
<asm/bootinfo.h> +#include <asm/time.h> + +static void
ath25_halt(void) +{ + local_irq_disable(); + while (1)
+ ; +} + +void __init plat_mem_setup(void) +{ +
_machine_halt = ath25_halt; + pm_power_off = ath25_halt; +
+ /* Disable data watchpoints */ +
write_c0_watchlo0(0); +} + +asmlinkage void
plat_irq_dispatch(void) +{ +} + +void __init
plat_time_init(void) +{ +} + +unsigned int __cpuinit
get_c0_compare_int(void) +{ + return
CP0_LEGACY_COMPARE_IRQ; +} + +void __init arch_init_irq(void)
+{ + clear_c0_status(ST0_IM); + mips_cpu_irq_init();
+} + diff --git a/arch/mips/ath25/devices.c
b/arch/mips/ath25/devices.c new file mode 100644 index
0000000..e30afbc --- /dev/null +++ b/arch/mips/ath25/devices.c
@@ -0,0 +1,11 @@ +#include <linux/kernel.h> +#include
<linux/init.h> +#include <asm/bootinfo.h> + +#include
"devices.h" + +const char *get_system_type(void) +{ +
return "Atheros (unknown)"; +} + diff --git
a/arch/mips/ath25/devices.h b/arch/mips/ath25/devices.h new
file mode 100644 index 0000000..edda636 --- /dev/null +++
__ATH25_DEVICES_H +#define __ATH25_DEVICES_H + +#include
<linux/cpu.h> + +static inline bool is_ar2315(void) +{ +
return (current_cpu_data.cputype == CPU_4KEC); +} + +static
inline bool is_ar5312(void) +{ + return !is_ar2315(); +} +
+#endif diff --git a/arch/mips/ath25/prom.c
b/arch/mips/ath25/prom.c new file mode 100644 index
conditions of the GNU General Public + * License. See the file
"COPYING" in the main directory of this archive + * for more
details. + * + * Copyright MontaVista Software Inc + *
Copyright (C) 2003 Atheros Communications, Inc., All Rights
Reserved. + * Copyright (C) 2006 FON Technology, SL. + *
setup file for AR5312/AR231x SoCs + */ + +#include
<linux/init.h> +#include <asm/bootinfo.h> + +void __init
prom_init(void) +{ +} + +void __init
prom_free_prom_memory(void) +{ +} diff --git
a/arch/mips/include/asm/mach-ath25/ath25.h
b/arch/mips/include/asm/mach-ath25/ath25.h new file mode
100644 index 0000000..bd66ce7 --- /dev/null +++
+#ifndef __ASM_MACH_ATH25_H +#define __ASM_MACH_ATH25_H +
+#include <linux/io.h> + +#define ATH25_REG_MS(_val, _field)
(((_val) & _field##_M) >> _field##_S) + +static inline u32
ath25_read_reg(u32 reg) +{ + return __raw_readl((void
__iomem *)KSEG1ADDR(reg)); +} + +static inline void
ath25_write_reg(u32 reg, u32 val) +{ + __raw_writel(val,
(void __iomem *)KSEG1ADDR(reg)); +} +
using KSEG1ADDR is a bad idea. EVA will obselete these. please
use ioremap() to get a void __iomem pointer and then use this as
a register base. the current code will also lead to a addr cast
with every call of the functions.
I will investigate that.
And BTW, what the EVA is?
Enhanced Virtual Addressing
Sergey Ryazanov
2014-10-21 23:03:40 UTC
Permalink
Add basic support for Atheros AR5312/AR2312 SoCs: registers definition
file and initial setup code.

Signed-off-by: Sergey Ryazanov <***@gmail.com>
---

Changes since v1:
- rename MIPS machine ar231x -> ath25

arch/mips/Kconfig | 1 +
arch/mips/ath25/Kconfig | 4 +
arch/mips/ath25/Makefile | 2 +
arch/mips/ath25/ar5312.c | 134 +++++++++++++++++
arch/mips/ath25/ar5312.h | 18 +++
arch/mips/ath25/board.c | 7 +
arch/mips/ath25/prom.c | 5 +
arch/mips/include/asm/mach-ath25/ar5312_regs.h | 190 +++++++++++++++++++++++++
8 files changed, 361 insertions(+)
create mode 100644 arch/mips/ath25/Kconfig
create mode 100644 arch/mips/ath25/ar5312.c
create mode 100644 arch/mips/ath25/ar5312.h
create mode 100644 arch/mips/include/asm/mach-ath25/ar5312_regs.h

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 54abb9a..baa1c5b 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -848,6 +848,7 @@ config MIPS_PARAVIRT
endchoice

source "arch/mips/alchemy/Kconfig"
+source "arch/mips/ath25/Kconfig"
source "arch/mips/ath79/Kconfig"
source "arch/mips/bcm47xx/Kconfig"
source "arch/mips/bcm63xx/Kconfig"
diff --git a/arch/mips/ath25/Kconfig b/arch/mips/ath25/Kconfig
new file mode 100644
index 0000000..cf933ea
--- /dev/null
+++ b/arch/mips/ath25/Kconfig
@@ -0,0 +1,4 @@
+config SOC_AR5312
+ bool "Atheros AR5312/AR2312+ SoC support"
+ depends on ATH25
+ default y
diff --git a/arch/mips/ath25/Makefile b/arch/mips/ath25/Makefile
index 9199fa1..3361619 100644
--- a/arch/mips/ath25/Makefile
+++ b/arch/mips/ath25/Makefile
@@ -9,3 +9,5 @@
#

obj-y += board.o prom.o devices.o
+
+obj-$(CONFIG_SOC_AR5312) += ar5312.o
diff --git a/arch/mips/ath25/ar5312.c b/arch/mips/ath25/ar5312.c
new file mode 100644
index 0000000..80d7ed7
--- /dev/null
+++ b/arch/mips/ath25/ar5312.c
@@ -0,0 +1,134 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 Atheros Communications, Inc., All Rights Reserved.
+ * Copyright (C) 2006 FON Technology, SL.
+ * Copyright (C) 2006 Imre Kaloz <***@openwrt.org>
+ * Copyright (C) 2006-2009 Felix Fietkau <***@openwrt.org>
+ * Copyright (C) 2012 Alexandros C. Couloumbis <***@ozo.com>
+ */
+
+/*
+ * Platform devices for Atheros AR5312 SoCs
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/reboot.h>
+#include <asm/bootinfo.h>
+#include <asm/reboot.h>
+#include <asm/time.h>
+
+#include <ar5312_regs.h>
+#include <ath25.h>
+
+#include "devices.h"
+#include "ar5312.h"
+
+static void ar5312_restart(char *command)
+{
+ /* reset the system */
+ local_irq_disable();
+ while (1)
+ ath25_write_reg(AR5312_RESET, AR5312_RESET_SYSTEM);
+}
+
+/*
+ * This table is indexed by bits 5..4 of the CLOCKCTL1 register
+ * to determine the predevisor value.
+ */
+static unsigned clockctl1_predivide_table[4] __initdata = { 1, 2, 4, 5 };
+
+static unsigned __init ar5312_cpu_frequency(void)
+{
+ u32 scratch, devid, clock_ctl1;
+ u32 predivide_mask, multiplier_mask, doubler_mask;
+ unsigned predivide_shift, multiplier_shift;
+ unsigned predivide_select, predivisor, multiplier;
+
+ /* Trust the bootrom's idea of cpu frequency. */
+ scratch = ath25_read_reg(AR5312_SCRATCH);
+ if (scratch)
+ return scratch;
+
+ devid = ath25_read_reg(AR5312_REV);
+ devid = (devid & AR5312_REV_MAJ) >> AR5312_REV_MAJ_S;
+ if (devid == AR5312_REV_MAJ_AR2313) {
+ predivide_mask = AR2313_CLOCKCTL1_PREDIVIDE_MASK;
+ predivide_shift = AR2313_CLOCKCTL1_PREDIVIDE_SHIFT;
+ multiplier_mask = AR2313_CLOCKCTL1_MULTIPLIER_MASK;
+ multiplier_shift = AR2313_CLOCKCTL1_MULTIPLIER_SHIFT;
+ doubler_mask = AR2313_CLOCKCTL1_DOUBLER_MASK;
+ } else { /* AR5312 and AR2312 */
+ predivide_mask = AR5312_CLOCKCTL1_PREDIVIDE_MASK;
+ predivide_shift = AR5312_CLOCKCTL1_PREDIVIDE_SHIFT;
+ multiplier_mask = AR5312_CLOCKCTL1_MULTIPLIER_MASK;
+ multiplier_shift = AR5312_CLOCKCTL1_MULTIPLIER_SHIFT;
+ doubler_mask = AR5312_CLOCKCTL1_DOUBLER_MASK;
+ }
+
+ /*
+ * Clocking is derived from a fixed 40MHz input clock.
+ *
+ * cpu_freq = input_clock * MULT (where MULT is PLL multiplier)
+ * sys_freq = cpu_freq / 4 (used for APB clock, serial,
+ * flash, Timer, Watchdog Timer)
+ *
+ * cnt_freq = cpu_freq / 2 (use for CPU count/compare)
+ *
+ * So, for example, with a PLL multiplier of 5, we have
+ *
+ * cpu_freq = 200MHz
+ * sys_freq = 50MHz
+ * cnt_freq = 100MHz
+ *
+ * We compute the CPU frequency, based on PLL settings.
+ */
+
+ clock_ctl1 = ath25_read_reg(AR5312_CLOCKCTL1);
+ predivide_select = (clock_ctl1 & predivide_mask) >> predivide_shift;
+ predivisor = clockctl1_predivide_table[predivide_select];
+ multiplier = (clock_ctl1 & multiplier_mask) >> multiplier_shift;
+
+ if (clock_ctl1 & doubler_mask)
+ multiplier <<= 1;
+
+ return (40000000 / predivisor) * multiplier;
+}
+
+static inline unsigned ar5312_sys_frequency(void)
+{
+ return ar5312_cpu_frequency() / 4;
+}
+
+void __init ar5312_plat_time_init(void)
+{
+ mips_hpt_frequency = ar5312_cpu_frequency() / 2;
+}
+
+void __init ar5312_plat_mem_setup(void)
+{
+ /* Clear any lingering AHB errors */
+ ath25_read_reg(AR5312_PROCADDR);
+ ath25_read_reg(AR5312_DMAADDR);
+ ath25_write_reg(AR5312_WD_CTRL, AR5312_WD_CTRL_IGNORE_EXPIRATION);
+
+ _machine_restart = ar5312_restart;
+}
+
+void __init ar5312_prom_init(void)
+{
+ u32 memsize, memcfg, bank0_ac, bank1_ac;
+
+ /* Detect memory size */
+ memcfg = ath25_read_reg(AR5312_MEM_CFG1);
+ bank0_ac = ATH25_REG_MS(memcfg, AR5312_MEM_CFG1_AC0);
+ bank1_ac = ATH25_REG_MS(memcfg, AR5312_MEM_CFG1_AC1);
+ memsize = (bank0_ac ? (1 << (bank0_ac + 1)) : 0) +
+ (bank1_ac ? (1 << (bank1_ac + 1)) : 0);
+ memsize <<= 20;
+ add_memory_region(0, memsize, BOOT_MEM_RAM);
+}
+
diff --git a/arch/mips/ath25/ar5312.h b/arch/mips/ath25/ar5312.h
new file mode 100644
index 0000000..339b28e
--- /dev/null
+++ b/arch/mips/ath25/ar5312.h
@@ -0,0 +1,18 @@
+#ifndef __AR5312_H
+#define __AR5312_H
+
+#ifdef CONFIG_SOC_AR5312
+
+void ar5312_plat_time_init(void);
+void ar5312_plat_mem_setup(void);
+void ar5312_prom_init(void);
+
+#else
+
+static inline void ar5312_plat_time_init(void) {}
+static inline void ar5312_plat_mem_setup(void) {}
+static inline void ar5312_prom_init(void) {}
+
+#endif
+
+#endif /* __AR5312_H */
diff --git a/arch/mips/ath25/board.c b/arch/mips/ath25/board.c
index cbc6d7b..80683e3 100644
--- a/arch/mips/ath25/board.c
+++ b/arch/mips/ath25/board.c
@@ -16,6 +16,8 @@
#include <asm/bootinfo.h>
#include <asm/time.h>

+#include "ar5312.h"
+
static void ath25_halt(void)
{
local_irq_disable();
@@ -28,6 +30,9 @@ void __init plat_mem_setup(void)
_machine_halt = ath25_halt;
pm_power_off = ath25_halt;

+ if (is_ar5312())
+ ar5312_plat_mem_setup();
+
/* Disable data watchpoints */
write_c0_watchlo0(0);
}
@@ -38,6 +43,8 @@ asmlinkage void plat_irq_dispatch(void)

void __init plat_time_init(void)
{
+ if (is_ar5312())
+ ar5312_plat_time_init();
}

unsigned int __cpuinit get_c0_compare_int(void)
diff --git a/arch/mips/ath25/prom.c b/arch/mips/ath25/prom.c
index edf82be..ec60b0f 100644
--- a/arch/mips/ath25/prom.c
+++ b/arch/mips/ath25/prom.c
@@ -17,8 +17,13 @@
#include <linux/init.h>
#include <asm/bootinfo.h>

+#include "devices.h"
+#include "ar5312.h"
+
void __init prom_init(void)
{
+ if (is_ar5312())
+ ar5312_prom_init();
}

void __init prom_free_prom_memory(void)
diff --git a/arch/mips/include/asm/mach-ath25/ar5312_regs.h b/arch/mips/include/asm/mach-ath25/ar5312_regs.h
new file mode 100644
index 0000000..76856d8
--- /dev/null
+++ b/arch/mips/include/asm/mach-ath25/ar5312_regs.h
@@ -0,0 +1,190 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 Atheros Communications, Inc., All Rights Reserved.
+ * Copyright (C) 2006 Imre Kaloz <***@openwrt.org>
+ * Copyright (C) 2006 Felix Fietkau <***@openwrt.org>
+ */
+
+#ifndef __ASM_MACH_ATH25_AR5312_REGS_H
+#define __ASM_MACH_ATH25_AR5312_REGS_H
+
+/*
+ * Address Map
+ *
+ * The AR5312 supports 2 enet MACS, even though many reference boards only
+ * actually use 1 of them (i.e. Only MAC 0 is actually connected to an enet
+ * PHY or PHY switch. The AR2312 supports 1 enet MAC.
+ */
+#define AR5312_WLAN0 0x18000000
+#define AR5312_WLAN1 0x18500000
+#define AR5312_ENET0 0x18100000
+#define AR5312_ENET1 0x18200000
+#define AR5312_SDRAMCTL 0x18300000
+#define AR5312_FLASHCTL 0x18400000
+#define AR5312_APBBASE 0x1c000000
+#define AR5312_UART0 0x1c000000 /* UART MMR */
+#define AR5312_FLASH 0x1e000000
+
+/*
+ * Need these defines to determine true number of ethernet MACs
+ */
+#define AR5312_AR5312_REV2 0x0052 /* AR5312 WMAC (AP31) */
+#define AR5312_AR5312_REV7 0x0057 /* AR5312 WMAC (AP30-040) */
+#define AR5312_AR2313_REV8 0x0058 /* AR2313 WMAC (AP43-030) */
+
+/* Reset/Timer Block Address Map */
+#define AR5312_RESETTMR (AR5312_APBBASE + 0x3000)
+#define AR5312_TIMER (AR5312_RESETTMR + 0x0000) /* countdown timer */
+#define AR5312_WD_CTRL (AR5312_RESETTMR + 0x0008) /* watchdog cntrl */
+#define AR5312_WD_TIMER (AR5312_RESETTMR + 0x000c) /* watchdog timer */
+#define AR5312_ISR (AR5312_RESETTMR + 0x0010) /* Intr Status Reg */
+#define AR5312_IMR (AR5312_RESETTMR + 0x0014) /* Intr Mask Reg */
+#define AR5312_RESET (AR5312_RESETTMR + 0x0020)
+#define AR5312_CLOCKCTL1 (AR5312_RESETTMR + 0x0064)
+#define AR5312_SCRATCH (AR5312_RESETTMR + 0x006c)
+#define AR5312_PROCADDR (AR5312_RESETTMR + 0x0070)
+#define AR5312_PROC1 (AR5312_RESETTMR + 0x0074)
+#define AR5312_DMAADDR (AR5312_RESETTMR + 0x0078)
+#define AR5312_DMA1 (AR5312_RESETTMR + 0x007c)
+#define AR5312_ENABLE (AR5312_RESETTMR + 0x0080) /* interface enb */
+#define AR5312_REV (AR5312_RESETTMR + 0x0090) /* revision */
+
+/* AR5312_WD_CTRL register bit field definitions */
+#define AR5312_WD_CTRL_IGNORE_EXPIRATION 0x0000
+#define AR5312_WD_CTRL_NMI 0x0001
+#define AR5312_WD_CTRL_RESET 0x0002
+
+/* AR5312_ISR register bit field definitions */
+#define AR5312_ISR_TIMER 0x0001
+#define AR5312_ISR_AHBPROC 0x0002
+#define AR5312_ISR_AHBDMA 0x0004
+#define AR5312_ISR_GPIO 0x0008
+#define AR5312_ISR_UART0 0x0010
+#define AR5312_ISR_UART0DMA 0x0020
+#define AR5312_ISR_WD 0x0040
+#define AR5312_ISR_LOCAL 0x0080
+
+/* AR5312_RESET register bit field definitions */
+#define AR5312_RESET_SYSTEM 0x00000001 /* cold reset full system */
+#define AR5312_RESET_PROC 0x00000002 /* cold reset MIPS core */
+#define AR5312_RESET_WLAN0 0x00000004 /* cold reset WLAN MAC/BB */
+#define AR5312_RESET_EPHY0 0x00000008 /* cold reset ENET0 phy */
+#define AR5312_RESET_EPHY1 0x00000010 /* cold reset ENET1 phy */
+#define AR5312_RESET_ENET0 0x00000020 /* cold reset ENET0 MAC */
+#define AR5312_RESET_ENET1 0x00000040 /* cold reset ENET1 MAC */
+#define AR5312_RESET_UART0 0x00000100 /* cold reset UART0 */
+#define AR5312_RESET_WLAN1 0x00000200 /* cold reset WLAN MAC/BB */
+#define AR5312_RESET_APB 0x00000400 /* cold reset APB ar5312 */
+#define AR5312_RESET_WARM_PROC 0x00001000 /* warm reset MIPS core */
+#define AR5312_RESET_WARM_WLAN0_MAC 0x00002000 /* warm reset WLAN0 MAC */
+#define AR5312_RESET_WARM_WLAN0_BB 0x00004000 /* warm reset WLAN0 BB */
+#define AR5312_RESET_NMI 0x00010000 /* send an NMI to the CPU */
+#define AR5312_RESET_WARM_WLAN1_MAC 0x00020000 /* warm reset WLAN1 MAC */
+#define AR5312_RESET_WARM_WLAN1_BB 0x00040000 /* warm reset WLAN1 BB */
+#define AR5312_RESET_LOCAL_BUS 0x00080000 /* reset local bus */
+#define AR5312_RESET_WDOG 0x00100000 /* last reset was a wdt */
+
+#define AR5312_RESET_WMAC0_BITS (AR5312_RESET_WLAN0 |\
+ AR5312_RESET_WARM_WLAN0_MAC |\
+ AR5312_RESET_WARM_WLAN0_BB)
+
+#define AR5312_RESET_WMAC1_BITS (AR5312_RESET_WLAN1 |\
+ AR5312_RESET_WARM_WLAN1_MAC |\
+ AR5312_RESET_WARM_WLAN1_BB)
+
+/* AR5312_CLOCKCTL1 register bit field definitions */
+#define AR5312_CLOCKCTL1_PREDIVIDE_MASK 0x00000030
+#define AR5312_CLOCKCTL1_PREDIVIDE_SHIFT 4
+#define AR5312_CLOCKCTL1_MULTIPLIER_MASK 0x00001f00
+#define AR5312_CLOCKCTL1_MULTIPLIER_SHIFT 8
+#define AR5312_CLOCKCTL1_DOUBLER_MASK 0x00010000
+
+/* Valid for AR5312 and AR2312 */
+#define AR5312_CLOCKCTL1_PREDIVIDE_MASK 0x00000030
+#define AR5312_CLOCKCTL1_PREDIVIDE_SHIFT 4
+#define AR5312_CLOCKCTL1_MULTIPLIER_MASK 0x00001f00
+#define AR5312_CLOCKCTL1_MULTIPLIER_SHIFT 8
+#define AR5312_CLOCKCTL1_DOUBLER_MASK 0x00010000
+
+/* Valid for AR2313 */
+#define AR2313_CLOCKCTL1_PREDIVIDE_MASK 0x00003000
+#define AR2313_CLOCKCTL1_PREDIVIDE_SHIFT 12
+#define AR2313_CLOCKCTL1_MULTIPLIER_MASK 0x001f0000
+#define AR2313_CLOCKCTL1_MULTIPLIER_SHIFT 16
+#define AR2313_CLOCKCTL1_DOUBLER_MASK 0x00000000
+
+/* AR5312_ENABLE register bit field definitions */
+#define AR5312_ENABLE_WLAN0 0x0001
+#define AR5312_ENABLE_ENET0 0x0002
+#define AR5312_ENABLE_ENET1 0x0004
+#define AR5312_ENABLE_UART_AND_WLAN1_PIO 0x0008 /* UART & WLAN1 PIOs */
+#define AR5312_ENABLE_WLAN1_DMA 0x0010 /* WLAN1 DMAs */
+#define AR5312_ENABLE_WLAN1 (AR5312_ENABLE_UART_AND_WLAN1_PIO |\
+ AR5312_ENABLE_WLAN1_DMA)
+
+/* AR5312_REV register bit field definitions */
+#define AR5312_REV_WMAC_MAJ 0xf000
+#define AR5312_REV_WMAC_MAJ_S 12
+#define AR5312_REV_WMAC_MIN 0x0f00
+#define AR5312_REV_WMAC_MIN_S 8
+#define AR5312_REV_MAJ 0x00f0
+#define AR5312_REV_MAJ_S 4
+#define AR5312_REV_MIN 0x000f
+#define AR5312_REV_MIN_S 0
+#define AR5312_REV_CHIP (AR5312_REV_MAJ|AR5312_REV_MIN)
+
+/* Major revision numbers, bits 7..4 of Revision ID register */
+#define AR5312_REV_MAJ_AR5312 0x4
+#define AR5312_REV_MAJ_AR2313 0x5
+
+/* Minor revision numbers, bits 3..0 of Revision ID register */
+#define AR5312_REV_MIN_DUAL 0x0 /* Dual WLAN version */
+#define AR5312_REV_MIN_SINGLE 0x1 /* Single WLAN version */
+
+/* AR5312_FLASHCTL register bit field definitions */
+#define AR5312_FLASHCTL_IDCY 0x0000000f /* Idle cycle turnaround time */
+#define AR5312_FLASHCTL_IDCY_S 0
+#define AR5312_FLASHCTL_WST1 0x000003e0 /* Wait state 1 */
+#define AR5312_FLASHCTL_WST1_S 5
+#define AR5312_FLASHCTL_RBLE 0x00000400 /* Read byte lane enable */
+#define AR5312_FLASHCTL_WST2 0x0000f800 /* Wait state 2 */
+#define AR5312_FLASHCTL_WST2_S 11
+#define AR5312_FLASHCTL_AC 0x00070000 /* Flash addr check (added) */
+#define AR5312_FLASHCTL_AC_S 16
+#define AR5312_FLASHCTL_AC_128K 0x00000000
+#define AR5312_FLASHCTL_AC_256K 0x00010000
+#define AR5312_FLASHCTL_AC_512K 0x00020000
+#define AR5312_FLASHCTL_AC_1M 0x00030000
+#define AR5312_FLASHCTL_AC_2M 0x00040000
+#define AR5312_FLASHCTL_AC_4M 0x00050000
+#define AR5312_FLASHCTL_AC_8M 0x00060000
+#define AR5312_FLASHCTL_AC_RES 0x00070000 /* 16MB is not supported */
+#define AR5312_FLASHCTL_E 0x00080000 /* Flash bank enable (added) */
+#define AR5312_FLASHCTL_BUSERR 0x01000000 /* Bus transfer error flag */
+#define AR5312_FLASHCTL_WPERR 0x02000000 /* Write protect error flag */
+#define AR5312_FLASHCTL_WP 0x04000000 /* Write protect */
+#define AR5312_FLASHCTL_BM 0x08000000 /* Burst mode */
+#define AR5312_FLASHCTL_MW 0x30000000 /* Mem width */
+#define AR5312_FLASHCTL_MW8 0x00000000 /* Mem width x8 */
+#define AR5312_FLASHCTL_MW16 0x10000000 /* Mem width x16 */
+#define AR5312_FLASHCTL_MW32 0x20000000 /* Mem width x32 (not supp) */
+#define AR5312_FLASHCTL_ATNR 0x00000000 /* Access == no retry */
+#define AR5312_FLASHCTL_ATR 0x80000000 /* Access == retry every */
+#define AR5312_FLASHCTL_ATR4 0xc0000000 /* Access == retry every 4 */
+
+/* ARM Flash Controller -- 3 flash banks with either x8 or x16 devices. */
+#define AR5312_FLASHCTL0 (AR5312_FLASHCTL + 0x00)
+#define AR5312_FLASHCTL1 (AR5312_FLASHCTL + 0x04)
+#define AR5312_FLASHCTL2 (AR5312_FLASHCTL + 0x08)
+
+/* ARM SDRAM Controller -- just enough to determine memory size */
+#define AR5312_MEM_CFG1 (AR5312_SDRAMCTL + 0x04)
+#define AR5312_MEM_CFG1_AC0_M 0x00000700 /* bank 0: SDRAM addr check */
+#define AR5312_MEM_CFG1_AC0_S 8
+#define AR5312_MEM_CFG1_AC1_M 0x00007000 /* bank 1: SDRAM addr check */
+#define AR5312_MEM_CFG1_AC1_S 12
+
+#endif /* __ASM_MACH_ATH25_AR5312_REGS_H */
--
1.8.5.5
John Crispin
2014-10-21 23:48:34 UTC
Permalink
1 comment inline
Post by Sergey Ryazanov
Add basic support for Atheros AR5312/AR2312 SoCs: registers
definition file and initial setup code.
Changes since v1: - rename MIPS machine ar231x -> ath25
arch/mips/Kconfig | 1 +
arch/mips/ath25/Kconfig | 4 +
arch/mips/ath25/Makefile | 2 +
arch/mips/ath25/ar5312.c | 134
+++++++++++++++++ arch/mips/ath25/ar5312.h |
18 +++ arch/mips/ath25/board.c | 7 +
arch/mips/ath25/prom.c | 5 +
arch/mips/include/asm/mach-ath25/ar5312_regs.h | 190
+++++++++++++++++++++++++ 8 files changed, 361 insertions(+) create
mode 100644 arch/mips/ath25/Kconfig create mode 100644
arch/mips/ath25/ar5312.c create mode 100644
arch/mips/ath25/ar5312.h create mode 100644
arch/mips/include/asm/mach-ath25/ar5312_regs.h
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index
54abb9a..baa1c5b 100644 --- a/arch/mips/Kconfig +++
endchoice
source "arch/mips/alchemy/Kconfig" +source
"arch/mips/ath25/Kconfig" source "arch/mips/ath79/Kconfig" source
"arch/mips/bcm47xx/Kconfig" source "arch/mips/bcm63xx/Kconfig" diff
--git a/arch/mips/ath25/Kconfig b/arch/mips/ath25/Kconfig new file
mode 100644 index 0000000..cf933ea --- /dev/null +++
"Atheros AR5312/AR2312+ SoC support" + depends on ATH25 + default
y diff --git a/arch/mips/ath25/Makefile b/arch/mips/ath25/Makefile
index 9199fa1..3361619 100644 --- a/arch/mips/ath25/Makefile +++
obj-y += board.o prom.o devices.o + +obj-$(CONFIG_SOC_AR5312) +=
ar5312.o diff --git a/arch/mips/ath25/ar5312.c
b/arch/mips/ath25/ar5312.c new file mode 100644 index
conditions of the GNU General Public + * License. See the file
"COPYING" in the main directory of this archive + * for more
details. + * + * Copyright (C) 2003 Atheros Communications, Inc.,
All Rights Reserved. + * Copyright (C) 2006 FON Technology, SL. + *
devices for Atheros AR5312 SoCs + */ + +#include <linux/init.h>
+#include <linux/kernel.h> +#include <linux/reboot.h> +#include
<asm/bootinfo.h> +#include <asm/reboot.h> +#include <asm/time.h> +
+#include <ar5312_regs.h> +#include <ath25.h> + +#include
"devices.h" +#include "ar5312.h" + +static void ar5312_restart(char
*command) +{ + /* reset the system */ + local_irq_disable(); +
while (1) + ath25_write_reg(AR5312_RESET, AR5312_RESET_SYSTEM);
+} + +/* + * This table is indexed by bits 5..4 of the CLOCKCTL1
register + * to determine the predevisor value. + */ +static
unsigned clockctl1_predivide_table[4] __initdata = { 1, 2, 4, 5 };
+ +static unsigned __init ar5312_cpu_frequency(void) +{ + u32
scratch, devid, clock_ctl1; + u32 predivide_mask, multiplier_mask,
doubler_mask; + unsigned predivide_shift, multiplier_shift; +
unsigned predivide_select, predivisor, multiplier; + + /* Trust the
bootrom's idea of cpu frequency. */ + scratch =
ath25_read_reg(AR5312_SCRATCH); + if (scratch) + return scratch;
+ + devid = ath25_read_reg(AR5312_REV); + devid = (devid &
AR5312_REV_MAJ) >> AR5312_REV_MAJ_S; + if (devid ==
AR5312_REV_MAJ_AR2313) { + predivide_mask =
AR2313_CLOCKCTL1_PREDIVIDE_MASK; + predivide_shift =
AR2313_CLOCKCTL1_PREDIVIDE_SHIFT; + multiplier_mask =
AR2313_CLOCKCTL1_MULTIPLIER_MASK; + multiplier_shift =
AR2313_CLOCKCTL1_MULTIPLIER_SHIFT; + doubler_mask =
AR2313_CLOCKCTL1_DOUBLER_MASK; + } else { /* AR5312 and AR2312 */ +
predivide_mask = AR5312_CLOCKCTL1_PREDIVIDE_MASK; +
predivide_shift = AR5312_CLOCKCTL1_PREDIVIDE_SHIFT; +
multiplier_mask = AR5312_CLOCKCTL1_MULTIPLIER_MASK; +
multiplier_shift = AR5312_CLOCKCTL1_MULTIPLIER_SHIFT; +
doubler_mask = AR5312_CLOCKCTL1_DOUBLER_MASK; + } + + /* + *
Clocking is derived from a fixed 40MHz input clock. + * + *
cpu_freq = input_clock * MULT (where MULT is PLL multiplier) + *
sys_freq = cpu_freq / 4 (used for APB clock, serial, + *
flash, Timer, Watchdog Timer) + * + * cnt_freq = cpu_freq / 2
(use for CPU count/compare) + * + * So, for example, with a PLL
multiplier of 5, we have + * + * cpu_freq = 200MHz + *
sys_freq = 50MHz + * cnt_freq = 100MHz + * + * We compute the
CPU frequency, based on PLL settings. + */ + + clock_ctl1 =
ath25_read_reg(AR5312_CLOCKCTL1); + predivide_select = (clock_ctl1
& predivide_mask) >> predivide_shift; + predivisor =
clockctl1_predivide_table[predivide_select]; + multiplier =
(clock_ctl1 & multiplier_mask) >> multiplier_shift; + + if
(clock_ctl1 & doubler_mask) + multiplier <<= 1; + + return
(40000000 / predivisor) * multiplier; +} + +static inline unsigned
ar5312_sys_frequency(void) +{ + return ar5312_cpu_frequency() / 4;
+} + +void __init ar5312_plat_time_init(void) +{ +
mips_hpt_frequency = ar5312_cpu_frequency() / 2; +} + +void __init
ar5312_plat_mem_setup(void) +{ + /* Clear any lingering AHB errors
*/ + ath25_read_reg(AR5312_PROCADDR); +
ath25_read_reg(AR5312_DMAADDR); + ath25_write_reg(AR5312_WD_CTRL,
AR5312_WD_CTRL_IGNORE_EXPIRATION); + + _machine_restart =
ar5312_restart; +} + +void __init ar5312_prom_init(void) +{ + u32
memsize, memcfg, bank0_ac, bank1_ac; + + /* Detect memory size */ +
memcfg = ath25_read_reg(AR5312_MEM_CFG1); + bank0_ac =
ATH25_REG_MS(memcfg, AR5312_MEM_CFG1_AC0); + bank1_ac =
ATH25_REG_MS(memcfg, AR5312_MEM_CFG1_AC1); + memsize = (bank0_ac ?
(1 << (bank0_ac + 1)) : 0) + + (bank1_ac ? (1 << (bank1_ac + 1))
: 0); + memsize <<= 20; + add_memory_region(0, memsize,
BOOT_MEM_RAM); +} + diff --git a/arch/mips/ath25/ar5312.h
b/arch/mips/ath25/ar5312.h new file mode 100644 index
CONFIG_SOC_AR5312 + +void ar5312_plat_time_init(void); +void
ar5312_plat_mem_setup(void); +void ar5312_prom_init(void); +
+#else + +static inline void ar5312_plat_time_init(void) {} +static
inline void ar5312_plat_mem_setup(void) {} +static inline void
ar5312_prom_init(void) {} + +#endif + +#endif /* __AR5312_H */ diff
--git a/arch/mips/ath25/board.c b/arch/mips/ath25/board.c index
cbc6d7b..80683e3 100644 --- a/arch/mips/ath25/board.c +++
<asm/bootinfo.h> #include <asm/time.h>
+#include "ar5312.h" + static void ath25_halt(void) {
plat_mem_setup(void) _machine_halt = ath25_halt; pm_power_off =
ath25_halt;
+ if (is_ar5312()) + ar5312_plat_mem_setup(); +
if i am reading this correct then is_ar5312() can return true even if
CONFIG_SOC_AR5312 is not selected

how about

if (IS_ENABLED(CONFIG_SOC_AR5312) && is_ar5312())
pr_info("AR5312");
else if (IS_ENABLED(CONFIG_SOC_AR2315) && is_ar2315())
pr_info("AR2315");
else
panic("failed to init memory");

somewhere early in the code
Post by Sergey Ryazanov
void __init plat_time_init(void) { + if (is_ar5312()) +
ar5312_plat_time_init(); }
unsigned int __cpuinit get_c0_compare_int(void) diff --git
a/arch/mips/ath25/prom.c b/arch/mips/ath25/prom.c index
edf82be..ec60b0f 100644 --- a/arch/mips/ath25/prom.c +++
<linux/init.h> #include <asm/bootinfo.h>
+#include "devices.h" +#include "ar5312.h" + void __init
prom_init(void) { + if (is_ar5312()) + ar5312_prom_init(); }
void __init prom_free_prom_memory(void) diff --git
a/arch/mips/include/asm/mach-ath25/ar5312_regs.h
b/arch/mips/include/asm/mach-ath25/ar5312_regs.h new file mode
100644 index 0000000..76856d8 --- /dev/null +++
+/* + * This file is subject to the terms and conditions of the GNU
General Public + * License. See the file "COPYING" in the main
directory of this archive + * for more details. + * + * Copyright
(C) 2003 Atheros Communications, Inc., All Rights Reserved. + *
__ASM_MACH_ATH25_AR5312_REGS_H +#define
__ASM_MACH_ATH25_AR5312_REGS_H + +/* + * Address Map + * + * The
AR5312 supports 2 enet MACS, even though many reference boards
only + * actually use 1 of them (i.e. Only MAC 0 is actually
connected to an enet + * PHY or PHY switch. The AR2312 supports 1
enet MAC. + */ +#define AR5312_WLAN0 0x18000000 +#define
AR5312_WLAN1 0x18500000 +#define AR5312_ENET0 0x18100000 +#define
AR5312_ENET1 0x18200000 +#define AR5312_SDRAMCTL 0x18300000
+#define AR5312_FLASHCTL 0x18400000 +#define AR5312_APBBASE
0x1c000000 +#define AR5312_UART0 0x1c000000 /* UART MMR */
+#define AR5312_FLASH 0x1e000000 + +/* + * Need these defines to
determine true number of ethernet MACs + */ +#define
AR5312_AR5312_REV2 0x0052 /* AR5312 WMAC (AP31) */ +#define
AR5312_AR5312_REV7 0x0057 /* AR5312 WMAC (AP30-040) */ +#define
AR5312_AR2313_REV8 0x0058 /* AR2313 WMAC (AP43-030) */ + +/*
Reset/Timer Block Address Map */ +#define AR5312_RESETTMR
(AR5312_APBBASE + 0x3000) +#define AR5312_TIMER (AR5312_RESETTMR
+ 0x0000) /* countdown timer */ +#define AR5312_WD_CTRL
(AR5312_RESETTMR + 0x0008) /* watchdog cntrl */ +#define
AR5312_WD_TIMER (AR5312_RESETTMR + 0x000c) /* watchdog timer */
+#define AR5312_ISR (AR5312_RESETTMR + 0x0010) /* Intr Status Reg
*/ +#define AR5312_IMR (AR5312_RESETTMR + 0x0014) /* Intr Mask Reg
*/ +#define AR5312_RESET (AR5312_RESETTMR + 0x0020) +#define
AR5312_CLOCKCTL1 (AR5312_RESETTMR + 0x0064) +#define AR5312_SCRATCH
(AR5312_RESETTMR + 0x006c) +#define AR5312_PROCADDR
(AR5312_RESETTMR + 0x0070) +#define AR5312_PROC1 (AR5312_RESETTMR
+ 0x0074) +#define AR5312_DMAADDR (AR5312_RESETTMR + 0x0078)
+#define AR5312_DMA1 (AR5312_RESETTMR + 0x007c) +#define
AR5312_ENABLE (AR5312_RESETTMR + 0x0080) /* interface enb */
+#define AR5312_REV (AR5312_RESETTMR + 0x0090) /* revision */ +
+/* AR5312_WD_CTRL register bit field definitions */ +#define
AR5312_WD_CTRL_IGNORE_EXPIRATION 0x0000 +#define AR5312_WD_CTRL_NMI
0x0001 +#define AR5312_WD_CTRL_RESET 0x0002 + +/* AR5312_ISR
register bit field definitions */ +#define AR5312_ISR_TIMER 0x0001
+#define AR5312_ISR_AHBPROC 0x0002 +#define AR5312_ISR_AHBDMA
0x0004 +#define AR5312_ISR_GPIO 0x0008 +#define AR5312_ISR_UART0
0x0010 +#define AR5312_ISR_UART0DMA 0x0020 +#define AR5312_ISR_WD
0x0040 +#define AR5312_ISR_LOCAL 0x0080 + +/* AR5312_RESET register
bit field definitions */ +#define AR5312_RESET_SYSTEM 0x00000001
/* cold reset full system */ +#define AR5312_RESET_PROC 0x00000002
/* cold reset MIPS core */ +#define AR5312_RESET_WLAN0 0x00000004
/* cold reset WLAN MAC/BB */ +#define AR5312_RESET_EPHY0
0x00000008 /* cold reset ENET0 phy */ +#define AR5312_RESET_EPHY1
0x00000010 /* cold reset ENET1 phy */ +#define AR5312_RESET_ENET0
0x00000020 /* cold reset ENET0 MAC */ +#define AR5312_RESET_ENET1
0x00000040 /* cold reset ENET1 MAC */ +#define AR5312_RESET_UART0
0x00000100 /* cold reset UART0 */ +#define AR5312_RESET_WLAN1
0x00000200 /* cold reset WLAN MAC/BB */ +#define AR5312_RESET_APB
0x00000400 /* cold reset APB ar5312 */ +#define
AR5312_RESET_WARM_PROC 0x00001000 /* warm reset MIPS core */
+#define AR5312_RESET_WARM_WLAN0_MAC 0x00002000 /* warm reset
WLAN0 MAC */ +#define AR5312_RESET_WARM_WLAN0_BB 0x00004000 /*
warm reset WLAN0 BB */ +#define AR5312_RESET_NMI 0x00010000 /*
send an NMI to the CPU */ +#define AR5312_RESET_WARM_WLAN1_MAC
0x00020000 /* warm reset WLAN1 MAC */ +#define
AR5312_RESET_WARM_WLAN1_BB 0x00040000 /* warm reset WLAN1 BB */
+#define AR5312_RESET_LOCAL_BUS 0x00080000 /* reset local bus */
+#define AR5312_RESET_WDOG 0x00100000 /* last reset was a wdt */
+ +#define AR5312_RESET_WMAC0_BITS (AR5312_RESET_WLAN0 |\ +
AR5312_RESET_WARM_WLAN0_MAC |\ + AR5312_RESET_WARM_WLAN0_BB)
+ +#define AR5312_RESET_WMAC1_BITS (AR5312_RESET_WLAN1 |\ +
AR5312_RESET_WARM_WLAN1_MAC |\ + AR5312_RESET_WARM_WLAN1_BB)
+ +/* AR5312_CLOCKCTL1 register bit field definitions */ +#define
AR5312_CLOCKCTL1_PREDIVIDE_MASK 0x00000030 +#define
AR5312_CLOCKCTL1_PREDIVIDE_SHIFT 4 +#define
AR5312_CLOCKCTL1_MULTIPLIER_MASK 0x00001f00 +#define
AR5312_CLOCKCTL1_MULTIPLIER_SHIFT 8 +#define
AR5312_CLOCKCTL1_DOUBLER_MASK 0x00010000 + +/* Valid for AR5312
and AR2312 */ +#define AR5312_CLOCKCTL1_PREDIVIDE_MASK 0x00000030
+#define AR5312_CLOCKCTL1_PREDIVIDE_SHIFT 4 +#define
AR5312_CLOCKCTL1_MULTIPLIER_MASK 0x00001f00 +#define
AR5312_CLOCKCTL1_MULTIPLIER_SHIFT 8 +#define
AR5312_CLOCKCTL1_DOUBLER_MASK 0x00010000 + +/* Valid for AR2313
*/ +#define AR2313_CLOCKCTL1_PREDIVIDE_MASK 0x00003000 +#define
AR2313_CLOCKCTL1_PREDIVIDE_SHIFT 12 +#define
AR2313_CLOCKCTL1_MULTIPLIER_MASK 0x001f0000 +#define
AR2313_CLOCKCTL1_MULTIPLIER_SHIFT 16 +#define
AR2313_CLOCKCTL1_DOUBLER_MASK 0x00000000 + +/* AR5312_ENABLE
register bit field definitions */ +#define AR5312_ENABLE_WLAN0
0x0001 +#define AR5312_ENABLE_ENET0 0x0002 +#define
AR5312_ENABLE_ENET1 0x0004 +#define
AR5312_ENABLE_UART_AND_WLAN1_PIO 0x0008 /* UART & WLAN1 PIOs */
+#define AR5312_ENABLE_WLAN1_DMA 0x0010 /* WLAN1 DMAs */
+#define AR5312_ENABLE_WLAN1 (AR5312_ENABLE_UART_AND_WLAN1_PIO |\
+ AR5312_ENABLE_WLAN1_DMA) + +/* AR5312_REV register bit field
definitions */ +#define AR5312_REV_WMAC_MAJ 0xf000 +#define
AR5312_REV_WMAC_MAJ_S 12 +#define AR5312_REV_WMAC_MIN 0x0f00
+#define AR5312_REV_WMAC_MIN_S 8 +#define AR5312_REV_MAJ 0x00f0
+#define AR5312_REV_MAJ_S 4 +#define AR5312_REV_MIN 0x000f
+#define AR5312_REV_MIN_S 0 +#define AR5312_REV_CHIP
(AR5312_REV_MAJ|AR5312_REV_MIN) + +/* Major revision numbers, bits
7..4 of Revision ID register */ +#define AR5312_REV_MAJ_AR5312
0x4 +#define AR5312_REV_MAJ_AR2313 0x5 + +/* Minor revision
numbers, bits 3..0 of Revision ID register */ +#define
AR5312_REV_MIN_DUAL 0x0 /* Dual WLAN version */ +#define
AR5312_REV_MIN_SINGLE 0x1 /* Single WLAN version */ + +/*
AR5312_FLASHCTL register bit field definitions */ +#define
AR5312_FLASHCTL_IDCY 0x0000000f /* Idle cycle turnaround time */
+#define AR5312_FLASHCTL_IDCY_S 0 +#define AR5312_FLASHCTL_WST1
0x000003e0 /* Wait state 1 */ +#define AR5312_FLASHCTL_WST1_S 5
+#define AR5312_FLASHCTL_RBLE 0x00000400 /* Read byte lane enable
*/ +#define AR5312_FLASHCTL_WST2 0x0000f800 /* Wait state 2 */
+#define AR5312_FLASHCTL_WST2_S 11 +#define AR5312_FLASHCTL_AC
0x00070000 /* Flash addr check (added) */ +#define
AR5312_FLASHCTL_AC_S 16 +#define AR5312_FLASHCTL_AC_128K
0x00000000 +#define AR5312_FLASHCTL_AC_256K 0x00010000 +#define
AR5312_FLASHCTL_AC_512K 0x00020000 +#define AR5312_FLASHCTL_AC_1M
0x00030000 +#define AR5312_FLASHCTL_AC_2M 0x00040000 +#define
AR5312_FLASHCTL_AC_4M 0x00050000 +#define AR5312_FLASHCTL_AC_8M
0x00060000 +#define AR5312_FLASHCTL_AC_RES 0x00070000 /* 16MB is
not supported */ +#define AR5312_FLASHCTL_E 0x00080000 /* Flash
bank enable (added) */ +#define AR5312_FLASHCTL_BUSERR 0x01000000
/* Bus transfer error flag */ +#define AR5312_FLASHCTL_WPERR
0x02000000 /* Write protect error flag */ +#define
AR5312_FLASHCTL_WP 0x04000000 /* Write protect */ +#define
AR5312_FLASHCTL_BM 0x08000000 /* Burst mode */ +#define
AR5312_FLASHCTL_MW 0x30000000 /* Mem width */ +#define
AR5312_FLASHCTL_MW8 0x00000000 /* Mem width x8 */ +#define
AR5312_FLASHCTL_MW16 0x10000000 /* Mem width x16 */ +#define
AR5312_FLASHCTL_MW32 0x20000000 /* Mem width x32 (not supp) */
+#define AR5312_FLASHCTL_ATNR 0x00000000 /* Access == no retry */
+#define AR5312_FLASHCTL_ATR 0x80000000 /* Access == retry every
*/ +#define AR5312_FLASHCTL_ATR4 0xc0000000 /* Access == retry
every 4 */ + +/* ARM Flash Controller -- 3 flash banks with either
x8 or x16 devices. */ +#define AR5312_FLASHCTL0 (AR5312_FLASHCTL +
0x00) +#define AR5312_FLASHCTL1 (AR5312_FLASHCTL + 0x04) +#define
AR5312_FLASHCTL2 (AR5312_FLASHCTL + 0x08) + +/* ARM SDRAM
Controller -- just enough to determine memory size */ +#define
AR5312_MEM_CFG1 (AR5312_SDRAMCTL + 0x04) +#define
AR5312_MEM_CFG1_AC0_M 0x00000700 /* bank 0: SDRAM addr check */
+#define AR5312_MEM_CFG1_AC0_S 8 +#define AR5312_MEM_CFG1_AC1_M
0x00007000 /* bank 1: SDRAM addr check */ +#define
AR5312_MEM_CFG1_AC1_S 12 + +#endif /*
__ASM_MACH_ATH25_AR5312_REGS_H */
John Crispin
2014-10-22 00:03:05 UTC
Permalink
yikees ... i updated my mail client and now it is chewing the white
spaces. i will review the rest tomorrow after fixing my mail client .
Post by John Crispin
1 comment inline
Post by Sergey Ryazanov
Add basic support for Atheros AR5312/AR2312 SoCs: registers
definition file and initial setup code.
Changes since v1: - rename MIPS machine ar231x -> ath25
arch/mips/Kconfig | 1 +
arch/mips/ath25/Kconfig | 4 +
arch/mips/ath25/Makefile | 2 +
arch/mips/ath25/ar5312.c | 134
+++++++++++++++++ arch/mips/ath25/ar5312.h
| 18 +++ arch/mips/ath25/board.c | 7 +
arch/mips/ath25/prom.c | 5 +
arch/mips/include/asm/mach-ath25/ar5312_regs.h | 190
+++++++++++++++++++++++++ 8 files changed, 361 insertions(+)
create mode 100644 arch/mips/ath25/Kconfig create mode 100644
arch/mips/ath25/ar5312.c create mode 100644
arch/mips/ath25/ar5312.h create mode 100644
arch/mips/include/asm/mach-ath25/ar5312_regs.h
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index
54abb9a..baa1c5b 100644 --- a/arch/mips/Kconfig +++
endchoice
source "arch/mips/alchemy/Kconfig" +source
"arch/mips/ath25/Kconfig" source "arch/mips/ath79/Kconfig"
source "arch/mips/bcm47xx/Kconfig" source
"arch/mips/bcm63xx/Kconfig" diff --git a/arch/mips/ath25/Kconfig
b/arch/mips/ath25/Kconfig new file mode 100644 index
SoC support" + depends on ATH25 + default y diff --git
a/arch/mips/ath25/Makefile b/arch/mips/ath25/Makefile index
9199fa1..3361619 100644 --- a/arch/mips/ath25/Makefile +++
obj-y += board.o prom.o devices.o + +obj-$(CONFIG_SOC_AR5312) +=
ar5312.o diff --git a/arch/mips/ath25/ar5312.c
b/arch/mips/ath25/ar5312.c new file mode 100644 index
conditions of the GNU General Public + * License. See the file
"COPYING" in the main directory of this archive + * for more
details. + * + * Copyright (C) 2003 Atheros Communications,
Inc., All Rights Reserved. + * Copyright (C) 2006 FON Technology,
+/* + * Platform devices for Atheros AR5312 SoCs + */ + +#include
<linux/init.h> +#include <linux/kernel.h> +#include
<linux/reboot.h> +#include <asm/bootinfo.h> +#include
<asm/reboot.h> +#include <asm/time.h> + +#include <ar5312_regs.h>
+#include <ath25.h> + +#include "devices.h" +#include "ar5312.h"
+ +static void ar5312_restart(char *command) +{ + /* reset the
system */ + local_irq_disable(); + while (1) +
ath25_write_reg(AR5312_RESET, AR5312_RESET_SYSTEM); +} + +/* + *
This table is indexed by bits 5..4 of the CLOCKCTL1 register + *
to determine the predevisor value. + */ +static unsigned
clockctl1_predivide_table[4] __initdata = { 1, 2, 4, 5 }; +
+static unsigned __init ar5312_cpu_frequency(void) +{ + u32
scratch, devid, clock_ctl1; + u32 predivide_mask,
multiplier_mask, doubler_mask; + unsigned predivide_shift,
multiplier_shift; + unsigned predivide_select, predivisor,
multiplier; + + /* Trust the bootrom's idea of cpu frequency. */
+ scratch = ath25_read_reg(AR5312_SCRATCH); + if (scratch) +
return scratch; + + devid = ath25_read_reg(AR5312_REV); + devid =
(devid & AR5312_REV_MAJ) >> AR5312_REV_MAJ_S; + if (devid ==
AR5312_REV_MAJ_AR2313) { + predivide_mask =
AR2313_CLOCKCTL1_PREDIVIDE_MASK; + predivide_shift =
AR2313_CLOCKCTL1_PREDIVIDE_SHIFT; + multiplier_mask =
AR2313_CLOCKCTL1_MULTIPLIER_MASK; + multiplier_shift =
AR2313_CLOCKCTL1_MULTIPLIER_SHIFT; + doubler_mask =
AR2313_CLOCKCTL1_DOUBLER_MASK; + } else { /* AR5312 and AR2312 */
+ predivide_mask = AR5312_CLOCKCTL1_PREDIVIDE_MASK; +
predivide_shift = AR5312_CLOCKCTL1_PREDIVIDE_SHIFT; +
multiplier_mask = AR5312_CLOCKCTL1_MULTIPLIER_MASK; +
multiplier_shift = AR5312_CLOCKCTL1_MULTIPLIER_SHIFT; +
doubler_mask = AR5312_CLOCKCTL1_DOUBLER_MASK; + } + + /* + *
Clocking is derived from a fixed 40MHz input clock. + * + *
cpu_freq = input_clock * MULT (where MULT is PLL multiplier) +
* sys_freq = cpu_freq / 4 (used for APB clock, serial, + *
flash, Timer, Watchdog Timer) + * + * cnt_freq = cpu_freq / 2
(use for CPU count/compare) + * + * So, for example, with a
PLL multiplier of 5, we have + * + * cpu_freq = 200MHz + *
sys_freq = 50MHz + * cnt_freq = 100MHz + * + * We compute
the CPU frequency, based on PLL settings. + */ + + clock_ctl1 =
ath25_read_reg(AR5312_CLOCKCTL1); + predivide_select =
(clock_ctl1 & predivide_mask) >> predivide_shift; + predivisor =
clockctl1_predivide_table[predivide_select]; + multiplier =
(clock_ctl1 & multiplier_mask) >> multiplier_shift; + + if
(clock_ctl1 & doubler_mask) + multiplier <<= 1; + + return
(40000000 / predivisor) * multiplier; +} + +static inline
unsigned ar5312_sys_frequency(void) +{ + return
ar5312_cpu_frequency() / 4; +} + +void __init
ar5312_plat_time_init(void) +{ + mips_hpt_frequency =
ar5312_cpu_frequency() / 2; +} + +void __init
ar5312_plat_mem_setup(void) +{ + /* Clear any lingering AHB
errors */ + ath25_read_reg(AR5312_PROCADDR); +
ath25_read_reg(AR5312_DMAADDR); +
ath25_write_reg(AR5312_WD_CTRL,
AR5312_WD_CTRL_IGNORE_EXPIRATION); + + _machine_restart =
ar5312_restart; +} + +void __init ar5312_prom_init(void) +{ +
u32 memsize, memcfg, bank0_ac, bank1_ac; + + /* Detect memory
size */ + memcfg = ath25_read_reg(AR5312_MEM_CFG1); + bank0_ac =
ATH25_REG_MS(memcfg, AR5312_MEM_CFG1_AC0); + bank1_ac =
ATH25_REG_MS(memcfg, AR5312_MEM_CFG1_AC1); + memsize = (bank0_ac
? (1 << (bank0_ac + 1)) : 0) + + (bank1_ac ? (1 << (bank1_ac +
1)) : 0); + memsize <<= 20; + add_memory_region(0, memsize,
BOOT_MEM_RAM); +} + diff --git a/arch/mips/ath25/ar5312.h
b/arch/mips/ath25/ar5312.h new file mode 100644 index
CONFIG_SOC_AR5312 + +void ar5312_plat_time_init(void); +void
ar5312_plat_mem_setup(void); +void ar5312_prom_init(void); +
+#else + +static inline void ar5312_plat_time_init(void) {}
+static inline void ar5312_plat_mem_setup(void) {} +static inline
void ar5312_prom_init(void) {} + +#endif + +#endif /* __AR5312_H
*/ diff --git a/arch/mips/ath25/board.c b/arch/mips/ath25/board.c
index cbc6d7b..80683e3 100644 --- a/arch/mips/ath25/board.c +++
<asm/bootinfo.h> #include <asm/time.h>
+#include "ar5312.h" + static void ath25_halt(void) {
plat_mem_setup(void) _machine_halt = ath25_halt; pm_power_off =
ath25_halt;
+ if (is_ar5312()) + ar5312_plat_mem_setup(); +
if i am reading this correct then is_ar5312() can return true even
if CONFIG_SOC_AR5312 is not selected
how about
if (IS_ENABLED(CONFIG_SOC_AR5312) && is_ar5312())
pr_info("AR5312"); else if (IS_ENABLED(CONFIG_SOC_AR2315) &&
is_ar2315()) pr_info("AR2315"); else panic("failed to init
memory");
somewhere early in the code
Post by Sergey Ryazanov
void __init plat_time_init(void) { + if (is_ar5312()) +
ar5312_plat_time_init(); }
unsigned int __cpuinit get_c0_compare_int(void) diff --git
a/arch/mips/ath25/prom.c b/arch/mips/ath25/prom.c index
edf82be..ec60b0f 100644 --- a/arch/mips/ath25/prom.c +++
<linux/init.h> #include <asm/bootinfo.h>
+#include "devices.h" +#include "ar5312.h" + void __init
prom_init(void) { + if (is_ar5312()) + ar5312_prom_init(); }
void __init prom_free_prom_memory(void) diff --git
a/arch/mips/include/asm/mach-ath25/ar5312_regs.h
b/arch/mips/include/asm/mach-ath25/ar5312_regs.h new file mode
100644 index 0000000..76856d8 --- /dev/null +++
@@ +/* + * This file is subject to the terms and conditions of
the GNU General Public + * License. See the file "COPYING" in
the main directory of this archive + * for more details. + * + *
Copyright (C) 2003 Atheros Communications, Inc., All Rights
+#ifndef __ASM_MACH_ATH25_AR5312_REGS_H +#define
__ASM_MACH_ATH25_AR5312_REGS_H + +/* + * Address Map + * + * The
AR5312 supports 2 enet MACS, even though many reference boards
only + * actually use 1 of them (i.e. Only MAC 0 is actually
connected to an enet + * PHY or PHY switch. The AR2312 supports
1 enet MAC. + */ +#define AR5312_WLAN0 0x18000000 +#define
AR5312_WLAN1 0x18500000 +#define AR5312_ENET0 0x18100000
+#define AR5312_ENET1 0x18200000 +#define AR5312_SDRAMCTL
0x18300000 +#define AR5312_FLASHCTL 0x18400000 +#define
AR5312_APBBASE 0x1c000000 +#define AR5312_UART0 0x1c000000 /*
UART MMR */ +#define AR5312_FLASH 0x1e000000 + +/* + * Need
these defines to determine true number of ethernet MACs + */
+#define AR5312_AR5312_REV2 0x0052 /* AR5312 WMAC (AP31) */
+#define AR5312_AR5312_REV7 0x0057 /* AR5312 WMAC (AP30-040) */
+#define AR5312_AR2313_REV8 0x0058 /* AR2313 WMAC (AP43-030) */
+ +/* Reset/Timer Block Address Map */ +#define AR5312_RESETTMR
(AR5312_APBBASE + 0x3000) +#define AR5312_TIMER
(AR5312_RESETTMR + 0x0000) /* countdown timer */ +#define
AR5312_WD_CTRL (AR5312_RESETTMR + 0x0008) /* watchdog cntrl */
+#define AR5312_WD_TIMER (AR5312_RESETTMR + 0x000c) /* watchdog
timer */ +#define AR5312_ISR (AR5312_RESETTMR + 0x0010) /* Intr
Status Reg */ +#define AR5312_IMR (AR5312_RESETTMR + 0x0014) /*
Intr Mask Reg */ +#define AR5312_RESET (AR5312_RESETTMR +
0x0020) +#define AR5312_CLOCKCTL1 (AR5312_RESETTMR + 0x0064)
+#define AR5312_SCRATCH (AR5312_RESETTMR + 0x006c) +#define
AR5312_PROCADDR (AR5312_RESETTMR + 0x0070) +#define AR5312_PROC1
(AR5312_RESETTMR + 0x0074) +#define AR5312_DMAADDR
(AR5312_RESETTMR + 0x0078) +#define AR5312_DMA1 (AR5312_RESETTMR
+ 0x007c) +#define AR5312_ENABLE (AR5312_RESETTMR + 0x0080) /*
interface enb */ +#define AR5312_REV (AR5312_RESETTMR + 0x0090)
/* revision */ + +/* AR5312_WD_CTRL register bit field
definitions */ +#define AR5312_WD_CTRL_IGNORE_EXPIRATION 0x0000
+#define AR5312_WD_CTRL_NMI 0x0001 +#define AR5312_WD_CTRL_RESET
0x0002 + +/* AR5312_ISR register bit field definitions */
+#define AR5312_ISR_TIMER 0x0001 +#define AR5312_ISR_AHBPROC
0x0002 +#define AR5312_ISR_AHBDMA 0x0004 +#define AR5312_ISR_GPIO
0x0008 +#define AR5312_ISR_UART0 0x0010 +#define
AR5312_ISR_UART0DMA 0x0020 +#define AR5312_ISR_WD 0x0040 +#define
AR5312_ISR_LOCAL 0x0080 + +/* AR5312_RESET register bit field
definitions */ +#define AR5312_RESET_SYSTEM 0x00000001 /* cold
reset full system */ +#define AR5312_RESET_PROC 0x00000002 /*
cold reset MIPS core */ +#define AR5312_RESET_WLAN0 0x00000004
/* cold reset WLAN MAC/BB */ +#define AR5312_RESET_EPHY0
0x00000008 /* cold reset ENET0 phy */ +#define
AR5312_RESET_EPHY1 0x00000010 /* cold reset ENET1 phy */
+#define AR5312_RESET_ENET0 0x00000020 /* cold reset ENET0 MAC
*/ +#define AR5312_RESET_ENET1 0x00000040 /* cold reset ENET1
MAC */ +#define AR5312_RESET_UART0 0x00000100 /* cold reset
UART0 */ +#define AR5312_RESET_WLAN1 0x00000200 /* cold reset
WLAN MAC/BB */ +#define AR5312_RESET_APB 0x00000400 /* cold
reset APB ar5312 */ +#define AR5312_RESET_WARM_PROC 0x00001000
/* warm reset MIPS core */ +#define AR5312_RESET_WARM_WLAN0_MAC
0x00002000 /* warm reset WLAN0 MAC */ +#define
AR5312_RESET_WARM_WLAN0_BB 0x00004000 /* warm reset WLAN0 BB */
+#define AR5312_RESET_NMI 0x00010000 /* send an NMI to the CPU
*/ +#define AR5312_RESET_WARM_WLAN1_MAC 0x00020000 /* warm reset
WLAN1 MAC */ +#define AR5312_RESET_WARM_WLAN1_BB 0x00040000 /*
warm reset WLAN1 BB */ +#define AR5312_RESET_LOCAL_BUS
0x00080000 /* reset local bus */ +#define AR5312_RESET_WDOG
0x00100000 /* last reset was a wdt */ + +#define
AR5312_RESET_WMAC0_BITS (AR5312_RESET_WLAN0 |\ +
AR5312_RESET_WARM_WLAN0_MAC |\ + AR5312_RESET_WARM_WLAN0_BB)
+ +#define AR5312_RESET_WMAC1_BITS (AR5312_RESET_WLAN1 |\ +
AR5312_RESET_WARM_WLAN1_MAC |\ + AR5312_RESET_WARM_WLAN1_BB)
+ +/* AR5312_CLOCKCTL1 register bit field definitions */
+#define AR5312_CLOCKCTL1_PREDIVIDE_MASK 0x00000030 +#define
AR5312_CLOCKCTL1_PREDIVIDE_SHIFT 4 +#define
AR5312_CLOCKCTL1_MULTIPLIER_MASK 0x00001f00 +#define
AR5312_CLOCKCTL1_MULTIPLIER_SHIFT 8 +#define
AR5312_CLOCKCTL1_DOUBLER_MASK 0x00010000 + +/* Valid for AR5312
and AR2312 */ +#define AR5312_CLOCKCTL1_PREDIVIDE_MASK
0x00000030 +#define AR5312_CLOCKCTL1_PREDIVIDE_SHIFT 4 +#define
AR5312_CLOCKCTL1_MULTIPLIER_MASK 0x00001f00 +#define
AR5312_CLOCKCTL1_MULTIPLIER_SHIFT 8 +#define
AR5312_CLOCKCTL1_DOUBLER_MASK 0x00010000 + +/* Valid for AR2313
*/ +#define AR2313_CLOCKCTL1_PREDIVIDE_MASK 0x00003000 +#define
AR2313_CLOCKCTL1_PREDIVIDE_SHIFT 12 +#define
AR2313_CLOCKCTL1_MULTIPLIER_MASK 0x001f0000 +#define
AR2313_CLOCKCTL1_MULTIPLIER_SHIFT 16 +#define
AR2313_CLOCKCTL1_DOUBLER_MASK 0x00000000 + +/* AR5312_ENABLE
register bit field definitions */ +#define AR5312_ENABLE_WLAN0
0x0001 +#define AR5312_ENABLE_ENET0 0x0002 +#define
AR5312_ENABLE_ENET1 0x0004 +#define
AR5312_ENABLE_UART_AND_WLAN1_PIO 0x0008 /* UART & WLAN1 PIOs */
+#define AR5312_ENABLE_WLAN1_DMA 0x0010 /* WLAN1 DMAs */
+#define AR5312_ENABLE_WLAN1 (AR5312_ENABLE_UART_AND_WLAN1_PIO
|\ + AR5312_ENABLE_WLAN1_DMA) + +/* AR5312_REV register bit
field definitions */ +#define AR5312_REV_WMAC_MAJ 0xf000
+#define AR5312_REV_WMAC_MAJ_S 12 +#define AR5312_REV_WMAC_MIN
0x0f00 +#define AR5312_REV_WMAC_MIN_S 8 +#define AR5312_REV_MAJ
0x00f0 +#define AR5312_REV_MAJ_S 4 +#define AR5312_REV_MIN
0x000f +#define AR5312_REV_MIN_S 0 +#define AR5312_REV_CHIP
(AR5312_REV_MAJ|AR5312_REV_MIN) + +/* Major revision numbers,
bits 7..4 of Revision ID register */ +#define
AR5312_REV_MAJ_AR5312 0x4 +#define AR5312_REV_MAJ_AR2313 0x5 +
+/* Minor revision numbers, bits 3..0 of Revision ID register */
+#define AR5312_REV_MIN_DUAL 0x0 /* Dual WLAN version */
+#define AR5312_REV_MIN_SINGLE 0x1 /* Single WLAN version */ +
+/* AR5312_FLASHCTL register bit field definitions */ +#define
AR5312_FLASHCTL_IDCY 0x0000000f /* Idle cycle turnaround time */
+#define AR5312_FLASHCTL_IDCY_S 0 +#define AR5312_FLASHCTL_WST1
0x000003e0 /* Wait state 1 */ +#define AR5312_FLASHCTL_WST1_S 5
+#define AR5312_FLASHCTL_RBLE 0x00000400 /* Read byte lane
enable */ +#define AR5312_FLASHCTL_WST2 0x0000f800 /* Wait state
2 */ +#define AR5312_FLASHCTL_WST2_S 11 +#define
AR5312_FLASHCTL_AC 0x00070000 /* Flash addr check (added) */
+#define AR5312_FLASHCTL_AC_S 16 +#define
AR5312_FLASHCTL_AC_128K 0x00000000 +#define
AR5312_FLASHCTL_AC_256K 0x00010000 +#define
AR5312_FLASHCTL_AC_512K 0x00020000 +#define
AR5312_FLASHCTL_AC_1M 0x00030000 +#define AR5312_FLASHCTL_AC_2M
0x00040000 +#define AR5312_FLASHCTL_AC_4M 0x00050000 +#define
AR5312_FLASHCTL_AC_8M 0x00060000 +#define AR5312_FLASHCTL_AC_RES
0x00070000 /* 16MB is not supported */ +#define AR5312_FLASHCTL_E
0x00080000 /* Flash bank enable (added) */ +#define
AR5312_FLASHCTL_BUSERR 0x01000000 /* Bus transfer error flag */
+#define AR5312_FLASHCTL_WPERR 0x02000000 /* Write protect error
flag */ +#define AR5312_FLASHCTL_WP 0x04000000 /* Write protect
*/ +#define AR5312_FLASHCTL_BM 0x08000000 /* Burst mode */
+#define AR5312_FLASHCTL_MW 0x30000000 /* Mem width */ +#define
AR5312_FLASHCTL_MW8 0x00000000 /* Mem width x8 */ +#define
AR5312_FLASHCTL_MW16 0x10000000 /* Mem width x16 */ +#define
AR5312_FLASHCTL_MW32 0x20000000 /* Mem width x32 (not supp) */
+#define AR5312_FLASHCTL_ATNR 0x00000000 /* Access == no retry */
+#define AR5312_FLASHCTL_ATR 0x80000000 /* Access == retry
every */ +#define AR5312_FLASHCTL_ATR4 0xc0000000 /* Access ==
retry every 4 */ + +/* ARM Flash Controller -- 3 flash banks with
either x8 or x16 devices. */ +#define AR5312_FLASHCTL0
(AR5312_FLASHCTL + 0x00) +#define AR5312_FLASHCTL1
(AR5312_FLASHCTL + 0x04) +#define AR5312_FLASHCTL2
(AR5312_FLASHCTL + 0x08) + +/* ARM SDRAM Controller -- just
enough to determine memory size */ +#define AR5312_MEM_CFG1
(AR5312_SDRAMCTL + 0x04) +#define AR5312_MEM_CFG1_AC0_M
0x00000700 /* bank 0: SDRAM addr check */ +#define
AR5312_MEM_CFG1_AC0_S 8 +#define AR5312_MEM_CFG1_AC1_M 0x00007000
/* bank 1: SDRAM addr check */ +#define AR5312_MEM_CFG1_AC1_S 12
+ +#endif /* __ASM_MACH_ATH25_AR5312_REGS_H */
Sergey Ryazanov
2014-10-22 14:11:05 UTC
Permalink
Post by John Crispin
1 comment inline
Post by Sergey Ryazanov
Add basic support for Atheros AR5312/AR2312 SoCs: registers
definition file and initial setup code.
Changes since v1: - rename MIPS machine ar231x -> ath25
[snip]
Post by John Crispin
Post by Sergey Ryazanov
void __init prom_init(void)
{
+ if (is_ar5312())
+ ar5312_prom_init();
}
if i am reading this correct then is_ar5312() can return true even if
CONFIG_SOC_AR5312 is not selected
Yep. It checks the version of SoC MIPS core, to distinguish chip
families. If SOC_AR5312 or SOC_AR2315 not selected then respective
chip specific functions are replaced by stubs.
Post by John Crispin
how about
if (IS_ENABLED(CONFIG_SOC_AR5312) && is_ar5312())
pr_info("AR5312");
else if (IS_ENABLED(CONFIG_SOC_AR2315) && is_ar2315())
pr_info("AR2315");
else
panic("failed to init memory");
somewhere early in the code
If you want show to user some message, when kernel was built with
wrong options, then may be:

#if !defined(CONFIG_SOC_AR5312) && !defined(CONFIG_SOC_AR2315)
#error "You should select at least one SoC support option"
#endif

if (!IS_ENABLED(CONFIG_SOC_AR5312) && is_ar5312())
panic("AR5312 SoC support is not builtin");
if (!IS_ENABLED(CONFIG_SOC_AR2315) && is_ar2315())
panic("AR5312 SoC support is not builtin");

IMHO these checks in general is odd.
--
BR,
Sergey
Sergey Ryazanov
2014-10-21 23:03:41 UTC
Permalink
Add basic support for Atheros AR2315+ SoCs: registers definition file
and initial setup code.

Signed-off-by: Sergey Ryazanov <***@gmail.com>
---

Changes since v1:
- rename MIPS machine ar231x -> ath25

arch/mips/ath25/Kconfig | 5 +
arch/mips/ath25/Makefile | 1 +
arch/mips/ath25/ar2315.c | 127 +++++
arch/mips/ath25/ar2315.h | 18 +
arch/mips/ath25/board.c | 5 +
arch/mips/ath25/prom.c | 3 +
arch/mips/include/asm/mach-ath25/ar2315_regs.h | 529 +++++++++++++++++++++
.../include/asm/mach-ath25/cpu-feature-overrides.h | 10 +-
8 files changed, 697 insertions(+), 1 deletion(-)
create mode 100644 arch/mips/ath25/ar2315.c
create mode 100644 arch/mips/ath25/ar2315.h
create mode 100644 arch/mips/include/asm/mach-ath25/ar2315_regs.h

diff --git a/arch/mips/ath25/Kconfig b/arch/mips/ath25/Kconfig
index cf933ea..ca3dde4 100644
--- a/arch/mips/ath25/Kconfig
+++ b/arch/mips/ath25/Kconfig
@@ -2,3 +2,8 @@ config SOC_AR5312
bool "Atheros AR5312/AR2312+ SoC support"
depends on ATH25
default y
+
+config SOC_AR2315
+ bool "Atheros AR2315+ SoC support"
+ depends on ATH25
+ default y
diff --git a/arch/mips/ath25/Makefile b/arch/mips/ath25/Makefile
index 3361619..201b7d4 100644
--- a/arch/mips/ath25/Makefile
+++ b/arch/mips/ath25/Makefile
@@ -11,3 +11,4 @@
obj-y += board.o prom.o devices.o

obj-$(CONFIG_SOC_AR5312) += ar5312.o
+obj-$(CONFIG_SOC_AR2315) += ar2315.o
diff --git a/arch/mips/ath25/ar2315.c b/arch/mips/ath25/ar2315.c
new file mode 100644
index 0000000..4eee362
--- /dev/null
+++ b/arch/mips/ath25/ar2315.c
@@ -0,0 +1,127 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 Atheros Communications, Inc., All Rights Reserved.
+ * Copyright (C) 2006 FON Technology, SL.
+ * Copyright (C) 2006 Imre Kaloz <***@openwrt.org>
+ * Copyright (C) 2006 Felix Fietkau <***@openwrt.org>
+ * Copyright (C) 2012 Alexandros C. Couloumbis <***@ozo.com>
+ */
+
+/*
+ * Platform devices for Atheros AR2315 SoCs
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/reboot.h>
+#include <asm/bootinfo.h>
+#include <asm/reboot.h>
+#include <asm/time.h>
+
+#include <ar2315_regs.h>
+#include <ath25.h>
+
+#include "devices.h"
+#include "ar2315.h"
+
+static void ar2315_restart(char *command)
+{
+ void (*mips_reset_vec)(void) = (void *)0xbfc00000;
+
+ local_irq_disable();
+
+ /* try reset the system via reset control */
+ ath25_write_reg(AR2315_COLD_RESET, AR2317_RESET_SYSTEM);
+
+ /* Attempt to jump to the mips reset location - the boot loader
+ * itself might be able to recover the system */
+ mips_reset_vec();
+}
+
+/*
+ * This table is indexed by bits 5..4 of the CLOCKCTL1 register
+ * to determine the predevisor value.
+ */
+static int clockctl1_predivide_table[4] __initdata = { 1, 2, 4, 5 };
+static int pllc_divide_table[5] __initdata = { 2, 3, 4, 6, 3 };
+
+static unsigned __init ar2315_sys_clk(u32 clock_ctl)
+{
+ unsigned int pllc_ctrl, cpu_div;
+ unsigned int pllc_out, refdiv, fdiv, divby2;
+ unsigned int clk_div;
+
+ pllc_ctrl = ath25_read_reg(AR2315_PLLC_CTL);
+ refdiv = ATH25_REG_MS(pllc_ctrl, AR2315_PLLC_REF_DIV);
+ refdiv = clockctl1_predivide_table[refdiv];
+ fdiv = ATH25_REG_MS(pllc_ctrl, AR2315_PLLC_FDBACK_DIV);
+ divby2 = ATH25_REG_MS(pllc_ctrl, AR2315_PLLC_ADD_FDBACK_DIV) + 1;
+ pllc_out = (40000000 / refdiv) * (2 * divby2) * fdiv;
+
+ /* clkm input selected */
+ switch (clock_ctl & AR2315_CPUCLK_CLK_SEL_M) {
+ case 0:
+ case 1:
+ clk_div = ATH25_REG_MS(pllc_ctrl, AR2315_PLLC_CLKM_DIV);
+ clk_div = pllc_divide_table[clk_div];
+ break;
+ case 2:
+ clk_div = ATH25_REG_MS(pllc_ctrl, AR2315_PLLC_CLKC_DIV);
+ clk_div = pllc_divide_table[clk_div];
+ break;
+ default:
+ pllc_out = 40000000;
+ clk_div = 1;
+ break;
+ }
+
+ cpu_div = ATH25_REG_MS(clock_ctl, AR2315_CPUCLK_CLK_DIV);
+ cpu_div = cpu_div * 2 ?: 1;
+
+ return pllc_out / (clk_div * cpu_div);
+}
+
+static inline unsigned ar2315_cpu_frequency(void)
+{
+ return ar2315_sys_clk(ath25_read_reg(AR2315_CPUCLK));
+}
+
+static inline unsigned ar2315_apb_frequency(void)
+{
+ return ar2315_sys_clk(ath25_read_reg(AR2315_AMBACLK));
+}
+
+void __init ar2315_plat_time_init(void)
+{
+ mips_hpt_frequency = ar2315_cpu_frequency() / 2;
+}
+
+void __init ar2315_plat_mem_setup(void)
+{
+ u32 config;
+
+ /* Clear any lingering AHB errors */
+ config = read_c0_config();
+ write_c0_config(config & ~0x3);
+ ath25_write_reg(AR2315_AHB_ERR0, AR2315_AHB_ERROR_DET);
+ ath25_read_reg(AR2315_AHB_ERR1);
+ ath25_write_reg(AR2315_WDC, AR2315_WDC_IGNORE_EXPIRATION);
+
+ _machine_restart = ar2315_restart;
+}
+
+void __init ar2315_prom_init(void)
+{
+ u32 memsize, memcfg;
+
+ memcfg = ath25_read_reg(AR2315_MEM_CFG);
+ memsize = 1 + ATH25_REG_MS(memcfg, AR2315_MEM_CFG_DATA_WIDTH);
+ memsize <<= 1 + ATH25_REG_MS(memcfg, AR2315_MEM_CFG_COL_WIDTH);
+ memsize <<= 1 + ATH25_REG_MS(memcfg, AR2315_MEM_CFG_ROW_WIDTH);
+ memsize <<= 3;
+ add_memory_region(0, memsize, BOOT_MEM_RAM);
+}
+
diff --git a/arch/mips/ath25/ar2315.h b/arch/mips/ath25/ar2315.h
new file mode 100644
index 0000000..98d32b2
--- /dev/null
+++ b/arch/mips/ath25/ar2315.h
@@ -0,0 +1,18 @@
+#ifndef __AR2315_H
+#define __AR2315_H
+
+#ifdef CONFIG_SOC_AR2315
+
+void ar2315_plat_time_init(void);
+void ar2315_plat_mem_setup(void);
+void ar2315_prom_init(void);
+
+#else
+
+static inline void ar2315_plat_time_init(void) {}
+static inline void ar2315_plat_mem_setup(void) {}
+static inline void ar2315_prom_init(void) {}
+
+#endif
+
+#endif /* __AR2315_H */
diff --git a/arch/mips/ath25/board.c b/arch/mips/ath25/board.c
index 80683e3..a6b8c26 100644
--- a/arch/mips/ath25/board.c
+++ b/arch/mips/ath25/board.c
@@ -17,6 +17,7 @@
#include <asm/time.h>

#include "ar5312.h"
+#include "ar2315.h"

static void ath25_halt(void)
{
@@ -32,6 +33,8 @@ void __init plat_mem_setup(void)

if (is_ar5312())
ar5312_plat_mem_setup();
+ else
+ ar2315_plat_mem_setup();

/* Disable data watchpoints */
write_c0_watchlo0(0);
@@ -45,6 +48,8 @@ void __init plat_time_init(void)
{
if (is_ar5312())
ar5312_plat_time_init();
+ else
+ ar2315_plat_time_init();
}

unsigned int __cpuinit get_c0_compare_int(void)
diff --git a/arch/mips/ath25/prom.c b/arch/mips/ath25/prom.c
index ec60b0f..3fc4f93 100644
--- a/arch/mips/ath25/prom.c
+++ b/arch/mips/ath25/prom.c
@@ -19,11 +19,14 @@

#include "devices.h"
#include "ar5312.h"
+#include "ar2315.h"

void __init prom_init(void)
{
if (is_ar5312())
ar5312_prom_init();
+ else
+ ar2315_prom_init();
}

void __init prom_free_prom_memory(void)
diff --git a/arch/mips/include/asm/mach-ath25/ar2315_regs.h b/arch/mips/include/asm/mach-ath25/ar2315_regs.h
new file mode 100644
index 0000000..ff9a4a8
--- /dev/null
+++ b/arch/mips/include/asm/mach-ath25/ar2315_regs.h
@@ -0,0 +1,529 @@
+/*
+ * Register definitions for AR2315+
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 Atheros Communications, Inc., All Rights Reserved.
+ * Copyright (C) 2006 FON Technology, SL.
+ * Copyright (C) 2006 Imre Kaloz <***@openwrt.org>
+ * Copyright (C) 2006-2008 Felix Fietkau <***@openwrt.org>
+ */
+
+#ifndef __ASM_MACH_ATH25_AR2315_REGS_H
+#define __ASM_MACH_ATH25_AR2315_REGS_H
+
+/*
+ * Address map
+ */
+#define AR2315_SPI_READ 0x08000000 /* SPI flash */
+#define AR2315_WLAN0 0x10000000 /* Wireless MMR */
+#define AR2315_PCI 0x10100000 /* PCI MMR */
+#define AR2315_SDRAMCTL 0x10300000 /* SDRAM MMR */
+#define AR2315_LOCAL 0x10400000 /* Local bus MMR */
+#define AR2315_ENET0 0x10500000 /* Ethernet MMR */
+#define AR2315_DSLBASE 0x11000000 /* Reset control MMR */
+#define AR2315_UART0 0x11100000 /* UART MMR */
+#define AR2315_SPI_MMR 0x11300000 /* SPI flash MMR */
+#define AR2315_PCIEXT 0x80000000 /* PCI external */
+#define AR2315_PCIEXT_SZ 0x40000000
+
+/*
+ * Cold reset register
+ */
+#define AR2315_COLD_RESET (AR2315_DSLBASE + 0x0000)
+
+#define AR2315_RESET_COLD_AHB 0x00000001
+#define AR2315_RESET_COLD_APB 0x00000002
+#define AR2315_RESET_COLD_CPU 0x00000004
+#define AR2315_RESET_COLD_CPUWARM 0x00000008
+#define AR2315_RESET_SYSTEM (RESET_COLD_CPU |\
+ RESET_COLD_APB |\
+ RESET_COLD_AHB) /* full system */
+#define AR2317_RESET_SYSTEM 0x00000010
+
+/*
+ * Reset register
+ */
+#define AR2315_RESET (AR2315_DSLBASE + 0x0004)
+
+#define AR2315_RESET_WARM_WLAN0_MAC 0x00000001 /* warm reset WLAN0 MAC */
+#define AR2315_RESET_WARM_WLAN0_BB 0x00000002 /* warm reset WLAN0 BB */
+#define AR2315_RESET_MPEGTS_RSVD 0x00000004 /* warm reset MPEG-TS */
+#define AR2315_RESET_PCIDMA 0x00000008 /* warm reset PCI ahb/dma */
+#define AR2315_RESET_MEMCTL 0x00000010 /* warm reset mem control */
+#define AR2315_RESET_LOCAL 0x00000020 /* warm reset local bus */
+#define AR2315_RESET_I2C_RSVD 0x00000040 /* warm reset I2C bus */
+#define AR2315_RESET_SPI 0x00000080 /* warm reset SPI iface */
+#define AR2315_RESET_UART0 0x00000100 /* warm reset UART0 */
+#define AR2315_RESET_IR_RSVD 0x00000200 /* warm reset IR iface */
+#define AR2315_RESET_EPHY0 0x00000400 /* cold reset ENET0 phy */
+#define AR2315_RESET_ENET0 0x00000800 /* cold reset ENET0 MAC */
+
+/*
+ * AHB master arbitration control
+ */
+#define AR2315_AHB_ARB_CTL (AR2315_DSLBASE + 0x0008)
+
+#define AR2315_ARB_CPU 0x00000001 /* CPU, default */
+#define AR2315_ARB_WLAN 0x00000002 /* WLAN */
+#define AR2315_ARB_MPEGTS_RSVD 0x00000004 /* MPEG-TS */
+#define AR2315_ARB_LOCAL 0x00000008 /* Local bus */
+#define AR2315_ARB_PCI 0x00000010 /* PCI bus */
+#define AR2315_ARB_ETHERNET 0x00000020 /* Ethernet */
+#define AR2315_ARB_RETRY 0x00000100 /* Retry policy (debug) */
+
+/*
+ * Config Register
+ */
+#define AR2315_ENDIAN_CTL (AR2315_DSLBASE + 0x000c)
+
+#define AR2315_CONFIG_AHB 0x00000001 /* EC-AHB bridge endian */
+#define AR2315_CONFIG_WLAN 0x00000002 /* WLAN byteswap */
+#define AR2315_CONFIG_MPEGTS_RSVD 0x00000004 /* MPEG-TS byteswap */
+#define AR2315_CONFIG_PCI 0x00000008 /* PCI byteswap */
+#define AR2315_CONFIG_MEMCTL 0x00000010 /* Mem controller endian */
+#define AR2315_CONFIG_LOCAL 0x00000020 /* Local bus byteswap */
+#define AR2315_CONFIG_ETHERNET 0x00000040 /* Ethernet byteswap */
+#define AR2315_CONFIG_MERGE 0x00000200 /* CPU write buffer merge */
+#define AR2315_CONFIG_CPU 0x00000400 /* CPU big endian */
+#define AR2315_CONFIG_BIG 0x00000400
+#define AR2315_CONFIG_PCIAHB 0x00000800
+#define AR2315_CONFIG_PCIAHB_BRIDGE 0x00001000
+#define AR2315_CONFIG_SPI 0x00008000 /* SPI byteswap */
+#define AR2315_CONFIG_CPU_DRAM 0x00010000
+#define AR2315_CONFIG_CPU_PCI 0x00020000
+#define AR2315_CONFIG_CPU_MMR 0x00040000
+
+/*
+ * NMI control
+ */
+#define AR2315_NMI_CTL (AR2315_DSLBASE + 0x0010)
+
+#define AR2315_NMI_EN 1
+
+/*
+ * Revision Register - Initial value is 0x3010 (WMAC 3.0, AR231X 1.0).
+ */
+#define AR2315_SREV (AR2315_DSLBASE + 0x0014)
+
+#define AR2315_REV_MAJ 0x00f0
+#define AR2315_REV_MAJ_S 4
+#define AR2315_REV_MIN 0x000f
+#define AR2315_REV_MIN_S 0
+#define AR2315_REV_CHIP (AR2315_REV_MAJ | AR2315_REV_MIN)
+
+/*
+ * Interface Enable
+ */
+#define AR2315_IF_CTL (AR2315_DSLBASE + 0x0018)
+
+#define AR2315_IF_MASK 0x00000007
+#define AR2315_IF_DISABLED 0 /* Disable all */
+#define AR2315_IF_PCI 1 /* PCI */
+#define AR2315_IF_TS_LOCAL 2 /* Local bus */
+#define AR2315_IF_ALL 3 /* Emulation only */
+#define AR2315_IF_LOCAL_HOST 0x00000008
+#define AR2315_IF_PCI_HOST 0x00000010
+#define AR2315_IF_PCI_INTR 0x00000020
+#define AR2315_IF_PCI_CLK_MASK 0x00030000
+#define AR2315_IF_PCI_CLK_INPUT 0
+#define AR2315_IF_PCI_CLK_OUTPUT_LOW 1
+#define AR2315_IF_PCI_CLK_OUTPUT_CLK 2
+#define AR2315_IF_PCI_CLK_OUTPUT_HIGH 3
+#define AR2315_IF_PCI_CLK_SHIFT 16
+
+/*
+ * APB Interrupt control
+ */
+
+#define AR2315_ISR (AR2315_DSLBASE + 0x0020)
+#define AR2315_IMR (AR2315_DSLBASE + 0x0024)
+#define AR2315_GISR (AR2315_DSLBASE + 0x0028)
+
+#define AR2315_ISR_UART0 0x0001 /* high speed UART */
+#define AR2315_ISR_I2C_RSVD 0x0002 /* I2C bus */
+#define AR2315_ISR_SPI 0x0004 /* SPI bus */
+#define AR2315_ISR_AHB 0x0008 /* AHB error */
+#define AR2315_ISR_APB 0x0010 /* APB error */
+#define AR2315_ISR_TIMER 0x0020 /* Timer */
+#define AR2315_ISR_GPIO 0x0040 /* GPIO */
+#define AR2315_ISR_WD 0x0080 /* Watchdog */
+#define AR2315_ISR_IR_RSVD 0x0100 /* IR */
+
+#define AR2315_GISR_MISC 0x0001 /* Misc */
+#define AR2315_GISR_WLAN0 0x0002 /* WLAN0 */
+#define AR2315_GISR_MPEGTS_RSVD 0x0004 /* MPEG-TS */
+#define AR2315_GISR_LOCALPCI 0x0008 /* Local/PCI bus */
+#define AR2315_GISR_WMACPOLL 0x0010
+#define AR2315_GISR_TIMER 0x0020
+#define AR2315_GISR_ETHERNET 0x0040 /* Ethernet */
+
+/*
+ * Timers
+ */
+#define AR2315_TIMER (AR2315_DSLBASE + 0x0030)
+#define AR2315_RELOAD (AR2315_DSLBASE + 0x0034)
+#define AR2315_WD (AR2315_DSLBASE + 0x0038)
+#define AR2315_WDC (AR2315_DSLBASE + 0x003c)
+
+#define AR2315_WDC_IGNORE_EXPIRATION 0x00000000
+#define AR2315_WDC_NMI 0x00000001 /* NMI on watchdog */
+#define AR2315_WDC_RESET 0x00000002 /* reset on watchdog */
+
+/*
+ * CPU Performance Counters
+ */
+#define AR2315_PERFCNT0 (AR2315_DSLBASE + 0x0048)
+#define AR2315_PERFCNT1 (AR2315_DSLBASE + 0x004c)
+
+#define AR2315_PERF0_DATAHIT 0x0001 /* Count Data Cache Hits */
+#define AR2315_PERF0_DATAMISS 0x0002 /* Count Data Cache Misses */
+#define AR2315_PERF0_INSTHIT 0x0004 /* Count Instruction Cache Hits */
+#define AR2315_PERF0_INSTMISS 0x0008 /* Count Instruction Cache Misses */
+#define AR2315_PERF0_ACTIVE 0x0010 /* Count Active Processor Cycles */
+#define AR2315_PERF0_WBHIT 0x0020 /* Count CPU Write Buffer Hits */
+#define AR2315_PERF0_WBMISS 0x0040 /* Count CPU Write Buffer Misses */
+
+#define AR2315_PERF1_EB_ARDY 0x0001 /* Count EB_ARdy signal */
+#define AR2315_PERF1_EB_AVALID 0x0002 /* Count EB_AValid signal */
+#define AR2315_PERF1_EB_WDRDY 0x0004 /* Count EB_WDRdy signal */
+#define AR2315_PERF1_EB_RDVAL 0x0008 /* Count EB_RdVal signal */
+#define AR2315_PERF1_VRADDR 0x0010 /* Count valid read address cycles */
+#define AR2315_PERF1_VWADDR 0x0020 /* Count valid write address cycles */
+#define AR2315_PERF1_VWDATA 0x0040 /* Count valid write data cycles */
+
+/*
+ * AHB Error Reporting.
+ */
+#define AR2315_AHB_ERR0 (AR2315_DSLBASE + 0x0050) /* error */
+#define AR2315_AHB_ERR1 (AR2315_DSLBASE + 0x0054) /* haddr */
+#define AR2315_AHB_ERR2 (AR2315_DSLBASE + 0x0058) /* hwdata */
+#define AR2315_AHB_ERR3 (AR2315_DSLBASE + 0x005c) /* hrdata */
+#define AR2315_AHB_ERR4 (AR2315_DSLBASE + 0x0060) /* status */
+
+#define AR2315_AHB_ERROR_DET 1 /* AHB Error has been detected, */
+ /* write 1 to clear all bits in ERR0 */
+#define AR2315_AHB_ERROR_OVR 2 /* AHB Error overflow has been detected */
+#define AR2315_AHB_ERROR_WDT 4 /* AHB Error due to wdt instead of hresp */
+
+#define AR2315_PROCERR_HMAST 0x0000000f
+#define AR2315_PROCERR_HMAST_DFLT 0
+#define AR2315_PROCERR_HMAST_WMAC 1
+#define AR2315_PROCERR_HMAST_ENET 2
+#define AR2315_PROCERR_HMAST_PCIENDPT 3
+#define AR2315_PROCERR_HMAST_LOCAL 4
+#define AR2315_PROCERR_HMAST_CPU 5
+#define AR2315_PROCERR_HMAST_PCITGT 6
+#define AR2315_PROCERR_HMAST_S 0
+#define AR2315_PROCERR_HWRITE 0x00000010
+#define AR2315_PROCERR_HSIZE 0x00000060
+#define AR2315_PROCERR_HSIZE_S 5
+#define AR2315_PROCERR_HTRANS 0x00000180
+#define AR2315_PROCERR_HTRANS_S 7
+#define AR2315_PROCERR_HBURST 0x00000e00
+#define AR2315_PROCERR_HBURST_S 9
+
+/*
+ * Clock Control
+ */
+#define AR2315_PLLC_CTL (AR2315_DSLBASE + 0x0064)
+#define AR2315_PLLV_CTL (AR2315_DSLBASE + 0x0068)
+#define AR2315_CPUCLK (AR2315_DSLBASE + 0x006c)
+#define AR2315_AMBACLK (AR2315_DSLBASE + 0x0070)
+#define AR2315_SYNCCLK (AR2315_DSLBASE + 0x0074)
+#define AR2315_DSL_SLEEP_CTL (AR2315_DSLBASE + 0x0080)
+#define AR2315_DSL_SLEEP_DUR (AR2315_DSLBASE + 0x0084)
+
+/* PLLc Control fields */
+#define AR2315_PLLC_REF_DIV_M 0x00000003
+#define AR2315_PLLC_REF_DIV_S 0
+#define AR2315_PLLC_FDBACK_DIV_M 0x0000007C
+#define AR2315_PLLC_FDBACK_DIV_S 2
+#define AR2315_PLLC_ADD_FDBACK_DIV_M 0x00000080
+#define AR2315_PLLC_ADD_FDBACK_DIV_S 7
+#define AR2315_PLLC_CLKC_DIV_M 0x0001c000
+#define AR2315_PLLC_CLKC_DIV_S 14
+#define AR2315_PLLC_CLKM_DIV_M 0x00700000
+#define AR2315_PLLC_CLKM_DIV_S 20
+
+/* CPU CLK Control fields */
+#define AR2315_CPUCLK_CLK_SEL_M 0x00000003
+#define AR2315_CPUCLK_CLK_SEL_S 0
+#define AR2315_CPUCLK_CLK_DIV_M 0x0000000c
+#define AR2315_CPUCLK_CLK_DIV_S 2
+
+/* AMBA CLK Control fields */
+#define AR2315_AMBACLK_CLK_SEL_M 0x00000003
+#define AR2315_AMBACLK_CLK_SEL_S 0
+#define AR2315_AMBACLK_CLK_DIV_M 0x0000000c
+#define AR2315_AMBACLK_CLK_DIV_S 2
+
+/*
+ * PCI Clock Control
+ */
+#define AR2315_PCICLK (AR2315_DSLBASE + 0x00a4)
+
+#define AR2315_PCICLK_INPUT_M 0x3
+#define AR2315_PCICLK_INPUT_S 0
+#define AR2315_PCICLK_PLLC_CLKM 0
+#define AR2315_PCICLK_PLLC_CLKM1 1
+#define AR2315_PCICLK_PLLC_CLKC 2
+#define AR2315_PCICLK_REF_CLK 3
+#define AR2315_PCICLK_DIV_M 0xc
+#define AR2315_PCICLK_DIV_S 2
+#define AR2315_PCICLK_IN_FREQ 0
+#define AR2315_PCICLK_IN_FREQ_DIV_6 1
+#define AR2315_PCICLK_IN_FREQ_DIV_8 2
+#define AR2315_PCICLK_IN_FREQ_DIV_10 3
+
+/*
+ * Observation Control Register
+ */
+#define AR2315_OCR (AR2315_DSLBASE + 0x00b0)
+
+#define AR2315_OCR_GPIO0_IRIN 0x0040
+#define AR2315_OCR_GPIO1_IROUT 0x0080
+#define AR2315_OCR_GPIO3_RXCLR 0x0200
+
+/*
+ * General Clock Control
+ */
+
+#define AR2315_MISCCLK (AR2315_DSLBASE + 0x00b4)
+
+#define AR2315_MISCCLK_PLLBYPASS_EN 0x00000001
+#define AR2315_MISCCLK_PROCREFCLK 0x00000002
+
+/*
+ * SDRAM Controller
+ * - No read or write buffers are included.
+ */
+#define AR2315_MEM_CFG (AR2315_SDRAMCTL + 0x00)
+#define AR2315_MEM_CTRL (AR2315_SDRAMCTL + 0x0c)
+#define AR2315_MEM_REF (AR2315_SDRAMCTL + 0x10)
+
+#define AR2315_MEM_CFG_DATA_WIDTH_M 0x00006000
+#define AR2315_MEM_CFG_DATA_WIDTH_S 13
+#define AR2315_MEM_CFG_COL_WIDTH_M 0x00001E00
+#define AR2315_MEM_CFG_COL_WIDTH_S 9
+#define AR2315_MEM_CFG_ROW_WIDTH_M 0x000001E0
+#define AR2315_MEM_CFG_ROW_WIDTH_S 5
+#define AR2315_MEM_CFG_BANKADDR_BITS_M 0x00000018
+#define AR2315_MEM_CFG_BANKADDR_BITS_S 3
+
+/*
+ * PCI Bus Interface Registers
+ */
+#define AR2315_PCI_1MS_REG (AR2315_PCI + 0x0008)
+
+#define AR2315_PCI_1MS_MASK 0x3FFFF /* # of AHB clk cycles in 1ms */
+
+#define AR2315_PCI_MISC_CONFIG (AR2315_PCI + 0x000c)
+
+#define AR2315_PCIMISC_TXD_EN 0x00000001 /* Enable TXD for fragments */
+#define AR2315_PCIMISC_CFG_SEL 0x00000002 /* Mem or Config cycles */
+#define AR2315_PCIMISC_GIG_MASK 0x0000000C /* bits 31-30 for pci req */
+#define AR2315_PCIMISC_RST_MODE 0x00000030
+#define AR2315_PCIRST_INPUT 0x00000000 /* 4:5=0 rst is input */
+#define AR2315_PCIRST_LOW 0x00000010 /* 4:5=1 rst to GND */
+#define AR2315_PCIRST_HIGH 0x00000020 /* 4:5=2 rst to VDD */
+#define AR2315_PCIGRANT_EN 0x00000000 /* 6:7=0 early grant en */
+#define AR2315_PCIGRANT_FRAME 0x00000040 /* 6:7=1 grant waits 4 frame */
+#define AR2315_PCIGRANT_IDLE 0x00000080 /* 6:7=2 grant waits 4 idle */
+#define AR2315_PCIGRANT_GAP 0x00000000 /* 6:7=2 grant waits 4 idle */
+#define AR2315_PCICACHE_DIS 0x00001000 /* PCI external access cache
+ * disable */
+
+#define AR2315_PCI_OUT_TSTAMP (AR2315_PCI + 0x0010)
+
+#define AR2315_PCI_UNCACHE_CFG (AR2315_PCI + 0x0014)
+
+#define AR2315_PCI_IN_EN (AR2315_PCI + 0x0100)
+
+#define AR2315_PCI_IN_EN0 0x01 /* Enable chain 0 */
+#define AR2315_PCI_IN_EN1 0x02 /* Enable chain 1 */
+#define AR2315_PCI_IN_EN2 0x04 /* Enable chain 2 */
+#define AR2315_PCI_IN_EN3 0x08 /* Enable chain 3 */
+
+#define AR2315_PCI_IN_DIS (AR2315_PCI + 0x0104)
+
+#define AR2315_PCI_IN_DIS0 0x01 /* Disable chain 0 */
+#define AR2315_PCI_IN_DIS1 0x02 /* Disable chain 1 */
+#define AR2315_PCI_IN_DIS2 0x04 /* Disable chain 2 */
+#define AR2315_PCI_IN_DIS3 0x08 /* Disable chain 3 */
+
+#define AR2315_PCI_IN_PTR (AR2315_PCI + 0x0200)
+
+#define AR2315_PCI_OUT_EN (AR2315_PCI + 0x0400)
+
+#define AR2315_PCI_OUT_EN0 0x01 /* Enable chain 0 */
+
+#define AR2315_PCI_OUT_DIS (AR2315_PCI + 0x0404)
+
+#define AR2315_PCI_OUT_DIS0 0x01 /* Disable chain 0 */
+
+#define AR2315_PCI_OUT_PTR (AR2315_PCI + 0x0408)
+
+/*
+ * PCI interrupt status
+ * Write one to clear
+ */
+#define AR2315_PCI_ISR (AR2315_PCI + 0x0500)
+
+#define AR2315_PCI_INT_TX 0x00000001 /* Desc In Completed */
+#define AR2315_PCI_INT_TXOK 0x00000002 /* Desc In OK */
+#define AR2315_PCI_INT_TXERR 0x00000004 /* Desc In ERR */
+#define AR2315_PCI_INT_TXEOL 0x00000008 /* Desc In End-of-List */
+#define AR2315_PCI_INT_RX 0x00000010 /* Desc Out Completed */
+#define AR2315_PCI_INT_RXOK 0x00000020 /* Desc Out OK */
+#define AR2315_PCI_INT_RXERR 0x00000040 /* Desc Out ERR */
+#define AR2315_PCI_INT_RXEOL 0x00000080 /* Desc Out EOL */
+#define AR2315_PCI_INT_TXOOD 0x00000200 /* Desc In Out-of-Desc */
+#define AR2315_PCI_INT_DESCMASK 0x0000FFFF /* Desc Mask */
+#define AR2315_PCI_INT_EXT 0x02000000 /* Extern PCI INTA */
+#define AR2315_PCI_INT_ABORT 0x04000000 /* PCI bus abort event */
+
+/* PCI interrupt mask */
+#define AR2315_PCI_IMR (AR2315_PCI + 0x0504)
+
+/* Global PCI interrupt enable */
+#define AR2315_PCI_IER (AR2315_PCI + 0x0508)
+
+#define AR2315_PCI_IER_DISABLE 0x00 /* disable pci interrupts */
+#define AR2315_PCI_IER_ENABLE 0x01 /* enable pci interrupts */
+
+#define AR2315_PCI_HOST_IN_EN (AR2315_PCI + 0x0800)
+#define AR2315_PCI_HOST_IN_DIS (AR2315_PCI + 0x0804)
+#define AR2315_PCI_HOST_IN_PTR (AR2315_PCI + 0x0810)
+#define AR2315_PCI_HOST_OUT_EN (AR2315_PCI + 0x0900)
+#define AR2315_PCI_HOST_OUT_DIS (AR2315_PCI + 0x0904)
+#define AR2315_PCI_HOST_OUT_PTR (AR2315_PCI + 0x0908)
+
+/*
+ * Local Bus Interface Registers
+ */
+#define AR2315_LB_CONFIG (AR2315_LOCAL + 0x0000)
+
+#define AR2315_LBCONF_OE 0x00000001 /* =1 OE is low-true */
+#define AR2315_LBCONF_CS0 0x00000002 /* =1 first CS is low-true */
+#define AR2315_LBCONF_CS1 0x00000004 /* =1 2nd CS is low-true */
+#define AR2315_LBCONF_RDY 0x00000008 /* =1 RDY is low-true */
+#define AR2315_LBCONF_WE 0x00000010 /* =1 Write En is low-true */
+#define AR2315_LBCONF_WAIT 0x00000020 /* =1 WAIT is low-true */
+#define AR2315_LBCONF_ADS 0x00000040 /* =1 Adr Strobe is low-true */
+#define AR2315_LBCONF_MOT 0x00000080 /* =0 Intel, =1 Motorola */
+#define AR2315_LBCONF_8CS 0x00000100 /* =1 8 bits CS, 0= 16bits */
+#define AR2315_LBCONF_8DS 0x00000200 /* =1 8 bits Data S, 0=16bits */
+#define AR2315_LBCONF_ADS_EN 0x00000400 /* =1 Enable ADS */
+#define AR2315_LBCONF_ADR_OE 0x00000800 /* =1 Adr cap on OE, WE or DS */
+#define AR2315_LBCONF_ADDT_MUX 0x00001000 /* =1 Adr and Data share bus */
+#define AR2315_LBCONF_DATA_OE 0x00002000 /* =1 Data cap on OE, WE, DS */
+#define AR2315_LBCONF_16DATA 0x00004000 /* =1 Data is 16 bits wide */
+#define AR2315_LBCONF_SWAPDT 0x00008000 /* =1 Byte swap data */
+#define AR2315_LBCONF_SYNC 0x00010000 /* =1 Bus synchronous to clk */
+#define AR2315_LBCONF_INT 0x00020000 /* =1 Intr is low true */
+#define AR2315_LBCONF_INT_CTR0 0x00000000 /* GND high-Z, Vdd is high-Z */
+#define AR2315_LBCONF_INT_CTR1 0x00040000 /* GND drive, Vdd is high-Z */
+#define AR2315_LBCONF_INT_CTR2 0x00080000 /* GND high-Z, Vdd drive */
+#define AR2315_LBCONF_INT_CTR3 0x000C0000 /* GND drive, Vdd drive */
+#define AR2315_LBCONF_RDY_WAIT 0x00100000 /* =1 RDY is negative of WAIT */
+#define AR2315_LBCONF_INT_PULSE 0x00200000 /* =1 Interrupt is a pulse */
+#define AR2315_LBCONF_ENABLE 0x00400000 /* =1 Falcon respond to LB */
+
+#define AR2315_LB_CLKSEL (AR2315_LOCAL + 0x0004)
+
+#define AR2315_LBCLK_EXT 0x0001 /* use external clk for lb */
+
+#define AR2315_LB_1MS (AR2315_LOCAL + 0x0008)
+
+#define AR2315_LB1MS_MASK 0x3FFFF /* # of AHB clk cycles in 1ms */
+
+#define AR2315_LB_MISCCFG (AR2315_LOCAL + 0x000C)
+
+#define AR2315_LBM_TXD_EN 0x00000001 /* Enable TXD for fragments */
+#define AR2315_LBM_RX_INTEN 0x00000002 /* Enable LB ints on RX ready */
+#define AR2315_LBM_MBOXWR_INTEN 0x00000004 /* Enable LB ints on mbox wr */
+#define AR2315_LBM_MBOXRD_INTEN 0x00000008 /* Enable LB ints on mbox rd */
+#define AR2315_LMB_DESCSWAP_EN 0x00000010 /* Byte swap desc enable */
+#define AR2315_LBM_TIMEOUT_M 0x00FFFF80
+#define AR2315_LBM_TIMEOUT_S 7
+#define AR2315_LBM_PORTMUX 0x07000000
+
+#define AR2315_LB_RXTSOFF (AR2315_LOCAL + 0x0010)
+
+#define AR2315_LB_TX_CHAIN_EN (AR2315_LOCAL + 0x0100)
+
+#define AR2315_LB_TXEN_0 0x01
+#define AR2315_LB_TXEN_1 0x02
+#define AR2315_LB_TXEN_2 0x04
+#define AR2315_LB_TXEN_3 0x08
+
+#define AR2315_LB_TX_CHAIN_DIS (AR2315_LOCAL + 0x0104)
+#define AR2315_LB_TX_DESC_PTR (AR2315_LOCAL + 0x0200)
+
+#define AR2315_LB_RX_CHAIN_EN (AR2315_LOCAL + 0x0400)
+
+#define AR2315_LB_RXEN 0x01
+
+#define AR2315_LB_RX_CHAIN_DIS (AR2315_LOCAL + 0x0404)
+#define AR2315_LB_RX_DESC_PTR (AR2315_LOCAL + 0x0408)
+
+#define AR2315_LB_INT_STATUS (AR2315_LOCAL + 0x0500)
+
+#define AR2315_INT_TX_DESC 0x0001
+#define AR2315_INT_TX_OK 0x0002
+#define AR2315_INT_TX_ERR 0x0004
+#define AR2315_INT_TX_EOF 0x0008
+#define AR2315_INT_RX_DESC 0x0010
+#define AR2315_INT_RX_OK 0x0020
+#define AR2315_INT_RX_ERR 0x0040
+#define AR2315_INT_RX_EOF 0x0080
+#define AR2315_INT_TX_TRUNC 0x0100
+#define AR2315_INT_TX_STARVE 0x0200
+#define AR2315_INT_LB_TIMEOUT 0x0400
+#define AR2315_INT_LB_ERR 0x0800
+#define AR2315_INT_MBOX_WR 0x1000
+#define AR2315_INT_MBOX_RD 0x2000
+
+/* Bit definitions for INT MASK are the same as INT_STATUS */
+#define AR2315_LB_INT_MASK (AR2315_LOCAL + 0x0504)
+
+#define AR2315_LB_INT_EN (AR2315_LOCAL + 0x0508)
+#define AR2315_LB_MBOX (AR2315_LOCAL + 0x0600)
+
+/*
+ * IR Interface Registers
+ */
+#define AR2315_IR_PKTDATA (AR2315_IR + 0x0000)
+
+#define AR2315_IR_PKTLEN (AR2315_IR + 0x07fc) /* 0 - 63 */
+
+#define AR2315_IR_CONTROL (AR2315_IR + 0x0800)
+
+#define AR2315_IRCTL_TX 0x00000000 /* use as tranmitter */
+#define AR2315_IRCTL_RX 0x00000001 /* use as receiver */
+#define AR2315_IRCTL_SAMPLECLK_M 0x00003ffe /* Sample clk divisor */
+#define AR2315_IRCTL_SAMPLECLK_S 1
+#define AR2315_IRCTL_OUTPUTCLK_M 0x03ffc000 /* Output clk div */
+#define AR2315_IRCTL_OUTPUTCLK_S 14
+
+#define AR2315_IR_STATUS (AR2315_IR + 0x0804)
+
+#define AR2315_IRSTS_RX 0x00000001 /* receive in progress */
+#define AR2315_IRSTS_TX 0x00000002 /* transmit in progress */
+
+#define AR2315_IR_CONFIG (AR2315_IR + 0x0808)
+
+#define AR2315_IRCFG_INVIN 0x00000001 /* invert in polarity */
+#define AR2315_IRCFG_INVOUT 0x00000002 /* invert out polarity */
+#define AR2315_IRCFG_SEQ_START_WIN_SEL 0x00000004 /* 1 => 28, 0 => 7 */
+#define AR2315_IRCFG_SEQ_START_THRESH 0x000000f0
+#define AR2315_IRCFG_SEQ_END_UNIT_SEL 0x00000100
+#define AR2315_IRCFG_SEQ_END_UNIT_THRESH 0x00007e00
+#define AR2315_IRCFG_SEQ_END_WIN_SEL 0x00008000
+#define AR2315_IRCFG_SEQ_END_WIN_THRESH 0x001f0000
+#define AR2315_IRCFG_NUM_BACKOFF_WORDS 0x01e00000
+
+#endif /* __ASM_MACH_ATH25_AR2315_REGS_H */
diff --git a/arch/mips/include/asm/mach-ath25/cpu-feature-overrides.h b/arch/mips/include/asm/mach-ath25/cpu-feature-overrides.h
index c1aebdc..e66ca0d 100644
--- a/arch/mips/include/asm/mach-ath25/cpu-feature-overrides.h
+++ b/arch/mips/include/asm/mach-ath25/cpu-feature-overrides.h
@@ -36,11 +36,15 @@
/* #define cpu_has_mcheck ? */
#define cpu_has_ejtag 1

+#if !defined(CONFIG_SOC_AR5312)
+# define cpu_has_llsc 1
+#else
/*
* The MIPS 4Kc V0.9 core in the AR5312/AR2312 have problems with the
* ll/sc instructions.
*/
-#define cpu_has_llsc 0
+# define cpu_has_llsc 0
+#endif

#define cpu_has_mips16 0
#define cpu_has_mdmx 0
@@ -56,6 +60,10 @@

#define cpu_has_mips32r1 1

+#if !defined(CONFIG_SOC_AR5312)
+# define cpu_has_mips32r2 1
+#endif
+
#define cpu_has_mips64r1 0
#define cpu_has_mips64r2 0
--
1.8.5.5
Sergey Ryazanov
2014-10-21 23:03:42 UTC
Permalink
Add interrupts initialization and handling routines, also add AHB bus
error interrupt handlers for both SoCs families.

Signed-off-by: Sergey Ryazanov <***@gmail.com>
---

Changes since RFC:
- add all interrupts
- use dynamic IRQ numbers allocation

Changes since v1:
- rename MIPS machine ar231x -> ath25

arch/mips/ath25/ar2315.c | 108 +++++++++++++++++++++++++
arch/mips/ath25/ar2315.h | 2 +
arch/mips/ath25/ar5312.c | 103 +++++++++++++++++++++++
arch/mips/ath25/ar5312.h | 2 +
arch/mips/ath25/board.c | 10 +++
arch/mips/ath25/devices.h | 2 +
arch/mips/include/asm/mach-ath25/ar2315_regs.h | 23 ++++++
arch/mips/include/asm/mach-ath25/ar5312_regs.h | 23 ++++++
arch/mips/include/asm/mach-ath25/ath25.h | 2 +
9 files changed, 275 insertions(+)

diff --git a/arch/mips/ath25/ar2315.c b/arch/mips/ath25/ar2315.c
index 4eee362..e1a338b 100644
--- a/arch/mips/ath25/ar2315.c
+++ b/arch/mips/ath25/ar2315.c
@@ -27,6 +27,114 @@
#include "devices.h"
#include "ar2315.h"

+static unsigned ar2315_misc_irq_base;
+
+static irqreturn_t ar2315_ahb_err_handler(int cpl, void *dev_id)
+{
+ ath25_write_reg(AR2315_AHB_ERR0, AR2315_AHB_ERROR_DET);
+ ath25_read_reg(AR2315_AHB_ERR1);
+
+ pr_emerg("AHB fatal error\n");
+ machine_restart("AHB error"); /* Catastrophic failure */
+
+ return IRQ_HANDLED;
+}
+
+static struct irqaction ar2315_ahb_err_interrupt = {
+ .handler = ar2315_ahb_err_handler,
+ .name = "ar2315-ahb-error",
+};
+
+static void ar2315_misc_irq_handler(unsigned irq, struct irq_desc *desc)
+{
+ u32 pending = ath25_read_reg(AR2315_ISR) & ath25_read_reg(AR2315_IMR);
+ unsigned base = ar2315_misc_irq_base;
+
+ if (pending & AR2315_ISR_SPI)
+ generic_handle_irq(base + AR2315_MISC_IRQ_SPI);
+ else if (pending & AR2315_ISR_TIMER)
+ generic_handle_irq(base + AR2315_MISC_IRQ_TIMER);
+ else if (pending & AR2315_ISR_AHB)
+ generic_handle_irq(base + AR2315_MISC_IRQ_AHB);
+ else if (pending & AR2315_ISR_GPIO) {
+ ath25_write_reg(AR2315_ISR, AR2315_ISR_GPIO);
+ generic_handle_irq(base + AR2315_MISC_IRQ_GPIO);
+ } else if (pending & AR2315_ISR_UART0)
+ generic_handle_irq(base + AR2315_MISC_IRQ_UART0);
+ else if (pending & AR2315_ISR_WD) {
+ ath25_write_reg(AR2315_ISR, AR2315_ISR_WD);
+ generic_handle_irq(base + AR2315_MISC_IRQ_WATCHDOG);
+ } else
+ spurious_interrupt();
+}
+
+static void ar2315_misc_irq_unmask(struct irq_data *d)
+{
+ u32 imr = ath25_read_reg(AR2315_IMR);
+
+ imr |= 1 << (d->irq - ar2315_misc_irq_base);
+ ath25_write_reg(AR2315_IMR, imr);
+}
+
+static void ar2315_misc_irq_mask(struct irq_data *d)
+{
+ u32 imr = ath25_read_reg(AR2315_IMR);
+
+ imr &= ~(1 << (d->irq - ar2315_misc_irq_base));
+ ath25_write_reg(AR2315_IMR, imr);
+}
+
+static struct irq_chip ar2315_misc_irq_chip = {
+ .name = "ar2315-misc",
+ .irq_unmask = ar2315_misc_irq_unmask,
+ .irq_mask = ar2315_misc_irq_mask,
+};
+
+/*
+ * Called when an interrupt is received, this function
+ * determines exactly which interrupt it was, and it
+ * invokes the appropriate handler.
+ *
+ * Implicitly, we also define interrupt priority by
+ * choosing which to dispatch first.
+ */
+static void ar2315_irq_dispatch(void)
+{
+ u32 pending = read_c0_status() & read_c0_cause();
+
+ if (pending & CAUSEF_IP3)
+ do_IRQ(AR2315_IRQ_WLAN0);
+ else if (pending & CAUSEF_IP2)
+ do_IRQ(AR2315_IRQ_MISC);
+ else if (pending & CAUSEF_IP7)
+ do_IRQ(ATH25_IRQ_CPU_CLOCK);
+ else
+ spurious_interrupt();
+}
+
+void __init ar2315_arch_init_irq(void)
+{
+ unsigned i;
+ int res;
+
+ ath25_irq_dispatch = ar2315_irq_dispatch;
+
+ res = irq_alloc_descs(-1, 0, AR2315_MISC_IRQ_COUNT, 0);
+ if (res < 0)
+ pr_emerg("Failed to allocate misc IRQ numbers\n");
+ ar2315_misc_irq_base = res;
+
+ for (i = 0; i < AR2315_MISC_IRQ_COUNT; i++) {
+ unsigned irq = ar2315_misc_irq_base + i;
+
+ irq_set_chip_and_handler(irq, &ar2315_misc_irq_chip,
+ handle_level_irq);
+ }
+ setup_irq(ar2315_misc_irq_base + AR2315_MISC_IRQ_AHB,
+ &ar2315_ahb_err_interrupt);
+ irq_set_chained_handler(AR2315_IRQ_MISC, ar2315_misc_irq_handler);
+}
+
static void ar2315_restart(char *command)
{
void (*mips_reset_vec)(void) = (void *)0xbfc00000;
diff --git a/arch/mips/ath25/ar2315.h b/arch/mips/ath25/ar2315.h
index 98d32b2..2a57858 100644
--- a/arch/mips/ath25/ar2315.h
+++ b/arch/mips/ath25/ar2315.h
@@ -3,12 +3,14 @@

#ifdef CONFIG_SOC_AR2315

+void ar2315_arch_init_irq(void);
void ar2315_plat_time_init(void);
void ar2315_plat_mem_setup(void);
void ar2315_prom_init(void);

#else

+static inline void ar2315_arch_init_irq(void) {}
static inline void ar2315_plat_time_init(void) {}
static inline void ar2315_plat_mem_setup(void) {}
static inline void ar2315_prom_init(void) {}
diff --git a/arch/mips/ath25/ar5312.c b/arch/mips/ath25/ar5312.c
index 80d7ed7..e9c7f71 100644
--- a/arch/mips/ath25/ar5312.c
+++ b/arch/mips/ath25/ar5312.c
@@ -27,6 +27,109 @@
#include "devices.h"
#include "ar5312.h"

+static unsigned ar5312_misc_irq_base;
+
+static irqreturn_t ar5312_ahb_err_handler(int cpl, void *dev_id)
+{
+ u32 proc1 = ath25_read_reg(AR5312_PROC1);
+ u32 proc_addr = ath25_read_reg(AR5312_PROCADDR); /* clears error */
+ u32 dma1 = ath25_read_reg(AR5312_DMA1);
+ u32 dma_addr = ath25_read_reg(AR5312_DMAADDR); /* clears error */
+
+ pr_emerg("AHB interrupt: PROCADDR=0x%8.8x PROC1=0x%8.8x DMAADDR=0x%8.8x DMA1=0x%8.8x\n",
+ proc_addr, proc1, dma_addr, dma1);
+
+ machine_restart("AHB error"); /* Catastrophic failure */
+ return IRQ_HANDLED;
+}
+
+static struct irqaction ar5312_ahb_err_interrupt = {
+ .handler = ar5312_ahb_err_handler,
+ .name = "ar5312-ahb-error",
+};
+
+static void ar5312_misc_irq_handler(unsigned irq, struct irq_desc *desc)
+{
+ u32 pending = ath25_read_reg(AR5312_ISR) & ath25_read_reg(AR5312_IMR);
+ unsigned base = ar5312_misc_irq_base;
+
+ if (pending & AR5312_ISR_TIMER) {
+ generic_handle_irq(base + AR5312_MISC_IRQ_TIMER);
+ (void)ath25_read_reg(AR5312_TIMER);
+ } else if (pending & AR5312_ISR_AHBPROC)
+ generic_handle_irq(base + AR5312_MISC_IRQ_AHB_PROC);
+ else if (pending & AR5312_ISR_UART0)
+ generic_handle_irq(base + AR5312_MISC_IRQ_UART0);
+ else if (pending & AR5312_ISR_WD)
+ generic_handle_irq(base + AR5312_MISC_IRQ_WATCHDOG);
+ else
+ spurious_interrupt();
+}
+
+/* Enable the specified AR5312_MISC_IRQ interrupt */
+static void ar5312_misc_irq_unmask(struct irq_data *d)
+{
+ u32 imr = ath25_read_reg(AR5312_IMR);
+
+ imr |= 1 << (d->irq - ar5312_misc_irq_base);
+ ath25_write_reg(AR5312_IMR, imr);
+}
+
+/* Disable the specified AR5312_MISC_IRQ interrupt */
+static void ar5312_misc_irq_mask(struct irq_data *d)
+{
+ u32 imr = ath25_read_reg(AR5312_IMR);
+
+ imr &= ~(1 << (d->irq - ar5312_misc_irq_base));
+ ath25_write_reg(AR5312_IMR, imr);
+ ath25_read_reg(AR5312_IMR); /* flush write buffer */
+}
+
+static struct irq_chip ar5312_misc_irq_chip = {
+ .name = "ar5312-misc",
+ .irq_unmask = ar5312_misc_irq_unmask,
+ .irq_mask = ar5312_misc_irq_mask,
+};
+
+static void ar5312_irq_dispatch(void)
+{
+ u32 pending = read_c0_status() & read_c0_cause();
+
+ if (pending & CAUSEF_IP2)
+ do_IRQ(AR5312_IRQ_WLAN0);
+ else if (pending & CAUSEF_IP5)
+ do_IRQ(AR5312_IRQ_WLAN1);
+ else if (pending & CAUSEF_IP6)
+ do_IRQ(AR5312_IRQ_MISC);
+ else if (pending & CAUSEF_IP7)
+ do_IRQ(ATH25_IRQ_CPU_CLOCK);
+ else
+ spurious_interrupt();
+}
+
+void __init ar5312_arch_init_irq(void)
+{
+ unsigned i;
+ int res;
+
+ ath25_irq_dispatch = ar5312_irq_dispatch;
+
+ res = irq_alloc_descs(-1, 0, AR5312_MISC_IRQ_COUNT, 0);
+ if (res < 0)
+ pr_emerg("Failed to allocate misc IRQ numbers\n");
+ ar5312_misc_irq_base = res;
+
+ for (i = 0; i < AR5312_MISC_IRQ_COUNT; i++) {
+ unsigned irq = ar5312_misc_irq_base + i;
+
+ irq_set_chip_and_handler(irq, &ar5312_misc_irq_chip,
+ handle_level_irq);
+ }
+ setup_irq(ar5312_misc_irq_base + AR5312_MISC_IRQ_AHB_PROC,
+ &ar5312_ahb_err_interrupt);
+ irq_set_chained_handler(AR5312_IRQ_MISC, ar5312_misc_irq_handler);
+}
+
static void ar5312_restart(char *command)
{
/* reset the system */
diff --git a/arch/mips/ath25/ar5312.h b/arch/mips/ath25/ar5312.h
index 339b28e..b60ad38 100644
--- a/arch/mips/ath25/ar5312.h
+++ b/arch/mips/ath25/ar5312.h
@@ -3,12 +3,14 @@

#ifdef CONFIG_SOC_AR5312

+void ar5312_arch_init_irq(void);
void ar5312_plat_time_init(void);
void ar5312_plat_mem_setup(void);
void ar5312_prom_init(void);

#else

+static inline void ar5312_arch_init_irq(void) {}
static inline void ar5312_plat_time_init(void) {}
static inline void ar5312_plat_mem_setup(void) {}
static inline void ar5312_prom_init(void) {}
diff --git a/arch/mips/ath25/board.c b/arch/mips/ath25/board.c
index a6b8c26..68447d3 100644
--- a/arch/mips/ath25/board.c
+++ b/arch/mips/ath25/board.c
@@ -16,9 +16,12 @@
#include <asm/bootinfo.h>
#include <asm/time.h>

+#include "devices.h"
#include "ar5312.h"
#include "ar2315.h"

+void (*ath25_irq_dispatch)(void);
+
static void ath25_halt(void)
{
local_irq_disable();
@@ -42,6 +45,7 @@ void __init plat_mem_setup(void)

asmlinkage void plat_irq_dispatch(void)
{
+ ath25_irq_dispatch();
}

void __init plat_time_init(void)
@@ -61,5 +65,11 @@ void __init arch_init_irq(void)
{
clear_c0_status(ST0_IM);
mips_cpu_irq_init();
+
+ /* Initialize interrupt controllers */
+ if (is_ar5312())
+ ar5312_arch_init_irq();
+ else
+ ar2315_arch_init_irq();
}

diff --git a/arch/mips/ath25/devices.h b/arch/mips/ath25/devices.h
index edda636..bbf2988 100644
--- a/arch/mips/ath25/devices.h
+++ b/arch/mips/ath25/devices.h
@@ -3,6 +3,8 @@

#include <linux/cpu.h>

+extern void (*ath25_irq_dispatch)(void);
+
static inline bool is_ar2315(void)
{
return (current_cpu_data.cputype == CPU_4KEC);
diff --git a/arch/mips/include/asm/mach-ath25/ar2315_regs.h b/arch/mips/include/asm/mach-ath25/ar2315_regs.h
index ff9a4a8..e680abc 100644
--- a/arch/mips/include/asm/mach-ath25/ar2315_regs.h
+++ b/arch/mips/include/asm/mach-ath25/ar2315_regs.h
@@ -15,6 +15,29 @@
#define __ASM_MACH_ATH25_AR2315_REGS_H

/*
+ * IRQs
+ */
+#define AR2315_IRQ_MISC (MIPS_CPU_IRQ_BASE + 2) /* C0_CAUSE: 0x0400 */
+#define AR2315_IRQ_WLAN0 (MIPS_CPU_IRQ_BASE + 3) /* C0_CAUSE: 0x0800 */
+#define AR2315_IRQ_ENET0 (MIPS_CPU_IRQ_BASE + 4) /* C0_CAUSE: 0x1000 */
+#define AR2315_IRQ_LCBUS_PCI (MIPS_CPU_IRQ_BASE + 5) /* C0_CAUSE: 0x2000 */
+#define AR2315_IRQ_WLAN0_POLL (MIPS_CPU_IRQ_BASE + 6) /* C0_CAUSE: 0x4000 */
+
+/*
+ * Miscellaneous interrupts, which share IP2.
+ */
+#define AR2315_MISC_IRQ_UART0 0
+#define AR2315_MISC_IRQ_I2C_RSVD 1
+#define AR2315_MISC_IRQ_SPI 2
+#define AR2315_MISC_IRQ_AHB 3
+#define AR2315_MISC_IRQ_APB 4
+#define AR2315_MISC_IRQ_TIMER 5
+#define AR2315_MISC_IRQ_GPIO 6
+#define AR2315_MISC_IRQ_WATCHDOG 7
+#define AR2315_MISC_IRQ_IR_RSVD 8
+#define AR2315_MISC_IRQ_COUNT 9
+
+/*
* Address map
*/
#define AR2315_SPI_READ 0x08000000 /* SPI flash */
diff --git a/arch/mips/include/asm/mach-ath25/ar5312_regs.h b/arch/mips/include/asm/mach-ath25/ar5312_regs.h
index 76856d8..afcd0b2 100644
--- a/arch/mips/include/asm/mach-ath25/ar5312_regs.h
+++ b/arch/mips/include/asm/mach-ath25/ar5312_regs.h
@@ -12,6 +12,29 @@
#define __ASM_MACH_ATH25_AR5312_REGS_H

/*
+ * IRQs
+ */
+#define AR5312_IRQ_WLAN0 (MIPS_CPU_IRQ_BASE + 2) /* C0_CAUSE: 0x0400 */
+#define AR5312_IRQ_ENET0 (MIPS_CPU_IRQ_BASE + 3) /* C0_CAUSE: 0x0800 */
+#define AR5312_IRQ_ENET1 (MIPS_CPU_IRQ_BASE + 4) /* C0_CAUSE: 0x1000 */
+#define AR5312_IRQ_WLAN1 (MIPS_CPU_IRQ_BASE + 5) /* C0_CAUSE: 0x2000 */
+#define AR5312_IRQ_MISC (MIPS_CPU_IRQ_BASE + 6) /* C0_CAUSE: 0x4000 */
+
+/*
+ * Miscellaneous interrupts, which share IP6.
+ */
+#define AR5312_MISC_IRQ_TIMER 0
+#define AR5312_MISC_IRQ_AHB_PROC 1
+#define AR5312_MISC_IRQ_AHB_DMA 2
+#define AR5312_MISC_IRQ_GPIO 3
+#define AR5312_MISC_IRQ_UART0 4
+#define AR5312_MISC_IRQ_UART0_DMA 5
+#define AR5312_MISC_IRQ_WATCHDOG 6
+#define AR5312_MISC_IRQ_LOCAL 7
+#define AR5312_MISC_IRQ_SPI 8
+#define AR5312_MISC_IRQ_COUNT 9
+
+/*
* Address Map
*
* The AR5312 supports 2 enet MACS, even though many reference boards only
diff --git a/arch/mips/include/asm/mach-ath25/ath25.h b/arch/mips/include/asm/mach-ath25/ath25.h
index bd66ce7..caf0794 100644
--- a/arch/mips/include/asm/mach-ath25/ath25.h
+++ b/arch/mips/include/asm/mach-ath25/ath25.h
@@ -3,6 +3,8 @@

#include <linux/io.h>

+#define ATH25_IRQ_CPU_CLOCK (MIPS_CPU_IRQ_BASE + 7) /* C0_CAUSE: 0x8000 */
+
#define ATH25_REG_MS(_val, _field) (((_val) & _field##_M) >> _field##_S)

static inline u32 ath25_read_reg(u32 reg)
--
1.8.5.5
John Crispin
2014-10-22 08:26:46 UTC
Permalink
few comments inline ....
Post by Sergey Ryazanov
Add interrupts initialization and handling routines, also add AHB bus
error interrupt handlers for both SoCs families.
---
- add all interrupts
- use dynamic IRQ numbers allocation
- rename MIPS machine ar231x -> ath25
arch/mips/ath25/ar2315.c | 108 +++++++++++++++++++++++++
arch/mips/ath25/ar2315.h | 2 +
arch/mips/ath25/ar5312.c | 103 +++++++++++++++++++++++
arch/mips/ath25/ar5312.h | 2 +
arch/mips/ath25/board.c | 10 +++
arch/mips/ath25/devices.h | 2 +
arch/mips/include/asm/mach-ath25/ar2315_regs.h | 23 ++++++
arch/mips/include/asm/mach-ath25/ar5312_regs.h | 23 ++++++
arch/mips/include/asm/mach-ath25/ath25.h | 2 +
9 files changed, 275 insertions(+)
diff --git a/arch/mips/ath25/ar2315.c b/arch/mips/ath25/ar2315.c
index 4eee362..e1a338b 100644
--- a/arch/mips/ath25/ar2315.c
+++ b/arch/mips/ath25/ar2315.c
@@ -27,6 +27,114 @@
#include "devices.h"
#include "ar2315.h"
+static unsigned ar2315_misc_irq_base;
+
+static irqreturn_t ar2315_ahb_err_handler(int cpl, void *dev_id)
+{
+ ath25_write_reg(AR2315_AHB_ERR0, AR2315_AHB_ERROR_DET);
+ ath25_read_reg(AR2315_AHB_ERR1);
+
+ pr_emerg("AHB fatal error\n");
+ machine_restart("AHB error"); /* Catastrophic failure */
+
+ return IRQ_HANDLED;
+}
+
+static struct irqaction ar2315_ahb_err_interrupt = {
+ .handler = ar2315_ahb_err_handler,
+ .name = "ar2315-ahb-error",
+};
+
+static void ar2315_misc_irq_handler(unsigned irq, struct irq_desc *desc)
+{
+ u32 pending = ath25_read_reg(AR2315_ISR) & ath25_read_reg(AR2315_IMR);
+ unsigned base = ar2315_misc_irq_base;
+
+ if (pending & AR2315_ISR_SPI)
+ generic_handle_irq(base + AR2315_MISC_IRQ_SPI);
+ else if (pending & AR2315_ISR_TIMER)
+ generic_handle_irq(base + AR2315_MISC_IRQ_TIMER);
+ else if (pending & AR2315_ISR_AHB)
+ generic_handle_irq(base + AR2315_MISC_IRQ_AHB);
+ else if (pending & AR2315_ISR_GPIO) {
+ ath25_write_reg(AR2315_ISR, AR2315_ISR_GPIO);
+ generic_handle_irq(base + AR2315_MISC_IRQ_GPIO);
+ } else if (pending & AR2315_ISR_UART0)
+ generic_handle_irq(base + AR2315_MISC_IRQ_UART0);
+ else if (pending & AR2315_ISR_WD) {
+ ath25_write_reg(AR2315_ISR, AR2315_ISR_WD);
+ generic_handle_irq(base + AR2315_MISC_IRQ_WATCHDOG);
+ } else
+ spurious_interrupt();
+}
+
+static void ar2315_misc_irq_unmask(struct irq_data *d)
+{
+ u32 imr = ath25_read_reg(AR2315_IMR);
+
+ imr |= 1 << (d->irq - ar2315_misc_irq_base);
+ ath25_write_reg(AR2315_IMR, imr);
+}
+
+static void ar2315_misc_irq_mask(struct irq_data *d)
+{
+ u32 imr = ath25_read_reg(AR2315_IMR);
+
+ imr &= ~(1 << (d->irq - ar2315_misc_irq_base));
+ ath25_write_reg(AR2315_IMR, imr);
+}
+
+static struct irq_chip ar2315_misc_irq_chip = {
+ .name = "ar2315-misc",
+ .irq_unmask = ar2315_misc_irq_unmask,
+ .irq_mask = ar2315_misc_irq_mask,
+};
+
+/*
+ * Called when an interrupt is received, this function
+ * determines exactly which interrupt it was, and it
+ * invokes the appropriate handler.
+ *
+ * Implicitly, we also define interrupt priority by
+ * choosing which to dispatch first.
+ */
+static void ar2315_irq_dispatch(void)
+{
+ u32 pending = read_c0_status() & read_c0_cause();
+
+ if (pending & CAUSEF_IP3)
+ do_IRQ(AR2315_IRQ_WLAN0);
+ else if (pending & CAUSEF_IP2)
+ do_IRQ(AR2315_IRQ_MISC);
+ else if (pending & CAUSEF_IP7)
+ do_IRQ(ATH25_IRQ_CPU_CLOCK);
+ else
+ spurious_interrupt();
+}
+
+void __init ar2315_arch_init_irq(void)
+{
+ unsigned i;
+ int res;
+
+ ath25_irq_dispatch = ar2315_irq_dispatch;
+
+ res = irq_alloc_descs(-1, 0, AR2315_MISC_IRQ_COUNT, 0);
+ if (res < 0)
+ pr_emerg("Failed to allocate misc IRQ numbers\n");
+ ar2315_misc_irq_base = res;
+
+ for (i = 0; i < AR2315_MISC_IRQ_COUNT; i++) {
+ unsigned irq = ar2315_misc_irq_base + i;
+
+ irq_set_chip_and_handler(irq, &ar2315_misc_irq_chip,
+ handle_level_irq);
+ }
+ setup_irq(ar2315_misc_irq_base + AR2315_MISC_IRQ_AHB,
+ &ar2315_ahb_err_interrupt);
+ irq_set_chained_handler(AR2315_IRQ_MISC, ar2315_misc_irq_handler);
+}
+
you should use irq_doamin here with a xlate function. this is just a 3
liner. look at arch/mips/ralink/irq.c
Post by Sergey Ryazanov
static void ar2315_restart(char *command)
{
void (*mips_reset_vec)(void) = (void *)0xbfc00000;
diff --git a/arch/mips/ath25/ar2315.h b/arch/mips/ath25/ar2315.h
index 98d32b2..2a57858 100644
--- a/arch/mips/ath25/ar2315.h
+++ b/arch/mips/ath25/ar2315.h
@@ -3,12 +3,14 @@
#ifdef CONFIG_SOC_AR2315
+void ar2315_arch_init_irq(void);
void ar2315_plat_time_init(void);
void ar2315_plat_mem_setup(void);
void ar2315_prom_init(void);
#else
+static inline void ar2315_arch_init_irq(void) {}
static inline void ar2315_plat_time_init(void) {}
static inline void ar2315_plat_mem_setup(void) {}
static inline void ar2315_prom_init(void) {}
diff --git a/arch/mips/ath25/ar5312.c b/arch/mips/ath25/ar5312.c
index 80d7ed7..e9c7f71 100644
--- a/arch/mips/ath25/ar5312.c
+++ b/arch/mips/ath25/ar5312.c
@@ -27,6 +27,109 @@
#include "devices.h"
#include "ar5312.h"
+static unsigned ar5312_misc_irq_base;
+
+static irqreturn_t ar5312_ahb_err_handler(int cpl, void *dev_id)
+{
+ u32 proc1 = ath25_read_reg(AR5312_PROC1);
+ u32 proc_addr = ath25_read_reg(AR5312_PROCADDR); /* clears error */
+ u32 dma1 = ath25_read_reg(AR5312_DMA1);
+ u32 dma_addr = ath25_read_reg(AR5312_DMAADDR); /* clears error */
+
+ pr_emerg("AHB interrupt: PROCADDR=0x%8.8x PROC1=0x%8.8x DMAADDR=0x%8.8x DMA1=0x%8.8x\n",
+ proc_addr, proc1, dma_addr, dma1);
+
+ machine_restart("AHB error"); /* Catastrophic failure */
+ return IRQ_HANDLED;
+}
+
+static struct irqaction ar5312_ahb_err_interrupt = {
+ .handler = ar5312_ahb_err_handler,
+ .name = "ar5312-ahb-error",
+};
+
+static void ar5312_misc_irq_handler(unsigned irq, struct irq_desc *desc)
+{
+ u32 pending = ath25_read_reg(AR5312_ISR) & ath25_read_reg(AR5312_IMR);
+ unsigned base = ar5312_misc_irq_base;
+
+ if (pending & AR5312_ISR_TIMER) {
+ generic_handle_irq(base + AR5312_MISC_IRQ_TIMER);
+ (void)ath25_read_reg(AR5312_TIMER);
+ } else if (pending & AR5312_ISR_AHBPROC)
+ generic_handle_irq(base + AR5312_MISC_IRQ_AHB_PROC);
+ else if (pending & AR5312_ISR_UART0)
+ generic_handle_irq(base + AR5312_MISC_IRQ_UART0);
+ else if (pending & AR5312_ISR_WD)
+ generic_handle_irq(base + AR5312_MISC_IRQ_WATCHDOG);
+ else
+ spurious_interrupt();
+}
+
+/* Enable the specified AR5312_MISC_IRQ interrupt */
+static void ar5312_misc_irq_unmask(struct irq_data *d)
+{
+ u32 imr = ath25_read_reg(AR5312_IMR);
+
+ imr |= 1 << (d->irq - ar5312_misc_irq_base);
+ ath25_write_reg(AR5312_IMR, imr);
+}
+
+/* Disable the specified AR5312_MISC_IRQ interrupt */
+static void ar5312_misc_irq_mask(struct irq_data *d)
+{
+ u32 imr = ath25_read_reg(AR5312_IMR);
+
+ imr &= ~(1 << (d->irq - ar5312_misc_irq_base));
+ ath25_write_reg(AR5312_IMR, imr);
+ ath25_read_reg(AR5312_IMR); /* flush write buffer */
+}
+
+static struct irq_chip ar5312_misc_irq_chip = {
+ .name = "ar5312-misc",
+ .irq_unmask = ar5312_misc_irq_unmask,
+ .irq_mask = ar5312_misc_irq_mask,
+};
+
+static void ar5312_irq_dispatch(void)
+{
+ u32 pending = read_c0_status() & read_c0_cause();
+
+ if (pending & CAUSEF_IP2)
+ do_IRQ(AR5312_IRQ_WLAN0);
+ else if (pending & CAUSEF_IP5)
+ do_IRQ(AR5312_IRQ_WLAN1);
+ else if (pending & CAUSEF_IP6)
+ do_IRQ(AR5312_IRQ_MISC);
+ else if (pending & CAUSEF_IP7)
+ do_IRQ(ATH25_IRQ_CPU_CLOCK);
+ else
+ spurious_interrupt();
+}
+
+void __init ar5312_arch_init_irq(void)
+{
+ unsigned i;
+ int res;
+
+ ath25_irq_dispatch = ar5312_irq_dispatch;
+
+ res = irq_alloc_descs(-1, 0, AR5312_MISC_IRQ_COUNT, 0);
+ if (res < 0)
+ pr_emerg("Failed to allocate misc IRQ numbers\n");
+ ar5312_misc_irq_base = res;
+
+ for (i = 0; i < AR5312_MISC_IRQ_COUNT; i++) {
+ unsigned irq = ar5312_misc_irq_base + i;
+
+ irq_set_chip_and_handler(irq, &ar5312_misc_irq_chip,
+ handle_level_irq);
+ }
+ setup_irq(ar5312_misc_irq_base + AR5312_MISC_IRQ_AHB_PROC,
+ &ar5312_ahb_err_interrupt);
+ irq_set_chained_handler(AR5312_IRQ_MISC, ar5312_misc_irq_handler);
+}
same here, irq_domain is the current best practice
Post by Sergey Ryazanov
+
static void ar5312_restart(char *command)
{
/* reset the system */
diff --git a/arch/mips/ath25/ar5312.h b/arch/mips/ath25/ar5312.h
index 339b28e..b60ad38 100644
--- a/arch/mips/ath25/ar5312.h
+++ b/arch/mips/ath25/ar5312.h
@@ -3,12 +3,14 @@
#ifdef CONFIG_SOC_AR5312
+void ar5312_arch_init_irq(void);
void ar5312_plat_time_init(void);
void ar5312_plat_mem_setup(void);
void ar5312_prom_init(void);
#else
+static inline void ar5312_arch_init_irq(void) {}
static inline void ar5312_plat_time_init(void) {}
static inline void ar5312_plat_mem_setup(void) {}
static inline void ar5312_prom_init(void) {}
diff --git a/arch/mips/ath25/board.c b/arch/mips/ath25/board.c
index a6b8c26..68447d3 100644
--- a/arch/mips/ath25/board.c
+++ b/arch/mips/ath25/board.c
@@ -16,9 +16,12 @@
#include <asm/bootinfo.h>
#include <asm/time.h>
+#include "devices.h"
#include "ar5312.h"
#include "ar2315.h"
+void (*ath25_irq_dispatch)(void);
+
static void ath25_halt(void)
{
local_irq_disable();
@@ -42,6 +45,7 @@ void __init plat_mem_setup(void)
asmlinkage void plat_irq_dispatch(void)
{
+ ath25_irq_dispatch();
}
void __init plat_time_init(void)
@@ -61,5 +65,11 @@ void __init arch_init_irq(void)
{
clear_c0_status(ST0_IM);
mips_cpu_irq_init();
+
+ /* Initialize interrupt controllers */
+ if (is_ar5312())
+ ar5312_arch_init_irq();
+ else
+ ar2315_arch_init_irq();
}
diff --git a/arch/mips/ath25/devices.h b/arch/mips/ath25/devices.h
index edda636..bbf2988 100644
--- a/arch/mips/ath25/devices.h
+++ b/arch/mips/ath25/devices.h
@@ -3,6 +3,8 @@
#include <linux/cpu.h>
+extern void (*ath25_irq_dispatch)(void);
+
static inline bool is_ar2315(void)
{
return (current_cpu_data.cputype == CPU_4KEC);
diff --git a/arch/mips/include/asm/mach-ath25/ar2315_regs.h b/arch/mips/include/asm/mach-ath25/ar2315_regs.h
index ff9a4a8..e680abc 100644
--- a/arch/mips/include/asm/mach-ath25/ar2315_regs.h
+++ b/arch/mips/include/asm/mach-ath25/ar2315_regs.h
@@ -15,6 +15,29 @@
#define __ASM_MACH_ATH25_AR2315_REGS_H
/*
+ * IRQs
+ */
+#define AR2315_IRQ_MISC (MIPS_CPU_IRQ_BASE + 2) /* C0_CAUSE: 0x0400 */
+#define AR2315_IRQ_WLAN0 (MIPS_CPU_IRQ_BASE + 3) /* C0_CAUSE: 0x0800 */
+#define AR2315_IRQ_ENET0 (MIPS_CPU_IRQ_BASE + 4) /* C0_CAUSE: 0x1000 */
+#define AR2315_IRQ_LCBUS_PCI (MIPS_CPU_IRQ_BASE + 5) /* C0_CAUSE: 0x2000 */
+#define AR2315_IRQ_WLAN0_POLL (MIPS_CPU_IRQ_BASE + 6) /* C0_CAUSE: 0x4000 */
+
+/*
+ * Miscellaneous interrupts, which share IP2.
+ */
+#define AR2315_MISC_IRQ_UART0 0
+#define AR2315_MISC_IRQ_I2C_RSVD 1
+#define AR2315_MISC_IRQ_SPI 2
+#define AR2315_MISC_IRQ_AHB 3
+#define AR2315_MISC_IRQ_APB 4
+#define AR2315_MISC_IRQ_TIMER 5
+#define AR2315_MISC_IRQ_GPIO 6
+#define AR2315_MISC_IRQ_WATCHDOG 7
+#define AR2315_MISC_IRQ_IR_RSVD 8
+#define AR2315_MISC_IRQ_COUNT 9
+
+/*
* Address map
*/
#define AR2315_SPI_READ 0x08000000 /* SPI flash */
diff --git a/arch/mips/include/asm/mach-ath25/ar5312_regs.h b/arch/mips/include/asm/mach-ath25/ar5312_regs.h
index 76856d8..afcd0b2 100644
--- a/arch/mips/include/asm/mach-ath25/ar5312_regs.h
+++ b/arch/mips/include/asm/mach-ath25/ar5312_regs.h
@@ -12,6 +12,29 @@
#define __ASM_MACH_ATH25_AR5312_REGS_H
/*
+ * IRQs
+ */
+#define AR5312_IRQ_WLAN0 (MIPS_CPU_IRQ_BASE + 2) /* C0_CAUSE: 0x0400 */
+#define AR5312_IRQ_ENET0 (MIPS_CPU_IRQ_BASE + 3) /* C0_CAUSE: 0x0800 */
+#define AR5312_IRQ_ENET1 (MIPS_CPU_IRQ_BASE + 4) /* C0_CAUSE: 0x1000 */
+#define AR5312_IRQ_WLAN1 (MIPS_CPU_IRQ_BASE + 5) /* C0_CAUSE: 0x2000 */
+#define AR5312_IRQ_MISC (MIPS_CPU_IRQ_BASE + 6) /* C0_CAUSE: 0x4000 */
+
+/*
+ * Miscellaneous interrupts, which share IP6.
+ */
+#define AR5312_MISC_IRQ_TIMER 0
+#define AR5312_MISC_IRQ_AHB_PROC 1
+#define AR5312_MISC_IRQ_AHB_DMA 2
+#define AR5312_MISC_IRQ_GPIO 3
+#define AR5312_MISC_IRQ_UART0 4
+#define AR5312_MISC_IRQ_UART0_DMA 5
+#define AR5312_MISC_IRQ_WATCHDOG 6
+#define AR5312_MISC_IRQ_LOCAL 7
+#define AR5312_MISC_IRQ_SPI 8
+#define AR5312_MISC_IRQ_COUNT 9
+
+/*
* Address Map
*
* The AR5312 supports 2 enet MACS, even though many reference boards only
diff --git a/arch/mips/include/asm/mach-ath25/ath25.h b/arch/mips/include/asm/mach-ath25/ath25.h
index bd66ce7..caf0794 100644
--- a/arch/mips/include/asm/mach-ath25/ath25.h
+++ b/arch/mips/include/asm/mach-ath25/ath25.h
@@ -3,6 +3,8 @@
#include <linux/io.h>
+#define ATH25_IRQ_CPU_CLOCK (MIPS_CPU_IRQ_BASE + 7) /* C0_CAUSE: 0x8000 */
+
#define ATH25_REG_MS(_val, _field) (((_val) & _field##_M) >> _field##_S)
static inline u32 ath25_read_reg(u32 reg)
Sergey Ryazanov
2014-10-22 14:51:49 UTC
Permalink
Post by John Crispin
few comments inline ....
Post by Sergey Ryazanov
Add interrupts initialization and handling routines, also add AHB bus
error interrupt handlers for both SoCs families.
---
- add all interrupts
- use dynamic IRQ numbers allocation
- rename MIPS machine ar231x -> ath25
arch/mips/ath25/ar2315.c | 108 +++++++++++++++++++++++++
arch/mips/ath25/ar2315.h | 2 +
arch/mips/ath25/ar5312.c | 103 +++++++++++++++++++++++
arch/mips/ath25/ar5312.h | 2 +
arch/mips/ath25/board.c | 10 +++
arch/mips/ath25/devices.h | 2 +
arch/mips/include/asm/mach-ath25/ar2315_regs.h | 23 ++++++
arch/mips/include/asm/mach-ath25/ar5312_regs.h | 23 ++++++
arch/mips/include/asm/mach-ath25/ath25.h | 2 +
9 files changed, 275 insertions(+)
diff --git a/arch/mips/ath25/ar2315.c b/arch/mips/ath25/ar2315.c
index 4eee362..e1a338b 100644
--- a/arch/mips/ath25/ar2315.c
+++ b/arch/mips/ath25/ar2315.c
@@ -27,6 +27,114 @@
#include "devices.h"
#include "ar2315.h"
+static unsigned ar2315_misc_irq_base;
+
+static irqreturn_t ar2315_ahb_err_handler(int cpl, void *dev_id)
+{
+ ath25_write_reg(AR2315_AHB_ERR0, AR2315_AHB_ERROR_DET);
+ ath25_read_reg(AR2315_AHB_ERR1);
+
+ pr_emerg("AHB fatal error\n");
+ machine_restart("AHB error"); /* Catastrophic failure */
+
+ return IRQ_HANDLED;
+}
+
+static struct irqaction ar2315_ahb_err_interrupt = {
+ .handler = ar2315_ahb_err_handler,
+ .name = "ar2315-ahb-error",
+};
+
+static void ar2315_misc_irq_handler(unsigned irq, struct irq_desc *desc)
+{
+ u32 pending = ath25_read_reg(AR2315_ISR) & ath25_read_reg(AR2315_IMR);
+ unsigned base = ar2315_misc_irq_base;
+
+ if (pending & AR2315_ISR_SPI)
+ generic_handle_irq(base + AR2315_MISC_IRQ_SPI);
+ else if (pending & AR2315_ISR_TIMER)
+ generic_handle_irq(base + AR2315_MISC_IRQ_TIMER);
+ else if (pending & AR2315_ISR_AHB)
+ generic_handle_irq(base + AR2315_MISC_IRQ_AHB);
+ else if (pending & AR2315_ISR_GPIO) {
+ ath25_write_reg(AR2315_ISR, AR2315_ISR_GPIO);
+ generic_handle_irq(base + AR2315_MISC_IRQ_GPIO);
+ } else if (pending & AR2315_ISR_UART0)
+ generic_handle_irq(base + AR2315_MISC_IRQ_UART0);
+ else if (pending & AR2315_ISR_WD) {
+ ath25_write_reg(AR2315_ISR, AR2315_ISR_WD);
+ generic_handle_irq(base + AR2315_MISC_IRQ_WATCHDOG);
+ } else
+ spurious_interrupt();
+}
+
+static void ar2315_misc_irq_unmask(struct irq_data *d)
+{
+ u32 imr = ath25_read_reg(AR2315_IMR);
+
+ imr |= 1 << (d->irq - ar2315_misc_irq_base);
+ ath25_write_reg(AR2315_IMR, imr);
+}
+
+static void ar2315_misc_irq_mask(struct irq_data *d)
+{
+ u32 imr = ath25_read_reg(AR2315_IMR);
+
+ imr &= ~(1 << (d->irq - ar2315_misc_irq_base));
+ ath25_write_reg(AR2315_IMR, imr);
+}
+
+static struct irq_chip ar2315_misc_irq_chip = {
+ .name = "ar2315-misc",
+ .irq_unmask = ar2315_misc_irq_unmask,
+ .irq_mask = ar2315_misc_irq_mask,
+};
+
+/*
+ * Called when an interrupt is received, this function
+ * determines exactly which interrupt it was, and it
+ * invokes the appropriate handler.
+ *
+ * Implicitly, we also define interrupt priority by
+ * choosing which to dispatch first.
+ */
+static void ar2315_irq_dispatch(void)
+{
+ u32 pending = read_c0_status() & read_c0_cause();
+
+ if (pending & CAUSEF_IP3)
+ do_IRQ(AR2315_IRQ_WLAN0);
+ else if (pending & CAUSEF_IP2)
+ do_IRQ(AR2315_IRQ_MISC);
+ else if (pending & CAUSEF_IP7)
+ do_IRQ(ATH25_IRQ_CPU_CLOCK);
+ else
+ spurious_interrupt();
+}
+
+void __init ar2315_arch_init_irq(void)
+{
+ unsigned i;
+ int res;
+
+ ath25_irq_dispatch = ar2315_irq_dispatch;
+
+ res = irq_alloc_descs(-1, 0, AR2315_MISC_IRQ_COUNT, 0);
+ if (res < 0)
+ pr_emerg("Failed to allocate misc IRQ numbers\n");
+ ar2315_misc_irq_base = res;
+
+ for (i = 0; i < AR2315_MISC_IRQ_COUNT; i++) {
+ unsigned irq = ar2315_misc_irq_base + i;
+
+ irq_set_chip_and_handler(irq, &ar2315_misc_irq_chip,
+ handle_level_irq);
+ }
+ setup_irq(ar2315_misc_irq_base + AR2315_MISC_IRQ_AHB,
+ &ar2315_ahb_err_interrupt);
+ irq_set_chained_handler(AR2315_IRQ_MISC, ar2315_misc_irq_handler);
+}
+
you should use irq_doamin here with a xlate function. this is just a 3
liner.
I would like add code as-is, and then update it to use irq_domain. But
seems that everybody likes the irq_domain and this work should be done
now.
Post by John Crispin
look at arch/mips/ralink/irq.c
Thank you for example!
Post by John Crispin
Post by Sergey Ryazanov
static void ar2315_restart(char *command)
{
void (*mips_reset_vec)(void) = (void *)0xbfc00000;
diff --git a/arch/mips/ath25/ar2315.h b/arch/mips/ath25/ar2315.h
index 98d32b2..2a57858 100644
--- a/arch/mips/ath25/ar2315.h
+++ b/arch/mips/ath25/ar2315.h
@@ -3,12 +3,14 @@
#ifdef CONFIG_SOC_AR2315
+void ar2315_arch_init_irq(void);
void ar2315_plat_time_init(void);
void ar2315_plat_mem_setup(void);
void ar2315_prom_init(void);
#else
+static inline void ar2315_arch_init_irq(void) {}
static inline void ar2315_plat_time_init(void) {}
static inline void ar2315_plat_mem_setup(void) {}
static inline void ar2315_prom_init(void) {}
diff --git a/arch/mips/ath25/ar5312.c b/arch/mips/ath25/ar5312.c
index 80d7ed7..e9c7f71 100644
--- a/arch/mips/ath25/ar5312.c
+++ b/arch/mips/ath25/ar5312.c
@@ -27,6 +27,109 @@
#include "devices.h"
#include "ar5312.h"
+static unsigned ar5312_misc_irq_base;
+
+static irqreturn_t ar5312_ahb_err_handler(int cpl, void *dev_id)
+{
+ u32 proc1 = ath25_read_reg(AR5312_PROC1);
+ u32 proc_addr = ath25_read_reg(AR5312_PROCADDR); /* clears error */
+ u32 dma1 = ath25_read_reg(AR5312_DMA1);
+ u32 dma_addr = ath25_read_reg(AR5312_DMAADDR); /* clears error */
+
+ pr_emerg("AHB interrupt: PROCADDR=0x%8.8x PROC1=0x%8.8x DMAADDR=0x%8.8x DMA1=0x%8.8x\n",
+ proc_addr, proc1, dma_addr, dma1);
+
+ machine_restart("AHB error"); /* Catastrophic failure */
+ return IRQ_HANDLED;
+}
+
+static struct irqaction ar5312_ahb_err_interrupt = {
+ .handler = ar5312_ahb_err_handler,
+ .name = "ar5312-ahb-error",
+};
+
+static void ar5312_misc_irq_handler(unsigned irq, struct irq_desc *desc)
+{
+ u32 pending = ath25_read_reg(AR5312_ISR) & ath25_read_reg(AR5312_IMR);
+ unsigned base = ar5312_misc_irq_base;
+
+ if (pending & AR5312_ISR_TIMER) {
+ generic_handle_irq(base + AR5312_MISC_IRQ_TIMER);
+ (void)ath25_read_reg(AR5312_TIMER);
+ } else if (pending & AR5312_ISR_AHBPROC)
+ generic_handle_irq(base + AR5312_MISC_IRQ_AHB_PROC);
+ else if (pending & AR5312_ISR_UART0)
+ generic_handle_irq(base + AR5312_MISC_IRQ_UART0);
+ else if (pending & AR5312_ISR_WD)
+ generic_handle_irq(base + AR5312_MISC_IRQ_WATCHDOG);
+ else
+ spurious_interrupt();
+}
+
+/* Enable the specified AR5312_MISC_IRQ interrupt */
+static void ar5312_misc_irq_unmask(struct irq_data *d)
+{
+ u32 imr = ath25_read_reg(AR5312_IMR);
+
+ imr |= 1 << (d->irq - ar5312_misc_irq_base);
+ ath25_write_reg(AR5312_IMR, imr);
+}
+
+/* Disable the specified AR5312_MISC_IRQ interrupt */
+static void ar5312_misc_irq_mask(struct irq_data *d)
+{
+ u32 imr = ath25_read_reg(AR5312_IMR);
+
+ imr &= ~(1 << (d->irq - ar5312_misc_irq_base));
+ ath25_write_reg(AR5312_IMR, imr);
+ ath25_read_reg(AR5312_IMR); /* flush write buffer */
+}
+
+static struct irq_chip ar5312_misc_irq_chip = {
+ .name = "ar5312-misc",
+ .irq_unmask = ar5312_misc_irq_unmask,
+ .irq_mask = ar5312_misc_irq_mask,
+};
+
+static void ar5312_irq_dispatch(void)
+{
+ u32 pending = read_c0_status() & read_c0_cause();
+
+ if (pending & CAUSEF_IP2)
+ do_IRQ(AR5312_IRQ_WLAN0);
+ else if (pending & CAUSEF_IP5)
+ do_IRQ(AR5312_IRQ_WLAN1);
+ else if (pending & CAUSEF_IP6)
+ do_IRQ(AR5312_IRQ_MISC);
+ else if (pending & CAUSEF_IP7)
+ do_IRQ(ATH25_IRQ_CPU_CLOCK);
+ else
+ spurious_interrupt();
+}
+
+void __init ar5312_arch_init_irq(void)
+{
+ unsigned i;
+ int res;
+
+ ath25_irq_dispatch = ar5312_irq_dispatch;
+
+ res = irq_alloc_descs(-1, 0, AR5312_MISC_IRQ_COUNT, 0);
+ if (res < 0)
+ pr_emerg("Failed to allocate misc IRQ numbers\n");
+ ar5312_misc_irq_base = res;
+
+ for (i = 0; i < AR5312_MISC_IRQ_COUNT; i++) {
+ unsigned irq = ar5312_misc_irq_base + i;
+
+ irq_set_chip_and_handler(irq, &ar5312_misc_irq_chip,
+ handle_level_irq);
+ }
+ setup_irq(ar5312_misc_irq_base + AR5312_MISC_IRQ_AHB_PROC,
+ &ar5312_ahb_err_interrupt);
+ irq_set_chained_handler(AR5312_IRQ_MISC, ar5312_misc_irq_handler);
+}
same here, irq_domain is the current best practice
Post by Sergey Ryazanov
+
static void ar5312_restart(char *command)
{
/* reset the system */
diff --git a/arch/mips/ath25/ar5312.h b/arch/mips/ath25/ar5312.h
index 339b28e..b60ad38 100644
--- a/arch/mips/ath25/ar5312.h
+++ b/arch/mips/ath25/ar5312.h
@@ -3,12 +3,14 @@
#ifdef CONFIG_SOC_AR5312
+void ar5312_arch_init_irq(void);
void ar5312_plat_time_init(void);
void ar5312_plat_mem_setup(void);
void ar5312_prom_init(void);
#else
+static inline void ar5312_arch_init_irq(void) {}
static inline void ar5312_plat_time_init(void) {}
static inline void ar5312_plat_mem_setup(void) {}
static inline void ar5312_prom_init(void) {}
diff --git a/arch/mips/ath25/board.c b/arch/mips/ath25/board.c
index a6b8c26..68447d3 100644
--- a/arch/mips/ath25/board.c
+++ b/arch/mips/ath25/board.c
@@ -16,9 +16,12 @@
#include <asm/bootinfo.h>
#include <asm/time.h>
+#include "devices.h"
#include "ar5312.h"
#include "ar2315.h"
+void (*ath25_irq_dispatch)(void);
+
static void ath25_halt(void)
{
local_irq_disable();
@@ -42,6 +45,7 @@ void __init plat_mem_setup(void)
asmlinkage void plat_irq_dispatch(void)
{
+ ath25_irq_dispatch();
}
void __init plat_time_init(void)
@@ -61,5 +65,11 @@ void __init arch_init_irq(void)
{
clear_c0_status(ST0_IM);
mips_cpu_irq_init();
+
+ /* Initialize interrupt controllers */
+ if (is_ar5312())
+ ar5312_arch_init_irq();
+ else
+ ar2315_arch_init_irq();
}
diff --git a/arch/mips/ath25/devices.h b/arch/mips/ath25/devices.h
index edda636..bbf2988 100644
--- a/arch/mips/ath25/devices.h
+++ b/arch/mips/ath25/devices.h
@@ -3,6 +3,8 @@
#include <linux/cpu.h>
+extern void (*ath25_irq_dispatch)(void);
+
static inline bool is_ar2315(void)
{
return (current_cpu_data.cputype == CPU_4KEC);
diff --git a/arch/mips/include/asm/mach-ath25/ar2315_regs.h b/arch/mips/include/asm/mach-ath25/ar2315_regs.h
index ff9a4a8..e680abc 100644
--- a/arch/mips/include/asm/mach-ath25/ar2315_regs.h
+++ b/arch/mips/include/asm/mach-ath25/ar2315_regs.h
@@ -15,6 +15,29 @@
#define __ASM_MACH_ATH25_AR2315_REGS_H
/*
+ * IRQs
+ */
+#define AR2315_IRQ_MISC (MIPS_CPU_IRQ_BASE + 2) /* C0_CAUSE: 0x0400 */
+#define AR2315_IRQ_WLAN0 (MIPS_CPU_IRQ_BASE + 3) /* C0_CAUSE: 0x0800 */
+#define AR2315_IRQ_ENET0 (MIPS_CPU_IRQ_BASE + 4) /* C0_CAUSE: 0x1000 */
+#define AR2315_IRQ_LCBUS_PCI (MIPS_CPU_IRQ_BASE + 5) /* C0_CAUSE: 0x2000 */
+#define AR2315_IRQ_WLAN0_POLL (MIPS_CPU_IRQ_BASE + 6) /* C0_CAUSE: 0x4000 */
+
+/*
+ * Miscellaneous interrupts, which share IP2.
+ */
+#define AR2315_MISC_IRQ_UART0 0
+#define AR2315_MISC_IRQ_I2C_RSVD 1
+#define AR2315_MISC_IRQ_SPI 2
+#define AR2315_MISC_IRQ_AHB 3
+#define AR2315_MISC_IRQ_APB 4
+#define AR2315_MISC_IRQ_TIMER 5
+#define AR2315_MISC_IRQ_GPIO 6
+#define AR2315_MISC_IRQ_WATCHDOG 7
+#define AR2315_MISC_IRQ_IR_RSVD 8
+#define AR2315_MISC_IRQ_COUNT 9
+
+/*
* Address map
*/
#define AR2315_SPI_READ 0x08000000 /* SPI flash */
diff --git a/arch/mips/include/asm/mach-ath25/ar5312_regs.h b/arch/mips/include/asm/mach-ath25/ar5312_regs.h
index 76856d8..afcd0b2 100644
--- a/arch/mips/include/asm/mach-ath25/ar5312_regs.h
+++ b/arch/mips/include/asm/mach-ath25/ar5312_regs.h
@@ -12,6 +12,29 @@
#define __ASM_MACH_ATH25_AR5312_REGS_H
/*
+ * IRQs
+ */
+#define AR5312_IRQ_WLAN0 (MIPS_CPU_IRQ_BASE + 2) /* C0_CAUSE: 0x0400 */
+#define AR5312_IRQ_ENET0 (MIPS_CPU_IRQ_BASE + 3) /* C0_CAUSE: 0x0800 */
+#define AR5312_IRQ_ENET1 (MIPS_CPU_IRQ_BASE + 4) /* C0_CAUSE: 0x1000 */
+#define AR5312_IRQ_WLAN1 (MIPS_CPU_IRQ_BASE + 5) /* C0_CAUSE: 0x2000 */
+#define AR5312_IRQ_MISC (MIPS_CPU_IRQ_BASE + 6) /* C0_CAUSE: 0x4000 */
+
+/*
+ * Miscellaneous interrupts, which share IP6.
+ */
+#define AR5312_MISC_IRQ_TIMER 0
+#define AR5312_MISC_IRQ_AHB_PROC 1
+#define AR5312_MISC_IRQ_AHB_DMA 2
+#define AR5312_MISC_IRQ_GPIO 3
+#define AR5312_MISC_IRQ_UART0 4
+#define AR5312_MISC_IRQ_UART0_DMA 5
+#define AR5312_MISC_IRQ_WATCHDOG 6
+#define AR5312_MISC_IRQ_LOCAL 7
+#define AR5312_MISC_IRQ_SPI 8
+#define AR5312_MISC_IRQ_COUNT 9
+
+/*
* Address Map
*
* The AR5312 supports 2 enet MACS, even though many reference boards only
diff --git a/arch/mips/include/asm/mach-ath25/ath25.h b/arch/mips/include/asm/mach-ath25/ath25.h
index bd66ce7..caf0794 100644
--- a/arch/mips/include/asm/mach-ath25/ath25.h
+++ b/arch/mips/include/asm/mach-ath25/ath25.h
@@ -3,6 +3,8 @@
#include <linux/io.h>
+#define ATH25_IRQ_CPU_CLOCK (MIPS_CPU_IRQ_BASE + 7) /* C0_CAUSE: 0x8000 */
+
#define ATH25_REG_MS(_val, _field) (((_val) & _field##_M) >> _field##_S)
static inline u32 ath25_read_reg(u32 reg)
--
BR,
Sergey
John Crispin
2014-10-22 08:49:40 UTC
Permalink
Hi,

just stumbled across this aswell ->
Post by Sergey Ryazanov
+static void ar2315_misc_irq_handler(unsigned irq, struct irq_desc
*desc) +{ + u32 pending = ath25_read_reg(AR2315_ISR) &
ath25_read_reg(AR2315_IMR); + unsigned base =
ar2315_misc_irq_base; + + if (pending & AR2315_ISR_SPI) +
generic_handle_irq(base + AR2315_MISC_IRQ_SPI); + else if (pending
& AR2315_ISR_TIMER) + generic_handle_irq(base +
AR2315_MISC_IRQ_TIMER); + else if (pending & AR2315_ISR_AHB) +
generic_handle_irq(base + AR2315_MISC_IRQ_AHB); + else if (pending
& AR2315_ISR_GPIO) { + ath25_write_reg(AR2315_ISR,
AR2315_ISR_GPIO); + generic_handle_irq(base +
AR2315_MISC_IRQ_GPIO); + } else if (pending & AR2315_ISR_UART0) +
generic_handle_irq(base + AR2315_MISC_IRQ_UART0); + else if
(pending & AR2315_ISR_WD) { + ath25_write_reg(AR2315_ISR,
AR2315_ISR_WD); + generic_handle_irq(base +
AR2315_MISC_IRQ_WATCHDOG); + } else + spurious_interrupt(); +} +
please use {} for all or none of the blocks. in this case it needs to
be for all as there are 2 multi-line blocks

looking forward to V3, i think we are getting close now and i can
already see this in 3.19 :)

John
Sergey Ryazanov
2014-10-21 23:03:43 UTC
Permalink
Signed-off-by: Sergey Ryazanov <***@gmail.com>
---

Changes since v1:
- rename MIPS machine ar231x -> ath25

arch/mips/Kconfig | 1 +
arch/mips/ath25/Makefile | 2 ++
arch/mips/ath25/early_printk.c | 45 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 48 insertions(+)
create mode 100644 arch/mips/ath25/early_printk.c

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index baa1c5b..b7466f1 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -106,6 +106,7 @@ config ATH25
select SYS_SUPPORTS_BIG_ENDIAN
select SYS_SUPPORTS_32BIT_KERNEL
select ARCH_REQUIRE_GPIOLIB
+ select SYS_HAS_EARLY_PRINTK
help
Support for Atheros AR231x and Atheros AR531x based boards

diff --git a/arch/mips/ath25/Makefile b/arch/mips/ath25/Makefile
index 201b7d4..eabad7d 100644
--- a/arch/mips/ath25/Makefile
+++ b/arch/mips/ath25/Makefile
@@ -10,5 +10,7 @@

obj-y += board.o prom.o devices.o

+obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
+
obj-$(CONFIG_SOC_AR5312) += ar5312.o
obj-$(CONFIG_SOC_AR2315) += ar2315.o
diff --git a/arch/mips/ath25/early_printk.c b/arch/mips/ath25/early_printk.c
new file mode 100644
index 0000000..31ef23e
--- /dev/null
+++ b/arch/mips/ath25/early_printk.c
@@ -0,0 +1,45 @@
+/*
+ * 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) 2010 Gabor Juhos <***@openwrt.org>
+ */
+
+#include <linux/mm.h>
+#include <linux/io.h>
+#include <linux/serial_reg.h>
+
+#include <ar2315_regs.h>
+#include <ar5312_regs.h>
+#include "devices.h"
+
+static inline void prom_uart_wr(void __iomem *base, unsigned reg,
+ unsigned char ch)
+{
+ __raw_writel(ch, base + 4 * reg);
+}
+
+static inline unsigned char prom_uart_rr(void __iomem *base, unsigned reg)
+{
+ return __raw_readl(base + 4 * reg);
+}
+
+void prom_putchar(unsigned char ch)
+{
+ static void __iomem *base;
+
+ if (unlikely(base == NULL)) {
+ if (is_ar2315())
+ base = (void __iomem *)(KSEG1ADDR(AR2315_UART0));
+ else
+ base = (void __iomem *)(KSEG1ADDR(AR5312_UART0));
+ }
+
+ while ((prom_uart_rr(base, UART_LSR) & UART_LSR_THRE) == 0)
+ ;
+ prom_uart_wr(base, UART_TX, ch);
+ while ((prom_uart_rr(base, UART_LSR) & UART_LSR_THRE) == 0)
+ ;
+}
+
--
1.8.5.5
Sergey Ryazanov
2014-10-21 23:03:44 UTC
Permalink
Signed-off-by: Sergey Ryazanov <***@gmail.com>
---

Changes since RFC:
- register UART during arch initialization

Changes since v1:
- rename MIPS machine ar231x -> ath25

arch/mips/ath25/ar2315.c | 6 ++++++
arch/mips/ath25/ar2315.h | 2 ++
arch/mips/ath25/ar5312.c | 6 ++++++
arch/mips/ath25/ar5312.h | 2 ++
arch/mips/ath25/devices.c | 28 ++++++++++++++++++++++++++++
arch/mips/ath25/devices.h | 2 ++
6 files changed, 46 insertions(+)

diff --git a/arch/mips/ath25/ar2315.c b/arch/mips/ath25/ar2315.c
index e1a338b..897f538 100644
--- a/arch/mips/ath25/ar2315.c
+++ b/arch/mips/ath25/ar2315.c
@@ -233,3 +233,9 @@ void __init ar2315_prom_init(void)
add_memory_region(0, memsize, BOOT_MEM_RAM);
}

+void __init ar2315_arch_init(void)
+{
+ ath25_serial_setup(AR2315_UART0, ar2315_misc_irq_base +
+ AR2315_MISC_IRQ_UART0, ar2315_apb_frequency());
+}
+
diff --git a/arch/mips/ath25/ar2315.h b/arch/mips/ath25/ar2315.h
index 2a57858..9af22db 100644
--- a/arch/mips/ath25/ar2315.h
+++ b/arch/mips/ath25/ar2315.h
@@ -7,6 +7,7 @@ void ar2315_arch_init_irq(void);
void ar2315_plat_time_init(void);
void ar2315_plat_mem_setup(void);
void ar2315_prom_init(void);
+void ar2315_arch_init(void);

#else

@@ -14,6 +15,7 @@ static inline void ar2315_arch_init_irq(void) {}
static inline void ar2315_plat_time_init(void) {}
static inline void ar2315_plat_mem_setup(void) {}
static inline void ar2315_prom_init(void) {}
+static inline void ar2315_arch_init(void) {}

#endif

diff --git a/arch/mips/ath25/ar5312.c b/arch/mips/ath25/ar5312.c
index e9c7f71..ad36aab 100644
--- a/arch/mips/ath25/ar5312.c
+++ b/arch/mips/ath25/ar5312.c
@@ -235,3 +235,9 @@ void __init ar5312_prom_init(void)
add_memory_region(0, memsize, BOOT_MEM_RAM);
}

+void __init ar5312_arch_init(void)
+{
+ ath25_serial_setup(AR5312_UART0, ar5312_misc_irq_base +
+ AR5312_MISC_IRQ_UART0, ar5312_sys_frequency());
+}
+
diff --git a/arch/mips/ath25/ar5312.h b/arch/mips/ath25/ar5312.h
index b60ad38..d04a33d 100644
--- a/arch/mips/ath25/ar5312.h
+++ b/arch/mips/ath25/ar5312.h
@@ -7,6 +7,7 @@ void ar5312_arch_init_irq(void);
void ar5312_plat_time_init(void);
void ar5312_plat_mem_setup(void);
void ar5312_prom_init(void);
+void ar5312_arch_init(void);

#else

@@ -14,6 +15,7 @@ static inline void ar5312_arch_init_irq(void) {}
static inline void ar5312_plat_time_init(void) {}
static inline void ar5312_plat_mem_setup(void) {}
static inline void ar5312_prom_init(void) {}
+static inline void ar5312_arch_init(void) {}

#endif

diff --git a/arch/mips/ath25/devices.c b/arch/mips/ath25/devices.c
index e30afbc..0416cd2 100644
--- a/arch/mips/ath25/devices.c
+++ b/arch/mips/ath25/devices.c
@@ -1,5 +1,6 @@
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/serial_8250.h>
#include <asm/bootinfo.h>

#include "devices.h"
@@ -9,3 +10,30 @@ const char *get_system_type(void)
return "Atheros (unknown)";
}

+void __init ath25_serial_setup(u32 mapbase, int irq, unsigned int uartclk)
+{
+ struct uart_port s;
+
+ memset(&s, 0, sizeof(s));
+
+ s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP;
+ s.iotype = UPIO_MEM32;
+ s.irq = irq;
+ s.regshift = 2;
+ s.mapbase = mapbase;
+ s.uartclk = uartclk;
+
+ early_serial_setup(&s);
+}
+
+static int __init ath25_arch_init(void)
+{
+ if (is_ar5312())
+ ar5312_arch_init();
+ else
+ ar2315_arch_init();
+
+ return 0;
+}
+
+arch_initcall(ath25_arch_init);
diff --git a/arch/mips/ath25/devices.h b/arch/mips/ath25/devices.h
index bbf2988..54fafd3 100644
--- a/arch/mips/ath25/devices.h
+++ b/arch/mips/ath25/devices.h
@@ -5,6 +5,8 @@

extern void (*ath25_irq_dispatch)(void);

+void ath25_serial_setup(u32 mapbase, int irq, unsigned int uartclk);
+
static inline bool is_ar2315(void)
{
return (current_cpu_data.cputype == CPU_4KEC);
--
1.8.5.5
Sergey Ryazanov
2014-10-21 23:03:45 UTC
Permalink
All boards based on AR5312/AR2315 SoC have a special structure located
at the end of flash. This structure contains board-specific data such as
Ethernet and Wireless MAC addresses. The flash is mapped to the memmory
at predefined location.

Signed-off-by: Sergey Ryazanov <***@gmail.com>
---

Changes since v1:
- rename MIPS machine ar231x -> ath25

arch/mips/ath25/ar2315.c | 14 ++
arch/mips/ath25/ar2315.h | 2 +
arch/mips/ath25/ar5312.c | 38 ++++++
arch/mips/ath25/ar5312.h | 2 +
arch/mips/ath25/board.c | 153 ++++++++++++++++++++++
arch/mips/ath25/devices.c | 17 +++
arch/mips/ath25/devices.h | 2 +
arch/mips/include/asm/mach-ath25/ath25_platform.h | 73 +++++++++++
8 files changed, 301 insertions(+)
create mode 100644 arch/mips/include/asm/mach-ath25/ath25_platform.h

diff --git a/arch/mips/ath25/ar2315.c b/arch/mips/ath25/ar2315.c
index 897f538..d3ff812 100644
--- a/arch/mips/ath25/ar2315.c
+++ b/arch/mips/ath25/ar2315.c
@@ -135,6 +135,20 @@ void __init ar2315_arch_init_irq(void)
irq_set_chained_handler(AR2315_IRQ_MISC, ar2315_misc_irq_handler);
}

+/*
+ * NB: We use mapping size that is larger than the actual flash size,
+ * but this shouldn't be a problem here, because the flash will simply
+ * be mapped multiple times.
+ */
+static const u8 * const __initconst
+ar2315_flash_limit = (u8 *)KSEG1ADDR(AR2315_SPI_READ + 0x1000000);
+
+void __init ar2315_init_devices(void)
+{
+ /* Find board configuration */
+ ath25_find_config(ar2315_flash_limit);
+}
+
static void ar2315_restart(char *command)
{
void (*mips_reset_vec)(void) = (void *)0xbfc00000;
diff --git a/arch/mips/ath25/ar2315.h b/arch/mips/ath25/ar2315.h
index 9af22db..308379a 100644
--- a/arch/mips/ath25/ar2315.h
+++ b/arch/mips/ath25/ar2315.h
@@ -4,6 +4,7 @@
#ifdef CONFIG_SOC_AR2315

void ar2315_arch_init_irq(void);
+void ar2315_init_devices(void);
void ar2315_plat_time_init(void);
void ar2315_plat_mem_setup(void);
void ar2315_prom_init(void);
@@ -12,6 +13,7 @@ void ar2315_arch_init(void);
#else

static inline void ar2315_arch_init_irq(void) {}
+static inline void ar2315_init_devices(void) {}
static inline void ar2315_plat_time_init(void) {}
static inline void ar2315_plat_mem_setup(void) {}
static inline void ar2315_prom_init(void) {}
diff --git a/arch/mips/ath25/ar5312.c b/arch/mips/ath25/ar5312.c
index ad36aab..2d66665 100644
--- a/arch/mips/ath25/ar5312.c
+++ b/arch/mips/ath25/ar5312.c
@@ -130,6 +130,44 @@ void __init ar5312_arch_init_irq(void)
irq_set_chained_handler(AR5312_IRQ_MISC, ar5312_misc_irq_handler);
}

+static void __init ar5312_flash_init(void)
+{
+ u32 ctl;
+
+ /*
+ * Configure flash bank 0.
+ * Assume 8M window size. Flash will be aliased if it's smaller
+ */
+ ctl = ath25_read_reg(AR5312_FLASHCTL0) & AR5312_FLASHCTL_MW;
+ ctl |= AR5312_FLASHCTL_E | AR5312_FLASHCTL_AC_8M | AR5312_FLASHCTL_RBLE;
+ ctl |= 0x01 << AR5312_FLASHCTL_IDCY_S;
+ ctl |= 0x07 << AR5312_FLASHCTL_WST1_S;
+ ctl |= 0x07 << AR5312_FLASHCTL_WST2_S;
+ ath25_write_reg(AR5312_FLASHCTL0, ctl);
+
+ /* Disable other flash banks */
+ ath25_mask_reg(AR5312_FLASHCTL1, AR5312_FLASHCTL_E |
+ AR5312_FLASHCTL_AC, 0);
+ ath25_mask_reg(AR5312_FLASHCTL2, AR5312_FLASHCTL_E |
+ AR5312_FLASHCTL_AC, 0);
+}
+
+/*
+ * NB: This mapping size is larger than the actual flash size,
+ * but this shouldn't be a problem here, because the flash
+ * will simply be mapped multiple times.
+ */
+static const u8 * const __initconst
+ar5312_flash_limit = (u8 *)KSEG1ADDR(AR5312_FLASH + 0x800000);
+
+void __init ar5312_init_devices(void)
+{
+ ar5312_flash_init();
+
+ /* Locate board/radio config data */
+ ath25_find_config(ar5312_flash_limit);
+}
+
static void ar5312_restart(char *command)
{
/* reset the system */
diff --git a/arch/mips/ath25/ar5312.h b/arch/mips/ath25/ar5312.h
index d04a33d..211992f 100644
--- a/arch/mips/ath25/ar5312.h
+++ b/arch/mips/ath25/ar5312.h
@@ -4,6 +4,7 @@
#ifdef CONFIG_SOC_AR5312

void ar5312_arch_init_irq(void);
+void ar5312_init_devices(void);
void ar5312_plat_time_init(void);
void ar5312_plat_mem_setup(void);
void ar5312_prom_init(void);
@@ -12,6 +13,7 @@ void ar5312_arch_init(void);
#else

static inline void ar5312_arch_init_irq(void) {}
+static inline void ar5312_init_devices(void) {}
static inline void ar5312_plat_time_init(void) {}
static inline void ar5312_plat_mem_setup(void) {}
static inline void ar5312_prom_init(void) {}
diff --git a/arch/mips/ath25/board.c b/arch/mips/ath25/board.c
index 68447d3..7db5a8e 100644
--- a/arch/mips/ath25/board.c
+++ b/arch/mips/ath25/board.c
@@ -16,12 +16,165 @@
#include <asm/bootinfo.h>
#include <asm/time.h>

+#include <ath25_platform.h>
#include "devices.h"
#include "ar5312.h"
#include "ar2315.h"

void (*ath25_irq_dispatch)(void);

+static inline bool check_radio_magic(const u8 *addr)
+{
+ addr += 0x7a; /* offset for flash magic */
+ return (addr[0] == 0x5a) && (addr[1] == 0xa5);
+}
+
+static inline bool check_notempty(const u8 *addr)
+{
+ return *(u32 *)addr != 0xffffffff;
+}
+
+static inline bool check_board_data(const u8 *flash_limit, const u8 *addr,
+ bool broken)
+{
+ /* config magic found */
+ if (*((u32 *)addr) == ATH25_BD_MAGIC)
+ return true;
+
+ if (!broken)
+ return false;
+
+ if (check_radio_magic(addr + 0xf8))
+ ath25_board.radio = addr + 0xf8;
+ if ((addr < flash_limit + 0x10000) &&
+ check_radio_magic(addr + 0x10000))
+ ath25_board.radio = addr + 0x10000;
+
+ if (ath25_board.radio) {
+ /* broken board data detected, use radio data to find the
+ * offset, user will fix this */
+ return true;
+ }
+
+ return false;
+}
+
+static const u8 * __init find_board_config(const u8 *flash_limit, bool broken)
+{
+ const u8 *addr;
+ const u8 *begin = flash_limit - 0x1000;
+ const u8 *end = flash_limit - 0x30000;
+
+ for (addr = begin; addr >= end; addr -= 0x1000)
+ if (check_board_data(flash_limit, addr, broken))
+ return addr;
+
+ return NULL;
+}
+
+static const u8 * __init find_radio_config(const u8 *flash_limit,
+ const u8 *bcfg)
+{
+ const u8 *rcfg, *begin, *end;
+
+ /*
+ * Now find the start of Radio Configuration data, using heuristics:
+ * Search forward from Board Configuration data by 0x1000 bytes
+ * at a time until we find non-0xffffffff.
+ */
+ begin = bcfg + 0x1000;
+ end = flash_limit;
+ for (rcfg = begin; rcfg < end; rcfg += 0x1000)
+ if (check_notempty(rcfg) && check_radio_magic(rcfg))
+ return rcfg;
+
+ /* AR2316 relocates radio config to new location */
+ begin = bcfg + 0xf8;
+ end = flash_limit - 0x1000 + 0xf8;
+ for (rcfg = begin; rcfg < end; rcfg += 0x1000)
+ if (check_notempty(rcfg) && check_radio_magic(rcfg))
+ return rcfg;
+
+ pr_warn("WARNING: Could not find Radio Configuration data\n");
+
+ return NULL;
+}
+
+int __init ath25_find_config(const u8 *flash_limit)
+{
+ struct ath25_boarddata *config;
+ unsigned int rcfg_size;
+ int broken_boarddata = 0;
+ const u8 *bcfg, *rcfg;
+ u8 *board_data;
+ u8 *radio_data;
+ u8 *mac_addr;
+ u32 offset;
+
+ ath25_board.config = NULL;
+ ath25_board.radio = NULL;
+ /* Copy the board and radio data to RAM, because accessing the mapped
+ * memory of the flash directly after booting is not safe */
+
+ /* Try to find valid board and radio data */
+ bcfg = find_board_config(flash_limit, false);
+
+ /* If that fails, try to at least find valid radio data */
+ if (!bcfg) {
+ bcfg = find_board_config(flash_limit, true);
+ broken_boarddata = 1;
+ }
+
+ if (!bcfg) {
+ pr_warn("WARNING: No board configuration data found!\n");
+ return -ENODEV;
+ }
+
+ board_data = kzalloc(BOARD_CONFIG_BUFSZ, GFP_KERNEL);
+ ath25_board.config = (struct ath25_boarddata *)board_data;
+ memcpy(board_data, bcfg, 0x100);
+ if (broken_boarddata) {
+ pr_warn("WARNING: broken board data detected\n");
+ config = ath25_board.config;
+ if (is_zero_ether_addr(config->enet0_mac)) {
+ pr_info("Fixing up empty mac addresses\n");
+ config->reset_config_gpio = 0xffff;
+ config->sys_led_gpio = 0xffff;
+ random_ether_addr(config->wlan0_mac);
+ config->wlan0_mac[0] &= ~0x06;
+ random_ether_addr(config->enet0_mac);
+ random_ether_addr(config->enet1_mac);
+ }
+ }
+
+ /* Radio config starts 0x100 bytes after board config, regardless
+ * of what the physical layout on the flash chip looks like */
+
+ if (ath25_board.radio)
+ rcfg = (u8 *)ath25_board.radio;
+ else
+ rcfg = find_radio_config(flash_limit, bcfg);
+
+ if (!rcfg)
+ return -ENODEV;
+
+ radio_data = board_data + 0x100 + ((rcfg - bcfg) & 0xfff);
+ ath25_board.radio = radio_data;
+ offset = radio_data - board_data;
+ pr_info("Radio config found at offset 0x%x (0x%x)\n", rcfg - bcfg,
+ offset);
+ rcfg_size = BOARD_CONFIG_BUFSZ - offset;
+ memcpy(radio_data, rcfg, rcfg_size);
+
+ mac_addr = &radio_data[0x1d * 2];
+ if (is_broadcast_ether_addr(mac_addr)) {
+ pr_info("Radio MAC is blank; using board-data\n");
+ ether_addr_copy(mac_addr, ath25_board.config->wlan0_mac);
+ }
+
+ return 0;
+}
+
static void ath25_halt(void)
{
local_irq_disable();
diff --git a/arch/mips/ath25/devices.c b/arch/mips/ath25/devices.c
index 0416cd2..d24dbb1 100644
--- a/arch/mips/ath25/devices.c
+++ b/arch/mips/ath25/devices.c
@@ -3,7 +3,12 @@
#include <linux/serial_8250.h>
#include <asm/bootinfo.h>

+#include <ath25_platform.h>
#include "devices.h"
+#include "ar5312.h"
+#include "ar2315.h"
+
+struct ar231x_board_config ath25_board;

const char *get_system_type(void)
{
@@ -26,6 +31,18 @@ void __init ath25_serial_setup(u32 mapbase, int irq, unsigned int uartclk)
early_serial_setup(&s);
}

+static int __init ath25_register_devices(void)
+{
+ if (is_ar5312())
+ ar5312_init_devices();
+ else
+ ar2315_init_devices();
+
+ return 0;
+}
+
+device_initcall(ath25_register_devices);
+
static int __init ath25_arch_init(void)
{
if (is_ar5312())
diff --git a/arch/mips/ath25/devices.h b/arch/mips/ath25/devices.h
index 54fafd3..10f196d 100644
--- a/arch/mips/ath25/devices.h
+++ b/arch/mips/ath25/devices.h
@@ -3,8 +3,10 @@

#include <linux/cpu.h>

+extern struct ar231x_board_config ath25_board;
extern void (*ath25_irq_dispatch)(void);

+int ath25_find_config(const u8 *flash_limit);
void ath25_serial_setup(u32 mapbase, int irq, unsigned int uartclk);

static inline bool is_ar2315(void)
diff --git a/arch/mips/include/asm/mach-ath25/ath25_platform.h b/arch/mips/include/asm/mach-ath25/ath25_platform.h
new file mode 100644
index 0000000..4f4ee4f
--- /dev/null
+++ b/arch/mips/include/asm/mach-ath25/ath25_platform.h
@@ -0,0 +1,73 @@
+#ifndef __ASM_MACH_ATH25_PLATFORM_H
+#define __ASM_MACH_ATH25_PLATFORM_H
+
+#include <linux/etherdevice.h>
+
+/*
+ * This is board-specific data that is stored in a "fixed" location in flash.
+ * It is shared across operating systems, so it should not be changed lightly.
+ * The main reason we need it is in order to extract the ethernet MAC
+ * address(es).
+ */
+struct ath25_boarddata {
+ u32 magic; /* board data is valid */
+#define ATH25_BD_MAGIC 0x35333131 /* "5311", for all 531x/231x platforms */
+ u16 cksum; /* checksum (starting with BD_REV 2) */
+ u16 rev; /* revision of this struct */
+#define BD_REV 4
+ char board_name[64]; /* Name of board */
+ u16 major; /* Board major number */
+ u16 minor; /* Board minor number */
+ u32 flags; /* Board configuration */
+#define BD_ENET0 0x00000001 /* ENET0 is stuffed */
+#define BD_ENET1 0x00000002 /* ENET1 is stuffed */
+#define BD_UART1 0x00000004 /* UART1 is stuffed */
+#define BD_UART0 0x00000008 /* UART0 is stuffed (dma) */
+#define BD_RSTFACTORY 0x00000010 /* Reset factory defaults stuffed */
+#define BD_SYSLED 0x00000020 /* System LED stuffed */
+#define BD_EXTUARTCLK 0x00000040 /* External UART clock */
+#define BD_CPUFREQ 0x00000080 /* cpu freq is valid in nvram */
+#define BD_SYSFREQ 0x00000100 /* sys freq is set in nvram */
+#define BD_WLAN0 0x00000200 /* Enable WLAN0 */
+#define BD_MEMCAP 0x00000400 /* CAP SDRAM @ mem_cap for testing */
+#define BD_DISWATCHDOG 0x00000800 /* disable system watchdog */
+#define BD_WLAN1 0x00001000 /* Enable WLAN1 (ar5212) */
+#define BD_ISCASPER 0x00002000 /* FLAG for AR2312 */
+#define BD_WLAN0_2G_EN 0x00004000 /* FLAG for radio0_2G */
+#define BD_WLAN0_5G_EN 0x00008000 /* FLAG for radio0_2G */
+#define BD_WLAN1_2G_EN 0x00020000 /* FLAG for radio0_2G */
+#define BD_WLAN1_5G_EN 0x00040000 /* FLAG for radio0_2G */
+ u16 reset_config_gpio; /* Reset factory GPIO pin */
+ u16 sys_led_gpio; /* System LED GPIO pin */
+
+ u32 cpu_freq; /* CPU core frequency in Hz */
+ u32 sys_freq; /* System frequency in Hz */
+ u32 cnt_freq; /* Calculated C0_COUNT frequency */
+
+ u8 wlan0_mac[ETH_ALEN];
+ u8 enet0_mac[ETH_ALEN];
+ u8 enet1_mac[ETH_ALEN];
+
+ u16 pci_id; /* Pseudo PCIID for common code */
+ u16 mem_cap; /* cap bank1 in MB */
+
+ /* version 3 */
+ u8 wlan1_mac[ETH_ALEN]; /* (ar5212) */
+};
+
+#define BOARD_CONFIG_BUFSZ 0x1000
+
+/*
+ * Platform device information for the Wireless MAC
+ */
+struct ar231x_board_config {
+ u16 devid;
+
+ /* board config data */
+ struct ath25_boarddata *config;
+
+ /* radio calibration data */
+ const char *radio;
+};
+
+#endif /* __ASM_MACH_ATH25_PLATFORM_H */
--
1.8.5.5
Sergey Ryazanov
2014-10-21 23:03:46 UTC
Permalink
Detect SoC type based on device ID and board configuration data.

Signed-off-by: Sergey Ryazanov <***@gmail.com>
---

Changes since v1:
- rename MIPS machine ar231x -> ath25
- rename dev_type -> soc_type

arch/mips/ath25/ar2315.c | 22 +++++++++++++++++++++-
arch/mips/ath25/ar5312.c | 22 ++++++++++++++++++++++
arch/mips/ath25/devices.c | 17 ++++++++++++++++-
arch/mips/ath25/devices.h | 16 ++++++++++++++++
4 files changed, 75 insertions(+), 2 deletions(-)

diff --git a/arch/mips/ath25/ar2315.c b/arch/mips/ath25/ar2315.c
index d3ff812..f239035 100644
--- a/arch/mips/ath25/ar2315.c
+++ b/arch/mips/ath25/ar2315.c
@@ -22,6 +22,7 @@
#include <asm/time.h>

#include <ar2315_regs.h>
+#include <ath25_platform.h>
#include <ath25.h>

#include "devices.h"
@@ -237,7 +238,7 @@ void __init ar2315_plat_mem_setup(void)

void __init ar2315_prom_init(void)
{
- u32 memsize, memcfg;
+ u32 memsize, memcfg, devid;

memcfg = ath25_read_reg(AR2315_MEM_CFG);
memsize = 1 + ATH25_REG_MS(memcfg, AR2315_MEM_CFG_DATA_WIDTH);
@@ -245,6 +246,25 @@ void __init ar2315_prom_init(void)
memsize <<= 1 + ATH25_REG_MS(memcfg, AR2315_MEM_CFG_ROW_WIDTH);
memsize <<= 3;
add_memory_region(0, memsize, BOOT_MEM_RAM);
+
+ /* Detect the hardware based on the device ID */
+ devid = ath25_read_reg(AR2315_SREV) & AR2315_REV_CHIP;
+ switch (devid) {
+ case 0x91: /* Need to check */
+ ath25_soc = ATH25_SOC_AR2318;
+ break;
+ case 0x90:
+ ath25_soc = ATH25_SOC_AR2317;
+ break;
+ case 0x87:
+ ath25_soc = ATH25_SOC_AR2316;
+ break;
+ case 0x86:
+ default:
+ ath25_soc = ATH25_SOC_AR2315;
+ break;
+ }
+ ath25_board.devid = devid;
}

void __init ar2315_arch_init(void)
diff --git a/arch/mips/ath25/ar5312.c b/arch/mips/ath25/ar5312.c
index 2d66665..faa0633 100644
--- a/arch/mips/ath25/ar5312.c
+++ b/arch/mips/ath25/ar5312.c
@@ -22,6 +22,7 @@
#include <asm/time.h>

#include <ar5312_regs.h>
+#include <ath25_platform.h>
#include <ath25.h>

#include "devices.h"
@@ -162,10 +163,25 @@ ar5312_flash_limit = (u8 *)KSEG1ADDR(AR5312_FLASH + 0x800000);

void __init ar5312_init_devices(void)
{
+ struct ath25_boarddata *config;
+
ar5312_flash_init();

/* Locate board/radio config data */
ath25_find_config(ar5312_flash_limit);
+ config = ath25_board.config;
+
+ /* AR2313 has CPU minor rev. 10 */
+ if ((current_cpu_data.processor_id & 0xff) == 0x0a)
+ ath25_soc = ATH25_SOC_AR2313;
+
+ /* AR2312 shares the same Silicon ID as AR5312 */
+ else if (config->flags & BD_ISCASPER)
+ ath25_soc = ATH25_SOC_AR2312;
+
+ /* Everything else is probably AR5312 or compatible */
+ else
+ ath25_soc = ATH25_SOC_AR5312;
}

static void ar5312_restart(char *command)
@@ -262,6 +278,7 @@ void __init ar5312_plat_mem_setup(void)
void __init ar5312_prom_init(void)
{
u32 memsize, memcfg, bank0_ac, bank1_ac;
+ u32 devid;

/* Detect memory size */
memcfg = ath25_read_reg(AR5312_MEM_CFG1);
@@ -271,6 +288,11 @@ void __init ar5312_prom_init(void)
(bank1_ac ? (1 << (bank1_ac + 1)) : 0);
memsize <<= 20;
add_memory_region(0, memsize, BOOT_MEM_RAM);
+
+ devid = ath25_read_reg(AR5312_REV);
+ devid >>= AR5312_REV_WMAC_MIN_S;
+ devid &= AR5312_REV_CHIP;
+ ath25_board.devid = (u16)devid;
}

void __init ar5312_arch_init(void)
diff --git a/arch/mips/ath25/devices.c b/arch/mips/ath25/devices.c
index d24dbb1..6218547 100644
--- a/arch/mips/ath25/devices.c
+++ b/arch/mips/ath25/devices.c
@@ -9,10 +9,25 @@
#include "ar2315.h"

struct ar231x_board_config ath25_board;
+enum ath25_soc_type ath25_soc = ATH25_SOC_UNKNOWN;
+
+static const char * const soc_type_strings[] = {
+ [ATH25_SOC_AR5312] = "Atheros AR5312",
+ [ATH25_SOC_AR2312] = "Atheros AR2312",
+ [ATH25_SOC_AR2313] = "Atheros AR2313",
+ [ATH25_SOC_AR2315] = "Atheros AR2315",
+ [ATH25_SOC_AR2316] = "Atheros AR2316",
+ [ATH25_SOC_AR2317] = "Atheros AR2317",
+ [ATH25_SOC_AR2318] = "Atheros AR2318",
+ [ATH25_SOC_UNKNOWN] = "Atheros (unknown)",
+};

const char *get_system_type(void)
{
- return "Atheros (unknown)";
+ if ((ath25_soc >= ARRAY_SIZE(soc_type_strings)) ||
+ !soc_type_strings[ath25_soc])
+ return soc_type_strings[ATH25_SOC_UNKNOWN];
+ return soc_type_strings[ath25_soc];
}

void __init ath25_serial_setup(u32 mapbase, int irq, unsigned int uartclk)
diff --git a/arch/mips/ath25/devices.h b/arch/mips/ath25/devices.h
index 10f196d..8555e32 100644
--- a/arch/mips/ath25/devices.h
+++ b/arch/mips/ath25/devices.h
@@ -3,6 +3,22 @@

#include <linux/cpu.h>

+enum ath25_soc_type {
+ /* handled by ar5312.c */
+ ATH25_SOC_AR2312,
+ ATH25_SOC_AR2313,
+ ATH25_SOC_AR5312,
+
+ /* handled by ar2315.c */
+ ATH25_SOC_AR2315,
+ ATH25_SOC_AR2316,
+ ATH25_SOC_AR2317,
+ ATH25_SOC_AR2318,
+
+ ATH25_SOC_UNKNOWN
+};
+
+extern enum ath25_soc_type ath25_soc;
extern struct ar231x_board_config ath25_board;
extern void (*ath25_irq_dispatch)(void);
--
1.8.5.5
Sergey Ryazanov
2014-10-21 23:03:47 UTC
Permalink
Register GPIO, watchdog and flash devices.

Signed-off-by: Sergey Ryazanov <***@gmail.com>
---

Changes since v1:
- rename MIPS machine ar231x -> ath25

arch/mips/ath25/Kconfig | 2 +
arch/mips/ath25/ar2315.c | 86 +++++++++++++++++++++++++-
arch/mips/ath25/ar5312.c | 53 +++++++++++++++-
arch/mips/include/asm/mach-ath25/ar2315_regs.h | 5 ++
arch/mips/include/asm/mach-ath25/ar5312_regs.h | 2 +
5 files changed, 144 insertions(+), 4 deletions(-)

diff --git a/arch/mips/ath25/Kconfig b/arch/mips/ath25/Kconfig
index ca3dde4..7bcdbf3 100644
--- a/arch/mips/ath25/Kconfig
+++ b/arch/mips/ath25/Kconfig
@@ -1,9 +1,11 @@
config SOC_AR5312
bool "Atheros AR5312/AR2312+ SoC support"
depends on ATH25
+ select GPIO_AR5312
default y

config SOC_AR2315
bool "Atheros AR2315+ SoC support"
depends on ATH25
+ select GPIO_AR2315
default y
diff --git a/arch/mips/ath25/ar2315.c b/arch/mips/ath25/ar2315.c
index f239035..ac784d7 100644
--- a/arch/mips/ath25/ar2315.c
+++ b/arch/mips/ath25/ar2315.c
@@ -16,7 +16,10 @@

#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/platform_device.h>
#include <linux/reboot.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
#include <asm/bootinfo.h>
#include <asm/reboot.h>
#include <asm/time.h>
@@ -136,6 +139,66 @@ void __init ar2315_arch_init_irq(void)
irq_set_chained_handler(AR2315_IRQ_MISC, ar2315_misc_irq_handler);
}

+static struct resource ar2315_spiflash_res[] = {
+ {
+ .name = "spiflash_read",
+ .flags = IORESOURCE_MEM,
+ .start = AR2315_SPI_READ,
+ .end = AR2315_SPI_READ + 0x1000000 - 1,
+ },
+ {
+ .name = "spiflash_mmr",
+ .flags = IORESOURCE_MEM,
+ .start = AR2315_SPI_MMR,
+ .end = AR2315_SPI_MMR + 12 - 1,
+ },
+};
+
+static struct platform_device ar2315_spiflash = {
+ .id = -1,
+ .name = "ar2315-spiflash",
+ .resource = ar2315_spiflash_res,
+ .num_resources = ARRAY_SIZE(ar2315_spiflash_res)
+};
+
+static struct resource ar2315_wdt_res[] = {
+ {
+ .flags = IORESOURCE_MEM,
+ .start = AR2315_WD,
+ .end = AR2315_WD + 8 - 1,
+ },
+ {
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct platform_device ar2315_wdt = {
+ .id = -1,
+ .name = "ar2315-wdt",
+ .resource = ar2315_wdt_res,
+ .num_resources = ARRAY_SIZE(ar2315_wdt_res)
+};
+
+static struct resource ar2315_gpio_res[] = {
+ {
+ .name = "ar2315-gpio",
+ .flags = IORESOURCE_MEM,
+ .start = AR2315_GPIO,
+ .end = AR2315_GPIO + 0x10 - 1,
+ },
+ {
+ .name = "ar2315-gpio",
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device ar2315_gpio = {
+ .id = -1,
+ .name = "ar2315-gpio",
+ .resource = ar2315_gpio_res,
+ .num_resources = ARRAY_SIZE(ar2315_gpio_res)
+};
+
/*
* NB: We use mapping size that is larger than the actual flash size,
* but this shouldn't be a problem here, because the flash will simply
@@ -146,8 +209,20 @@ ar2315_flash_limit = (u8 *)KSEG1ADDR(AR2315_SPI_READ + 0x1000000);

void __init ar2315_init_devices(void)
{
+ struct resource *res;
+
/* Find board configuration */
ath25_find_config(ar2315_flash_limit);
+
+ res = &ar2315_gpio_res[1];
+ res->start = ar2315_misc_irq_base + AR2315_MISC_IRQ_GPIO;
+ res->end = res->start;
+ platform_device_register(&ar2315_gpio);
+ res = &ar2315_wdt_res[1];
+ res->start = ar2315_misc_irq_base + AR2315_MISC_IRQ_WATCHDOG;
+ res->end = res->start;
+ platform_device_register(&ar2315_wdt);
+ platform_device_register(&ar2315_spiflash);
}

static void ar2315_restart(char *command)
@@ -159,8 +234,15 @@ static void ar2315_restart(char *command)
/* try reset the system via reset control */
ath25_write_reg(AR2315_COLD_RESET, AR2317_RESET_SYSTEM);

- /* Attempt to jump to the mips reset location - the boot loader
- * itself might be able to recover the system */
+ /* Cold reset does not work on the AR2315/6, use the GPIO reset bits
+ * a workaround. Give it some time to attempt a gpio based hardware
+ * reset (atheros reference design workaround) */
+ gpio_request_one(AR2315_RESET_GPIO, GPIOF_OUT_INIT_LOW, "Reset");
+ mdelay(100);
+
+ /* Some boards (e.g. Senao EOC-2610) don't implement the reset logic
+ * workaround. Attempt to jump to the mips reset location -
+ * the boot loader itself might be able to recover the system */
mips_reset_vec();
}

diff --git a/arch/mips/ath25/ar5312.c b/arch/mips/ath25/ar5312.c
index faa0633..99c2745 100644
--- a/arch/mips/ath25/ar5312.c
+++ b/arch/mips/ath25/ar5312.c
@@ -16,6 +16,8 @@

#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
#include <linux/reboot.h>
#include <asm/bootinfo.h>
#include <asm/reboot.h>
@@ -131,15 +133,59 @@ void __init ar5312_arch_init_irq(void)
irq_set_chained_handler(AR5312_IRQ_MISC, ar5312_misc_irq_handler);
}

+static struct physmap_flash_data ar5312_flash_data = {
+ .width = 2,
+};
+
+static struct resource ar5312_flash_resource = {
+ .start = AR5312_FLASH,
+ .end = AR5312_FLASH + 0x800000 - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device ar5312_physmap_flash = {
+ .name = "physmap-flash",
+ .id = 0,
+ .dev.platform_data = &ar5312_flash_data,
+ .resource = &ar5312_flash_resource,
+ .num_resources = 1,
+};
+
+static struct resource ar5312_gpio_res[] = {
+ {
+ .name = "ar5312-gpio",
+ .flags = IORESOURCE_MEM,
+ .start = AR5312_GPIO,
+ .end = AR5312_GPIO + 0x0c - 1,
+ },
+};
+
+static struct platform_device ar5312_gpio = {
+ .name = "ar5312-gpio",
+ .id = -1,
+ .resource = ar5312_gpio_res,
+ .num_resources = ARRAY_SIZE(ar5312_gpio_res),
+};
+
static void __init ar5312_flash_init(void)
{
- u32 ctl;
+ u32 ctl = ath25_read_reg(AR5312_FLASHCTL0) & AR5312_FLASHCTL_MW;
+
+ /* fixup flash width */
+ switch (ctl) {
+ case AR5312_FLASHCTL_MW16:
+ ar5312_flash_data.width = 2;
+ break;
+ case AR5312_FLASHCTL_MW8:
+ default:
+ ar5312_flash_data.width = 1;
+ break;
+ }

/*
* Configure flash bank 0.
* Assume 8M window size. Flash will be aliased if it's smaller
*/
- ctl = ath25_read_reg(AR5312_FLASHCTL0) & AR5312_FLASHCTL_MW;
ctl |= AR5312_FLASHCTL_E | AR5312_FLASHCTL_AC_8M | AR5312_FLASHCTL_RBLE;
ctl |= 0x01 << AR5312_FLASHCTL_IDCY_S;
ctl |= 0x07 << AR5312_FLASHCTL_WST1_S;
@@ -182,6 +228,9 @@ void __init ar5312_init_devices(void)
/* Everything else is probably AR5312 or compatible */
else
ath25_soc = ATH25_SOC_AR5312;
+
+ platform_device_register(&ar5312_physmap_flash);
+ platform_device_register(&ar5312_gpio);
}

static void ar5312_restart(char *command)
diff --git a/arch/mips/include/asm/mach-ath25/ar2315_regs.h b/arch/mips/include/asm/mach-ath25/ar2315_regs.h
index e680abc..d61c8a1 100644
--- a/arch/mips/include/asm/mach-ath25/ar2315_regs.h
+++ b/arch/mips/include/asm/mach-ath25/ar2315_regs.h
@@ -283,6 +283,11 @@
#define AR2315_AMBACLK_CLK_DIV_M 0x0000000c
#define AR2315_AMBACLK_CLK_DIV_S 2

+/* GPIO MMR base address */
+#define AR2315_GPIO (AR2315_DSLBASE + 0x0088)
+
+#define AR2315_RESET_GPIO 5
+
/*
* PCI Clock Control
*/
diff --git a/arch/mips/include/asm/mach-ath25/ar5312_regs.h b/arch/mips/include/asm/mach-ath25/ar5312_regs.h
index afcd0b2..d715385 100644
--- a/arch/mips/include/asm/mach-ath25/ar5312_regs.h
+++ b/arch/mips/include/asm/mach-ath25/ar5312_regs.h
@@ -210,4 +210,6 @@
#define AR5312_MEM_CFG1_AC1_M 0x00007000 /* bank 1: SDRAM addr check */
#define AR5312_MEM_CFG1_AC1_S 12

+#define AR5312_GPIO (AR5312_APBBASE + 0x2000)
+
#endif /* __ASM_MACH_ATH25_AR5312_REGS_H */
--
1.8.5.5
John Crispin
2014-10-22 08:39:55 UTC
Permalink
Post by Sergey Ryazanov
Register GPIO, watchdog and flash devices.
Changes since v1: - rename MIPS machine ar231x -> ath25
arch/mips/ath25/Kconfig | 2 +
arch/mips/ath25/ar2315.c | 86
+++++++++++++++++++++++++- arch/mips/ath25/ar5312.c
| 53 +++++++++++++++-
arch/mips/include/asm/mach-ath25/ar2315_regs.h | 5 ++
arch/mips/include/asm/mach-ath25/ar5312_regs.h | 2 + 5 files
changed, 144 insertions(+), 4 deletions(-)
diff --git a/arch/mips/ath25/Kconfig b/arch/mips/ath25/Kconfig
index ca3dde4..7bcdbf3 100644 --- a/arch/mips/ath25/Kconfig +++
"Atheros AR5312/AR2312+ SoC support" depends on ATH25 + select
GPIO_AR5312 default y
config SOC_AR2315 bool "Atheros AR2315+ SoC support" depends on
ATH25 + select GPIO_AR2315 default y
please do not select these 2 until the driver
Post by Sergey Ryazanov
diff --git a/arch/mips/ath25/ar2315.c b/arch/mips/ath25/ar2315.c
index f239035..ac784d7 100644 --- a/arch/mips/ath25/ar2315.c +++
#include <linux/init.h> #include <linux/kernel.h> +#include
<linux/platform_device.h> #include <linux/reboot.h> +#include
<linux/delay.h> +#include <linux/gpio.h> #include <asm/bootinfo.h>
void __init ar2315_arch_init_irq(void)
irq_set_chained_handler(AR2315_IRQ_MISC, ar2315_misc_irq_handler);
}
+static struct resource ar2315_spiflash_res[] = { + { + .name =
"spiflash_read", + .flags = IORESOURCE_MEM, + .start =
AR2315_SPI_READ, + .end = AR2315_SPI_READ + 0x1000000 - 1, + }, +
{ + .name = "spiflash_mmr", + .flags = IORESOURCE_MEM, + .start
= AR2315_SPI_MMR, + .end = AR2315_SPI_MMR + 12 - 1, + }, +}; +
+static struct platform_device ar2315_spiflash = { + .id = -1, +
.name = "ar2315-spiflash", + .resource = ar2315_spiflash_res, +
.num_resources = ARRAY_SIZE(ar2315_spiflash_res) +}; + +static
struct resource ar2315_wdt_res[] = { + { + .flags =
IORESOURCE_MEM, + .start = AR2315_WD, + .end = AR2315_WD + 8 -
1, + }, + { + .flags = IORESOURCE_IRQ, + } +}; + +static struct
platform_device ar2315_wdt = { + .id = -1, + .name = "ar2315-wdt",
+ .resource = ar2315_wdt_res, + .num_resources =
ARRAY_SIZE(ar2315_wdt_res) +}; + +static struct resource
ar2315_gpio_res[] = { + { + .name = "ar2315-gpio", + .flags =
IORESOURCE_MEM, + .start = AR2315_GPIO, + .end = AR2315_GPIO +
0x10 - 1, + }, + { + .name = "ar2315-gpio", + .flags =
IORESOURCE_IRQ, + }, +}; + +static struct platform_device
ar2315_gpio = { + .id = -1, + .name = "ar2315-gpio", + .resource =
ar2315_gpio_res, + .num_resources = ARRAY_SIZE(ar2315_gpio_res)
+}; +
i think none of these needs to be part of the series. add them with
their corresponding drivers please
Post by Sergey Ryazanov
/* * NB: We use mapping size that is larger than the actual flash
size, * but this shouldn't be a problem here, because the flash
*)KSEG1ADDR(AR2315_SPI_READ + 0x1000000);
void __init ar2315_init_devices(void) { + struct resource *res; +
/* Find board configuration */
ath25_find_config(ar2315_flash_limit); + + res =
&ar2315_gpio_res[1]; + res->start = ar2315_misc_irq_base +
AR2315_MISC_IRQ_GPIO; + res->end = res->start; +
platform_device_register(&ar2315_gpio); + res =
&ar2315_wdt_res[1]; + res->start = ar2315_misc_irq_base +
AR2315_MISC_IRQ_WATCHDOG; + res->end = res->start; +
platform_device_register(&ar2315_wdt); +
platform_device_register(&ar2315_spiflash); }
static void ar2315_restart(char *command) /* try reset the system
via reset control */ ath25_write_reg(AR2315_COLD_RESET,
AR2317_RESET_SYSTEM);
- /* Attempt to jump to the mips reset location - the boot loader -
* itself might be able to recover the system */ + /* Cold reset
does not work on the AR2315/6, use the GPIO reset bits + * a
workaround. Give it some time to attempt a gpio based hardware + *
reset (atheros reference design workaround) */ +
gpio_request_one(AR2315_RESET_GPIO, GPIOF_OUT_INIT_LOW, "Reset");
same here ...
Post by Sergey Ryazanov
+ mdelay(100); + + /* Some boards (e.g. Senao EOC-2610) don't
implement the reset logic + * workaround. Attempt to jump to the
mips reset location - + * the boot loader itself might be able to
recover the system */ mips_reset_vec(); }
diff --git a/arch/mips/ath25/ar5312.c b/arch/mips/ath25/ar5312.c
index faa0633..99c2745 100644 --- a/arch/mips/ath25/ar5312.c +++
#include <linux/init.h> #include <linux/kernel.h> +#include
<linux/platform_device.h> +#include <linux/mtd/physmap.h> #include
<linux/reboot.h> #include <asm/bootinfo.h> #include <asm/reboot.h>
@@ -131,15 +133,59 @@ void __init ar5312_arch_init_irq(void)
irq_set_chained_handler(AR5312_IRQ_MISC, ar5312_misc_irq_handler);
}
+static struct physmap_flash_data ar5312_flash_data = { + .width =
2, +}; + +static struct resource ar5312_flash_resource = { + .start
= AR5312_FLASH, + .end = AR5312_FLASH + 0x800000 - 1, + .flags =
IORESOURCE_MEM, +}; + +static struct platform_device
ar5312_physmap_flash = { + .name = "physmap-flash", + .id = 0, +
.dev.platform_data = &ar5312_flash_data, + .resource =
&ar5312_flash_resource, + .num_resources = 1, +}; + +static struct
resource ar5312_gpio_res[] = { + { + .name = "ar5312-gpio", +
.flags = IORESOURCE_MEM, + .start = AR5312_GPIO, + .end =
AR5312_GPIO + 0x0c - 1, + }, +}; + +static struct platform_device
ar5312_gpio = { + .name = "ar5312-gpio", + .id = -1, + .resource =
ar5312_gpio_res, + .num_resources = ARRAY_SIZE(ar5312_gpio_res),
+}; +
and here .. etc etc
Post by Sergey Ryazanov
static void __init ar5312_flash_init(void) { - u32 ctl; + u32 ctl =
ath25_read_reg(AR5312_FLASHCTL0) & AR5312_FLASHCTL_MW; + + /* fixup
flash width */ + switch (ctl) { + case AR5312_FLASHCTL_MW16: +
+ default: + ar5312_flash_data.width = 1; + break; + }
/* * Configure flash bank 0. * Assume 8M window size. Flash will be
aliased if it's smaller */ - ctl = ath25_read_reg(AR5312_FLASHCTL0)
& AR5312_FLASHCTL_MW; ctl |= AR5312_FLASHCTL_E |
AR5312_FLASHCTL_AC_8M | AR5312_FLASHCTL_RBLE; ctl |= 0x01 <<
Everything else is probably AR5312 or compatible */ else ath25_soc
= ATH25_SOC_AR5312; + +
platform_device_register(&ar5312_physmap_flash); +
platform_device_register(&ar5312_gpio); }
static void ar5312_restart(char *command) diff --git
a/arch/mips/include/asm/mach-ath25/ar2315_regs.h
b/arch/mips/include/asm/mach-ath25/ar2315_regs.h index
e680abc..d61c8a1 100644 ---
a/arch/mips/include/asm/mach-ath25/ar2315_regs.h +++
@@ #define AR2315_AMBACLK_CLK_DIV_M 0x0000000c #define
AR2315_AMBACLK_CLK_DIV_S 2
+/* GPIO MMR base address */ +#define AR2315_GPIO (AR2315_DSLBASE
+ 0x0088) + +#define AR2315_RESET_GPIO 5 + /* * PCI Clock Control
*/ diff --git a/arch/mips/include/asm/mach-ath25/ar5312_regs.h
b/arch/mips/include/asm/mach-ath25/ar5312_regs.h index
afcd0b2..d715385 100644 ---
a/arch/mips/include/asm/mach-ath25/ar5312_regs.h +++
@@ #define AR5312_MEM_CFG1_AC1_M 0x00007000 /* bank 1: SDRAM addr
check */ #define AR5312_MEM_CFG1_AC1_S 12
+#define AR5312_GPIO (AR5312_APBBASE + 0x2000) + #endif /*
__ASM_MACH_ATH25_AR5312_REGS_H */
Sergey Ryazanov
2014-10-22 15:22:18 UTC
Permalink
Post by John Crispin
Post by Sergey Ryazanov
Register GPIO, watchdog and flash devices.
Changes since v1: - rename MIPS machine ar231x -> ath25
arch/mips/ath25/Kconfig | 2 +
arch/mips/ath25/ar2315.c | 86
+++++++++++++++++++++++++- arch/mips/ath25/ar5312.c
| 53 +++++++++++++++-
arch/mips/include/asm/mach-ath25/ar2315_regs.h | 5 ++
arch/mips/include/asm/mach-ath25/ar5312_regs.h | 2 + 5 files
changed, 144 insertions(+), 4 deletions(-)
diff --git a/arch/mips/ath25/Kconfig b/arch/mips/ath25/Kconfig
index ca3dde4..7bcdbf3 100644 --- a/arch/mips/ath25/Kconfig +++
"Atheros AR5312/AR2312+ SoC support" depends on ATH25 + select
GPIO_AR5312 default y
config SOC_AR2315 bool "Atheros AR2315+ SoC support" depends on
ATH25 + select GPIO_AR2315 default y
please do not select these 2 until the driver
Ok
Post by John Crispin
Post by Sergey Ryazanov
diff --git a/arch/mips/ath25/ar2315.c b/arch/mips/ath25/ar2315.c
index f239035..ac784d7 100644 --- a/arch/mips/ath25/ar2315.c +++
#include <linux/init.h> #include <linux/kernel.h> +#include
<linux/platform_device.h> #include <linux/reboot.h> +#include
<linux/delay.h> +#include <linux/gpio.h> #include <asm/bootinfo.h>
void __init ar2315_arch_init_irq(void)
irq_set_chained_handler(AR2315_IRQ_MISC, ar2315_misc_irq_handler);
}
+static struct resource ar2315_spiflash_res[] = { + { + .name =
"spiflash_read", + .flags = IORESOURCE_MEM, + .start =
AR2315_SPI_READ, + .end = AR2315_SPI_READ + 0x1000000 - 1, + }, +
{ + .name = "spiflash_mmr", + .flags = IORESOURCE_MEM, + .start
= AR2315_SPI_MMR, + .end = AR2315_SPI_MMR + 12 - 1, + }, +}; +
+static struct platform_device ar2315_spiflash = { + .id = -1, +
.name = "ar2315-spiflash", + .resource = ar2315_spiflash_res, +
.num_resources = ARRAY_SIZE(ar2315_spiflash_res) +}; + +static
struct resource ar2315_wdt_res[] = { + { + .flags =
IORESOURCE_MEM, + .start = AR2315_WD, + .end = AR2315_WD + 8 -
1, + }, + { + .flags = IORESOURCE_IRQ, + } +}; + +static struct
platform_device ar2315_wdt = { + .id = -1, + .name = "ar2315-wdt",
+ .resource = ar2315_wdt_res, + .num_resources =
ARRAY_SIZE(ar2315_wdt_res) +}; + +static struct resource
ar2315_gpio_res[] = { + { + .name = "ar2315-gpio", + .flags =
IORESOURCE_MEM, + .start = AR2315_GPIO, + .end = AR2315_GPIO +
0x10 - 1, + }, + { + .name = "ar2315-gpio", + .flags =
IORESOURCE_IRQ, + }, +}; + +static struct platform_device
ar2315_gpio = { + .id = -1, + .name = "ar2315-gpio", + .resource =
ar2315_gpio_res, + .num_resources = ARRAY_SIZE(ar2315_gpio_res)
+}; +
i think none of these needs to be part of the series. add them with
their corresponding drivers please
Ok
Post by John Crispin
Post by Sergey Ryazanov
/* * NB: We use mapping size that is larger than the actual flash
size, * but this shouldn't be a problem here, because the flash
*)KSEG1ADDR(AR2315_SPI_READ + 0x1000000);
void __init ar2315_init_devices(void) { + struct resource *res; +
/* Find board configuration */
ath25_find_config(ar2315_flash_limit); + + res =
&ar2315_gpio_res[1]; + res->start = ar2315_misc_irq_base +
AR2315_MISC_IRQ_GPIO; + res->end = res->start; +
platform_device_register(&ar2315_gpio); + res =
&ar2315_wdt_res[1]; + res->start = ar2315_misc_irq_base +
AR2315_MISC_IRQ_WATCHDOG; + res->end = res->start; +
platform_device_register(&ar2315_wdt); +
platform_device_register(&ar2315_spiflash); }
static void ar2315_restart(char *command) /* try reset the system
via reset control */ ath25_write_reg(AR2315_COLD_RESET,
AR2317_RESET_SYSTEM);
- /* Attempt to jump to the mips reset location - the boot loader -
* itself might be able to recover the system */ + /* Cold reset
does not work on the AR2315/6, use the GPIO reset bits + * a
workaround. Give it some time to attempt a gpio based hardware + *
reset (atheros reference design workaround) */ +
gpio_request_one(AR2315_RESET_GPIO, GPIOF_OUT_INIT_LOW, "Reset");
same here ...
Yep
Post by John Crispin
Post by Sergey Ryazanov
+ mdelay(100); + + /* Some boards (e.g. Senao EOC-2610) don't
implement the reset logic + * workaround. Attempt to jump to the
mips reset location - + * the boot loader itself might be able to
recover the system */ mips_reset_vec(); }
diff --git a/arch/mips/ath25/ar5312.c b/arch/mips/ath25/ar5312.c
index faa0633..99c2745 100644 --- a/arch/mips/ath25/ar5312.c +++
#include <linux/init.h> #include <linux/kernel.h> +#include
<linux/platform_device.h> +#include <linux/mtd/physmap.h> #include
<linux/reboot.h> #include <asm/bootinfo.h> #include <asm/reboot.h>
@@ -131,15 +133,59 @@ void __init ar5312_arch_init_irq(void)
irq_set_chained_handler(AR5312_IRQ_MISC, ar5312_misc_irq_handler);
}
+static struct physmap_flash_data ar5312_flash_data = { + .width =
2, +}; + +static struct resource ar5312_flash_resource = { + .start
= AR5312_FLASH, + .end = AR5312_FLASH + 0x800000 - 1, + .flags =
IORESOURCE_MEM, +}; + +static struct platform_device
ar5312_physmap_flash = { + .name = "physmap-flash", + .id = 0, +
.dev.platform_data = &ar5312_flash_data, + .resource =
&ar5312_flash_resource, + .num_resources = 1, +}; + +static struct
resource ar5312_gpio_res[] = { + { + .name = "ar5312-gpio", +
.flags = IORESOURCE_MEM, + .start = AR5312_GPIO, + .end =
AR5312_GPIO + 0x0c - 1, + }, +}; + +static struct platform_device
ar5312_gpio = { + .name = "ar5312-gpio", + .id = -1, + .resource =
ar5312_gpio_res, + .num_resources = ARRAY_SIZE(ar5312_gpio_res),
+}; +
and here .. etc etc
Ok
Post by John Crispin
Post by Sergey Ryazanov
static void __init ar5312_flash_init(void) { - u32 ctl; + u32 ctl =
ath25_read_reg(AR5312_FLASHCTL0) & AR5312_FLASHCTL_MW; + + /* fixup
flash width */ + switch (ctl) { + case AR5312_FLASHCTL_MW16: +
+ default: + ar5312_flash_data.width = 1; + break; + }
/* * Configure flash bank 0. * Assume 8M window size. Flash will be
aliased if it's smaller */ - ctl = ath25_read_reg(AR5312_FLASHCTL0)
& AR5312_FLASHCTL_MW; ctl |= AR5312_FLASHCTL_E |
AR5312_FLASHCTL_AC_8M | AR5312_FLASHCTL_RBLE; ctl |= 0x01 <<
Everything else is probably AR5312 or compatible */ else ath25_soc
= ATH25_SOC_AR5312; + +
platform_device_register(&ar5312_physmap_flash); +
platform_device_register(&ar5312_gpio); }
static void ar5312_restart(char *command) diff --git
a/arch/mips/include/asm/mach-ath25/ar2315_regs.h
b/arch/mips/include/asm/mach-ath25/ar2315_regs.h index
e680abc..d61c8a1 100644 ---
a/arch/mips/include/asm/mach-ath25/ar2315_regs.h +++
@@ #define AR2315_AMBACLK_CLK_DIV_M 0x0000000c #define
AR2315_AMBACLK_CLK_DIV_S 2
+/* GPIO MMR base address */ +#define AR2315_GPIO (AR2315_DSLBASE
+ 0x0088) + +#define AR2315_RESET_GPIO 5 + /* * PCI Clock Control
*/ diff --git a/arch/mips/include/asm/mach-ath25/ar5312_regs.h
b/arch/mips/include/asm/mach-ath25/ar5312_regs.h index
afcd0b2..d715385 100644 ---
a/arch/mips/include/asm/mach-ath25/ar5312_regs.h +++
@@ #define AR5312_MEM_CFG1_AC1_M 0x00007000 /* bank 1: SDRAM addr
check */ #define AR5312_MEM_CFG1_AC1_S 12
+#define AR5312_GPIO (AR5312_APBBASE + 0x2000) + #endif /*
__ASM_MACH_ATH25_AR5312_REGS_H */
--
BR,
Sergey
Sergey Ryazanov
2014-10-21 23:03:48 UTC
Permalink
Add PCI host controller driver and DMA address calculation hook.

Signed-off-by: Sergey Ryazanov <***@gmail.com>
---

Changes since RFC:
- use dynamic IRQ numbers allocation

Changes since v1:
- rename MIPS machine ar231x -> ath25

arch/mips/ath25/Kconfig | 7 +
arch/mips/ath25/ar2315.c | 9 +
arch/mips/include/asm/mach-ath25/ar2315_regs.h | 23 ++
arch/mips/include/asm/mach-ath25/dma-coherence.h | 18 +-
arch/mips/pci/Makefile | 1 +
arch/mips/pci/pci-ar2315.c | 352 +++++++++++++++++++++++
6 files changed, 407 insertions(+), 3 deletions(-)
create mode 100644 arch/mips/pci/pci-ar2315.c

diff --git a/arch/mips/ath25/Kconfig b/arch/mips/ath25/Kconfig
index 7bcdbf3..c83b70d 100644
--- a/arch/mips/ath25/Kconfig
+++ b/arch/mips/ath25/Kconfig
@@ -9,3 +9,10 @@ config SOC_AR2315
depends on ATH25
select GPIO_AR2315
default y
+
+config PCI_AR2315
+ bool "Atheros AR2315 PCI controller support"
+ depends on SOC_AR2315
+ select HW_HAS_PCI
+ select PCI
+ default y
diff --git a/arch/mips/ath25/ar2315.c b/arch/mips/ath25/ar2315.c
index ac784d7..76679c0 100644
--- a/arch/mips/ath25/ar2315.c
+++ b/arch/mips/ath25/ar2315.c
@@ -108,6 +108,10 @@ static void ar2315_irq_dispatch(void)

if (pending & CAUSEF_IP3)
do_IRQ(AR2315_IRQ_WLAN0);
+#ifdef CONFIG_PCI_AR2315
+ else if (pending & CAUSEF_IP5)
+ do_IRQ(AR2315_IRQ_LCBUS_PCI);
+#endif
else if (pending & CAUSEF_IP2)
do_IRQ(AR2315_IRQ_MISC);
else if (pending & CAUSEF_IP7)
@@ -353,5 +357,10 @@ void __init ar2315_arch_init(void)
{
ath25_serial_setup(AR2315_UART0, ar2315_misc_irq_base +
AR2315_MISC_IRQ_UART0, ar2315_apb_frequency());
+
+#ifdef CONFIG_PCI_AR2315
+ if (ath25_soc == ATH25_SOC_AR2315)
+ platform_device_register_simple("ar2315-pci", -1, NULL, 0);
+#endif
}

diff --git a/arch/mips/include/asm/mach-ath25/ar2315_regs.h b/arch/mips/include/asm/mach-ath25/ar2315_regs.h
index d61c8a1..e732b9a 100644
--- a/arch/mips/include/asm/mach-ath25/ar2315_regs.h
+++ b/arch/mips/include/asm/mach-ath25/ar2315_regs.h
@@ -38,6 +38,15 @@
#define AR2315_MISC_IRQ_COUNT 9

/*
+ * PCI interrupts, which share IP5
+ * Keep ordered according to AR2315_PCI_INT_XXX bits
+ */
+#define AR2315_PCI_IRQ_EXT 0
+#define AR2315_PCI_IRQ_ABORT 1
+#define AR2315_PCI_IRQ_COUNT 2
+#define AR2315_PCI_IRQ_SHIFT 25 /* in AR2315_PCI_INT_STATUS */
+
+/*
* Address map
*/
#define AR2315_SPI_READ 0x08000000 /* SPI flash */
@@ -554,4 +563,18 @@
#define AR2315_IRCFG_SEQ_END_WIN_THRESH 0x001f0000
#define AR2315_IRCFG_NUM_BACKOFF_WORDS 0x01e00000

+/*
+ * We need some arbitrary non-zero value to be programmed to the BAR1 register
+ * of PCI host controller to enable DMA. The same value should be used as the
+ * offset to calculate the physical address of DMA buffer for PCI devices.
+ */
+#define AR2315_PCI_HOST_SDRAM_BASEADDR 0x20000000
+
+/* ??? access BAR */
+#define AR2315_PCI_HOST_MBAR0 0x10000000
+/* RAM access BAR */
+#define AR2315_PCI_HOST_MBAR1 AR2315_PCI_HOST_SDRAM_BASEADDR
+/* ??? access BAR */
+#define AR2315_PCI_HOST_MBAR2 0x30000000
+
#endif /* __ASM_MACH_ATH25_AR2315_REGS_H */
diff --git a/arch/mips/include/asm/mach-ath25/dma-coherence.h b/arch/mips/include/asm/mach-ath25/dma-coherence.h
index 8b3d0cc..063c1ca 100644
--- a/arch/mips/include/asm/mach-ath25/dma-coherence.h
+++ b/arch/mips/include/asm/mach-ath25/dma-coherence.h
@@ -11,23 +11,35 @@
#define __ASM_MACH_ATH25_DMA_COHERENCE_H

#include <linux/device.h>
+#include <ar2315_regs.h>
+
+static inline dma_addr_t ath25_dev_offset(struct device *dev)
+{
+#ifdef CONFIG_PCI
+ extern struct bus_type pci_bus_type;
+
+ if (dev && dev->bus == &pci_bus_type)
+ return AR2315_PCI_HOST_SDRAM_BASEADDR;
+#endif
+ return 0;
+}

static inline dma_addr_t
plat_map_dma_mem(struct device *dev, void *addr, size_t size)
{
- return virt_to_phys(addr);
+ return virt_to_phys(addr) + ath25_dev_offset(dev);
}

static inline dma_addr_t
plat_map_dma_mem_page(struct device *dev, struct page *page)
{
- return page_to_phys(page);
+ return page_to_phys(page) + ath25_dev_offset(dev);
}

static inline unsigned long
plat_dma_addr_to_phys(struct device *dev, dma_addr_t dma_addr)
{
- return dma_addr;
+ return dma_addr - ath25_dev_offset(dev);
}

static inline void
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
index 6523d55..ab6c857 100644
--- a/arch/mips/pci/Makefile
+++ b/arch/mips/pci/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_BCM47XX) += pci-bcm47xx.o
obj-$(CONFIG_BCM63XX) += pci-bcm63xx.o fixup-bcm63xx.o \
ops-bcm63xx.o
obj-$(CONFIG_MIPS_ALCHEMY) += pci-alchemy.o
+obj-$(CONFIG_PCI_AR2315) += pci-ar2315.o
obj-$(CONFIG_SOC_AR71XX) += pci-ar71xx.o
obj-$(CONFIG_PCI_AR724X) += pci-ar724x.o
obj-$(CONFIG_MIPS_PCI_VIRTIO) += pci-virtio-guest.o
diff --git a/arch/mips/pci/pci-ar2315.c b/arch/mips/pci/pci-ar2315.c
new file mode 100644
index 0000000..bb6498f
--- /dev/null
+++ b/arch/mips/pci/pci-ar2315.c
@@ -0,0 +1,352 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Both AR2315 and AR2316 chips have PCI interface unit, which supports DMA
+ * and interrupt. PCI interface supports MMIO access method, but does not
+ * seem to support I/O ports.
+ *
+ * Read/write operation in the region 0x80000000-0xBFFFFFFF causes
+ * a memory read/write command on the PCI bus. 30 LSBs of address on
+ * the bus are taken from memory read/write request and 2 MSBs are
+ * determined by PCI unit configuration.
+ *
+ * To work with the configuration space instead of memory is necessary set
+ * the CFG_SEL bit in the PCI_MISC_CONFIG register.
+ *
+ * Devices on the bus can perform DMA requests via chip BAR1. PCI host
+ * controller BARs are programmend as if an external device is programmed.
+ * Which means that during configuration, IDSEL pin of the chip should be
+ * asserted.
+ *
+ * We know (and support) only one board that uses the PCI interface -
+ * Fonera 2.0g (FON2202). It has a USB EHCI controller connected to the
+ * AR2315 PCI bus. IDSEL pin of USB controller is connected to AD[13] line
+ * and IDSEL pin of AR125 is connected to AD[16] line.
+ */
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <asm/paccess.h>
+#include <ath25.h>
+#include <ar2315_regs.h>
+
+/* Arbitrary size of memory region to access the configuration space */
+#define AR2315_PCI_CFG_SIZE 0x00100000
+
+#define AR2315_PCI_HOST_SLOT 3
+#define AR2315_PCI_HOST_DEVID ((0xff18 << 16) | PCI_VENDOR_ID_ATHEROS)
+
+static void __iomem *ar2315_pci_cfg_mem;
+static unsigned ar2315_pci_irq_base;
+
+static int ar2315_pci_cfg_access(int devfn, int where, int size, u32 *ptr,
+ bool write)
+{
+ int func = PCI_FUNC(devfn);
+ int dev = PCI_SLOT(devfn);
+ u32 addr = (1 << (13 + dev)) | (func << 8) | (where & ~3);
+ u32 mask = 0xffffffff >> 8 * (4 - size);
+ u32 sh = (where & 3) * 8;
+ u32 value, isr;
+
+ /* Prevent access past the remapped area */
+ if (addr >= AR2315_PCI_CFG_SIZE || dev > 18)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ /* Clear pending errors */
+ ath25_write_reg(AR2315_PCI_ISR, AR2315_PCI_INT_ABORT);
+ /* Select Configuration access */
+ ath25_mask_reg(AR2315_PCI_MISC_CONFIG, 0, AR2315_PCIMISC_CFG_SEL);
+
+ mb(); /* PCI must see space change before we begin */
+
+ value = __raw_readl(ar2315_pci_cfg_mem + addr);
+
+ isr = ath25_read_reg(AR2315_PCI_ISR);
+ if (isr & AR2315_PCI_INT_ABORT)
+ goto exit_err;
+
+ if (write) {
+ value = (value & ~(mask << sh)) | *ptr << sh;
+ __raw_writel(value, ar2315_pci_cfg_mem + addr);
+ isr = ath25_read_reg(AR2315_PCI_ISR);
+ if (isr & AR2315_PCI_INT_ABORT)
+ goto exit_err;
+ } else {
+ *ptr = (value >> sh) & mask;
+ }
+
+ goto exit;
+
+exit_err:
+ ath25_write_reg(AR2315_PCI_ISR, AR2315_PCI_INT_ABORT);
+ if (!write)
+ *ptr = 0xffffffff;
+
+exit:
+ /* Select Memory access */
+ ath25_mask_reg(AR2315_PCI_MISC_CONFIG, AR2315_PCIMISC_CFG_SEL, 0);
+
+ return isr & AR2315_PCI_INT_ABORT ? PCIBIOS_DEVICE_NOT_FOUND :
+ PCIBIOS_SUCCESSFUL;
+}
+
+static inline int ar2315_pci_local_cfg_rd(unsigned devfn, int where, u32 *val)
+{
+ return ar2315_pci_cfg_access(devfn, where, sizeof(u32), val, false);
+}
+
+static inline int ar2315_pci_local_cfg_wr(unsigned devfn, int where, u32 val)
+{
+ return ar2315_pci_cfg_access(devfn, where, sizeof(u32), &val, true);
+}
+
+static int ar2315_pci_cfg_read(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 *value)
+{
+ if (PCI_SLOT(devfn) == AR2315_PCI_HOST_SLOT)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ return ar2315_pci_cfg_access(devfn, where, size, value, 0);
+}
+
+static int ar2315_pci_cfg_write(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 value)
+{
+ if (PCI_SLOT(devfn) == AR2315_PCI_HOST_SLOT)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ return ar2315_pci_cfg_access(devfn, where, size, &value, 1);
+}
+
+static struct pci_ops ar2315_pci_ops = {
+ .read = ar2315_pci_cfg_read,
+ .write = ar2315_pci_cfg_write,
+};
+
+static struct resource ar2315_mem_resource = {
+ .name = "ar2315-pci-mem",
+ .start = AR2315_PCIEXT,
+ .end = AR2315_PCIEXT + AR2315_PCIEXT_SZ - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+/* PCI controller does not support I/O ports */
+static struct resource ar2315_io_resource = {
+ .name = "ar2315-pci-io",
+ .start = 0,
+ .end = 0,
+ .flags = IORESOURCE_IO,
+};
+
+static struct pci_controller ar2315_pci_controller = {
+ .pci_ops = &ar2315_pci_ops,
+ .mem_resource = &ar2315_mem_resource,
+ .io_resource = &ar2315_io_resource,
+ .mem_offset = 0x00000000UL,
+ .io_offset = 0x00000000UL,
+};
+
+static int ar2315_pci_host_setup(void)
+{
+ unsigned devfn = PCI_DEVFN(AR2315_PCI_HOST_SLOT, 0);
+ int res;
+ u32 id;
+
+ res = ar2315_pci_local_cfg_rd(devfn, PCI_VENDOR_ID, &id);
+ if (res != PCIBIOS_SUCCESSFUL || id != AR2315_PCI_HOST_DEVID)
+ return -ENODEV;
+
+ /* Program MBARs */
+ ar2315_pci_local_cfg_wr(devfn, PCI_BASE_ADDRESS_0,
+ AR2315_PCI_HOST_MBAR0);
+ ar2315_pci_local_cfg_wr(devfn, PCI_BASE_ADDRESS_1,
+ AR2315_PCI_HOST_MBAR1);
+ ar2315_pci_local_cfg_wr(devfn, PCI_BASE_ADDRESS_2,
+ AR2315_PCI_HOST_MBAR2);
+
+ /* Run */
+ ar2315_pci_local_cfg_wr(devfn, PCI_COMMAND, PCI_COMMAND_MEMORY |
+ PCI_COMMAND_MASTER | PCI_COMMAND_SPECIAL |
+ PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY |
+ PCI_COMMAND_SERR | PCI_COMMAND_FAST_BACK);
+
+ return 0;
+}
+
+static void ar2315_pci_irq_handler(unsigned irq, struct irq_desc *desc)
+{
+ u32 pending = ath25_read_reg(AR2315_PCI_ISR) &
+ ath25_read_reg(AR2315_PCI_IMR);
+
+ if (pending & AR2315_PCI_INT_EXT)
+ generic_handle_irq(ar2315_pci_irq_base + AR2315_PCI_IRQ_EXT);
+ else if (pending & AR2315_PCI_INT_ABORT)
+ generic_handle_irq(ar2315_pci_irq_base + AR2315_PCI_IRQ_ABORT);
+ else
+ spurious_interrupt();
+}
+
+static void ar2315_pci_irq_mask(struct irq_data *d)
+{
+ u32 m = 1 << (d->irq - ar2315_pci_irq_base + AR2315_PCI_IRQ_SHIFT);
+
+ ath25_mask_reg(AR2315_PCI_IMR, m, 0);
+}
+
+static void ar2315_pci_irq_mask_ack(struct irq_data *d)
+{
+ u32 m = 1 << (d->irq - ar2315_pci_irq_base + AR2315_PCI_IRQ_SHIFT);
+
+ ath25_mask_reg(AR2315_PCI_IMR, m, 0);
+ ath25_write_reg(AR2315_PCI_ISR, m);
+}
+
+static void ar2315_pci_irq_unmask(struct irq_data *d)
+{
+ u32 m = 1 << (d->irq - ar2315_pci_irq_base + AR2315_PCI_IRQ_SHIFT);
+
+ ath25_mask_reg(AR2315_PCI_IMR, 0, m);
+}
+
+static struct irq_chip ar2315_pci_irq_chip = {
+ .name = "AR2315-PCI",
+ .irq_mask = ar2315_pci_irq_mask,
+ .irq_mask_ack = ar2315_pci_irq_mask_ack,
+ .irq_unmask = ar2315_pci_irq_unmask,
+};
+
+static void ar2315_pci_irq_init(void)
+{
+ unsigned i;
+
+ ath25_mask_reg(AR2315_PCI_IER, AR2315_PCI_IER_ENABLE, 0);
+ ath25_mask_reg(AR2315_PCI_IMR, (AR2315_PCI_INT_ABORT |
+ AR2315_PCI_INT_EXT), 0);
+
+ for (i = 0; i < AR2315_PCI_IRQ_COUNT; ++i) {
+ unsigned irq = ar2315_pci_irq_base + i;
+
+ irq_set_chip_and_handler(irq, &ar2315_pci_irq_chip,
+ handle_level_irq);
+ }
+
+ irq_set_chained_handler(AR2315_IRQ_LCBUS_PCI, ar2315_pci_irq_handler);
+
+ /* Clear any pending Abort or external Interrupts
+ * and enable interrupt processing */
+ ath25_write_reg(AR2315_PCI_ISR, (AR2315_PCI_INT_ABORT |
+ AR2315_PCI_INT_EXT));
+ ath25_mask_reg(AR2315_PCI_IER, 0, AR2315_PCI_IER_ENABLE);
+}
+
+static int ar2315_pci_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ u32 reg;
+ int res;
+
+ /* Remap PCI config space */
+ ar2315_pci_cfg_mem = devm_ioremap_nocache(dev, AR2315_PCIEXT,
+ AR2315_PCI_CFG_SIZE);
+ if (!ar2315_pci_cfg_mem) {
+ dev_err(dev, "failed to remap PCI config space\n");
+ return -ENOMEM;
+ }
+
+ /* Reset PCI DMA logic */
+ reg = ath25_mask_reg(AR2315_RESET, 0, AR2315_RESET_PCIDMA);
+ msleep(20);
+ reg &= ~AR2315_RESET_PCIDMA;
+ ath25_write_reg(AR2315_RESET, reg);
+ msleep(20);
+
+ ath25_mask_reg(AR2315_ENDIAN_CTL, 0,
+ AR2315_CONFIG_PCIAHB | AR2315_CONFIG_PCIAHB_BRIDGE);
+
+ ath25_write_reg(AR2315_PCICLK, AR2315_PCICLK_PLLC_CLKM |
+ (AR2315_PCICLK_IN_FREQ_DIV_6 << AR2315_PCICLK_DIV_S));
+ ath25_mask_reg(AR2315_AHB_ARB_CTL, 0, AR2315_ARB_PCI);
+ ath25_mask_reg(AR2315_IF_CTL, AR2315_IF_PCI_CLK_MASK | AR2315_IF_MASK,
+ AR2315_IF_PCI | AR2315_IF_PCI_HOST |
+ AR2315_IF_PCI_INTR | (AR2315_IF_PCI_CLK_OUTPUT_CLK <<
+ AR2315_IF_PCI_CLK_SHIFT));
+
+ /* Reset the PCI bus by setting bits 5-4 in PCI_MCFG */
+ ath25_mask_reg(AR2315_PCI_MISC_CONFIG, AR2315_PCIMISC_RST_MODE,
+ AR2315_PCIRST_LOW);
+ msleep(100);
+
+ /* Bring the PCI out of reset */
+ ath25_mask_reg(AR2315_PCI_MISC_CONFIG, AR2315_PCIMISC_RST_MODE,
+ AR2315_PCIRST_HIGH | AR2315_PCICACHE_DIS | 0x8);
+
+ ath25_write_reg(AR2315_PCI_UNCACHE_CFG,
+ 0x1E | /* 1GB uncached */
+ (1 << 5) | /* Enable uncached */
+ (0x2 << 30) /* Base: 0x80000000 */);
+ ath25_read_reg(AR2315_PCI_UNCACHE_CFG);
+
+ msleep(500);
+
+ res = ar2315_pci_host_setup();
+ if (res)
+ return res;
+
+ res = irq_alloc_descs(-1, 0, AR2315_PCI_IRQ_COUNT, 0);
+ if (res < 0) {
+ dev_err(dev, "failed to allocate PCI IRQ numbers\n");
+ return res;
+ }
+ ar2315_pci_irq_base = res;
+
+ ar2315_pci_irq_init();
+
+ register_pci_controller(&ar2315_pci_controller);
+
+ return 0;
+}
+
+static struct platform_driver ar2315_pci_driver = {
+ .probe = ar2315_pci_probe,
+ .driver = {
+ .name = "ar2315-pci",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init ar2315_pci_init(void)
+{
+ return platform_driver_register(&ar2315_pci_driver);
+}
+arch_initcall(ar2315_pci_init);
+
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+ return ar2315_pci_irq_base + AR2315_PCI_IRQ_EXT;
+}
+
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ return 0;
+}
--
1.8.5.5
John Crispin
2014-10-22 08:47:11 UTC
Permalink
Post by Sergey Ryazanov
Add PCI host controller driver and DMA address calculation hook.
---
- use dynamic IRQ numbers allocation
- rename MIPS machine ar231x -> ath25
arch/mips/ath25/Kconfig | 7 +
arch/mips/ath25/ar2315.c | 9 +
arch/mips/include/asm/mach-ath25/ar2315_regs.h | 23 ++
arch/mips/include/asm/mach-ath25/dma-coherence.h | 18 +-
arch/mips/pci/Makefile | 1 +
arch/mips/pci/pci-ar2315.c | 352 +++++++++++++++++++++++
6 files changed, 407 insertions(+), 3 deletions(-)
create mode 100644 arch/mips/pci/pci-ar2315.c
diff --git a/arch/mips/ath25/Kconfig b/arch/mips/ath25/Kconfig
index 7bcdbf3..c83b70d 100644
--- a/arch/mips/ath25/Kconfig
+++ b/arch/mips/ath25/Kconfig
@@ -9,3 +9,10 @@ config SOC_AR2315
depends on ATH25
select GPIO_AR2315
default y
+
+config PCI_AR2315
+ bool "Atheros AR2315 PCI controller support"
+ depends on SOC_AR2315
+ select HW_HAS_PCI
+ select PCI
+ default y
diff --git a/arch/mips/ath25/ar2315.c b/arch/mips/ath25/ar2315.c
index ac784d7..76679c0 100644
--- a/arch/mips/ath25/ar2315.c
+++ b/arch/mips/ath25/ar2315.c
@@ -108,6 +108,10 @@ static void ar2315_irq_dispatch(void)
if (pending & CAUSEF_IP3)
do_IRQ(AR2315_IRQ_WLAN0);
+#ifdef CONFIG_PCI_AR2315
+ else if (pending & CAUSEF_IP5)
+ do_IRQ(AR2315_IRQ_LCBUS_PCI);
+#endif
else if (pending & CAUSEF_IP2)
do_IRQ(AR2315_IRQ_MISC);
else if (pending & CAUSEF_IP7)
@@ -353,5 +357,10 @@ void __init ar2315_arch_init(void)
{
ath25_serial_setup(AR2315_UART0, ar2315_misc_irq_base +
AR2315_MISC_IRQ_UART0, ar2315_apb_frequency());
+
+#ifdef CONFIG_PCI_AR2315
+ if (ath25_soc == ATH25_SOC_AR2315)
+ platform_device_register_simple("ar2315-pci", -1, NULL, 0);
+#endif
}
diff --git a/arch/mips/include/asm/mach-ath25/ar2315_regs.h b/arch/mips/include/asm/mach-ath25/ar2315_regs.h
index d61c8a1..e732b9a 100644
--- a/arch/mips/include/asm/mach-ath25/ar2315_regs.h
+++ b/arch/mips/include/asm/mach-ath25/ar2315_regs.h
@@ -38,6 +38,15 @@
#define AR2315_MISC_IRQ_COUNT 9
/*
+ * PCI interrupts, which share IP5
+ * Keep ordered according to AR2315_PCI_INT_XXX bits
+ */
+#define AR2315_PCI_IRQ_EXT 0
+#define AR2315_PCI_IRQ_ABORT 1
+#define AR2315_PCI_IRQ_COUNT 2
+#define AR2315_PCI_IRQ_SHIFT 25 /* in AR2315_PCI_INT_STATUS */
+
+/*
* Address map
*/
#define AR2315_SPI_READ 0x08000000 /* SPI flash */
@@ -554,4 +563,18 @@
#define AR2315_IRCFG_SEQ_END_WIN_THRESH 0x001f0000
#define AR2315_IRCFG_NUM_BACKOFF_WORDS 0x01e00000
+/*
+ * We need some arbitrary non-zero value to be programmed to the BAR1 register
+ * of PCI host controller to enable DMA. The same value should be used as the
+ * offset to calculate the physical address of DMA buffer for PCI devices.
+ */
+#define AR2315_PCI_HOST_SDRAM_BASEADDR 0x20000000
+
+/* ??? access BAR */
+#define AR2315_PCI_HOST_MBAR0 0x10000000
+/* RAM access BAR */
+#define AR2315_PCI_HOST_MBAR1 AR2315_PCI_HOST_SDRAM_BASEADDR
+/* ??? access BAR */
+#define AR2315_PCI_HOST_MBAR2 0x30000000
+
#endif /* __ASM_MACH_ATH25_AR2315_REGS_H */
diff --git a/arch/mips/include/asm/mach-ath25/dma-coherence.h b/arch/mips/include/asm/mach-ath25/dma-coherence.h
index 8b3d0cc..063c1ca 100644
--- a/arch/mips/include/asm/mach-ath25/dma-coherence.h
+++ b/arch/mips/include/asm/mach-ath25/dma-coherence.h
@@ -11,23 +11,35 @@
#define __ASM_MACH_ATH25_DMA_COHERENCE_H
#include <linux/device.h>
+#include <ar2315_regs.h>
+
+static inline dma_addr_t ath25_dev_offset(struct device *dev)
+{
+#ifdef CONFIG_PCI
+ extern struct bus_type pci_bus_type;
+
+ if (dev && dev->bus == &pci_bus_type)
+ return AR2315_PCI_HOST_SDRAM_BASEADDR;
+#endif
+ return 0;
+}
static inline dma_addr_t
plat_map_dma_mem(struct device *dev, void *addr, size_t size)
{
- return virt_to_phys(addr);
+ return virt_to_phys(addr) + ath25_dev_offset(dev);
}
static inline dma_addr_t
plat_map_dma_mem_page(struct device *dev, struct page *page)
{
- return page_to_phys(page);
+ return page_to_phys(page) + ath25_dev_offset(dev);
}
static inline unsigned long
plat_dma_addr_to_phys(struct device *dev, dma_addr_t dma_addr)
{
- return dma_addr;
+ return dma_addr - ath25_dev_offset(dev);
}
static inline void
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
index 6523d55..ab6c857 100644
--- a/arch/mips/pci/Makefile
+++ b/arch/mips/pci/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_BCM47XX) += pci-bcm47xx.o
obj-$(CONFIG_BCM63XX) += pci-bcm63xx.o fixup-bcm63xx.o \
ops-bcm63xx.o
obj-$(CONFIG_MIPS_ALCHEMY) += pci-alchemy.o
+obj-$(CONFIG_PCI_AR2315) += pci-ar2315.o
obj-$(CONFIG_SOC_AR71XX) += pci-ar71xx.o
obj-$(CONFIG_PCI_AR724X) += pci-ar724x.o
obj-$(CONFIG_MIPS_PCI_VIRTIO) += pci-virtio-guest.o
diff --git a/arch/mips/pci/pci-ar2315.c b/arch/mips/pci/pci-ar2315.c
new file mode 100644
index 0000000..bb6498f
--- /dev/null
+++ b/arch/mips/pci/pci-ar2315.c
@@ -0,0 +1,352 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Both AR2315 and AR2316 chips have PCI interface unit, which supports DMA
+ * and interrupt. PCI interface supports MMIO access method, but does not
+ * seem to support I/O ports.
+ *
+ * Read/write operation in the region 0x80000000-0xBFFFFFFF causes
+ * a memory read/write command on the PCI bus. 30 LSBs of address on
+ * the bus are taken from memory read/write request and 2 MSBs are
+ * determined by PCI unit configuration.
+ *
+ * To work with the configuration space instead of memory is necessary set
+ * the CFG_SEL bit in the PCI_MISC_CONFIG register.
+ *
+ * Devices on the bus can perform DMA requests via chip BAR1. PCI host
+ * controller BARs are programmend as if an external device is programmed.
+ * Which means that during configuration, IDSEL pin of the chip should be
+ * asserted.
+ *
+ * We know (and support) only one board that uses the PCI interface -
+ * Fonera 2.0g (FON2202). It has a USB EHCI controller connected to the
+ * AR2315 PCI bus. IDSEL pin of USB controller is connected to AD[13] line
+ * and IDSEL pin of AR125 is connected to AD[16] line.
+ */
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <asm/paccess.h>
+#include <ath25.h>
+#include <ar2315_regs.h>
+
+/* Arbitrary size of memory region to access the configuration space */
+#define AR2315_PCI_CFG_SIZE 0x00100000
+
+#define AR2315_PCI_HOST_SLOT 3
+#define AR2315_PCI_HOST_DEVID ((0xff18 << 16) | PCI_VENDOR_ID_ATHEROS)
+
+static void __iomem *ar2315_pci_cfg_mem;
+static unsigned ar2315_pci_irq_base;
+
+static int ar2315_pci_cfg_access(int devfn, int where, int size, u32 *ptr,
+ bool write)
+{
+ int func = PCI_FUNC(devfn);
+ int dev = PCI_SLOT(devfn);
+ u32 addr = (1 << (13 + dev)) | (func << 8) | (where & ~3);
+ u32 mask = 0xffffffff >> 8 * (4 - size);
+ u32 sh = (where & 3) * 8;
+ u32 value, isr;
+
+ /* Prevent access past the remapped area */
+ if (addr >= AR2315_PCI_CFG_SIZE || dev > 18)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ /* Clear pending errors */
+ ath25_write_reg(AR2315_PCI_ISR, AR2315_PCI_INT_ABORT);
+ /* Select Configuration access */
+ ath25_mask_reg(AR2315_PCI_MISC_CONFIG, 0, AR2315_PCIMISC_CFG_SEL);
+
+ mb(); /* PCI must see space change before we begin */
+
+ value = __raw_readl(ar2315_pci_cfg_mem + addr);
+
+ isr = ath25_read_reg(AR2315_PCI_ISR);
+ if (isr & AR2315_PCI_INT_ABORT)
+ goto exit_err;
+
+ if (write) {
+ value = (value & ~(mask << sh)) | *ptr << sh;
+ __raw_writel(value, ar2315_pci_cfg_mem + addr);
+ isr = ath25_read_reg(AR2315_PCI_ISR);
+ if (isr & AR2315_PCI_INT_ABORT)
+ goto exit_err;
+ } else {
+ *ptr = (value >> sh) & mask;
+ }
+
+ goto exit;
+
+ ath25_write_reg(AR2315_PCI_ISR, AR2315_PCI_INT_ABORT);
+ if (!write)
+ *ptr = 0xffffffff;
+
+ /* Select Memory access */
+ ath25_mask_reg(AR2315_PCI_MISC_CONFIG, AR2315_PCIMISC_CFG_SEL, 0);
+
+ PCIBIOS_SUCCESSFUL;
+}
+
+static inline int ar2315_pci_local_cfg_rd(unsigned devfn, int where, u32 *val)
+{
+ return ar2315_pci_cfg_access(devfn, where, sizeof(u32), val, false);
+}
+
+static inline int ar2315_pci_local_cfg_wr(unsigned devfn, int where, u32 val)
+{
+ return ar2315_pci_cfg_access(devfn, where, sizeof(u32), &val, true);
+}
+
+static int ar2315_pci_cfg_read(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 *value)
+{
+ if (PCI_SLOT(devfn) == AR2315_PCI_HOST_SLOT)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ return ar2315_pci_cfg_access(devfn, where, size, value, 0);
+}
+
+static int ar2315_pci_cfg_write(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 value)
+{
+ if (PCI_SLOT(devfn) == AR2315_PCI_HOST_SLOT)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ return ar2315_pci_cfg_access(devfn, where, size, &value, 1);
+}
+
+static struct pci_ops ar2315_pci_ops = {
+ .read = ar2315_pci_cfg_read,
+ .write = ar2315_pci_cfg_write,
+};
+
+static struct resource ar2315_mem_resource = {
+ .name = "ar2315-pci-mem",
+ .start = AR2315_PCIEXT,
+ .end = AR2315_PCIEXT + AR2315_PCIEXT_SZ - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+/* PCI controller does not support I/O ports */
+static struct resource ar2315_io_resource = {
+ .name = "ar2315-pci-io",
+ .start = 0,
+ .end = 0,
+ .flags = IORESOURCE_IO,
+};
+
+static struct pci_controller ar2315_pci_controller = {
+ .pci_ops = &ar2315_pci_ops,
+ .mem_resource = &ar2315_mem_resource,
+ .io_resource = &ar2315_io_resource,
+ .mem_offset = 0x00000000UL,
+ .io_offset = 0x00000000UL,
+};
+
+static int ar2315_pci_host_setup(void)
+{
+ unsigned devfn = PCI_DEVFN(AR2315_PCI_HOST_SLOT, 0);
+ int res;
+ u32 id;
+
+ res = ar2315_pci_local_cfg_rd(devfn, PCI_VENDOR_ID, &id);
+ if (res != PCIBIOS_SUCCESSFUL || id != AR2315_PCI_HOST_DEVID)
+ return -ENODEV;
+
+ /* Program MBARs */
+ ar2315_pci_local_cfg_wr(devfn, PCI_BASE_ADDRESS_0,
+ AR2315_PCI_HOST_MBAR0);
+ ar2315_pci_local_cfg_wr(devfn, PCI_BASE_ADDRESS_1,
+ AR2315_PCI_HOST_MBAR1);
+ ar2315_pci_local_cfg_wr(devfn, PCI_BASE_ADDRESS_2,
+ AR2315_PCI_HOST_MBAR2);
+
+ /* Run */
+ ar2315_pci_local_cfg_wr(devfn, PCI_COMMAND, PCI_COMMAND_MEMORY |
+ PCI_COMMAND_MASTER | PCI_COMMAND_SPECIAL |
+ PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY |
+ PCI_COMMAND_SERR | PCI_COMMAND_FAST_BACK);
+
+ return 0;
+}
+
+static void ar2315_pci_irq_handler(unsigned irq, struct irq_desc *desc)
+{
+ u32 pending = ath25_read_reg(AR2315_PCI_ISR) &
+ ath25_read_reg(AR2315_PCI_IMR);
+
+ if (pending & AR2315_PCI_INT_EXT)
+ generic_handle_irq(ar2315_pci_irq_base + AR2315_PCI_IRQ_EXT);
+ else if (pending & AR2315_PCI_INT_ABORT)
+ generic_handle_irq(ar2315_pci_irq_base + AR2315_PCI_IRQ_ABORT);
+ else
+ spurious_interrupt();
+}
+
+static void ar2315_pci_irq_mask(struct irq_data *d)
+{
+ u32 m = 1 << (d->irq - ar2315_pci_irq_base + AR2315_PCI_IRQ_SHIFT);
+
+ ath25_mask_reg(AR2315_PCI_IMR, m, 0);
+}
+
+static void ar2315_pci_irq_mask_ack(struct irq_data *d)
+{
+ u32 m = 1 << (d->irq - ar2315_pci_irq_base + AR2315_PCI_IRQ_SHIFT);
+
+ ath25_mask_reg(AR2315_PCI_IMR, m, 0);
+ ath25_write_reg(AR2315_PCI_ISR, m);
+}
+
+static void ar2315_pci_irq_unmask(struct irq_data *d)
+{
+ u32 m = 1 << (d->irq - ar2315_pci_irq_base + AR2315_PCI_IRQ_SHIFT);
+
+ ath25_mask_reg(AR2315_PCI_IMR, 0, m);
+}
+
once you have irqdomain you will need to change these to use d->hwirq
instead of d->irq
Post by Sergey Ryazanov
+static struct irq_chip ar2315_pci_irq_chip = {
+ .name = "AR2315-PCI",
+ .irq_mask = ar2315_pci_irq_mask,
+ .irq_mask_ack = ar2315_pci_irq_mask_ack,
+ .irq_unmask = ar2315_pci_irq_unmask,
+};
+
+static void ar2315_pci_irq_init(void)
+{
+ unsigned i;
+
+ ath25_mask_reg(AR2315_PCI_IER, AR2315_PCI_IER_ENABLE, 0);
+ ath25_mask_reg(AR2315_PCI_IMR, (AR2315_PCI_INT_ABORT |
+ AR2315_PCI_INT_EXT), 0);
+
+ for (i = 0; i < AR2315_PCI_IRQ_COUNT; ++i) {
+ unsigned irq = ar2315_pci_irq_base + i;
+
+ irq_set_chip_and_handler(irq, &ar2315_pci_irq_chip,
+ handle_level_irq);
+ }
+
+ irq_set_chained_handler(AR2315_IRQ_LCBUS_PCI, ar2315_pci_irq_handler);
+
+ /* Clear any pending Abort or external Interrupts
+ * and enable interrupt processing */
+ ath25_write_reg(AR2315_PCI_ISR, (AR2315_PCI_INT_ABORT |
+ AR2315_PCI_INT_EXT));
+ ath25_mask_reg(AR2315_PCI_IER, 0, AR2315_PCI_IER_ENABLE);
+}
+
+static int ar2315_pci_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ u32 reg;
+ int res;
+
+ /* Remap PCI config space */
+ ar2315_pci_cfg_mem = devm_ioremap_nocache(dev, AR2315_PCIEXT,
+ AR2315_PCI_CFG_SIZE);
+ if (!ar2315_pci_cfg_mem) {
+ dev_err(dev, "failed to remap PCI config space\n");
+ return -ENOMEM;
+ }
+
+ /* Reset PCI DMA logic */
+ reg = ath25_mask_reg(AR2315_RESET, 0, AR2315_RESET_PCIDMA);
+ msleep(20);
+ reg &= ~AR2315_RESET_PCIDMA;
+ ath25_write_reg(AR2315_RESET, reg);
+ msleep(20);
+
+ ath25_mask_reg(AR2315_ENDIAN_CTL, 0,
+ AR2315_CONFIG_PCIAHB | AR2315_CONFIG_PCIAHB_BRIDGE);
+
+ ath25_write_reg(AR2315_PCICLK, AR2315_PCICLK_PLLC_CLKM |
+ (AR2315_PCICLK_IN_FREQ_DIV_6 << AR2315_PCICLK_DIV_S));
+ ath25_mask_reg(AR2315_AHB_ARB_CTL, 0, AR2315_ARB_PCI);
+ ath25_mask_reg(AR2315_IF_CTL, AR2315_IF_PCI_CLK_MASK | AR2315_IF_MASK,
+ AR2315_IF_PCI | AR2315_IF_PCI_HOST |
+ AR2315_IF_PCI_INTR | (AR2315_IF_PCI_CLK_OUTPUT_CLK <<
+ AR2315_IF_PCI_CLK_SHIFT));
+
+ /* Reset the PCI bus by setting bits 5-4 in PCI_MCFG */
+ ath25_mask_reg(AR2315_PCI_MISC_CONFIG, AR2315_PCIMISC_RST_MODE,
+ AR2315_PCIRST_LOW);
+ msleep(100);
+
+ /* Bring the PCI out of reset */
+ ath25_mask_reg(AR2315_PCI_MISC_CONFIG, AR2315_PCIMISC_RST_MODE,
+ AR2315_PCIRST_HIGH | AR2315_PCICACHE_DIS | 0x8);
+
+ ath25_write_reg(AR2315_PCI_UNCACHE_CFG,
+ 0x1E | /* 1GB uncached */
+ (1 << 5) | /* Enable uncached */
+ (0x2 << 30) /* Base: 0x80000000 */);
+ ath25_read_reg(AR2315_PCI_UNCACHE_CFG);
+
+ msleep(500);
+
+ res = ar2315_pci_host_setup();
+ if (res)
+ return res;
+
+ res = irq_alloc_descs(-1, 0, AR2315_PCI_IRQ_COUNT, 0);
+ if (res < 0) {
+ dev_err(dev, "failed to allocate PCI IRQ numbers\n");
+ return res;
+ }
+ ar2315_pci_irq_base = res;
+
+ ar2315_pci_irq_init();
+
+ register_pci_controller(&ar2315_pci_controller);
+
+ return 0;
+}
+
+static struct platform_driver ar2315_pci_driver = {
+ .probe = ar2315_pci_probe,
+ .driver = {
+ .name = "ar2315-pci",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init ar2315_pci_init(void)
+{
+ return platform_driver_register(&ar2315_pci_driver);
+}
+arch_initcall(ar2315_pci_init);
+
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+ return ar2315_pci_irq_base + AR2315_PCI_IRQ_EXT;
+}
+
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ return 0;
+}
Sergey Ryazanov
2014-10-22 15:25:55 UTC
Permalink
Post by John Crispin
Post by Sergey Ryazanov
Add PCI host controller driver and DMA address calculation hook.
---
- use dynamic IRQ numbers allocation
- rename MIPS machine ar231x -> ath25
arch/mips/ath25/Kconfig | 7 +
arch/mips/ath25/ar2315.c | 9 +
arch/mips/include/asm/mach-ath25/ar2315_regs.h | 23 ++
arch/mips/include/asm/mach-ath25/dma-coherence.h | 18 +-
arch/mips/pci/Makefile | 1 +
arch/mips/pci/pci-ar2315.c | 352 +++++++++++++++++++++++
6 files changed, 407 insertions(+), 3 deletions(-)
create mode 100644 arch/mips/pci/pci-ar2315.c
diff --git a/arch/mips/ath25/Kconfig b/arch/mips/ath25/Kconfig
index 7bcdbf3..c83b70d 100644
--- a/arch/mips/ath25/Kconfig
+++ b/arch/mips/ath25/Kconfig
@@ -9,3 +9,10 @@ config SOC_AR2315
depends on ATH25
select GPIO_AR2315
default y
+
+config PCI_AR2315
+ bool "Atheros AR2315 PCI controller support"
+ depends on SOC_AR2315
+ select HW_HAS_PCI
+ select PCI
+ default y
diff --git a/arch/mips/ath25/ar2315.c b/arch/mips/ath25/ar2315.c
index ac784d7..76679c0 100644
--- a/arch/mips/ath25/ar2315.c
+++ b/arch/mips/ath25/ar2315.c
@@ -108,6 +108,10 @@ static void ar2315_irq_dispatch(void)
if (pending & CAUSEF_IP3)
do_IRQ(AR2315_IRQ_WLAN0);
+#ifdef CONFIG_PCI_AR2315
+ else if (pending & CAUSEF_IP5)
+ do_IRQ(AR2315_IRQ_LCBUS_PCI);
+#endif
else if (pending & CAUSEF_IP2)
do_IRQ(AR2315_IRQ_MISC);
else if (pending & CAUSEF_IP7)
@@ -353,5 +357,10 @@ void __init ar2315_arch_init(void)
{
ath25_serial_setup(AR2315_UART0, ar2315_misc_irq_base +
AR2315_MISC_IRQ_UART0, ar2315_apb_frequency());
+
+#ifdef CONFIG_PCI_AR2315
+ if (ath25_soc == ATH25_SOC_AR2315)
+ platform_device_register_simple("ar2315-pci", -1, NULL, 0);
+#endif
}
diff --git a/arch/mips/include/asm/mach-ath25/ar2315_regs.h b/arch/mips/include/asm/mach-ath25/ar2315_regs.h
index d61c8a1..e732b9a 100644
--- a/arch/mips/include/asm/mach-ath25/ar2315_regs.h
+++ b/arch/mips/include/asm/mach-ath25/ar2315_regs.h
@@ -38,6 +38,15 @@
#define AR2315_MISC_IRQ_COUNT 9
/*
+ * PCI interrupts, which share IP5
+ * Keep ordered according to AR2315_PCI_INT_XXX bits
+ */
+#define AR2315_PCI_IRQ_EXT 0
+#define AR2315_PCI_IRQ_ABORT 1
+#define AR2315_PCI_IRQ_COUNT 2
+#define AR2315_PCI_IRQ_SHIFT 25 /* in AR2315_PCI_INT_STATUS */
+
+/*
* Address map
*/
#define AR2315_SPI_READ 0x08000000 /* SPI flash */
@@ -554,4 +563,18 @@
#define AR2315_IRCFG_SEQ_END_WIN_THRESH 0x001f0000
#define AR2315_IRCFG_NUM_BACKOFF_WORDS 0x01e00000
+/*
+ * We need some arbitrary non-zero value to be programmed to the BAR1 register
+ * of PCI host controller to enable DMA. The same value should be used as the
+ * offset to calculate the physical address of DMA buffer for PCI devices.
+ */
+#define AR2315_PCI_HOST_SDRAM_BASEADDR 0x20000000
+
+/* ??? access BAR */
+#define AR2315_PCI_HOST_MBAR0 0x10000000
+/* RAM access BAR */
+#define AR2315_PCI_HOST_MBAR1 AR2315_PCI_HOST_SDRAM_BASEADDR
+/* ??? access BAR */
+#define AR2315_PCI_HOST_MBAR2 0x30000000
+
#endif /* __ASM_MACH_ATH25_AR2315_REGS_H */
diff --git a/arch/mips/include/asm/mach-ath25/dma-coherence.h b/arch/mips/include/asm/mach-ath25/dma-coherence.h
index 8b3d0cc..063c1ca 100644
--- a/arch/mips/include/asm/mach-ath25/dma-coherence.h
+++ b/arch/mips/include/asm/mach-ath25/dma-coherence.h
@@ -11,23 +11,35 @@
#define __ASM_MACH_ATH25_DMA_COHERENCE_H
#include <linux/device.h>
+#include <ar2315_regs.h>
+
+static inline dma_addr_t ath25_dev_offset(struct device *dev)
+{
+#ifdef CONFIG_PCI
+ extern struct bus_type pci_bus_type;
+
+ if (dev && dev->bus == &pci_bus_type)
+ return AR2315_PCI_HOST_SDRAM_BASEADDR;
+#endif
+ return 0;
+}
static inline dma_addr_t
plat_map_dma_mem(struct device *dev, void *addr, size_t size)
{
- return virt_to_phys(addr);
+ return virt_to_phys(addr) + ath25_dev_offset(dev);
}
static inline dma_addr_t
plat_map_dma_mem_page(struct device *dev, struct page *page)
{
- return page_to_phys(page);
+ return page_to_phys(page) + ath25_dev_offset(dev);
}
static inline unsigned long
plat_dma_addr_to_phys(struct device *dev, dma_addr_t dma_addr)
{
- return dma_addr;
+ return dma_addr - ath25_dev_offset(dev);
}
static inline void
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
index 6523d55..ab6c857 100644
--- a/arch/mips/pci/Makefile
+++ b/arch/mips/pci/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_BCM47XX) += pci-bcm47xx.o
obj-$(CONFIG_BCM63XX) += pci-bcm63xx.o fixup-bcm63xx.o \
ops-bcm63xx.o
obj-$(CONFIG_MIPS_ALCHEMY) += pci-alchemy.o
+obj-$(CONFIG_PCI_AR2315) += pci-ar2315.o
obj-$(CONFIG_SOC_AR71XX) += pci-ar71xx.o
obj-$(CONFIG_PCI_AR724X) += pci-ar724x.o
obj-$(CONFIG_MIPS_PCI_VIRTIO) += pci-virtio-guest.o
diff --git a/arch/mips/pci/pci-ar2315.c b/arch/mips/pci/pci-ar2315.c
new file mode 100644
index 0000000..bb6498f
--- /dev/null
+++ b/arch/mips/pci/pci-ar2315.c
@@ -0,0 +1,352 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Both AR2315 and AR2316 chips have PCI interface unit, which supports DMA
+ * and interrupt. PCI interface supports MMIO access method, but does not
+ * seem to support I/O ports.
+ *
+ * Read/write operation in the region 0x80000000-0xBFFFFFFF causes
+ * a memory read/write command on the PCI bus. 30 LSBs of address on
+ * the bus are taken from memory read/write request and 2 MSBs are
+ * determined by PCI unit configuration.
+ *
+ * To work with the configuration space instead of memory is necessary set
+ * the CFG_SEL bit in the PCI_MISC_CONFIG register.
+ *
+ * Devices on the bus can perform DMA requests via chip BAR1. PCI host
+ * controller BARs are programmend as if an external device is programmed.
+ * Which means that during configuration, IDSEL pin of the chip should be
+ * asserted.
+ *
+ * We know (and support) only one board that uses the PCI interface -
+ * Fonera 2.0g (FON2202). It has a USB EHCI controller connected to the
+ * AR2315 PCI bus. IDSEL pin of USB controller is connected to AD[13] line
+ * and IDSEL pin of AR125 is connected to AD[16] line.
+ */
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <asm/paccess.h>
+#include <ath25.h>
+#include <ar2315_regs.h>
+
+/* Arbitrary size of memory region to access the configuration space */
+#define AR2315_PCI_CFG_SIZE 0x00100000
+
+#define AR2315_PCI_HOST_SLOT 3
+#define AR2315_PCI_HOST_DEVID ((0xff18 << 16) | PCI_VENDOR_ID_ATHEROS)
+
+static void __iomem *ar2315_pci_cfg_mem;
+static unsigned ar2315_pci_irq_base;
+
+static int ar2315_pci_cfg_access(int devfn, int where, int size, u32 *ptr,
+ bool write)
+{
+ int func = PCI_FUNC(devfn);
+ int dev = PCI_SLOT(devfn);
+ u32 addr = (1 << (13 + dev)) | (func << 8) | (where & ~3);
+ u32 mask = 0xffffffff >> 8 * (4 - size);
+ u32 sh = (where & 3) * 8;
+ u32 value, isr;
+
+ /* Prevent access past the remapped area */
+ if (addr >= AR2315_PCI_CFG_SIZE || dev > 18)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ /* Clear pending errors */
+ ath25_write_reg(AR2315_PCI_ISR, AR2315_PCI_INT_ABORT);
+ /* Select Configuration access */
+ ath25_mask_reg(AR2315_PCI_MISC_CONFIG, 0, AR2315_PCIMISC_CFG_SEL);
+
+ mb(); /* PCI must see space change before we begin */
+
+ value = __raw_readl(ar2315_pci_cfg_mem + addr);
+
+ isr = ath25_read_reg(AR2315_PCI_ISR);
+ if (isr & AR2315_PCI_INT_ABORT)
+ goto exit_err;
+
+ if (write) {
+ value = (value & ~(mask << sh)) | *ptr << sh;
+ __raw_writel(value, ar2315_pci_cfg_mem + addr);
+ isr = ath25_read_reg(AR2315_PCI_ISR);
+ if (isr & AR2315_PCI_INT_ABORT)
+ goto exit_err;
+ } else {
+ *ptr = (value >> sh) & mask;
+ }
+
+ goto exit;
+
+ ath25_write_reg(AR2315_PCI_ISR, AR2315_PCI_INT_ABORT);
+ if (!write)
+ *ptr = 0xffffffff;
+
+ /* Select Memory access */
+ ath25_mask_reg(AR2315_PCI_MISC_CONFIG, AR2315_PCIMISC_CFG_SEL, 0);
+
+ PCIBIOS_SUCCESSFUL;
+}
+
+static inline int ar2315_pci_local_cfg_rd(unsigned devfn, int where, u32 *val)
+{
+ return ar2315_pci_cfg_access(devfn, where, sizeof(u32), val, false);
+}
+
+static inline int ar2315_pci_local_cfg_wr(unsigned devfn, int where, u32 val)
+{
+ return ar2315_pci_cfg_access(devfn, where, sizeof(u32), &val, true);
+}
+
+static int ar2315_pci_cfg_read(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 *value)
+{
+ if (PCI_SLOT(devfn) == AR2315_PCI_HOST_SLOT)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ return ar2315_pci_cfg_access(devfn, where, size, value, 0);
+}
+
+static int ar2315_pci_cfg_write(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 value)
+{
+ if (PCI_SLOT(devfn) == AR2315_PCI_HOST_SLOT)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ return ar2315_pci_cfg_access(devfn, where, size, &value, 1);
+}
+
+static struct pci_ops ar2315_pci_ops = {
+ .read = ar2315_pci_cfg_read,
+ .write = ar2315_pci_cfg_write,
+};
+
+static struct resource ar2315_mem_resource = {
+ .name = "ar2315-pci-mem",
+ .start = AR2315_PCIEXT,
+ .end = AR2315_PCIEXT + AR2315_PCIEXT_SZ - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+/* PCI controller does not support I/O ports */
+static struct resource ar2315_io_resource = {
+ .name = "ar2315-pci-io",
+ .start = 0,
+ .end = 0,
+ .flags = IORESOURCE_IO,
+};
+
+static struct pci_controller ar2315_pci_controller = {
+ .pci_ops = &ar2315_pci_ops,
+ .mem_resource = &ar2315_mem_resource,
+ .io_resource = &ar2315_io_resource,
+ .mem_offset = 0x00000000UL,
+ .io_offset = 0x00000000UL,
+};
+
+static int ar2315_pci_host_setup(void)
+{
+ unsigned devfn = PCI_DEVFN(AR2315_PCI_HOST_SLOT, 0);
+ int res;
+ u32 id;
+
+ res = ar2315_pci_local_cfg_rd(devfn, PCI_VENDOR_ID, &id);
+ if (res != PCIBIOS_SUCCESSFUL || id != AR2315_PCI_HOST_DEVID)
+ return -ENODEV;
+
+ /* Program MBARs */
+ ar2315_pci_local_cfg_wr(devfn, PCI_BASE_ADDRESS_0,
+ AR2315_PCI_HOST_MBAR0);
+ ar2315_pci_local_cfg_wr(devfn, PCI_BASE_ADDRESS_1,
+ AR2315_PCI_HOST_MBAR1);
+ ar2315_pci_local_cfg_wr(devfn, PCI_BASE_ADDRESS_2,
+ AR2315_PCI_HOST_MBAR2);
+
+ /* Run */
+ ar2315_pci_local_cfg_wr(devfn, PCI_COMMAND, PCI_COMMAND_MEMORY |
+ PCI_COMMAND_MASTER | PCI_COMMAND_SPECIAL |
+ PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY |
+ PCI_COMMAND_SERR | PCI_COMMAND_FAST_BACK);
+
+ return 0;
+}
+
+static void ar2315_pci_irq_handler(unsigned irq, struct irq_desc *desc)
+{
+ u32 pending = ath25_read_reg(AR2315_PCI_ISR) &
+ ath25_read_reg(AR2315_PCI_IMR);
+
+ if (pending & AR2315_PCI_INT_EXT)
+ generic_handle_irq(ar2315_pci_irq_base + AR2315_PCI_IRQ_EXT);
+ else if (pending & AR2315_PCI_INT_ABORT)
+ generic_handle_irq(ar2315_pci_irq_base + AR2315_PCI_IRQ_ABORT);
+ else
+ spurious_interrupt();
+}
+
+static void ar2315_pci_irq_mask(struct irq_data *d)
+{
+ u32 m = 1 << (d->irq - ar2315_pci_irq_base + AR2315_PCI_IRQ_SHIFT);
+
+ ath25_mask_reg(AR2315_PCI_IMR, m, 0);
+}
+
+static void ar2315_pci_irq_mask_ack(struct irq_data *d)
+{
+ u32 m = 1 << (d->irq - ar2315_pci_irq_base + AR2315_PCI_IRQ_SHIFT);
+
+ ath25_mask_reg(AR2315_PCI_IMR, m, 0);
+ ath25_write_reg(AR2315_PCI_ISR, m);
+}
+
+static void ar2315_pci_irq_unmask(struct irq_data *d)
+{
+ u32 m = 1 << (d->irq - ar2315_pci_irq_base + AR2315_PCI_IRQ_SHIFT);
+
+ ath25_mask_reg(AR2315_PCI_IMR, 0, m);
+}
+
once you have irqdomain you will need to change these to use d->hwirq
instead of d->irq
Post by Sergey Ryazanov
+static struct irq_chip ar2315_pci_irq_chip = {
+ .name = "AR2315-PCI",
+ .irq_mask = ar2315_pci_irq_mask,
+ .irq_mask_ack = ar2315_pci_irq_mask_ack,
+ .irq_unmask = ar2315_pci_irq_unmask,
+};
+
+static void ar2315_pci_irq_init(void)
+{
+ unsigned i;
+
+ ath25_mask_reg(AR2315_PCI_IER, AR2315_PCI_IER_ENABLE, 0);
+ ath25_mask_reg(AR2315_PCI_IMR, (AR2315_PCI_INT_ABORT |
+ AR2315_PCI_INT_EXT), 0);
+
+ for (i = 0; i < AR2315_PCI_IRQ_COUNT; ++i) {
+ unsigned irq = ar2315_pci_irq_base + i;
+
+ irq_set_chip_and_handler(irq, &ar2315_pci_irq_chip,
+ handle_level_irq);
+ }
+
+ irq_set_chained_handler(AR2315_IRQ_LCBUS_PCI, ar2315_pci_irq_handler);
+
+ /* Clear any pending Abort or external Interrupts
+ * and enable interrupt processing */
+ ath25_write_reg(AR2315_PCI_ISR, (AR2315_PCI_INT_ABORT |
+ AR2315_PCI_INT_EXT));
+ ath25_mask_reg(AR2315_PCI_IER, 0, AR2315_PCI_IER_ENABLE);
+}
+
+static int ar2315_pci_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ u32 reg;
+ int res;
+
+ /* Remap PCI config space */
+ ar2315_pci_cfg_mem = devm_ioremap_nocache(dev, AR2315_PCIEXT,
+ AR2315_PCI_CFG_SIZE);
+ if (!ar2315_pci_cfg_mem) {
+ dev_err(dev, "failed to remap PCI config space\n");
+ return -ENOMEM;
+ }
+
+ /* Reset PCI DMA logic */
+ reg = ath25_mask_reg(AR2315_RESET, 0, AR2315_RESET_PCIDMA);
+ msleep(20);
+ reg &= ~AR2315_RESET_PCIDMA;
+ ath25_write_reg(AR2315_RESET, reg);
+ msleep(20);
+
+ ath25_mask_reg(AR2315_ENDIAN_CTL, 0,
+ AR2315_CONFIG_PCIAHB | AR2315_CONFIG_PCIAHB_BRIDGE);
+
+ ath25_write_reg(AR2315_PCICLK, AR2315_PCICLK_PLLC_CLKM |
+ (AR2315_PCICLK_IN_FREQ_DIV_6 << AR2315_PCICLK_DIV_S));
+ ath25_mask_reg(AR2315_AHB_ARB_CTL, 0, AR2315_ARB_PCI);
+ ath25_mask_reg(AR2315_IF_CTL, AR2315_IF_PCI_CLK_MASK | AR2315_IF_MASK,
+ AR2315_IF_PCI | AR2315_IF_PCI_HOST |
+ AR2315_IF_PCI_INTR | (AR2315_IF_PCI_CLK_OUTPUT_CLK <<
+ AR2315_IF_PCI_CLK_SHIFT));
+
+ /* Reset the PCI bus by setting bits 5-4 in PCI_MCFG */
+ ath25_mask_reg(AR2315_PCI_MISC_CONFIG, AR2315_PCIMISC_RST_MODE,
+ AR2315_PCIRST_LOW);
+ msleep(100);
+
+ /* Bring the PCI out of reset */
+ ath25_mask_reg(AR2315_PCI_MISC_CONFIG, AR2315_PCIMISC_RST_MODE,
+ AR2315_PCIRST_HIGH | AR2315_PCICACHE_DIS | 0x8);
+
+ ath25_write_reg(AR2315_PCI_UNCACHE_CFG,
+ 0x1E | /* 1GB uncached */
+ (1 << 5) | /* Enable uncached */
+ (0x2 << 30) /* Base: 0x80000000 */);
+ ath25_read_reg(AR2315_PCI_UNCACHE_CFG);
+
+ msleep(500);
+
+ res = ar2315_pci_host_setup();
+ if (res)
+ return res;
+
+ res = irq_alloc_descs(-1, 0, AR2315_PCI_IRQ_COUNT, 0);
+ if (res < 0) {
+ dev_err(dev, "failed to allocate PCI IRQ numbers\n");
+ return res;
+ }
+ ar2315_pci_irq_base = res;
+
+ ar2315_pci_irq_init();
+
+ register_pci_controller(&ar2315_pci_controller);
+
+ return 0;
+}
+
+static struct platform_driver ar2315_pci_driver = {
+ .probe = ar2315_pci_probe,
+ .driver = {
+ .name = "ar2315-pci",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init ar2315_pci_init(void)
+{
+ return platform_driver_register(&ar2315_pci_driver);
+}
+arch_initcall(ar2315_pci_init);
+
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+ return ar2315_pci_irq_base + AR2315_PCI_IRQ_EXT;
+}
+
John, I need some help here. How I should allocate IRQ to assign them
to device in this hook?
Post by John Crispin
Post by Sergey Ryazanov
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ return 0;
+}
--
BR,
Sergey
Sergey Ryazanov
2014-10-21 23:03:51 UTC
Permalink
Atheros AR5312 and AR2315 both have a builtin wireless device, this
patch add helper code and register platform device for all supported
WiSoCs.

Signed-off-by: Sergey Ryazanov <***@gmail.com>
---

Changes since v1:
- rename MIPS machine ar231x -> ath25

arch/mips/ath25/ar2315.c | 1 +
arch/mips/ath25/ar5312.c | 22 +++++++++++++++++++
arch/mips/ath25/devices.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++
arch/mips/ath25/devices.h | 1 +
4 files changed, 78 insertions(+)

diff --git a/arch/mips/ath25/ar2315.c b/arch/mips/ath25/ar2315.c
index 76679c0..b39440e 100644
--- a/arch/mips/ath25/ar2315.c
+++ b/arch/mips/ath25/ar2315.c
@@ -227,6 +227,7 @@ void __init ar2315_init_devices(void)
res->end = res->start;
platform_device_register(&ar2315_wdt);
platform_device_register(&ar2315_spiflash);
+ ath25_add_wmac(0, AR2315_WLAN0, AR2315_IRQ_WLAN0);
}

static void ar2315_restart(char *command)
diff --git a/arch/mips/ath25/ar5312.c b/arch/mips/ath25/ar5312.c
index 99c2745..043cf96 100644
--- a/arch/mips/ath25/ar5312.c
+++ b/arch/mips/ath25/ar5312.c
@@ -231,6 +231,28 @@ void __init ar5312_init_devices(void)

platform_device_register(&ar5312_physmap_flash);
platform_device_register(&ar5312_gpio);
+
+ switch (ath25_soc) {
+ case ATH25_SOC_AR5312:
+ if (!ath25_board.radio)
+ return;
+
+ if (!(config->flags & BD_WLAN0))
+ break;
+
+ ath25_add_wmac(0, AR5312_WLAN0, AR5312_IRQ_WLAN0);
+ break;
+ case ATH25_SOC_AR2312:
+ case ATH25_SOC_AR2313:
+ if (!ath25_board.radio)
+ return;
+ break;
+ default:
+ break;
+ }
+
+ if (config->flags & BD_WLAN1)
+ ath25_add_wmac(1, AR5312_WLAN1, AR5312_IRQ_WLAN1);
}

static void ar5312_restart(char *command)
diff --git a/arch/mips/ath25/devices.c b/arch/mips/ath25/devices.c
index 6218547..7a64567 100644
--- a/arch/mips/ath25/devices.c
+++ b/arch/mips/ath25/devices.c
@@ -1,6 +1,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/serial_8250.h>
+#include <linux/platform_device.h>
#include <asm/bootinfo.h>

#include <ath25_platform.h>
@@ -11,6 +12,45 @@
struct ar231x_board_config ath25_board;
enum ath25_soc_type ath25_soc = ATH25_SOC_UNKNOWN;

+static struct resource ath25_wmac0_res[] = {
+ {
+ .name = "wmac0_membase",
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "wmac0_irq",
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct resource ath25_wmac1_res[] = {
+ {
+ .name = "wmac1_membase",
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "wmac1_irq",
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct platform_device ath25_wmac[] = {
+ {
+ .id = 0,
+ .name = "ar231x-wmac",
+ .resource = ath25_wmac0_res,
+ .num_resources = ARRAY_SIZE(ath25_wmac0_res),
+ .dev.platform_data = &ath25_board,
+ },
+ {
+ .id = 1,
+ .name = "ar231x-wmac",
+ .resource = ath25_wmac1_res,
+ .num_resources = ARRAY_SIZE(ath25_wmac1_res),
+ .dev.platform_data = &ath25_board,
+ },
+};
+
static const char * const soc_type_strings[] = {
[ATH25_SOC_AR5312] = "Atheros AR5312",
[ATH25_SOC_AR2312] = "Atheros AR2312",
@@ -46,6 +86,20 @@ void __init ath25_serial_setup(u32 mapbase, int irq, unsigned int uartclk)
early_serial_setup(&s);
}

+int __init ath25_add_wmac(int nr, u32 base, int irq)
+{
+ struct resource *res;
+
+ ath25_wmac[nr].dev.platform_data = &ath25_board;
+ res = &ath25_wmac[nr].resource[0];
+ res->start = base;
+ res->end = base + 0x10000 - 1;
+ res++;
+ res->start = irq;
+ res->end = irq;
+ return platform_device_register(&ath25_wmac[nr]);
+}
+
static int __init ath25_register_devices(void)
{
if (is_ar5312())
diff --git a/arch/mips/ath25/devices.h b/arch/mips/ath25/devices.h
index 8555e32..eb8a1d1 100644
--- a/arch/mips/ath25/devices.h
+++ b/arch/mips/ath25/devices.h
@@ -24,6 +24,7 @@ extern void (*ath25_irq_dispatch)(void);

int ath25_find_config(const u8 *flash_limit);
void ath25_serial_setup(u32 mapbase, int irq, unsigned int uartclk);
+int ath25_add_wmac(int nr, u32 base, int irq);

static inline bool is_ar2315(void)
{
--
1.8.5.5
Loading...