ralink: add mt7621 support

there are still various missing pieces for full support.

Signed-off-by: John Crispin <blogic@openwrt.org>

SVN-Revision: 39040
v19.07.3_mercusys_ac12_duma
John Crispin 11 years ago
parent 594442a37e
commit b4b0a55aab

@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
ARCH:=mipsel
BOARD:=ramips
BOARDNAME:=Ralink RT288x/RT3xxx
SUBTARGETS:=rt305x mt7620a mt7620n rt3883 rt288x
SUBTARGETS:=rt305x mt7620a mt7620n mt7621 rt3883 rt288x
FEATURES:=squashfs gpio
LINUX_VERSION:=3.10.21

@ -0,0 +1,16 @@
/dts-v1/;
/include/ "mt7621.dtsi"
/ {
compatible = "ralink,mt7621-eval-board", "ralink,mt7621-soc";
model = "Ralink MT7621 evaluation board";
memory@0 {
reg = <0x0 0x2000000>;
};
chosen {
bootargs = "console=ttyS0,57600";
};
};

@ -0,0 +1,245 @@
/ {
#address-cells = <1>;
#size-cells = <1>;
compatible = "ralink,mtk7620a-soc";
cpus {
cpu@0 {
compatible = "mips,mips24KEc";
};
};
cpuintc: cpuintc@0 {
#address-cells = <0>;
#interrupt-cells = <1>;
interrupt-controller;
compatible = "mti,cpu-interrupt-controller";
};
palmbus@1E000000 {
compatible = "palmbus";
reg = <0x1E000000 0x100000>;
ranges = <0x0 0x1E000000 0x0FFFFF>;
#address-cells = <1>;
#size-cells = <1>;
sysc@0 {
compatible = "mtk,mt7621-sysc";
reg = <0x0 0x100>;
};
wdt@100 {
compatible = "mtk,mt7621-wdt";
reg = <0x100 0x100>;
};
gpio@600 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "mtk,mt7621-gpio";
reg = <0x600 0x100>;
gpio0: bank@0 {
reg = <0>;
compatible = "mtk,mt7621-gpio-bank";
gpio-controller;
#gpio-cells = <2>;
};
gpio1: bank@1 {
reg = <1>;
compatible = "mtk,mt7621-gpio-bank";
gpio-controller;
#gpio-cells = <2>;
};
gpio2: bank@2 {
reg = <2>;
compatible = "mtk,mt7621-gpio-bank";
gpio-controller;
#gpio-cells = <2>;
};
};
memc@5000 {
compatible = "mtk,mt7621-memc";
reg = <0x300 0x100>;
};
uartlite@c00 {
compatible = "ns16550a";
reg = <0xc00 0x100>;
/* interrupt-parent = <&gic>;
interrupts = <26>;*/
reg-shift = <2>;
reg-io-width = <4>;
no-loopback-test;
};
spi@b00 {
status = "okay";
compatible = "ralink,mt7621-spi";
reg = <0xb00 0x100>;
resets = <&rstctrl 18>;
reset-names = "spi";
#address-cells = <1>;
#size-cells = <1>;
/* pinctrl-names = "default";
pinctrl-0 = <&spi_pins>;*/
m25p80@0 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "en25q64";
reg = <0 0>;
linux,modalias = "m25p80", "en25q64";
spi-max-frequency = <10000000>;
m25p,chunked-io;
partition@0 {
label = "u-boot";
reg = <0x0 0x30000>;
read-only;
};
partition@30000 {
label = "u-boot-env";
reg = <0x30000 0x10000>;
read-only;
};
factory: partition@40000 {
label = "factory";
reg = <0x40000 0x10000>;
read-only;
};
partition@50000 {
label = "firmware";
reg = <0x50000 0x7a0000>;
};
partition@7f0000 {
label = "test";
reg = <0x7f0000 0x10000>;
};
};
};
};
rstctrl: rstctrl {
compatible = "ralink,rt2880-reset";
#reset-cells = <1>;
};
sdhci@1E130000 {
compatible = "ralink,mt7620a-sdhci";
reg = <0x1E130000 4000>;
interrupt-parent = <&gic>;
interrupts = <20>;
};
xhci@1E1C0000 {
compatible = "xhci-platform1";
reg = <0x1E1C0000 4000>;
interrupt-parent = <&gic>;
interrupts = <22>;
};
gic: gic@1fbc0000 {
#address-cells = <0>;
#interrupt-cells = <1>;
interrupt-controller;
compatible = "ralink,mt7621-gic";
reg = < 0x1fbc0000 0x80 /* gic */
0x1fbf0000 0x8000 /* cpc */
0x1fbf8000 0x8000 /* gpmc */
>;
};
nand@1e003000 {
compatible = "mtk,mt7621-nand";
bank-width = <2>;
reg = <0x1e003000 0x800
0x1e003800 0x800>;
#address-cells = <1>;
#size-cells = <1>;
partition@0 {
label = "uboot";
reg = <0x00000 0x80000>; /* 64 KB */
};
partition@80000 {
label = "uboot_env";
reg = <0x80000 0x80000>; /* 64 KB */
};
partition@100000 {
label = "factory";
reg = <0x100000 0x40000>;
};
partition@140000 {
label = "rootfs";
reg = <0x140000 0xec0000>;
};
};
ethernet@1e100000 {
compatible = "ralink,mt7621-eth";
reg = <0x1e100000 10000>;
#address-cells = <1>;
#size-cells = <0>;
ralink,port-map = "llllw";
interrupt-parent = <&gic>;
interrupts = <3>;
/* resets = <&rstctrl 21 &rstctrl 23>;
reset-names = "fe", "esw";
port@4 {
compatible = "ralink,mt7620a-gsw-port", "ralink,eth-port";
reg = <4>;
status = "disabled";
};
port@5 {
compatible = "ralink,mt7620a-gsw-port", "ralink,eth-port";
reg = <5>;
status = "disabled";
};
*/
mdio-bus {
#address-cells = <1>;
#size-cells = <0>;
phy1f: ethernet-phy@1f {
reg = <0x1f>;
phy-mode = "rgmii";
interrupt-parent = <&gic>;
interrupts = <23>;
};
};
};
gsw@1e110000 {
compatible = "ralink,mt7620a-gsw";
reg = <0x1e110000 8000>;
};
};

@ -29,10 +29,16 @@ define kernel_entry
-a 0x88000000 -e 0x88000000
endef
else
ifeq ($(CONFIG_SOC_MT7621),y)
define kernel_entry
-a 0x80001000 -e 0x80001000
endef
else
define kernel_entry
-a 0x80000000 -e 0x80000000
endef
endif
endif
define MkCombineduImage
$(call PatchKernelLzma,$(2),$(3))
@ -648,6 +654,19 @@ endef
endif
#
# MT7621 Profiles
#
Image/Build/Profile/MT7621=$(call BuildFirmware/Default4M/$(1),$(1),mt7621,MT7621)
ifeq ($(SUBTARGET),mt7621)
define Image/Build/Profile/Default
$(call Image/Build/Profile/MT7621,$(1))
endef
endif
#
# Generic Targets
#

@ -147,6 +147,7 @@ CONFIG_SERIAL_OF_PLATFORM=y
# CONFIG_SLAB is not set
CONFIG_SLUB=y
CONFIG_SOC_MT7620=y
# CONFIG_SOC_MT7621 is not set
# CONFIG_SOC_RT288X is not set
# CONFIG_SOC_RT305X is not set
# CONFIG_SOC_RT3883 is not set

@ -144,6 +144,7 @@ CONFIG_SERIAL_OF_PLATFORM=y
# CONFIG_SLAB is not set
CONFIG_SLUB=y
CONFIG_SOC_MT7620=y
# CONFIG_SOC_MT7621 is not set
# CONFIG_SOC_RT288X is not set
# CONFIG_SOC_RT305X is not set
# CONFIG_SOC_RT3883 is not set

@ -0,0 +1,200 @@
CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y
CONFIG_ARCH_DISCARD_MEMBLOCK=y
CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
CONFIG_ARCH_REQUIRE_GPIOLIB=y
CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
CONFIG_BOARD_SCACHE=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
# CONFIG_CEVT_GIC is not set
CONFIG_CEVT_R4K=y
CONFIG_CLKDEV_LOOKUP=y
CONFIG_CLONE_BACKWARDS=y
CONFIG_CMDLINE="rootfstype=squashfs,jffs2"
CONFIG_CMDLINE_BOOL=y
# CONFIG_CMDLINE_OVERRIDE is not set
CONFIG_CPU_GENERIC_DUMP_TLB=y
CONFIG_CPU_HAS_PREFETCH=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_CPU_MIPS32=y
# CONFIG_CPU_MIPS32_R1 is not set
CONFIG_CPU_MIPS32_R2=y
CONFIG_CPU_MIPSR2=y
CONFIG_CPU_MIPSR2_IRQ_EI=y
CONFIG_CPU_MIPSR2_IRQ_VI=y
CONFIG_CPU_R4K_CACHE_TLB=y
CONFIG_CPU_R4K_FPU=y
CONFIG_CPU_RMAP=y
CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
CONFIG_CPU_SUPPORTS_HIGHMEM=y
CONFIG_CSRC_R4K=y
CONFIG_DEBUG_PINCTRL=y
CONFIG_DMA_NONCOHERENT=y
# CONFIG_DTB_MT7621_EVAL is not set
CONFIG_DTB_RT_NONE=y
CONFIG_DTC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_ATOMIC64=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_GENERIC_IO=y
CONFIG_GENERIC_IRQ_SHOW=y
CONFIG_GENERIC_PCI_IOMAP=y
CONFIG_GENERIC_SMP_IDLE_THREAD=y
CONFIG_GPIOLIB=y
CONFIG_GPIO_DEVRES=y
# CONFIG_GPIO_MT7621 is not set
CONFIG_GPIO_RALINK=y
CONFIG_GPIO_SYSFS=y
CONFIG_HARDWARE_WATCHPOINTS=y
CONFIG_HAS_DMA=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
CONFIG_HAVE_ARCH_JUMP_LABEL=y
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
CONFIG_HAVE_CLK=y
CONFIG_HAVE_C_RECORDMCOUNT=y
CONFIG_HAVE_DEBUG_KMEMLEAK=y
CONFIG_HAVE_DMA_API_DEBUG=y
CONFIG_HAVE_DMA_ATTRS=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_HAVE_GENERIC_HARDIRQS=y
CONFIG_HAVE_IDE=y
CONFIG_HAVE_KVM=y
CONFIG_HAVE_MACH_CLKDEV=y
CONFIG_HAVE_MEMBLOCK=y
CONFIG_HAVE_MEMBLOCK_NODE_MAP=y
CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
CONFIG_HAVE_NET_DSA=y
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_PERF_EVENTS=y
CONFIG_HW_HAS_PCI=y
CONFIG_HW_RANDOM=m
CONFIG_HZ_PERIODIC=y
CONFIG_IMAGE_CMDLINE_HACK=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_IRQCHIP=y
CONFIG_IRQ_CPU=y
CONFIG_IRQ_DOMAIN=y
CONFIG_IRQ_FORCED_THREADING=y
CONFIG_IRQ_GIC=y
CONFIG_IRQ_WORK=y
CONFIG_M25PXX_USE_FAST_READ=y
CONFIG_MDIO_BOARDINFO=y
# CONFIG_MII is not set
CONFIG_MIPS=y
CONFIG_MIPS_CMP=y
CONFIG_MIPS_CPU_SCACHE=y
# CONFIG_MIPS_HUGE_TLB_SUPPORT is not set
CONFIG_MIPS_L1_CACHE_SHIFT=6
# CONFIG_MIPS_MACHINE is not set
CONFIG_MIPS_MT=y
# CONFIG_MIPS_MT_DISABLED is not set
CONFIG_MIPS_MT_FPAFF=y
CONFIG_MIPS_MT_SMP=y
# CONFIG_MIPS_MT_SMTC is not set
CONFIG_MIPS_PERF_SHARED_TC_COUNTERS=y
# CONFIG_MIPS_VPE_LOADER is not set
CONFIG_MODULES_USE_ELF_REL=y
# CONFIG_MT7621_WDT is not set
# CONFIG_MTD_CFI_INTELEXT is not set
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_M25P80=y
CONFIG_MTD_OF_PARTS=y
CONFIG_MTD_PHYSMAP=y
CONFIG_MTD_PHYSMAP_OF=y
CONFIG_MTD_SPLIT_FIRMWARE=y
CONFIG_MTD_UIMAGE_SPLIT=y
CONFIG_MUTEX_SPIN_ON_OWNER=y
CONFIG_NEED_DMA_MAP_STATE=y
# CONFIG_NET_RALINK is not set
CONFIG_NLS=m
CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y
CONFIG_NR_CPUS=4
CONFIG_NR_CPUS_DEFAULT_2=y
CONFIG_OF=y
CONFIG_OF_ADDRESS=y
CONFIG_OF_DEVICE=y
CONFIG_OF_EARLY_FLATTREE=y
CONFIG_OF_FLATTREE=y
CONFIG_OF_GPIO=y
CONFIG_OF_IRQ=y
CONFIG_OF_MDIO=y
CONFIG_OF_MTD=y
CONFIG_OF_NET=y
CONFIG_OF_PCI=y
CONFIG_OF_PCI_IRQ=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
CONFIG_PERF_USE_VMALLOC=y
CONFIG_PHYLIB=y
# CONFIG_PINCONF is not set
CONFIG_PINCTRL=y
CONFIG_PINCTRL_RT2880=y
# CONFIG_PINCTRL_SINGLE is not set
CONFIG_PINMUX=y
# CONFIG_PREEMPT_RCU is not set
CONFIG_RALINK=y
CONFIG_RALINK_USBPHY=y
CONFIG_RCU_STALL_COMMON=y
CONFIG_RESET_CONTROLLER=y
CONFIG_RFS_ACCEL=y
CONFIG_RPS=y
# CONFIG_SAMSUNG_USB2PHY is not set
# CONFIG_SAMSUNG_USB3PHY is not set
# CONFIG_SAMSUNG_USBPHY is not set
CONFIG_SCHED_SMT=y
# CONFIG_SCSI_DMA is not set
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_OF_PLATFORM=y
# CONFIG_SLAB is not set
CONFIG_SLUB=y
CONFIG_SMP=y
CONFIG_SMP_UP=y
# CONFIG_SOC_MT7620 is not set
CONFIG_SOC_MT7621=y
# CONFIG_SOC_RT288X is not set
# CONFIG_SOC_RT305X is not set
# CONFIG_SOC_RT3883 is not set
CONFIG_SPI=y
CONFIG_SPI_MASTER=y
CONFIG_SPI_RT2880=y
CONFIG_STOP_MACHINE=y
CONFIG_SWCONFIG=y
CONFIG_SYNC_R4K=y
CONFIG_SYS_HAS_CPU_MIPS32_R1=y
CONFIG_SYS_HAS_CPU_MIPS32_R2=y
CONFIG_SYS_HAS_EARLY_PRINTK=y
CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
CONFIG_SYS_SUPPORTS_MIPS_CMP=y
CONFIG_SYS_SUPPORTS_MULTITHREADING=y
CONFIG_SYS_SUPPORTS_SCHED_SMT=y
CONFIG_SYS_SUPPORTS_SMP=y
CONFIG_TICK_CPU_ACCOUNTING=y
CONFIG_TREE_RCU=y
CONFIG_UIDGID_CONVERTED=y
CONFIG_USB=m
CONFIG_USB_ARCH_HAS_XHCI=y
CONFIG_USB_COMMON=m
# CONFIG_USB_EHCI_HCD is not set
CONFIG_USB_PHY=y
CONFIG_USB_SUPPORT=y
# CONFIG_USB_UHCI_HCD is not set
CONFIG_USE_GENERIC_SMP_HELPERS=y
CONFIG_USE_OF=y
CONFIG_WATCHDOG_CORE=y
CONFIG_WEAK_ORDERING=y
CONFIG_XPS=y
CONFIG_ZONE_DMA_FLAG=0

@ -0,0 +1,18 @@
#
# Copyright (C) 2011 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
define Profile/Default
NAME:=Default Profile
PACKAGES:=\
kmod-usb-core kmod-usb-dwc2 \
kmod-ledtrig-usbdev
endef
define Profile/Default/Description
Default package set compatible with most boards.
endef
$(eval $(call Profile,Default))

@ -0,0 +1,15 @@
#
# Copyright (C) 2009 OpenWrt.org
#
SUBTARGET:=mt7621
BOARDNAME:=MT7621 based boards
ARCH_PACKAGES:=ramips_24kec
FEATURES+=usb
CPU_TYPE:=24kec
CPU_SUBTYPE:=dsp
define Target/Description
Build firmware images for Ralink MT7621 based boards.
endef

@ -0,0 +1,162 @@
From 926ae0ca5017a421709ab0478582683c29988b05 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Wed, 27 Nov 2013 20:58:16 +0100
Subject: [PATCH 10/20] MTD: add chunked read io to m25p80
Signed-off-by: John Crispin <blogic@openwrt.org>
---
drivers/mtd/devices/m25p80.c | 127 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 127 insertions(+)
Index: linux-3.10.21/drivers/mtd/devices/m25p80.c
===================================================================
--- linux-3.10.21.orig/drivers/mtd/devices/m25p80.c 2013-12-09 19:34:40.828651303 +0100
+++ linux-3.10.21/drivers/mtd/devices/m25p80.c 2013-12-09 19:40:37.636659793 +0100
@@ -392,6 +392,57 @@
return 0;
}
+static int m25p80_read_chunked(struct mtd_info *mtd, loff_t from, size_t len,
+ size_t *retlen, u_char *buf)
+{
+ struct m25p *flash = mtd_to_m25p(mtd);
+ struct spi_transfer t[2];
+ struct spi_message m;
+ uint8_t opcode;
+ int idx = 0;
+
+ pr_debug("%s: %s from 0x%08x, len %zd\n", dev_name(&flash->spi->dev),
+ __func__, (u32)from, len);
+
+ spi_message_init(&m);
+ memset(t, 0, (sizeof t));
+
+ t[0].tx_buf = flash->command;
+ t[0].len = m25p_cmdsz(flash);
+ spi_message_add_tail(&t[0], &m);
+ spi_message_add_tail(&t[1], &m);
+
+ while (idx < len) {
+ int rlen = (len - idx > 4) ? (4) : (len - idx);
+
+ t[1].rx_buf = &buf[idx];
+ t[1].len = rlen;
+
+ mutex_lock(&flash->lock);
+
+ /* Wait till previous write/erase is done. */
+ if (wait_till_ready(flash)) {
+ /* REVISIT status return?? */
+ mutex_unlock(&flash->lock);
+ return 1;
+ }
+
+ /* Set up the write data buffer. */
+ opcode = OPCODE_NORM_READ;
+ flash->command[0] = opcode;
+ m25p_addr2cmd(flash, from + idx, flash->command);
+
+ spi_sync(flash->spi, &m);
+
+ *retlen = m.actual_length - m25p_cmdsz(flash) -
+ (flash->fast_read ? 1 : 0);
+
+ mutex_unlock(&flash->lock);
+ idx += rlen;
+ }
+ return 0;
+}
+
/*
* Write an address range to the flash chip. Data must be written in
* FLASH_PAGESIZE chunks. The address range may be any size provided
@@ -479,6 +530,76 @@
return 0;
}
+static int m25p80_write_chunked(struct mtd_info *mtd, loff_t to, size_t len,
+ size_t *retlen, const u_char *buf)
+{
+ struct m25p *flash = mtd_to_m25p(mtd);
+ struct spi_transfer t;
+ struct spi_message m;
+ u32 i, page_size;
+ u8 tmp[8];
+
+ pr_debug("%s: %s to 0x%08x, len %zd\n", dev_name(&flash->spi->dev),
+ __func__, (u32)to, len);
+
+ spi_message_init(&m);
+ memset(&t, 0, (sizeof t));
+
+ t.tx_buf = tmp;
+ t.len = 8;
+ spi_message_add_tail(&t, &m);
+
+ mutex_lock(&flash->lock);
+
+ /* Wait until finished previous write command. */
+ if (wait_till_ready(flash)) {
+ mutex_unlock(&flash->lock);
+ return 1;
+ }
+
+ write_enable(flash);
+
+ /* Set up the opcode in the write buffer. */
+ flash->command[0] = OPCODE_PP;
+ m25p_addr2cmd(flash, to, flash->command);
+
+ t.len = 4 + (to & 0x3);
+ if (t.len == 4)
+ t.len = 8;
+ memcpy(tmp, flash->command, 4);
+ memcpy(&tmp[4], buf, t.len - 4);
+ spi_sync(flash->spi, &m);
+ page_size = t.len - 4;
+
+ *retlen = m.actual_length - m25p_cmdsz(flash);
+
+ /* write everything in flash->page_size chunks */
+ for (i = page_size; i < len; i += page_size) {
+ page_size = len - i;
+ if (page_size > 4)
+ page_size = 4;
+
+ /* write the next page to flash */
+ m25p_addr2cmd(flash, to + i, flash->command);
+
+ memcpy(tmp, flash->command, 4);
+ memcpy(&tmp[4], buf + i, page_size);
+ t.len = 4 + page_size;
+
+ wait_till_ready(flash);
+
+ write_enable(flash);
+
+ spi_sync(flash->spi, &m);
+
+ *retlen += m.actual_length - m25p_cmdsz(flash);
+ }
+
+ mutex_unlock(&flash->lock);
+
+ return 0;
+}
+
static int sst_write(struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const u_char *buf)
{
@@ -1057,6 +1178,12 @@
flash->fast_read = true;
#endif
+ if (np && of_property_read_bool(np, "m25p,chunked-io")) {
+ dev_warn(&spi->dev, "using chunked io\n");
+ flash->mtd._read = m25p80_read_chunked;
+ flash->mtd._write = m25p80_write_chunked;
+ }
+
#ifdef CONFIG_M25PXX_USE_FAST_READ
flash->fast_read = true;
#endif

@ -0,0 +1,336 @@
Index: linux-3.10.21/drivers/spi/spi-rt2880.c
===================================================================
--- linux-3.10.21.orig/drivers/spi/spi-rt2880.c 2013-12-09 20:17:54.380713104 +0100
+++ linux-3.10.21/drivers/spi/spi-rt2880.c 2013-12-09 20:35:08.004737585 +0100
@@ -21,8 +21,11 @@
#include <linux/io.h>
#include <linux/reset.h>
#include <linux/spi/spi.h>
+#include <linux/of_device.h>
#include <linux/platform_device.h>
+#include <ralink_regs.h>
+
#define DRIVER_NAME "spi-rt2880"
/* only one slave is supported*/
#define RALINK_NUM_CHIPSELECTS 1
@@ -63,6 +66,25 @@
/* SPIFIFOSTAT register bit field */
#define SPIFIFOSTAT_TXFULL BIT(17)
+#define MT7621_SPI_TRANS 0x00
+#define SPITRANS_BUSY BIT(16)
+#define MT7621_SPI_OPCODE 0x04
+#define MT7621_SPI_DATA0 0x08
+#define SPI_CTL_TX_RX_CNT_MASK 0xff
+#define SPI_CTL_START BIT(8)
+#define MT7621_SPI_POLAR 0x38
+#define MT7621_SPI_MASTER 0x28
+#define MT7621_SPI_SPACE 0x3c
+
+struct rt2880_spi;
+
+struct rt2880_spi_ops {
+ void (*init_hw)(struct rt2880_spi *rs);
+ void (*set_cs)(struct rt2880_spi *rs, int enable);
+ int (*baudrate_set)(struct spi_device *spi, unsigned int speed);
+ unsigned int (*write_read)(struct spi_device *spi, struct list_head *list, struct spi_transfer *xfer);
+};
+
struct rt2880_spi {
struct spi_master *master;
void __iomem *base;
@@ -70,6 +92,8 @@
unsigned int speed;
struct clk *clk;
spinlock_t lock;
+
+ struct rt2880_spi_ops *ops;
};
static inline struct rt2880_spi *spidev_to_rt2880_spi(struct spi_device *spi)
@@ -149,6 +173,17 @@
return 0;
}
+static int mt7621_spi_baudrate_set(struct spi_device *spi, unsigned int speed)
+{
+/* u32 master = rt2880_spi_read(rs, MT7621_SPI_MASTER);
+
+ // set default clock to hclk/5
+ master &= ~(0xfff << 16);
+ master |= 0x3 << 16;
+*/
+ return 0;
+}
+
/*
* called only when no transfer is active on the bus
*/
@@ -164,7 +199,7 @@
if (rs->speed != speed) {
dev_dbg(&spi->dev, "speed_hz:%u\n", speed);
- rc = rt2880_spi_baudrate_set(spi, speed);
+ rc = rs->ops->baudrate_set(spi, speed);
if (rc)
return rc;
}
@@ -180,6 +215,17 @@
rt2880_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_SPIENA);
}
+static void mt7621_spi_set_cs(struct rt2880_spi *rs, int enable)
+{
+ u32 polar = rt2880_spi_read(rs, MT7621_SPI_POLAR);
+
+ if (enable)
+ polar |= 1;
+ else
+ polar &= ~1;
+ rt2880_spi_write(rs, MT7621_SPI_POLAR, polar);
+}
+
static inline int rt2880_spi_wait_till_ready(struct rt2880_spi *rs)
{
int i;
@@ -198,8 +244,26 @@
return -ETIMEDOUT;
}
+static inline int mt7621_spi_wait_till_ready(struct rt2880_spi *rs)
+{
+ int i;
+
+ for (i = 0; i < RALINK_SPI_WAIT_MAX_LOOP; i++) {
+ u32 status;
+
+ status = rt2880_spi_read(rs, MT7621_SPI_TRANS);
+ if ((status & SPITRANS_BUSY) == 0) {
+ return 0;
+ }
+ cpu_relax();
+ udelay(1);
+ }
+
+ return -ETIMEDOUT;
+}
+
static unsigned int
-rt2880_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer)
+rt2880_spi_write_read(struct spi_device *spi, struct list_head *list, struct spi_transfer *xfer)
{
struct rt2880_spi *rs = spidev_to_rt2880_spi(spi);
unsigned count = 0;
@@ -239,6 +303,100 @@
return count;
}
+static unsigned int
+mt7621_spi_write_read(struct spi_device *spi, struct list_head *list, struct spi_transfer *xfer)
+{
+ struct rt2880_spi *rs = spidev_to_rt2880_spi(spi);
+ struct spi_transfer *next = NULL;
+ const u8 *tx = xfer->tx_buf;
+ u8 *rx = NULL;
+ u32 trans;
+ int len = xfer->len;
+
+ if (!tx)
+ return 0;
+
+ if (!list_is_last(&xfer->transfer_list, list)) {
+ next = list_entry(xfer->transfer_list.next, struct spi_transfer, transfer_list);
+ rx = next->rx_buf;
+ }
+
+ trans = rt2880_spi_read(rs, MT7621_SPI_TRANS);
+ trans &= ~SPI_CTL_TX_RX_CNT_MASK;
+
+ if (tx) {
+ u32 data0 = 0, opcode = 0;
+
+ switch (xfer->len) {
+ case 8:
+ data0 |= tx[7] << 24;
+ case 7:
+ data0 |= tx[6] << 16;
+ case 6:
+ data0 |= tx[5] << 8;
+ case 5:
+ data0 |= tx[4];
+ case 4:
+ opcode |= tx[3] << 8;
+ case 3:
+ opcode |= tx[2] << 16;
+ case 2:
+ opcode |= tx[1] << 24;
+ case 1:
+ opcode |= tx[0];
+ break;
+
+ default:
+ dev_err(&spi->dev, "trying to write too many bytes: %d\n", next->len);
+ return -EINVAL;
+ }
+
+ rt2880_spi_write(rs, MT7621_SPI_DATA0, data0);
+ rt2880_spi_write(rs, MT7621_SPI_OPCODE, opcode);
+ trans |= xfer->len;
+ }
+
+ if (rx)
+ trans |= (next->len << 4);
+ rt2880_spi_write(rs, MT7621_SPI_TRANS, trans);
+ trans |= SPI_CTL_START;
+ rt2880_spi_write(rs, MT7621_SPI_TRANS, trans);
+
+ mt7621_spi_wait_till_ready(rs);
+
+ if (rx) {
+ u32 data0 = rt2880_spi_read(rs, MT7621_SPI_DATA0);
+ u32 opcode = rt2880_spi_read(rs, MT7621_SPI_OPCODE);
+
+ switch (next->len) {
+ case 8:
+ rx[7] = (opcode >> 24) & 0xff;
+ case 7:
+ rx[6] = (opcode >> 16) & 0xff;
+ case 6:
+ rx[5] = (opcode >> 8) & 0xff;
+ case 5:
+ rx[4] = opcode & 0xff;
+ case 4:
+ rx[3] = (data0 >> 24) & 0xff;
+ case 3:
+ rx[2] = (data0 >> 16) & 0xff;
+ case 2:
+ rx[1] = (data0 >> 8) & 0xff;
+ case 1:
+ rx[0] = data0 & 0xff;
+ break;
+
+ default:
+ dev_err(&spi->dev, "trying to read too many bytes: %d\n", next->len);
+ return -EINVAL;
+ }
+ len += next->len;
+ }
+
+ return len;
+}
+
static int rt2880_spi_transfer_one_message(struct spi_master *master,
struct spi_message *m)
{
@@ -280,25 +438,25 @@
}
if (!cs_active) {
- rt2880_spi_set_cs(rs, 1);
+ rs->ops->set_cs(rs, 1);
cs_active = 1;
}
if (t->len)
- m->actual_length += rt2880_spi_write_read(spi, t);
+ m->actual_length += rs->ops->write_read(spi, &m->transfers, t);
if (t->delay_usecs)
udelay(t->delay_usecs);
if (t->cs_change) {
- rt2880_spi_set_cs(rs, 0);
+ rs->ops->set_cs(rs, 0);
cs_active = 0;
}
}
msg_done:
if (cs_active)
- rt2880_spi_set_cs(rs, 0);
+ rs->ops->set_cs(rs, 0);
m->status = status;
spi_finalize_current_message(master);
@@ -334,8 +492,41 @@
rt2880_spi_write(rs, RAMIPS_SPI_CTL, SPICTL_HIZSDO | SPICTL_SPIENA);
}
+static void mt7621_spi_reset(struct rt2880_spi *rs)
+{
+ u32 master = rt2880_spi_read(rs, MT7621_SPI_MASTER);
+
+ master &= ~(0xfff << 16);
+ master |= 3 << 16;
+
+ master |= 7 << 29;
+ rt2880_spi_write(rs, MT7621_SPI_MASTER, master);
+}
+
+static struct rt2880_spi_ops spi_ops[] = {
+ {
+ .init_hw = rt2880_spi_reset,
+ .set_cs = rt2880_spi_set_cs,
+ .baudrate_set = rt2880_spi_baudrate_set,
+ .write_read = rt2880_spi_write_read,
+ }, {
+ .init_hw = mt7621_spi_reset,
+ .set_cs = mt7621_spi_set_cs,
+ .baudrate_set = mt7621_spi_baudrate_set,
+ .write_read = mt7621_spi_write_read,
+ },
+};
+
+static const struct of_device_id rt2880_spi_match[] = {
+ { .compatible = "ralink,rt2880-spi", .data = &spi_ops[0]},
+ { .compatible = "ralink,mt7621-spi", .data = &spi_ops[1] },
+ {},
+};
+MODULE_DEVICE_TABLE(of, rt2880_spi_match);
+
static int rt2880_spi_probe(struct platform_device *pdev)
{
+ const struct of_device_id *match;
struct spi_master *master;
struct rt2880_spi *rs;
unsigned long flags;
@@ -344,6 +535,10 @@
int status = 0;
struct clk *clk;
+ match = of_match_device(rt2880_spi_match, &pdev->dev);
+ if (!match)
+ return -EINVAL;
+
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, r);
if (IS_ERR(base))
@@ -382,12 +577,13 @@
rs->clk = clk;
rs->master = master;
rs->sys_freq = clk_get_rate(rs->clk);
+ rs->ops = (struct rt2880_spi_ops *) match->data;
dev_dbg(&pdev->dev, "sys_freq: %u\n", rs->sys_freq);
spin_lock_irqsave(&rs->lock, flags);
device_reset(&pdev->dev);
- rt2880_spi_reset(rs);
+ rs->ops->init_hw(rs);
return spi_register_master(master);
}
@@ -408,12 +604,6 @@
MODULE_ALIAS("platform:" DRIVER_NAME);
-static const struct of_device_id rt2880_spi_match[] = {
- { .compatible = "ralink,rt2880-spi" },
- {},
-};
-MODULE_DEVICE_TABLE(of, rt2880_spi_match);
-
static struct platform_driver rt2880_spi_driver = {
.driver = {
.name = DRIVER_NAME,

@ -0,0 +1,26 @@
From e5327a1c6969316370af5cae7cfe6b8163178575 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Mon, 2 Dec 2013 16:07:23 +0100
Subject: [PATCH 500/507] MIPS: increase GIC_INTR_MAX
Signed-off-by: John Crispin <blogic@openwrt.org>
---
arch/mips/include/asm/gic.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/mips/include/asm/gic.h b/arch/mips/include/asm/gic.h
index b2e3e93..2902d93 100644
--- a/arch/mips/include/asm/gic.h
+++ b/arch/mips/include/asm/gic.h
@@ -19,7 +19,7 @@
#define GIC_TRIG_EDGE 1
#define GIC_TRIG_LEVEL 0
-#define GIC_NUM_INTRS (24 + NR_CPUS * 2)
+#define GIC_NUM_INTRS (56 + NR_CPUS * 2)
#define MSK(n) ((1 << (n)) - 1)
#define REG32(addr) (*(volatile unsigned int *) (addr))
--
1.7.10.4

@ -0,0 +1,683 @@
From 99342a0481d49b6e1ade90fdb02f597cb75f103f Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Mon, 2 Dec 2013 16:11:09 +0100
Subject: [PATCH 502/507] MIPS: ralink: add MT7621 support
Signed-off-by: John Crispin <blogic@openwrt.org>
---
arch/mips/include/asm/mach-ralink/mt7621.h | 39 +++++
arch/mips/ralink/Kconfig | 18 ++
arch/mips/ralink/Makefile | 7 +-
arch/mips/ralink/Platform | 5 +
arch/mips/ralink/irq-gic.c | 255 ++++++++++++++++++++++++++++
arch/mips/ralink/malta-amon.c | 81 +++++++++
arch/mips/ralink/mt7621.c | 186 ++++++++++++++++++++
7 files changed, 590 insertions(+), 1 deletion(-)
create mode 100644 arch/mips/include/asm/mach-ralink/mt7621.h
create mode 100644 arch/mips/ralink/irq-gic.c
create mode 100644 arch/mips/ralink/malta-amon.c
create mode 100644 arch/mips/ralink/mt7621.c
Index: linux-3.10.21/arch/mips/include/asm/mach-ralink/mt7621.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-3.10.21/arch/mips/include/asm/mach-ralink/mt7621.h 2013-12-09 19:52:51.752677298 +0100
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ *
+ * Parts of this file are based on Ralink's 2.6.21 BSP
+ *
+ * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
+ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ */
+
+#ifndef _MT7621_REGS_H_
+#define _MT7621_REGS_H_
+
+#define MT7621_SYSC_BASE 0x1E000000
+
+#define SYSC_REG_CHIP_NAME0 0x00
+#define SYSC_REG_CHIP_NAME1 0x04
+#define SYSC_REG_CHIP_REV 0x0c
+#define SYSC_REG_SYSTEM_CONFIG0 0x10
+#define SYSC_REG_SYSTEM_CONFIG1 0x14
+
+#define CHIP_REV_PKG_MASK 0x1
+#define CHIP_REV_PKG_SHIFT 16
+#define CHIP_REV_VER_MASK 0xf
+#define CHIP_REV_VER_SHIFT 8
+#define CHIP_REV_ECO_MASK 0xf
+
+#define MT7621_DRAM_BASE 0x0
+#define MT7621_DDR2_SIZE_MIN 32
+#define MT7621_DDR2_SIZE_MAX 256
+
+#define MT7621_CHIP_NAME0 0x3637544D
+#define MT7621_CHIP_NAME1 0x20203132
+
+#define MIPS_GIC_IRQ_BASE (MIPS_CPU_IRQ_BASE + 8)
+
+#endif
Index: linux-3.10.21/arch/mips/ralink/Kconfig
===================================================================
--- linux-3.10.21.orig/arch/mips/ralink/Kconfig 2013-12-09 19:51:55.600675960 +0100
+++ linux-3.10.21/arch/mips/ralink/Kconfig 2013-12-09 19:52:51.756677296 +0100
@@ -1,5 +1,10 @@
if RALINK
+config IRQ_INTC
+ bool
+ default y
+ depends on !SOC_MT7621
+
config CLKEVT_RT3352
bool "Systick Clockevent source"
depends on SOC_RT305X || SOC_MT7620
@@ -35,6 +40,15 @@
select USB_ARCH_HAS_EHCI
select HW_HAS_PCI
+ config SOC_MT7621
+ bool "MT7621"
+ select MIPS_CPU_SCACHE
+ select SYS_SUPPORTS_MULTITHREADING
+ select SYS_SUPPORTS_SMP
+ select SYS_SUPPORTS_MIPS_CMP
+ select IRQ_GIC
+ select HW_HAS_PCI
+
endchoice
choice
@@ -62,6 +76,10 @@
bool "MT7620A eval kit"
depends on SOC_MT7620
+ config DTB_MT7621_EVAL
+ bool "MT7621 eval kit"
+ depends on SOC_MT7621
+
endchoice
endif
Index: linux-3.10.21/arch/mips/ralink/Makefile
===================================================================
--- linux-3.10.21.orig/arch/mips/ralink/Makefile 2013-12-09 19:51:55.600675960 +0100
+++ linux-3.10.21/arch/mips/ralink/Makefile 2013-12-09 19:52:51.756677296 +0100
@@ -6,7 +6,11 @@
# Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org>
# Copyright (C) 2013 John Crispin <blogic@openwrt.org>
-obj-y := prom.o of.o reset.o clk.o irq.o timer.o
+obj-y := prom.o of.o reset.o clk.o timer.o
+
+obj-$(CONFIG_IRQ_INTC) += irq.o
+obj-$(CONFIG_IRQ_GIC) += irq-gic.o
+obj-$(CONFIG_MIPS_MT_SMP) += malta-amon.o
obj-$(CONFIG_CLKEVT_RT3352) += cevt-rt3352.o
@@ -16,6 +20,7 @@
obj-$(CONFIG_SOC_RT305X) += rt305x.o
obj-$(CONFIG_SOC_RT3883) += rt3883.o
obj-$(CONFIG_SOC_MT7620) += mt7620.o
+obj-$(CONFIG_SOC_MT7621) += mt7621.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
Index: linux-3.10.21/arch/mips/ralink/Platform
===================================================================
--- linux-3.10.21.orig/arch/mips/ralink/Platform 2013-12-09 19:51:55.000000000 +0100
+++ linux-3.10.21/arch/mips/ralink/Platform 2013-12-09 19:53:54.660678800 +0100
@@ -26,3 +26,10 @@
# Ralink MT7620
#
load-$(CONFIG_SOC_MT7620) += 0xffffffff80000000
+cflags-$(CONFIG_SOC_MT7620) += -I$(srctree)/arch/mips/include/asm/mach-ralink/mt7620
+
+#
+# Ralink MT7621
+#
+load-$(CONFIG_SOC_MT7621) += 0xffffffff80001000
+cflags-$(CONFIG_SOC_MT7620) += -I$(srctree)/arch/mips/include/asm/mach-ralink/mt7621
Index: linux-3.10.21/arch/mips/ralink/irq-gic.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-3.10.21/arch/mips/ralink/irq-gic.c 2013-12-09 19:52:51.756677296 +0100
@@ -0,0 +1,255 @@
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <linux/hardirq.h>
+#include <linux/preempt.h>
+#include <linux/irqdomain.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+
+#include <asm/irq_cpu.h>
+#include <asm/mipsregs.h>
+
+#include <asm/irq.h>
+#include <asm/setup.h>
+
+#include <asm/gic.h>
+#include <asm/gcmpregs.h>
+
+#include <asm/mach-ralink/mt7621.h>
+
+static unsigned long _gcmp_base;
+static int gic_resched_int_base = 56;
+static int gic_call_int_base = 60;
+static struct irq_chip *irq_gic;
+
+#define GIC_RESCHED_INT(cpu) (gic_resched_int_base+(cpu))
+#define GIC_CALL_INT(cpu) (gic_call_int_base+(cpu))
+
+static struct gic_intr_map gic_intr_map[GIC_NUM_INTRS] = {
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, //0
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+ { GIC_UNUSED },
+ { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, //FE
+ { 0, GIC_CPU_INT4, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, //PCIE0
+ { GIC_UNUSED},
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, //10
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+ { GIC_UNUSED },
+ { GIC_UNUSED },
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, //20
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+ { GIC_UNUSED },
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, //25
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },//30
+ { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+};
+
+static struct gic_intr_map ipi_intr_map[8] = {
+ { 0, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_EDGE, GIC_FLAG_IPI },
+ { 1, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_EDGE, GIC_FLAG_IPI },
+ { 2, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_EDGE, GIC_FLAG_IPI },
+ { 3, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_EDGE, GIC_FLAG_IPI },
+ { 0, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_EDGE, GIC_FLAG_IPI },
+ { 1, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_EDGE, GIC_FLAG_IPI },
+ { 2, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_EDGE, GIC_FLAG_IPI },
+ { 3, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_EDGE, GIC_FLAG_IPI },
+};
+
+static irqreturn_t
+ipi_resched_interrupt(int irq, void *dev_id)
+{
+ scheduler_ipi();
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t
+ipi_call_interrupt(int irq, void *dev_id)
+{
+ smp_call_function_interrupt();
+
+ return IRQ_HANDLED;
+}
+
+static struct irqaction irq_resched = {
+ .handler = ipi_resched_interrupt,
+ .flags = IRQF_DISABLED|IRQF_PERCPU,
+ .name = "ipi resched"
+};
+
+static struct irqaction irq_call = {
+ .handler = ipi_call_interrupt,
+ .flags = IRQF_DISABLED|IRQF_PERCPU,
+ .name = "ipi call"
+};
+
+void
+gic_irq_ack(struct irq_data *d)
+{
+ int irq = (d->irq - gic_irq_base);
+
+ GIC_CLR_INTR_MASK(irq);
+
+ if (gic_irq_flags[irq] & GIC_TRIG_EDGE)
+ GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), irq);
+}
+
+void
+gic_finish_irq(struct irq_data *d)
+{
+ GIC_SET_INTR_MASK(d->irq - gic_irq_base);
+}
+
+void __init
+gic_platform_init(int irqs, struct irq_chip *irq_controller)
+{
+ irq_gic = irq_controller;
+}
+
+static void
+vi_gic_irqdispatch(void)
+{
+ int irq = gic_get_int();
+
+ if (irq >= 0)
+ do_IRQ(MIPS_GIC_IRQ_BASE + irq);
+}
+
+static void
+vi_timer_irqdispatch(void)
+{
+ do_IRQ(cp0_compare_irq);
+}
+
+unsigned int
+plat_ipi_call_int_xlate(unsigned int cpu)
+{
+ return GIC_CALL_INT(cpu);
+}
+
+unsigned int
+plat_ipi_resched_int_xlate(unsigned int cpu)
+{
+ return GIC_RESCHED_INT(cpu);
+}
+
+asmlinkage void
+plat_irq_dispatch(void)
+{
+ unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
+
+ if (pending & CAUSEF_IP7)
+ do_IRQ(cp0_compare_irq);
+ else if (pending & (CAUSEF_IP4 | CAUSEF_IP3))
+ vi_gic_irqdispatch();
+ else
+ spurious_interrupt();
+}
+
+unsigned int __cpuinit
+get_c0_compare_int(void)
+{
+ return CP0_LEGACY_COMPARE_IRQ;
+}
+
+static int
+gic_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
+{
+ irq_set_chip_and_handler(irq, irq_gic, handle_percpu_irq);
+
+ return 0;
+}
+
+static const struct irq_domain_ops irq_domain_ops = {
+ .xlate = irq_domain_xlate_onecell,
+ .map = gic_map,
+};
+
+static int __init
+of_gic_init(struct device_node *node,
+ struct device_node *parent)
+{
+ struct irq_domain *domain;
+ struct resource gcmp = { 0 }, gic = { 0 };
+ unsigned int gic_rev;
+ int i;
+
+ if (of_address_to_resource(node, 0, &gic))
+ panic("Failed to get gic memory range");
+ if (request_mem_region(gic.start, resource_size(&gic),
+ gic.name) < 0)
+ panic("Failed to request gic memory");
+ if (of_address_to_resource(node, 2, &gcmp))
+ panic("Failed to get gic memory range");
+ if (request_mem_region(gcmp.start, resource_size(&gcmp),
+ gcmp.name) < 0)
+ panic("Failed to request gcmp memory");
+
+ _gcmp_base = (unsigned long) ioremap_nocache(gcmp.start, resource_size(&gcmp));
+ if (!_gcmp_base)
+ panic("Failed to remap gcmp memory\n");
+
+ if ((GCMPGCB(GCMPB) & GCMP_GCB_GCMPB_GCMPBASE_MSK) != gcmp.start)
+ panic("Failed to find gcmp core\n");
+
+ /* tell the gcmp where to find the gic */
+ GCMPGCB(GICBA) = gic.start | GCMP_GCB_GICBA_EN_MSK;
+ gic_present = 1;
+ if (cpu_has_vint) {
+ set_vi_handler(3, vi_gic_irqdispatch);
+ set_vi_handler(4, vi_gic_irqdispatch);
+ set_vi_handler(7, vi_timer_irqdispatch);
+ }
+
+ memcpy(&gic_intr_map[gic_resched_int_base], ipi_intr_map, sizeof(ipi_intr_map));
+ gic_init(gic.start, resource_size(&gic), gic_intr_map,
+ ARRAY_SIZE(gic_intr_map), MIPS_GIC_IRQ_BASE);
+
+ GICREAD(GIC_REG(SHARED, GIC_SH_REVISIONID), gic_rev);
+ pr_info("gic: revision %d.%d\n", (gic_rev >> 8) & 0xff, gic_rev & 0xff);
+
+ domain = irq_domain_add_legacy(node, GIC_NUM_INTRS, MIPS_GIC_IRQ_BASE,
+ 0, &irq_domain_ops, NULL);
+ if (!domain)
+ panic("Failed to add irqdomain");
+
+ for (i = 0; i < NR_CPUS; i++) {
+ setup_irq(MIPS_GIC_IRQ_BASE + GIC_RESCHED_INT(i), &irq_resched);
+ setup_irq(MIPS_GIC_IRQ_BASE + GIC_CALL_INT(i), &irq_call);
+ }
+
+ change_c0_status(ST0_IM, STATUSF_IP3 | STATUSF_IP4 | STATUSF_IP6 |
+ STATUSF_IP7);
+ return 0;
+}
+
+static struct of_device_id __initdata of_irq_ids[] = {
+ { .compatible = "mti,cpu-interrupt-controller", .data = mips_cpu_intc_init },
+ { .compatible = "ralink,mt7621-gic", .data = of_gic_init },
+ {},
+};
+
+void __init
+arch_init_irq(void)
+{
+ of_irq_init(of_irq_ids);
+}
Index: linux-3.10.21/arch/mips/ralink/malta-amon.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-3.10.21/arch/mips/ralink/malta-amon.c 2013-12-09 19:52:51.756677296 +0100
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2007 MIPS Technologies, Inc.
+ * All rights reserved.
+
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Arbitrary Monitor interface
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+
+#include <asm/addrspace.h>
+#include <asm/mips-boards/launch.h>
+#include <asm/mipsmtregs.h>
+
+int amon_cpu_avail(int cpu)
+{
+ struct cpulaunch *launch = (struct cpulaunch *)CKSEG0ADDR(CPULAUNCH);
+
+ if (cpu < 0 || cpu >= NCPULAUNCH) {
+ pr_debug("avail: cpu%d is out of range\n", cpu);
+ return 0;
+ }
+
+ launch += cpu;
+ if (!(launch->flags & LAUNCH_FREADY)) {
+ pr_debug("avail: cpu%d is not ready\n", cpu);
+ return 0;
+ }
+ if (launch->flags & (LAUNCH_FGO|LAUNCH_FGONE)) {
+ pr_debug("avail: too late.. cpu%d is already gone\n", cpu);
+ return 0;
+ }
+
+ return 1;
+}
+
+void amon_cpu_start(int cpu,
+ unsigned long pc, unsigned long sp,
+ unsigned long gp, unsigned long a0)
+{
+ volatile struct cpulaunch *launch =
+ (struct cpulaunch *)CKSEG0ADDR(CPULAUNCH);
+
+ if (!amon_cpu_avail(cpu))
+ return;
+ if (cpu == smp_processor_id()) {
+ pr_debug("launch: I am cpu%d!\n", cpu);
+ return;
+ }
+ launch += cpu;
+
+ pr_debug("launch: starting cpu%d\n", cpu);
+
+ launch->pc = pc;
+ launch->gp = gp;
+ launch->sp = sp;
+ launch->a0 = a0;
+
+ smp_wmb(); /* Target must see parameters before go */
+ launch->flags |= LAUNCH_FGO;
+ smp_wmb(); /* Target must see go before we poll */
+
+ while ((launch->flags & LAUNCH_FGONE) == 0)
+ ;
+ smp_rmb(); /* Target will be updating flags soon */
+ pr_debug("launch: cpu%d gone!\n", cpu);
+}
Index: linux-3.10.21/arch/mips/ralink/mt7621.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-3.10.21/arch/mips/ralink/mt7621.c 2013-12-09 19:52:51.760677296 +0100
@@ -0,0 +1,186 @@
+/*
+ * 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.
+ *
+ * Parts of this file are based on Ralink's 2.6.21 BSP
+ *
+ * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
+ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <asm/gcmpregs.h>
+
+#include <asm/mipsregs.h>
+#include <asm/mach-ralink/ralink_regs.h>
+#include <asm/mach-ralink/mt7621.h>
+
+#include <pinmux.h>
+
+#include "common.h"
+
+#define SYSC_REG_SYSCFG 0x10
+#define SYSC_REG_CPLL_CLKCFG0 0x2c
+#define SYSC_REG_CUR_CLK_STS 0x44
+#define CPU_CLK_SEL (BIT(30) | BIT(31))
+
+#define MT7621_GPIO_MODE_UART1 1
+#define MT7621_GPIO_MODE_I2C 2
+#define MT7621_GPIO_MODE_UART2 3
+#define MT7621_GPIO_MODE_UART3 5
+#define MT7621_GPIO_MODE_JTAG 7
+#define MT7621_GPIO_MODE_WDT_MASK 0x3
+#define MT7621_GPIO_MODE_WDT_SHIFT 8
+#define MT7621_GPIO_MODE_WDT_GPIO 1
+#define MT7621_GPIO_MODE_PCIE_RST 0
+#define MT7621_GPIO_MODE_PCIE_REF 2
+#define MT7621_GPIO_MODE_PCIE_MASK 0x3
+#define MT7621_GPIO_MODE_PCIE_SHIFT 10
+#define MT7621_GPIO_MODE_PCIE_GPIO 1
+#define MT7621_GPIO_MODE_MDIO 12
+#define MT7621_GPIO_MODE_RGMII1 14
+#define MT7621_GPIO_MODE_RGMII2 15
+#define MT7621_GPIO_MODE_SPI_MASK 0x3
+#define MT7621_GPIO_MODE_SPI_SHIFT 16
+#define MT7621_GPIO_MODE_SPI_GPIO 1
+#define MT7621_GPIO_MODE_SDHCI_MASK 0x3
+#define MT7621_GPIO_MODE_SDHCI_SHIFT 18
+#define MT7621_GPIO_MODE_SDHCI_GPIO 1
+
+static struct rt2880_pmx_func uart1_grp[] = { FUNC("uart1", 0, 1, 2) };
+static struct rt2880_pmx_func i2c_grp[] = { FUNC("i2c", 0, 3, 2) };
+static struct rt2880_pmx_func uart3_grp[] = { FUNC("uart3", 0, 5, 4) };
+static struct rt2880_pmx_func uart2_grp[] = { FUNC("uart2", 0, 9, 4) };
+static struct rt2880_pmx_func jtag_grp[] = { FUNC("jtag", 0, 13, 5) };
+static struct rt2880_pmx_func wdt_grp[] = {
+ FUNC("wdt rst", 0, 18, 1),
+ FUNC("wdt refclk", 2, 18, 1),
+};
+static struct rt2880_pmx_func pcie_rst_grp[] = {
+ FUNC("pcie rst", MT7621_GPIO_MODE_PCIE_RST, 19, 1),
+ FUNC("pcie refclk", MT7621_GPIO_MODE_PCIE_REF, 19, 1)
+};
+static struct rt2880_pmx_func mdio_grp[] = { FUNC("mdio", 0, 20, 2) };
+static struct rt2880_pmx_func rgmii2_grp[] = { FUNC("rgmii2", 0, 22, 12) };
+static struct rt2880_pmx_func spi_grp[] = {
+ FUNC("spi", 0, 34, 7),
+ FUNC("nand", 2, 34, 8),
+};
+static struct rt2880_pmx_func sdhci_grp[] = {
+ FUNC("sdhci", 0, 41, 8),
+ FUNC("nand", 2, 41, 8),
+};
+static struct rt2880_pmx_func rgmii1_grp[] = { FUNC("rgmii1", 0, 49, 12) };
+
+static struct rt2880_pmx_group mt7621_pinmux_data[] = {
+ GRP("uart1", uart1_grp, 1, MT7621_GPIO_MODE_UART1),
+ GRP("i2c", i2c_grp, 1, MT7621_GPIO_MODE_I2C),
+ GRP("uart3", uart2_grp, 1, MT7621_GPIO_MODE_UART2),
+ GRP("uart2", uart3_grp, 1, MT7621_GPIO_MODE_UART3),
+ GRP("jtag", jtag_grp, 1, MT7621_GPIO_MODE_JTAG),
+ GRP_G("wdt", wdt_grp, MT7621_GPIO_MODE_WDT_MASK,
+ MT7621_GPIO_MODE_WDT_GPIO, MT7621_GPIO_MODE_WDT_SHIFT),
+ GRP_G("pcie", pcie_rst_grp, MT7621_GPIO_MODE_PCIE_MASK,
+ MT7621_GPIO_MODE_PCIE_GPIO, MT7621_GPIO_MODE_PCIE_SHIFT),
+ GRP("mdio", mdio_grp, 1, MT7621_GPIO_MODE_MDIO),
+ GRP("rgmii2", rgmii2_grp, 1, MT7621_GPIO_MODE_RGMII2),
+ GRP_G("spi", spi_grp, MT7621_GPIO_MODE_SPI_MASK,
+ MT7621_GPIO_MODE_SPI_GPIO, MT7621_GPIO_MODE_SPI_SHIFT),
+ GRP_G("sdhci", sdhci_grp, MT7621_GPIO_MODE_SDHCI_MASK,
+ MT7621_GPIO_MODE_SDHCI_GPIO, MT7621_GPIO_MODE_SDHCI_SHIFT),
+ GRP("rgmii1", rgmii1_grp, 1, MT7621_GPIO_MODE_RGMII1),
+ { 0 }
+};
+
+void __init ralink_clk_init(void)
+{
+ int cpu_fdiv = 0;
+ int cpu_ffrac = 0;
+ int fbdiv = 0;
+ u32 clk_sts, syscfg;
+ u8 clk_sel = 0, xtal_mode;
+ u32 cpu_clk;
+
+ if ((rt_sysc_r32(SYSC_REG_CPLL_CLKCFG0) & CPU_CLK_SEL) != 0)
+ clk_sel = 1;
+
+ switch (clk_sel) {
+ case 0:
+ clk_sts = rt_sysc_r32(SYSC_REG_CUR_CLK_STS);
+ cpu_fdiv = ((clk_sts >> 8) & 0x1F);
+ cpu_ffrac = (clk_sts & 0x1F);
+ cpu_clk = (500 * cpu_ffrac / cpu_fdiv) * 1000 * 1000;
+ printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
+ break;
+
+ case 1:
+ fbdiv = ((rt_sysc_r32(0x648) >> 4) & 0x7F) + 1;
+ syscfg = rt_sysc_r32(SYSC_REG_SYSCFG);
+ xtal_mode = (syscfg >> 6) & 0x7;
+ printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
+ if(xtal_mode >= 6) { //25Mhz Xtal
+ printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
+ cpu_clk = 25 * fbdiv * 1000 * 1000;
+ } else if(xtal_mode >=3) { //40Mhz Xtal
+ printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
+ cpu_clk = 40 * fbdiv * 1000 * 1000;
+ } else { // 20Mhz Xtal
+ printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
+ cpu_clk = 20 * fbdiv * 1000 * 1000;
+ }
+ break;
+ }
+ cpu_clk = 880000000;
+ ralink_clk_add("cpu", cpu_clk);
+ ralink_clk_add("1e000b00.spi", 50000000);
+ ralink_clk_add("1e000c00.uartlite", 50000000);
+}
+
+void __init ralink_of_remap(void)
+{
+ rt_sysc_membase = plat_of_remap_node("mtk,mt7621-sysc");
+ rt_memc_membase = plat_of_remap_node("mtk,mt7621-memc");
+
+ if (!rt_sysc_membase || !rt_memc_membase)
+ panic("Failed to remap core resources");
+}
+
+void prom_soc_init(struct ralink_soc_info *soc_info)
+{
+ void __iomem *sysc = (void __iomem *) KSEG1ADDR(MT7621_SYSC_BASE);
+ unsigned char *name = NULL;
+ u32 n0;
+ u32 n1;
+ u32 rev;
+
+ n0 = __raw_readl(sysc + SYSC_REG_CHIP_NAME0);
+ n1 = __raw_readl(sysc + SYSC_REG_CHIP_NAME1);
+
+ if (n0 == MT7621_CHIP_NAME0 && n1 == MT7621_CHIP_NAME1) {
+ name = "MT7621";
+ soc_info->compatible = "mtk,mt7621-soc";
+ } else {
+ panic("mt7621: unknown SoC, n0:%08x n1:%08x\n", n0, n1);
+ }
+
+ rev = __raw_readl(sysc + SYSC_REG_CHIP_REV);
+
+ snprintf(soc_info->sys_type, RAMIPS_SYS_TYPE_LEN,
+ "Mediatek %s ver:%u eco:%u",
+ name,
+ (rev >> CHIP_REV_VER_SHIFT) & CHIP_REV_VER_MASK,
+ (rev & CHIP_REV_ECO_MASK));
+
+ soc_info->mem_size_min = MT7621_DDR2_SIZE_MIN;
+ soc_info->mem_size_max = MT7621_DDR2_SIZE_MAX;
+ soc_info->mem_base = MT7621_DRAM_BASE;
+
+ rt2880_pinmux_data = mt7621_pinmux_data;
+
+ if (register_cmp_smp_ops())
+ panic("failed to register_vsmp_smp_ops()");
+}

@ -0,0 +1,39 @@
From 643e61b22155cd95ae6e18e57da50acd120da091 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Mon, 2 Dec 2013 16:11:33 +0100
Subject: [PATCH 503/507] MIPS: ralink: add MT7621 early_printk support
Signed-off-by: John Crispin <blogic@openwrt.org>
---
arch/mips/ralink/early_printk.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
Index: linux-3.10.21/arch/mips/ralink/early_printk.c
===================================================================
--- linux-3.10.21.orig/arch/mips/ralink/early_printk.c 2013-11-29 20:12:03.000000000 +0100
+++ linux-3.10.21/arch/mips/ralink/early_printk.c 2013-12-09 20:11:51.600704498 +0100
@@ -13,6 +13,8 @@
#ifdef CONFIG_SOC_RT288X
#define EARLY_UART_BASE 0x300c00
+#elif defined(CONFIG_SOC_MT7621)
+#define EARLY_UART_BASE 0x1E000c00
#else
#define EARLY_UART_BASE 0x10000c00
#endif
@@ -40,9 +42,13 @@
void prom_putchar(unsigned char ch)
{
- while ((uart_r32(UART_REG_LSR) & UART_LSR_THRE) == 0)
+#ifdef CONFIG_SOC_MT7621
+ uart_w32(ch, UART_TX);
+ while ((uart_r32(0x14) & UART_LSR_THRE) == 0)
;
- uart_w32(ch, UART_REG_TX);
+#else
while ((uart_r32(UART_REG_LSR) & UART_LSR_THRE) == 0)
;
+ uart_w32(ch, UART_REG_TX);
+#endif
}

@ -0,0 +1,830 @@
From 50216a5b7b3cc269043e7123db4bea262e35364e Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Mon, 2 Dec 2013 16:13:40 +0100
Subject: [PATCH 504/507] MIPS: ralink: add pcie driver
Signed-off-by: John Crispin <blogic@openwrt.org>
---
arch/mips/pci/Makefile | 1 +
arch/mips/pci/pci-mt7621.c | 797 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 798 insertions(+)
create mode 100644 arch/mips/pci/pci-mt7621.c
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
index 719e455..80886fe 100644
--- a/arch/mips/pci/Makefile
+++ b/arch/mips/pci/Makefile
@@ -42,6 +42,7 @@ obj-$(CONFIG_SNI_RM) += fixup-sni.o ops-sni.o
obj-$(CONFIG_LANTIQ) += fixup-lantiq.o
obj-$(CONFIG_PCI_LANTIQ) += pci-lantiq.o ops-lantiq.o
obj-$(CONFIG_SOC_RT3883) += pci-rt3883.o
+obj-$(CONFIG_SOC_MT7621) += pci-mt7621.o
obj-$(CONFIG_TANBAC_TB0219) += fixup-tb0219.o
obj-$(CONFIG_TANBAC_TB0226) += fixup-tb0226.o
obj-$(CONFIG_TANBAC_TB0287) += fixup-tb0287.o
diff --git a/arch/mips/pci/pci-mt7621.c b/arch/mips/pci/pci-mt7621.c
new file mode 100644
index 0000000..0b58fce
--- /dev/null
+++ b/arch/mips/pci/pci-mt7621.c
@@ -0,0 +1,797 @@
+/**************************************************************************
+ *
+ * BRIEF MODULE DESCRIPTION
+ * PCI init for Ralink RT2880 solution
+ *
+ * Copyright 2007 Ralink Inc. (bruce_chang@ralinktech.com.tw)
+ *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ **************************************************************************
+ * May 2007 Bruce Chang
+ * Initial Release
+ *
+ * May 2009 Bruce Chang
+ * support RT2880/RT3883 PCIe
+ *
+ * May 2011 Bruce Chang
+ * support RT6855/MT7620 PCIe
+ *
+ **************************************************************************
+ */
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/version.h>
+#include <asm/pci.h>
+#include <asm/io.h>
+//#include <asm/mach-ralink/eureka_ep430.h>
+#include <linux/init.h>
+#include <linux/mod_devicetable.h>
+#include <linux/delay.h>
+//#include <asm/rt2880/surfboardint.h>
+
+#include <ralink_regs.h>
+
+extern void pcie_phy_init(void);
+extern void chk_phy_pll(void);
+
+/*
+ * These functions and structures provide the BIOS scan and mapping of the PCI
+ * devices.
+ */
+
+#define CONFIG_PCIE_PORT0
+#define CONFIG_PCIE_PORT1
+#define CONFIG_PCIE_PORT2
+#define RALINK_PCIE0_CLK_EN (1<<24)
+#define RALINK_PCIE1_CLK_EN (1<<25)
+#define RALINK_PCIE2_CLK_EN (1<<26)
+
+#define RALINK_PCI_CONFIG_ADDR 0x20
+#define RALINK_PCI_CONFIG_DATA_VIRTUAL_REG 0x24
+#define SURFBOARDINT_PCIE0 12 /* PCIE0 */
+#define RALINK_INT_PCIE0 SURFBOARDINT_PCIE0
+#define RALINK_INT_PCIE1 SURFBOARDINT_PCIE1
+#define RALINK_INT_PCIE2 SURFBOARDINT_PCIE2
+#define SURFBOARDINT_PCIE1 32 /* PCIE1 */
+#define SURFBOARDINT_PCIE2 33 /* PCIE2 */
+#define RALINK_PCI_MEMBASE *(volatile u32 *)(RALINK_PCI_BASE + 0x0028)
+#define RALINK_PCI_IOBASE *(volatile u32 *)(RALINK_PCI_BASE + 0x002C)
+#define RALINK_PCIE0_RST (1<<24)
+#define RALINK_PCIE1_RST (1<<25)
+#define RALINK_PCIE2_RST (1<<26)
+#define RALINK_SYSCTL_BASE 0xBE000000
+
+#define RALINK_PCI_PCICFG_ADDR *(volatile u32 *)(RALINK_PCI_BASE + 0x0000)
+#define RALINK_PCI_PCIMSK_ADDR *(volatile u32 *)(RALINK_PCI_BASE + 0x000C)
+#define RALINK_PCI_BASE 0xBE140000
+
+#define RALINK_PCIEPHY_P0P1_CTL_OFFSET (RALINK_PCI_BASE + 0x9000)
+#define RT6855_PCIE0_OFFSET 0x2000
+#define RT6855_PCIE1_OFFSET 0x3000
+#define RT6855_PCIE2_OFFSET 0x4000
+
+#define RALINK_PCI0_BAR0SETUP_ADDR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0010)
+#define RALINK_PCI0_IMBASEBAR0_ADDR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0018)
+#define RALINK_PCI0_ID *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0030)
+#define RALINK_PCI0_CLASS *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0034)
+#define RALINK_PCI0_SUBID *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0038)
+#define RALINK_PCI0_STATUS *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0050)
+#define RALINK_PCI0_DERR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0060)
+#define RALINK_PCI0_ECRC *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0064)
+
+#define RALINK_PCI1_BAR0SETUP_ADDR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0010)
+#define RALINK_PCI1_IMBASEBAR0_ADDR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0018)
+#define RALINK_PCI1_ID *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0030)
+#define RALINK_PCI1_CLASS *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0034)
+#define RALINK_PCI1_SUBID *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0038)
+#define RALINK_PCI1_STATUS *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0050)
+#define RALINK_PCI1_DERR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0060)
+#define RALINK_PCI1_ECRC *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0064)
+
+#define RALINK_PCI2_BAR0SETUP_ADDR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0010)
+#define RALINK_PCI2_IMBASEBAR0_ADDR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0018)
+#define RALINK_PCI2_ID *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0030)
+#define RALINK_PCI2_CLASS *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0034)
+#define RALINK_PCI2_SUBID *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0038)
+#define RALINK_PCI2_STATUS *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0050)
+#define RALINK_PCI2_DERR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0060)
+#define RALINK_PCI2_ECRC *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0064)
+
+#define RALINK_PCIEPHY_P0P1_CTL_OFFSET (RALINK_PCI_BASE + 0x9000)
+#define RALINK_PCIEPHY_P2_CTL_OFFSET (RALINK_PCI_BASE + 0xA000)
+
+
+#define MV_WRITE(ofs, data) \
+ *(volatile u32 *)(RALINK_PCI_BASE+(ofs)) = cpu_to_le32(data)
+#define MV_READ(ofs, data) \
+ *(data) = le32_to_cpu(*(volatile u32 *)(RALINK_PCI_BASE+(ofs)))
+#define MV_READ_DATA(ofs) \
+ le32_to_cpu(*(volatile u32 *)(RALINK_PCI_BASE+(ofs)))
+
+#define MV_WRITE_16(ofs, data) \
+ *(volatile u16 *)(RALINK_PCI_BASE+(ofs)) = cpu_to_le16(data)
+#define MV_READ_16(ofs, data) \
+ *(data) = le16_to_cpu(*(volatile u16 *)(RALINK_PCI_BASE+(ofs)))
+
+#define MV_WRITE_8(ofs, data) \
+ *(volatile u8 *)(RALINK_PCI_BASE+(ofs)) = data
+#define MV_READ_8(ofs, data) \
+ *(data) = *(volatile u8 *)(RALINK_PCI_BASE+(ofs))
+
+
+
+#define RALINK_PCI_MM_MAP_BASE 0x60000000
+#define RALINK_PCI_IO_MAP_BASE 0x1e160000
+
+#define RALINK_SYSTEM_CONTROL_BASE 0xbe000000
+#define GPIO_PERST
+#define ASSERT_SYSRST_PCIE(val) do { \
+ if (*(unsigned int *)(0xbe00000c) == 0x00030101) \
+ RALINK_RSTCTRL |= val; \
+ else \
+ RALINK_RSTCTRL &= ~val; \
+ } while(0)
+#define DEASSERT_SYSRST_PCIE(val) do { \
+ if (*(unsigned int *)(0xbe00000c) == 0x00030101) \
+ RALINK_RSTCTRL &= ~val; \
+ else \
+ RALINK_RSTCTRL |= val; \
+ } while(0)
+#define RALINK_SYSCFG1 *(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0x14)
+#define RALINK_CLKCFG1 *(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0x30)
+#define RALINK_RSTCTRL *(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0x34)
+#define RALINK_GPIOMODE *(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0x60)
+#define RALINK_PCIE_CLK_GEN *(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0x7c)
+#define RALINK_PCIE_CLK_GEN1 *(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0x80)
+#define PPLL_CFG1 *(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0x9c)
+#define PPLL_DRV *(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0xa0)
+//RALINK_SYSCFG1 bit
+#define RALINK_PCI_HOST_MODE_EN (1<<7)
+#define RALINK_PCIE_RC_MODE_EN (1<<8)
+//RALINK_RSTCTRL bit
+#define RALINK_PCIE_RST (1<<23)
+#define RALINK_PCI_RST (1<<24)
+//RALINK_CLKCFG1 bit
+#define RALINK_PCI_CLK_EN (1<<19)
+#define RALINK_PCIE_CLK_EN (1<<21)
+//RALINK_GPIOMODE bit
+#define PCI_SLOTx2 (1<<11)
+#define PCI_SLOTx1 (2<<11)
+//MTK PCIE PLL bit
+#define PDRV_SW_SET (1<<31)
+#define LC_CKDRVPD_ (1<<19)
+
+#define MEMORY_BASE 0x0
+int pcie_link_status = 0;
+
+void __inline__ read_config(unsigned long bus, unsigned long dev, unsigned long func, unsigned long reg, unsigned long *val);
+void __inline__ write_config(unsigned long bus, unsigned long dev, unsigned long func, unsigned long reg, unsigned long val);
+
+#define PCI_ACCESS_READ_1 0
+#define PCI_ACCESS_READ_2 1
+#define PCI_ACCESS_READ_4 2
+#define PCI_ACCESS_WRITE_1 3
+#define PCI_ACCESS_WRITE_2 4
+#define PCI_ACCESS_WRITE_4 5
+
+static int config_access(unsigned char access_type, struct pci_bus *bus,
+ unsigned int devfn, unsigned int where, u32 * data)
+{
+ unsigned int slot = PCI_SLOT(devfn);
+ u8 func = PCI_FUNC(devfn);
+ uint32_t address_reg, data_reg;
+ unsigned int address;
+
+ address_reg = RALINK_PCI_CONFIG_ADDR;
+ data_reg = RALINK_PCI_CONFIG_DATA_VIRTUAL_REG;
+
+ address = (((where&0xF00)>>8)<<24) |(bus->number << 16) | (slot << 11) | (func << 8) | (where & 0xfc) | 0x80000000;
+ MV_WRITE(address_reg, address);
+
+ switch(access_type) {
+ case PCI_ACCESS_WRITE_1:
+ MV_WRITE_8(data_reg+(where&0x3), *data);
+ break;
+ case PCI_ACCESS_WRITE_2:
+ MV_WRITE_16(data_reg+(where&0x3), *data);
+ break;
+ case PCI_ACCESS_WRITE_4:
+ MV_WRITE(data_reg, *data);
+ break;
+ case PCI_ACCESS_READ_1:
+ MV_READ_8( data_reg+(where&0x3), data);
+ break;
+ case PCI_ACCESS_READ_2:
+ MV_READ_16(data_reg+(where&0x3), data);
+ break;
+ case PCI_ACCESS_READ_4:
+ MV_READ(data_reg, data);
+ break;
+ default:
+ printk("no specify access type\n");
+ break;
+ }
+ return 0;
+}
+
+static int
+read_config_byte(struct pci_bus *bus, unsigned int devfn, int where, u8 * val)
+{
+ return config_access(PCI_ACCESS_READ_1, bus, devfn, (unsigned int)where, (u32 *)val);
+}
+
+static int
+read_config_word(struct pci_bus *bus, unsigned int devfn, int where, u16 * val)
+{
+ return config_access(PCI_ACCESS_READ_2, bus, devfn, (unsigned int)where, (u32 *)val);
+}
+
+static int
+read_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 * val)
+{
+ return config_access(PCI_ACCESS_READ_4, bus, devfn, (unsigned int)where, (u32 *)val);
+}
+
+static int
+write_config_byte(struct pci_bus *bus, unsigned int devfn, int where, u8 val)
+{
+ if (config_access(PCI_ACCESS_WRITE_1, bus, devfn, (unsigned int)where, (u32 *)&val))
+ return -1;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+write_config_word(struct pci_bus *bus, unsigned int devfn, int where, u16 val)
+{
+ if (config_access(PCI_ACCESS_WRITE_2, bus, devfn, where, (u32 *)&val))
+ return -1;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+write_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 val)
+{
+ if (config_access(PCI_ACCESS_WRITE_4, bus, devfn, where, &val))
+ return -1;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+
+static int
+pci_config_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 * val)
+{
+ switch (size) {
+ case 1:
+ return read_config_byte(bus, devfn, where, (u8 *) val);
+ case 2:
+ return read_config_word(bus, devfn, where, (u16 *) val);
+ default:
+ return read_config_dword(bus, devfn, where, val);
+ }
+}
+
+static int
+pci_config_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val)
+{
+ switch (size) {
+ case 1:
+ return write_config_byte(bus, devfn, where, (u8) val);
+ case 2:
+ return write_config_word(bus, devfn, where, (u16) val);
+ default:
+ return write_config_dword(bus, devfn, where, val);
+ }
+}
+
+struct pci_ops rt2880_pci_ops= {
+ .read = pci_config_read,
+ .write = pci_config_write,
+};
+
+static struct resource rt2880_res_pci_mem1 = {
+ .name = "PCI MEM1",
+ .start = RALINK_PCI_MM_MAP_BASE,
+ .end = (u32)((RALINK_PCI_MM_MAP_BASE + (unsigned char *)0x0fffffff)),
+ .flags = IORESOURCE_MEM,
+};
+static struct resource rt2880_res_pci_io1 = {
+ .name = "PCI I/O1",
+ .start = RALINK_PCI_IO_MAP_BASE,
+ .end = (u32)((RALINK_PCI_IO_MAP_BASE + (unsigned char *)0x0ffff)),
+ .flags = IORESOURCE_IO,
+};
+
+struct pci_controller rt2880_controller = {
+ .pci_ops = &rt2880_pci_ops,
+ .mem_resource = &rt2880_res_pci_mem1,
+ .io_resource = &rt2880_res_pci_io1,
+ .mem_offset = 0x00000000UL,
+ .io_offset = 0x00000000UL,
+ .io_map_base = 0xa0000000,
+};
+
+void __inline__
+read_config(unsigned long bus, unsigned long dev, unsigned long func, unsigned long reg, unsigned long *val)
+{
+ unsigned int address_reg, data_reg, address;
+
+ address_reg = RALINK_PCI_CONFIG_ADDR;
+ data_reg = RALINK_PCI_CONFIG_DATA_VIRTUAL_REG;
+ address = (((reg & 0xF00)>>8)<<24) | (bus << 16) | (dev << 11) | (func << 8) | (reg & 0xfc) | 0x80000000 ;
+ MV_WRITE(address_reg, address);
+ MV_READ(data_reg, val);
+ return;
+}
+
+void __inline__
+write_config(unsigned long bus, unsigned long dev, unsigned long func, unsigned long reg, unsigned long val)
+{
+ unsigned int address_reg, data_reg, address;
+
+ address_reg = RALINK_PCI_CONFIG_ADDR;
+ data_reg = RALINK_PCI_CONFIG_DATA_VIRTUAL_REG;
+ address = (((reg & 0xF00)>>8)<<24) | (bus << 16) | (dev << 11) | (func << 8) | (reg & 0xfc) | 0x80000000 ;
+ MV_WRITE(address_reg, address);
+ MV_WRITE(data_reg, val);
+ return;
+}
+
+
+int __init
+pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+ u16 cmd;
+ u32 val;
+ int irq = 0;
+
+ if ((dev->bus->number == 0) && (slot == 0)) {
+ write_config(0, 0, 0, PCI_BASE_ADDRESS_0, MEMORY_BASE);
+ read_config(0, 0, 0, PCI_BASE_ADDRESS_0, (unsigned long *)&val);
+ printk("BAR0 at slot 0 = %x\n", val);
+ printk("bus=0x%x, slot = 0x%x\n",dev->bus->number, slot);
+ } else if((dev->bus->number == 0) && (slot == 0x1)) {
+ write_config(0, 1, 0, PCI_BASE_ADDRESS_0, MEMORY_BASE);
+ read_config(0, 1, 0, PCI_BASE_ADDRESS_0, (unsigned long *)&val);
+ printk("BAR0 at slot 1 = %x\n", val);
+ printk("bus=0x%x, slot = 0x%x\n",dev->bus->number, slot);
+ } else if((dev->bus->number == 0) && (slot == 0x2)) {
+ write_config(0, 2, 0, PCI_BASE_ADDRESS_0, MEMORY_BASE);
+ read_config(0, 2, 0, PCI_BASE_ADDRESS_0, (unsigned long *)&val);
+ printk("BAR0 at slot 2 = %x\n", val);
+ printk("bus=0x%x, slot = 0x%x\n",dev->bus->number, slot);
+ } else if ((dev->bus->number == 1) && (slot == 0x0)) {
+ switch (pcie_link_status) {
+ case 2:
+ case 6:
+ irq = RALINK_INT_PCIE1;
+ break;
+ case 4:
+ irq = RALINK_INT_PCIE2;
+ break;
+ default:
+ irq = RALINK_INT_PCIE0;
+ }
+ printk("bus=0x%x, slot = 0x%x, irq=0x%x\n",dev->bus->number, slot, dev->irq);
+ } else if ((dev->bus->number == 2) && (slot == 0x0)) {
+ switch (pcie_link_status) {
+ case 5:
+ case 6:
+ irq = RALINK_INT_PCIE2;
+ break;
+ default:
+ irq = RALINK_INT_PCIE1;
+ }
+ printk("bus=0x%x, slot = 0x%x, irq=0x%x\n",dev->bus->number, slot, dev->irq);
+ } else if ((dev->bus->number == 2) && (slot == 0x1)) {
+ switch (pcie_link_status) {
+ case 5:
+ case 6:
+ irq = RALINK_INT_PCIE2;
+ break;
+ default:
+ irq = RALINK_INT_PCIE1;
+ }
+ printk("bus=0x%x, slot = 0x%x, irq=0x%x\n",dev->bus->number, slot, dev->irq);
+ } else if ((dev->bus->number ==3) && (slot == 0x0)) {
+ irq = RALINK_INT_PCIE2;
+ printk("bus=0x%x, slot = 0x%x, irq=0x%x\n",dev->bus->number, slot, dev->irq);
+ } else if ((dev->bus->number ==3) && (slot == 0x1)) {
+ irq = RALINK_INT_PCIE2;
+ printk("bus=0x%x, slot = 0x%x, irq=0x%x\n",dev->bus->number, slot, dev->irq);
+ } else if ((dev->bus->number ==3) && (slot == 0x2)) {
+ irq = RALINK_INT_PCIE2;
+ printk("bus=0x%x, slot = 0x%x, irq=0x%x\n",dev->bus->number, slot, dev->irq);
+ } else {
+ printk("bus=0x%x, slot = 0x%x\n",dev->bus->number, slot);
+ return 0;
+ }
+
+ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0x14); //configure cache line size 0x14
+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xFF); //configure latency timer 0x10
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+ cmd = cmd | PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
+ return irq;
+}
+
+void
+set_pcie_phy(u32 *addr, int start_b, int bits, int val)
+{
+// printk("0x%p:", addr);
+// printk(" %x", *addr);
+ *(unsigned int *)(addr) &= ~(((1<<bits) - 1)<<start_b);
+ *(unsigned int *)(addr) |= val << start_b;
+// printk(" -> %x\n", *addr);
+}
+
+void
+bypass_pipe_rst(void)
+{
+#if defined (CONFIG_PCIE_PORT0)
+ /* PCIe Port 0 */
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x02c), 12, 1, 0x01); // rg_pe1_pipe_rst_b
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x02c), 4, 1, 0x01); // rg_pe1_pipe_cmd_frc[4]
+#endif
+#if defined (CONFIG_PCIE_PORT1)
+ /* PCIe Port 1 */
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x12c), 12, 1, 0x01); // rg_pe1_pipe_rst_b
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x12c), 4, 1, 0x01); // rg_pe1_pipe_cmd_frc[4]
+#endif
+#if defined (CONFIG_PCIE_PORT2)
+ /* PCIe Port 2 */
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x02c), 12, 1, 0x01); // rg_pe1_pipe_rst_b
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x02c), 4, 1, 0x01); // rg_pe1_pipe_cmd_frc[4]
+#endif
+}
+
+void
+set_phy_for_ssc(void)
+{
+ unsigned long reg = (*(volatile u32 *)(RALINK_SYSCTL_BASE + 0x10));
+
+ reg = (reg >> 6) & 0x7;
+#if defined (CONFIG_PCIE_PORT0) || defined (CONFIG_PCIE_PORT1)
+ /* Set PCIe Port0 & Port1 PHY to disable SSC */
+ /* Debug Xtal Type */
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x400), 8, 1, 0x01); // rg_pe1_frc_h_xtal_type
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x400), 9, 2, 0x00); // rg_pe1_h_xtal_type
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x000), 4, 1, 0x01); // rg_pe1_frc_phy_en //Force Port 0 enable control
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x100), 4, 1, 0x01); // rg_pe1_frc_phy_en //Force Port 1 enable control
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x000), 5, 1, 0x00); // rg_pe1_phy_en //Port 0 disable
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x100), 5, 1, 0x00); // rg_pe1_phy_en //Port 1 disable
+ if(reg <= 5 && reg >= 3) { // 40MHz Xtal
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 6, 2, 0x01); // RG_PE1_H_PLL_PREDIV //Pre-divider ratio (for host mode)
+ printk("***** Xtal 40MHz *****\n");
+ } else { // 25MHz | 20MHz Xtal
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 6, 2, 0x00); // RG_PE1_H_PLL_PREDIV //Pre-divider ratio (for host mode)
+ if (reg >= 6) {
+ printk("***** Xtal 25MHz *****\n");
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4bc), 4, 2, 0x01); // RG_PE1_H_PLL_FBKSEL //Feedback clock select
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x49c), 0,31, 0x18000000); // RG_PE1_H_LCDDS_PCW_NCPO //DDS NCPO PCW (for host mode)
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4a4), 0,16, 0x18d); // RG_PE1_H_LCDDS_SSC_PRD //DDS SSC dither period control
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4a8), 0,12, 0x4a); // RG_PE1_H_LCDDS_SSC_DELTA //DDS SSC dither amplitude control
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4a8), 16,12, 0x4a); // RG_PE1_H_LCDDS_SSC_DELTA1 //DDS SSC dither amplitude control for initial
+ } else {
+ printk("***** Xtal 20MHz *****\n");
+ }
+ }
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4a0), 5, 1, 0x01); // RG_PE1_LCDDS_CLK_PH_INV //DDS clock inversion
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 22, 2, 0x02); // RG_PE1_H_PLL_BC
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 18, 4, 0x06); // RG_PE1_H_PLL_BP
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 12, 4, 0x02); // RG_PE1_H_PLL_IR
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 8, 4, 0x01); // RG_PE1_H_PLL_IC
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4ac), 16, 3, 0x00); // RG_PE1_H_PLL_BR
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 1, 3, 0x02); // RG_PE1_PLL_DIVEN
+ if(reg <= 5 && reg >= 3) { // 40MHz Xtal
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x414), 6, 2, 0x01); // rg_pe1_mstckdiv //value of da_pe1_mstckdiv when force mode enable
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x414), 5, 1, 0x01); // rg_pe1_frc_mstckdiv //force mode enable of da_pe1_mstckdiv
+ }
+ /* Enable PHY and disable force mode */
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x000), 5, 1, 0x01); // rg_pe1_phy_en //Port 0 enable
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x100), 5, 1, 0x01); // rg_pe1_phy_en //Port 1 enable
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x000), 4, 1, 0x00); // rg_pe1_frc_phy_en //Force Port 0 disable control
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x100), 4, 1, 0x00); // rg_pe1_frc_phy_en //Force Port 1 disable control
+#endif
+#if defined (CONFIG_PCIE_PORT2)
+ /* Set PCIe Port2 PHY to disable SSC */
+ /* Debug Xtal Type */
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x400), 8, 1, 0x01); // rg_pe1_frc_h_xtal_type
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x400), 9, 2, 0x00); // rg_pe1_h_xtal_type
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x000), 4, 1, 0x01); // rg_pe1_frc_phy_en //Force Port 0 enable control
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x000), 5, 1, 0x00); // rg_pe1_phy_en //Port 0 disable
+ if(reg <= 5 && reg >= 3) { // 40MHz Xtal
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 6, 2, 0x01); // RG_PE1_H_PLL_PREDIV //Pre-divider ratio (for host mode)
+ } else { // 25MHz | 20MHz Xtal
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 6, 2, 0x00); // RG_PE1_H_PLL_PREDIV //Pre-divider ratio (for host mode)
+ if (reg >= 6) { // 25MHz Xtal
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4bc), 4, 2, 0x01); // RG_PE1_H_PLL_FBKSEL //Feedback clock select
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x49c), 0,31, 0x18000000); // RG_PE1_H_LCDDS_PCW_NCPO //DDS NCPO PCW (for host mode)
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4a4), 0,16, 0x18d); // RG_PE1_H_LCDDS_SSC_PRD //DDS SSC dither period control
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4a8), 0,12, 0x4a); // RG_PE1_H_LCDDS_SSC_DELTA //DDS SSC dither amplitude control
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4a8), 16,12, 0x4a); // RG_PE1_H_LCDDS_SSC_DELTA1 //DDS SSC dither amplitude control for initial
+ }
+ }
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4a0), 5, 1, 0x01); // RG_PE1_LCDDS_CLK_PH_INV //DDS clock inversion
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 22, 2, 0x02); // RG_PE1_H_PLL_BC
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 18, 4, 0x06); // RG_PE1_H_PLL_BP
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 12, 4, 0x02); // RG_PE1_H_PLL_IR
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 8, 4, 0x01); // RG_PE1_H_PLL_IC
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4ac), 16, 3, 0x00); // RG_PE1_H_PLL_BR
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 1, 3, 0x02); // RG_PE1_PLL_DIVEN
+ if(reg <= 5 && reg >= 3) { // 40MHz Xtal
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x414), 6, 2, 0x01); // rg_pe1_mstckdiv //value of da_pe1_mstckdiv when force mode enable
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x414), 5, 1, 0x01); // rg_pe1_frc_mstckdiv //force mode enable of da_pe1_mstckdiv
+ }
+ /* Enable PHY and disable force mode */
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x000), 5, 1, 0x01); // rg_pe1_phy_en //Port 0 enable
+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x000), 4, 1, 0x00); // rg_pe1_frc_phy_en //Force Port 0 disable control
+#endif
+}
+
+int init_rt2880pci(void)
+{
+ unsigned long val = 0;
+ iomem_resource.start = 0;
+ iomem_resource.end= ~0;
+ ioport_resource.start= 0;
+ ioport_resource.end = ~0;
+
+#if defined (CONFIG_PCIE_PORT0)
+ val = RALINK_PCIE0_RST;
+#endif
+#if defined (CONFIG_PCIE_PORT1)
+ val |= RALINK_PCIE1_RST;
+#endif
+#if defined (CONFIG_PCIE_PORT2)
+ val |= RALINK_PCIE2_RST;
+#endif
+ DEASSERT_SYSRST_PCIE(val);
+ printk("release PCIe RST: RALINK_RSTCTRL = %x\n", RALINK_RSTCTRL);
+
+ bypass_pipe_rst();
+ set_phy_for_ssc();
+ ASSERT_SYSRST_PCIE(RALINK_PCIE0_RST | RALINK_PCIE1_RST | RALINK_PCIE2_RST);
+ printk("pull PCIe RST: RALINK_RSTCTRL = %x\n", RALINK_RSTCTRL);
+#if defined GPIO_PERST /* add GPIO control instead of PERST_N */ /*chhung*/
+ *(unsigned int *)(0xbe000060) &= ~(0x3<<10 | 0x3<<3);
+ *(unsigned int *)(0xbe000060) |= 0x1<<10 | 0x1<<3;
+ mdelay(100);
+ *(unsigned int *)(0xbe000600) |= 0x1<<19 | 0x1<<8 | 0x1<<7; // use GPIO19/GPIO8/GPIO7 (PERST_N/UART_RXD3/UART_TXD3)
+ mdelay(100);
+ *(unsigned int *)(0xbe000620) &= ~(0x1<<19 | 0x1<<8 | 0x1<<7); // clear DATA
+
+ mdelay(100);
+#else
+ *(unsigned int *)(0xbe000060) &= ~0x00000c00;
+#endif
+#if defined (CONFIG_PCIE_PORT0)
+ val = RALINK_PCIE0_RST;
+#endif
+#if defined (CONFIG_PCIE_PORT1)
+ val |= RALINK_PCIE1_RST;
+#endif
+#if defined (CONFIG_PCIE_PORT2)
+ val |= RALINK_PCIE2_RST;
+#endif
+ DEASSERT_SYSRST_PCIE(val);
+ printk("release PCIe RST: RALINK_RSTCTRL = %x\n", RALINK_RSTCTRL);
+#if defined (CONFIG_PCIE_PORT0)
+ read_config(0, 0, 0, 0x70c, &val);
+ val &= ~(0xff)<<8;
+ val |= 0x50<<8;
+ write_config(0, 0, 0, 0x70c, val);
+#endif
+#if defined (CONFIG_PCIE_PORT1)
+ read_config(0, 1, 0, 0x70c, &val);
+ val &= ~(0xff)<<8;
+ val |= 0x50<<8;
+ write_config(0, 1, 0, 0x70c, val);
+#endif
+#if defined (CONFIG_PCIE_PORT2)
+ read_config(0, 2, 0, 0x70c, &val);
+ val &= ~(0xff)<<8;
+ val |= 0x50<<8;
+ write_config(0, 2, 0, 0x70c, val);
+#endif
+
+#if defined (CONFIG_PCIE_PORT0)
+ read_config(0, 0, 0, 0x70c, &val);
+ printk("Port 0 N_FTS = %x\n", (unsigned int)val);
+#endif
+#if defined (CONFIG_PCIE_PORT1)
+ read_config(0, 1, 0, 0x70c, &val);
+ printk("Port 1 N_FTS = %x\n", (unsigned int)val);
+#endif
+#if defined (CONFIG_PCIE_PORT2)
+ read_config(0, 2, 0, 0x70c, &val);
+ printk("Port 2 N_FTS = %x\n", (unsigned int)val);
+#endif
+
+ RALINK_RSTCTRL = (RALINK_RSTCTRL | RALINK_PCIE_RST);
+ RALINK_SYSCFG1 &= ~(0x30);
+ RALINK_SYSCFG1 |= (2<<4);
+ RALINK_PCIE_CLK_GEN &= 0x7fffffff;
+ RALINK_PCIE_CLK_GEN1 &= 0x80ffffff;
+ RALINK_PCIE_CLK_GEN1 |= 0xa << 24;
+ RALINK_PCIE_CLK_GEN |= 0x80000000;
+ mdelay(50);
+ RALINK_RSTCTRL = (RALINK_RSTCTRL & ~RALINK_PCIE_RST);
+
+
+#if defined GPIO_PERST /* add GPIO control instead of PERST_N */ /*chhung*/
+ *(unsigned int *)(0xbe000620) |= 0x1<<19 | 0x1<<8 | 0x1<<7; // set DATA
+ mdelay(100);
+#else
+ RALINK_PCI_PCICFG_ADDR &= ~(1<<1); //de-assert PERST
+#endif
+ mdelay(500);
+
+
+ mdelay(500);
+#if defined (CONFIG_PCIE_PORT0)
+ if(( RALINK_PCI0_STATUS & 0x1) == 0)
+ {
+ printk("PCIE0 no card, disable it(RST&CLK)\n");
+ ASSERT_SYSRST_PCIE(RALINK_PCIE0_RST);
+ RALINK_CLKCFG1 = (RALINK_CLKCFG1 & ~RALINK_PCIE0_CLK_EN);
+ pcie_link_status &= ~(1<<0);
+ } else {
+ pcie_link_status |= 1<<0;
+ RALINK_PCI_PCIMSK_ADDR |= (1<<20); // enable pcie1 interrupt
+ }
+#endif
+#if defined (CONFIG_PCIE_PORT1)
+ if(( RALINK_PCI1_STATUS & 0x1) == 0)
+ {
+ printk("PCIE1 no card, disable it(RST&CLK)\n");
+ ASSERT_SYSRST_PCIE(RALINK_PCIE1_RST);
+ RALINK_CLKCFG1 = (RALINK_CLKCFG1 & ~RALINK_PCIE1_CLK_EN);
+ pcie_link_status &= ~(1<<1);
+ } else {
+ pcie_link_status |= 1<<1;
+ RALINK_PCI_PCIMSK_ADDR |= (1<<21); // enable pcie1 interrupt
+ }
+#endif
+#if defined (CONFIG_PCIE_PORT2)
+ if (( RALINK_PCI2_STATUS & 0x1) == 0) {
+ printk("PCIE2 no card, disable it(RST&CLK)\n");
+ ASSERT_SYSRST_PCIE(RALINK_PCIE2_RST);
+ RALINK_CLKCFG1 = (RALINK_CLKCFG1 & ~RALINK_PCIE2_CLK_EN);
+ pcie_link_status &= ~(1<<2);
+ } else {
+ pcie_link_status |= 1<<2;
+ RALINK_PCI_PCIMSK_ADDR |= (1<<22); // enable pcie2 interrupt
+ }
+#endif
+ if (pcie_link_status == 0)
+ return 0;
+
+/*
+pcie(2/1/0) link status pcie2_num pcie1_num pcie0_num
+3'b000 x x x
+3'b001 x x 0
+3'b010 x 0 x
+3'b011 x 1 0
+3'b100 0 x x
+3'b101 1 x 0
+3'b110 1 0 x
+3'b111 2 1 0
+*/
+ switch(pcie_link_status) {
+ case 2:
+ RALINK_PCI_PCICFG_ADDR &= ~0x00ff0000;
+ RALINK_PCI_PCICFG_ADDR |= 0x1 << 16; //port0
+ RALINK_PCI_PCICFG_ADDR |= 0x0 << 20; //port1
+ break;
+ case 4:
+ RALINK_PCI_PCICFG_ADDR &= ~0x0fff0000;
+ RALINK_PCI_PCICFG_ADDR |= 0x1 << 16; //port0
+ RALINK_PCI_PCICFG_ADDR |= 0x2 << 20; //port1
+ RALINK_PCI_PCICFG_ADDR |= 0x0 << 24; //port2
+ break;
+ case 5:
+ RALINK_PCI_PCICFG_ADDR &= ~0x0fff0000;
+ RALINK_PCI_PCICFG_ADDR |= 0x0 << 16; //port0
+ RALINK_PCI_PCICFG_ADDR |= 0x2 << 20; //port1
+ RALINK_PCI_PCICFG_ADDR |= 0x1 << 24; //port2
+ break;
+ case 6:
+ RALINK_PCI_PCICFG_ADDR &= ~0x0fff0000;
+ RALINK_PCI_PCICFG_ADDR |= 0x2 << 16; //port0
+ RALINK_PCI_PCICFG_ADDR |= 0x0 << 20; //port1
+ RALINK_PCI_PCICFG_ADDR |= 0x1 << 24; //port2
+ break;
+ }
+ printk(" -> %x\n", RALINK_PCI_PCICFG_ADDR);
+ //printk(" RALINK_PCI_ARBCTL = %x\n", RALINK_PCI_ARBCTL);
+
+/*
+ ioport_resource.start = rt2880_res_pci_io1.start;
+ ioport_resource.end = rt2880_res_pci_io1.end;
+*/
+
+ RALINK_PCI_MEMBASE = 0xffffffff; //RALINK_PCI_MM_MAP_BASE;
+ RALINK_PCI_IOBASE = RALINK_PCI_IO_MAP_BASE;
+
+#if defined (CONFIG_PCIE_PORT0)
+ //PCIe0
+ if((pcie_link_status & 0x1) != 0) {
+ RALINK_PCI0_BAR0SETUP_ADDR = 0x7FFF0001; //open 7FFF:2G; ENABLE
+ RALINK_PCI0_IMBASEBAR0_ADDR = MEMORY_BASE;
+ RALINK_PCI0_CLASS = 0x06040001;
+ printk("PCIE0 enabled\n");
+ }
+#endif
+#if defined (CONFIG_PCIE_PORT1)
+ //PCIe1
+ if ((pcie_link_status & 0x2) != 0) {
+ RALINK_PCI1_BAR0SETUP_ADDR = 0x7FFF0001; //open 7FFF:2G; ENABLE
+ RALINK_PCI1_IMBASEBAR0_ADDR = MEMORY_BASE;
+ RALINK_PCI1_CLASS = 0x06040001;
+ printk("PCIE1 enabled\n");
+ }
+#endif
+#if defined (CONFIG_PCIE_PORT2)
+ //PCIe2
+ if ((pcie_link_status & 0x4) != 0) {
+ RALINK_PCI2_BAR0SETUP_ADDR = 0x7FFF0001; //open 7FFF:2G; ENABLE
+ RALINK_PCI2_IMBASEBAR0_ADDR = MEMORY_BASE;
+ RALINK_PCI2_CLASS = 0x06040001;
+ printk("PCIE2 enabled\n");
+ }
+#endif
+
+
+ switch(pcie_link_status) {
+ case 7:
+ read_config(0, 2, 0, 0x4, &val);
+ write_config(0, 2, 0, 0x4, val|0x4);
+ // write_config(0, 1, 0, 0x4, val|0x7);
+ case 3:
+ case 5:
+ case 6:
+ read_config(0, 1, 0, 0x4, &val);
+ write_config(0, 1, 0, 0x4, val|0x4);
+ // write_config(0, 1, 0, 0x4, val|0x7);
+ default:
+ read_config(0, 0, 0, 0x4, &val);
+ write_config(0, 0, 0, 0x4, val|0x4); //bus master enable
+ // write_config(0, 0, 0, 0x4, val|0x7); //bus master enable
+ }
+ register_pci_controller(&rt2880_controller);
+ return 0;
+
+}
+arch_initcall(init_rt2880pci);
+
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ return 0;
+}
--
1.7.10.4

@ -0,0 +1,235 @@
From eb50d97682d78af68388d24956a74de4ab751cf7 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Mon, 2 Dec 2013 16:18:36 +0100
Subject: [PATCH 505/507] watchdog: add MT7621 support
Signed-off-by: John Crispin <blogic@openwrt.org>
---
drivers/watchdog/Kconfig | 7 ++
drivers/watchdog/Makefile | 1 +
drivers/watchdog/mt7621_wdt.c | 185 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 193 insertions(+)
create mode 100644 drivers/watchdog/mt7621_wdt.c
Index: linux-3.10.21/drivers/watchdog/Kconfig
===================================================================
--- linux-3.10.21.orig/drivers/watchdog/Kconfig 2013-12-09 19:56:09.360682007 +0100
+++ linux-3.10.21/drivers/watchdog/Kconfig 2013-12-09 19:59:20.636686594 +0100
@@ -1116,7 +1116,14 @@
config RALINK_WDT
tristate "Ralink SoC watchdog"
select WATCHDOG_CORE
- depends on RALINK
+ depends on RALINK && !SOC_MT7621
+ help
+ Hardware driver for the Ralink SoC Watchdog Timer.
+
+config MT7621_WDT
+ tristate "Mediatek SoC watchdog"
+ select WATCHDOG_CORE
+ depends on RALINK && SOC_MT7621
help
Hardware driver for the Ralink SoC Watchdog Timer.
Index: linux-3.10.21/drivers/watchdog/Makefile
===================================================================
--- linux-3.10.21.orig/drivers/watchdog/Makefile 2013-12-09 19:56:09.360682007 +0100
+++ linux-3.10.21/drivers/watchdog/Makefile 2013-12-09 19:56:09.752682016 +0100
@@ -136,6 +136,7 @@
octeon-wdt-y := octeon-wdt-main.o octeon-wdt-nmi.o
obj-$(CONFIG_LANTIQ_WDT) += lantiq_wdt.o
obj-$(CONFIG_RALINK_WDT) += rt2880_wdt.o
+obj-$(CONFIG_MT7621_WDT) += mt7621_wdt.o
# PARISC Architecture
Index: linux-3.10.21/drivers/watchdog/mt7621_wdt.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-3.10.21/drivers/watchdog/mt7621_wdt.c 2013-12-09 19:56:09.752682016 +0100
@@ -0,0 +1,185 @@
+/*
+ * Ralink RT288x/RT3xxx/MT76xx built-in hardware watchdog timer
+ *
+ * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
+ * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ *
+ * This driver was based on: drivers/watchdog/softdog.c
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/reset.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/watchdog.h>
+#include <linux/miscdevice.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach-ralink/ralink_regs.h>
+
+#define SYSC_RSTSTAT 0x38
+#define WDT_RST_CAUSE BIT(1)
+
+#define RALINK_WDT_TIMEOUT 30
+
+#define TIMER_REG_TMRSTAT 0x00
+#define TIMER_REG_TMR1LOAD 0x24
+#define TIMER_REG_TMR1CTL 0x20
+
+#define TMR1CTL_ENABLE BIT(7)
+#define TMR1CTL_RESTART BIT(9)
+
+static void __iomem *mt762x_wdt_base;
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
+MODULE_PARM_DESC(nowayout,
+ "Watchdog cannot be stopped once started (default="
+ __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+static inline void rt_wdt_w32(unsigned reg, u32 val)
+{
+ iowrite32(val, mt762x_wdt_base + reg);
+}
+
+static inline u32 rt_wdt_r32(unsigned reg)
+{
+ return ioread32(mt762x_wdt_base + reg);
+}
+
+static int mt762x_wdt_ping(struct watchdog_device *w)
+{
+ rt_wdt_w32(TIMER_REG_TMRSTAT, TMR1CTL_RESTART);
+
+ return 0;
+}
+
+static int mt762x_wdt_set_timeout(struct watchdog_device *w, unsigned int t)
+{
+ w->timeout = t;
+ rt_wdt_w32(TIMER_REG_TMR1LOAD, t * 1000);
+ mt762x_wdt_ping(w);
+
+ return 0;
+}
+
+static int mt762x_wdt_start(struct watchdog_device *w)
+{
+ u32 t;
+
+ rt_wdt_w32(TIMER_REG_TMR1CTL, 1000 << 16);
+ mt762x_wdt_set_timeout(w, w->timeout);
+
+ t = rt_wdt_r32(TIMER_REG_TMR1CTL);
+ t |= TMR1CTL_ENABLE;
+ rt_wdt_w32(TIMER_REG_TMR1CTL, t);
+
+ return 0;
+}
+
+static int mt762x_wdt_stop(struct watchdog_device *w)
+{
+ u32 t;
+
+ mt762x_wdt_ping(w);
+
+ t = rt_wdt_r32(TIMER_REG_TMR1CTL);
+ t &= ~TMR1CTL_ENABLE;
+ rt_wdt_w32(TIMER_REG_TMR1CTL, t);
+
+ return 0;
+}
+
+static int mt762x_wdt_bootcause(void)
+{
+ if (rt_sysc_r32(SYSC_RSTSTAT) & WDT_RST_CAUSE)
+ return WDIOF_CARDRESET;
+
+ return 0;
+}
+
+static struct watchdog_info mt762x_wdt_info = {
+ .identity = "Mediatek Watchdog",
+ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+};
+
+static struct watchdog_ops mt762x_wdt_ops = {
+ .owner = THIS_MODULE,
+ .start = mt762x_wdt_start,
+ .stop = mt762x_wdt_stop,
+ .ping = mt762x_wdt_ping,
+ .set_timeout = mt762x_wdt_set_timeout,
+};
+
+static struct watchdog_device mt762x_wdt_dev = {
+ .info = &mt762x_wdt_info,
+ .ops = &mt762x_wdt_ops,
+ .min_timeout = 1,
+};
+
+static int mt762x_wdt_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ int ret;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ mt762x_wdt_base = devm_request_and_ioremap(&pdev->dev, res);
+ if (IS_ERR(mt762x_wdt_base))
+ return PTR_ERR(mt762x_wdt_base);
+
+ device_reset(&pdev->dev);
+
+ mt762x_wdt_dev.dev = &pdev->dev;
+ mt762x_wdt_dev.bootstatus = mt762x_wdt_bootcause();
+ mt762x_wdt_dev.max_timeout = (0xfffful / 1000);
+ mt762x_wdt_dev.timeout = mt762x_wdt_dev.max_timeout;
+
+ watchdog_set_nowayout(&mt762x_wdt_dev, nowayout);
+
+ ret = watchdog_register_device(&mt762x_wdt_dev);
+ if (!ret)
+ dev_info(&pdev->dev, "Initialized\n");
+
+ return 0;
+}
+
+static int mt762x_wdt_remove(struct platform_device *pdev)
+{
+ watchdog_unregister_device(&mt762x_wdt_dev);
+
+ return 0;
+}
+
+static void mt762x_wdt_shutdown(struct platform_device *pdev)
+{
+ mt762x_wdt_stop(&mt762x_wdt_dev);
+}
+
+static const struct of_device_id mt762x_wdt_match[] = {
+ { .compatible = "mtk,mt7621-wdt" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, mt762x_wdt_match);
+
+static struct platform_driver mt762x_wdt_driver = {
+ .probe = mt762x_wdt_probe,
+ .remove = mt762x_wdt_remove,
+ .shutdown = mt762x_wdt_shutdown,
+ .driver = {
+ .name = KBUILD_MODNAME,
+ .owner = THIS_MODULE,
+ .of_match_table = mt762x_wdt_match,
+ },
+};
+
+module_platform_driver(mt762x_wdt_driver);
+
+MODULE_DESCRIPTION("MediaTek MT762x hardware watchdog driver");
+MODULE_AUTHOR("John Crispin <blogic@openwrt.org");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);

@ -0,0 +1,228 @@
From e19957560170d63c6a5f0b1d7ba63695e4d1f033 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Mon, 2 Dec 2013 16:14:28 +0100
Subject: [PATCH 506/507] GPIO: ralink: add mt7621 gpio controller
Signed-off-by: John Crispin <blogic@openwrt.org>
---
arch/mips/Kconfig | 1 +
drivers/gpio/Kconfig | 6 ++
drivers/gpio/Makefile | 1 +
drivers/gpio/gpio-mt7621.c | 183 ++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 191 insertions(+)
create mode 100644 drivers/gpio/gpio-mt7621.c
Index: linux-3.10.21/drivers/gpio/Kconfig
===================================================================
--- linux-3.10.21.orig/drivers/gpio/Kconfig 2013-12-09 19:56:09.376682007 +0100
+++ linux-3.10.21/drivers/gpio/Kconfig 2013-12-09 19:58:35.372685422 +0100
@@ -710,6 +710,12 @@
Enable support for GPIO on intel MSIC controllers found in
intel MID devices
+config GPIO_MT7621
+ bool "Mediatek GPIO Support"
+ depends on RALINK && SOC_MT7621
+ help
+ Say yes here to support the Mediatek SoC GPIO device
+
comment "USB GPIO expanders:"
config GPIO_VIPERBOARD
Index: linux-3.10.21/drivers/gpio/Makefile
===================================================================
--- linux-3.10.21.orig/drivers/gpio/Makefile 2013-12-09 19:56:09.376682007 +0100
+++ linux-3.10.21/drivers/gpio/Makefile 2013-12-09 19:56:09.760682017 +0100
@@ -88,3 +88,4 @@
obj-$(CONFIG_GPIO_WM8350) += gpio-wm8350.o
obj-$(CONFIG_GPIO_WM8994) += gpio-wm8994.o
obj-$(CONFIG_GPIO_XILINX) += gpio-xilinx.o
+obj-$(CONFIG_GPIO_MT7621) += gpio-mt7621.o
Index: linux-3.10.21/drivers/gpio/gpio-mt7621.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-3.10.21/drivers/gpio/gpio-mt7621.c 2013-12-09 19:56:09.760682017 +0100
@@ -0,0 +1,183 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org>
+ * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/of_irq.h>
+#include <linux/spinlock.h>
+#include <linux/irqdomain.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+
+#define MTK_BANK_WIDTH 32
+
+enum mediatek_gpio_reg {
+ GPIO_REG_CTRL = 0,
+ GPIO_REG_POL,
+ GPIO_REG_DATA,
+ GPIO_REG_DSET,
+ GPIO_REG_DCLR,
+};
+
+static void __iomem *mtk_gc_membase;
+
+struct mtk_gc {
+ struct gpio_chip chip;
+ spinlock_t lock;
+ int bank;
+};
+
+int
+gpio_to_irq(unsigned gpio)
+{
+ return -1;
+}
+
+static inline struct mtk_gc
+*to_mediatek_gpio(struct gpio_chip *chip)
+{
+ struct mtk_gc *mgc;
+
+ mgc = container_of(chip, struct mtk_gc, chip);
+
+ return mgc;
+}
+
+static inline void
+mtk_gpio_w32(struct mtk_gc *rg, u8 reg, u32 val)
+{
+ iowrite32(val, mtk_gc_membase + (reg * 0x10) + (rg->bank * 0x4));
+}
+
+static inline u32
+mtk_gpio_r32(struct mtk_gc *rg, u8 reg)
+{
+ return ioread32(mtk_gc_membase + (reg * 0x10) + (rg->bank * 0x4));
+}
+
+static void
+mediatek_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+ struct mtk_gc *rg = to_mediatek_gpio(chip);
+
+ mtk_gpio_w32(rg, (value) ? GPIO_REG_DSET : GPIO_REG_DCLR, BIT(offset));
+}
+
+static int
+mediatek_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+ struct mtk_gc *rg = to_mediatek_gpio(chip);
+
+ return !!(mtk_gpio_r32(rg, GPIO_REG_DATA) & BIT(offset));
+}
+
+static int
+mediatek_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+ struct mtk_gc *rg = to_mediatek_gpio(chip);
+ unsigned long flags;
+ u32 t;
+
+ spin_lock_irqsave(&rg->lock, flags);
+ t = mtk_gpio_r32(rg, GPIO_REG_CTRL);
+ t &= ~BIT(offset);
+ mtk_gpio_w32(rg, GPIO_REG_CTRL, t);
+ spin_unlock_irqrestore(&rg->lock, flags);
+
+ return 0;
+}
+
+static int
+mediatek_gpio_direction_output(struct gpio_chip *chip,
+ unsigned offset, int value)
+{
+ struct mtk_gc *rg = to_mediatek_gpio(chip);
+ unsigned long flags;
+ u32 t;
+
+ spin_lock_irqsave(&rg->lock, flags);
+ t = mtk_gpio_r32(rg, GPIO_REG_CTRL);
+ t |= BIT(offset);
+ mtk_gpio_w32(rg, GPIO_REG_CTRL, t);
+ mediatek_gpio_set(chip, offset, value);
+ spin_unlock_irqrestore(&rg->lock, flags);
+
+ return 0;
+}
+
+static int
+mediatek_gpio_bank_probe(struct platform_device *pdev, struct device_node *bank)
+{
+ const __be32 *id = of_get_property(bank, "reg", NULL);
+ struct mtk_gc *rg = devm_kzalloc(&pdev->dev,
+ sizeof(struct mtk_gc), GFP_KERNEL);
+ if (!rg || !id)
+ return -ENOMEM;
+
+ spin_lock_init(&rg->lock);
+
+ rg->chip.dev = &pdev->dev;
+ rg->chip.label = dev_name(&pdev->dev);
+ rg->chip.of_node = bank;
+ rg->chip.base = MTK_BANK_WIDTH * be32_to_cpu(*id);
+ rg->chip.ngpio = MTK_BANK_WIDTH;
+ rg->chip.direction_input = mediatek_gpio_direction_input;
+ rg->chip.direction_output = mediatek_gpio_direction_output;
+ rg->chip.get = mediatek_gpio_get;
+ rg->chip.set = mediatek_gpio_set;
+
+ /* set polarity to low for all gpios */
+ mtk_gpio_w32(rg, GPIO_REG_POL, 0);
+
+ dev_info(&pdev->dev, "registering %d gpios\n", rg->chip.ngpio);
+
+ return gpiochip_add(&rg->chip);
+}
+
+static int
+mediatek_gpio_probe(struct platform_device *pdev)
+{
+ struct device_node *bank, *np = pdev->dev.of_node;
+ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ mtk_gc_membase = devm_request_and_ioremap(&pdev->dev, res);
+ if (IS_ERR(mtk_gc_membase))
+ return PTR_ERR(mtk_gc_membase);
+
+ for_each_child_of_node(np, bank)
+ if (of_device_is_compatible(bank, "mtk,mt7621-gpio-bank"))
+ mediatek_gpio_bank_probe(pdev, bank);
+
+ return 0;
+}
+
+static const struct of_device_id mediatek_gpio_match[] = {
+ { .compatible = "mtk,mt7621-gpio" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, mediatek_gpio_match);
+
+static struct platform_driver mediatek_gpio_driver = {
+ .probe = mediatek_gpio_probe,
+ .driver = {
+ .name = "mt7621_gpio",
+ .owner = THIS_MODULE,
+ .of_match_table = mediatek_gpio_match,
+ },
+};
+
+static int __init
+mediatek_gpio_init(void)
+{
+ return platform_driver_register(&mediatek_gpio_driver);
+}
+
+subsys_initcall(mediatek_gpio_init);

@ -142,6 +142,7 @@ CONFIG_SERIAL_OF_PLATFORM=y
# CONFIG_SLAB is not set
CONFIG_SLUB=y
# CONFIG_SOC_MT7620 is not set
# CONFIG_SOC_MT7621 is not set
# CONFIG_SOC_RT288X is not set
CONFIG_SOC_RT305X=y
# CONFIG_SOC_RT3883 is not set

@ -150,6 +150,7 @@ CONFIG_SERIAL_OF_PLATFORM=y
# CONFIG_SLAB is not set
CONFIG_SLUB=y
# CONFIG_SOC_MT7620 is not set
# CONFIG_SOC_MT7621 is not set
# CONFIG_SOC_RT288X is not set
# CONFIG_SOC_RT305X is not set
CONFIG_SOC_RT3883=y

Loading…
Cancel
Save