ramips: refresh patches

Removed upstreamed/solved elsewhere upstream:
- 0001-MIPS-ralink-Add-rt3352-SPI_CS1-pinmux.patch
- 0002-MIPS-pci-rt2880-set-pci-controller-of_node.patch
- 0004-MIPS-ralink-add-MT7621-pcie-driver.patch
- 0009-PCI-MIPS-enable-PCIe-on-MT7688.patch
- 0025-pinctrl-ralink-add-pinctrl-driver.patch
- 0028-GPIO-ralink-add-mt7621-gpio-controller.patch
- 0043-spi-add-mt7621-support.patch
- 0045-i2c-add-mt7621-driver.patch
- 0047-DMA-ralink-add-rt2880-dma-engine.patch
- 0053-mtd-spi-nor-add-w25q256-3b-mode-switch.patch
- 0054-mtd-spi-nor-w25q256-respect-default-mode.patch
- 0099-pci-mt7620.patch
- 304-spi-nor-enable-4B-opcodes-for-mx25l25635f.patch

Removed because of the new NAND driver:
- 0038-Revert-mtd-nand-Remove-unused-chip-write_page-hook.patch
- 0039-mtd-add-mt7621-nand-support.patch
- 0040-nand-hack.patch

Remove patch that no longer applies (needs rework):
- 0034-NET-multi-phy-support.patch

Signed-off-by: DENG Qingfang <dengqf6@mail2.sysu.edu.cn>
master
DENG Qingfang 2020-03-01 17:06:45 +08:00 committed by Chuanhong Guo
parent d75c9b8f81
commit 6be0da90a1
44 changed files with 130 additions and 9770 deletions

View File

@ -1,45 +0,0 @@
From 35d017947401d9f449a7e55e52506744e0c62577 Mon Sep 17 00:00:00 2001
From: Mathias Kresin <dev@kresin.me>
Date: Wed, 22 Aug 2018 22:38:06 +0200
Subject: [PATCH] MIPS: ralink: Add rt3352 SPI_CS1 pinmux
The rt3352 has a pin that can be used as second spi chip select,
watchdog reset or GPIO. The pinmux setup was missing the definition of
said pin.
The pin is configured via the same bit on rt5350, so reuse the existing
macro.
Signed-off-by: Mathias Kresin <dev@kresin.me>
Signed-off-by: Paul Burton <paul.burton@mips.com>
Patchwork: https://patchwork.linux-mips.org/patch/20301/
Cc: John Crispin <john@phrozen.org>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: James Hogan <jhogan@kernel.org>
Cc: linux-mips@linux-mips.org
Cc: linux-kernel@vger.kernel.org
---
arch/mips/ralink/rt305x.c | 5 +++++
1 file changed, 5 insertions(+)
--- a/arch/mips/ralink/rt305x.c
+++ b/arch/mips/ralink/rt305x.c
@@ -49,6 +49,10 @@ static struct rt2880_pmx_func rgmii_func
static struct rt2880_pmx_func rt3352_lna_func[] = { FUNC("lna", 0, 36, 2) };
static struct rt2880_pmx_func rt3352_pa_func[] = { FUNC("pa", 0, 38, 2) };
static struct rt2880_pmx_func rt3352_led_func[] = { FUNC("led", 0, 40, 5) };
+static struct rt2880_pmx_func rt3352_cs1_func[] = {
+ FUNC("spi_cs1", 0, 45, 1),
+ FUNC("wdg_cs1", 1, 45, 1),
+};
static struct rt2880_pmx_group rt3050_pinmux_data[] = {
GRP("i2c", i2c_func, 1, RT305X_GPIO_MODE_I2C),
@@ -75,6 +79,7 @@ static struct rt2880_pmx_group rt3352_pi
GRP("lna", rt3352_lna_func, 1, RT3352_GPIO_MODE_LNA),
GRP("pa", rt3352_pa_func, 1, RT3352_GPIO_MODE_PA),
GRP("led", rt3352_led_func, 1, RT5350_GPIO_MODE_PHY_LED),
+ GRP("spi_cs1", rt3352_cs1_func, 2, RT5350_GPIO_MODE_SPI_CS1),
{ 0 }
};

View File

@ -1,32 +0,0 @@
From 0eb1cfffd5433d8dce3e4163a5cd9accc6000856 Mon Sep 17 00:00:00 2001
From: Tobias Wolf <dev-NTEO@vplace.de>
Date: Wed, 5 Sep 2018 08:51:26 +0200
Subject: [PATCH] MIPS: pci-rt2880: set pci controller of_node
Set the PCI controller of_node such that PCI devices can be
instantiated via device tree.
Signed-off-by: Tobias Wolf <dev-NTEO@vplace.de>
Signed-off-by: Mathias Kresin <dev@kresin.me>
Acked-by: John Crispin <john@phrozen.org>
Signed-off-by: Paul Burton <paul.burton@mips.com>
Patchwork: https://patchwork.linux-mips.org/patch/20423/
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: James Hogan <jhogan@kernel.org>
Cc: linux-mips@linux-mips.org
Cc: linux-kernel@vger.kernel.org
---
arch/mips/pci/pci-rt2880.c | 2 ++
1 file changed, 2 insertions(+)
--- a/arch/mips/pci/pci-rt2880.c
+++ b/arch/mips/pci/pci-rt2880.c
@@ -246,6 +246,8 @@ static int rt288x_pci_probe(struct platf
rt2880_pci_write_u32(PCI_BASE_ADDRESS_0, 0x08000000);
(void) rt2880_pci_read_u32(PCI_BASE_ADDRESS_0);
+ rt2880_pci_controller.of_node = pdev->dev.of_node;
+
register_pci_controller(&rt2880_pci_controller);
return 0;
}

View File

@ -16,27 +16,27 @@ Signed-off-by: Tobias Wolf <dev-NTEO@vplace.de>
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -369,6 +369,8 @@ static unsigned long __init bootmap_byte
return ALIGN(bytes, sizeof(long));
}
@@ -285,6 +285,8 @@ static unsigned long __init init_initrd(
* Initialize the bootmem allocator. It also setup initrd related data
* if needed.
*/
+static int usermem __initdata;
+
#if defined(CONFIG_SGI_IP27) || (defined(CONFIG_CPU_LOONGSON3) && defined(CONFIG_NUMA))
static void __init bootmem_init(void)
{
unsigned long reserved_end;
@@ -442,7 +444,7 @@ static void __init bootmem_init(void)
@@ -323,7 +325,7 @@ static void __init bootmem_init(void)
/*
* Reserve any memory between the start of RAM and PHYS_OFFSET
*/
- if (ramstart > PHYS_OFFSET)
+ if (usermem && ramstart > PHYS_OFFSET)
add_memory_region(PHYS_OFFSET, ramstart - PHYS_OFFSET,
BOOT_MEM_RESERVED);
memblock_reserve(PHYS_OFFSET, ramstart - PHYS_OFFSET);
@@ -652,8 +654,6 @@ static void __init bootmem_init(void)
* initialization hook for anything else was introduced.
*/
if (PFN_UP(ramstart) > ARCH_PFN_OFFSET) {
@@ -384,8 +386,6 @@ static void __init bootmem_init(void)
#endif /* CONFIG_SGI_IP27 */
-static int usermem __initdata;
-

View File

@ -1,861 +0,0 @@
From fec11d4e8dc5cc79bcd7c8fd55038ac21ac39965 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Sun, 16 Mar 2014 05:22:39 +0000
Subject: [PATCH 04/53] MIPS: ralink: add MT7621 pcie driver
Signed-off-by: John Crispin <blogic@openwrt.org>
---
arch/mips/pci/Makefile | 1 +
arch/mips/pci/pci-mt7621.c | 813 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 814 insertions(+)
create mode 100644 arch/mips/pci/pci-mt7621.c
--- a/arch/mips/pci/Makefile
+++ b/arch/mips/pci/Makefile
@@ -47,6 +47,7 @@ obj-$(CONFIG_SNI_RM) += fixup-sni.o ops
obj-$(CONFIG_LANTIQ) += fixup-lantiq.o
obj-$(CONFIG_PCI_LANTIQ) += pci-lantiq.o ops-lantiq.o
obj-$(CONFIG_SOC_MT7620) += pci-mt7620.o
+obj-$(CONFIG_SOC_MT7621) += pci-mt7621.o
obj-$(CONFIG_SOC_RT288X) += pci-rt2880.o
obj-$(CONFIG_SOC_RT3883) += pci-rt3883.o
obj-$(CONFIG_TANBAC_TB0219) += fixup-tb0219.o
--- /dev/null
+++ b/arch/mips/pci/pci-mt7621.c
@@ -0,0 +1,836 @@
+/**************************************************************************
+ *
+ * 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/mips-cm.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/of_pci.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.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 RALINK_INT_PCIE0 pcie_irq[0]
+#define RALINK_INT_PCIE1 pcie_irq[1]
+#define RALINK_INT_PCIE2 pcie_irq[2]
+#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
+static int pcie_link_status = 0;
+
+#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 pcie_irq[3];
+
+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 mt7621_pci_ops= {
+ .read = pci_config_read,
+ .write = pci_config_write,
+};
+
+static struct resource mt7621_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 mt7621_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,
+};
+
+static struct pci_controller mt7621_controller = {
+ .pci_ops = &mt7621_pci_ops,
+ .mem_resource = &mt7621_res_pci_mem1,
+ .io_resource = &mt7621_res_pci_io1,
+ .mem_offset = 0x00000000UL,
+ .io_offset = 0x00000000UL,
+ .io_map_base = 0xa0000000,
+};
+
+static void
+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;
+}
+
+static void
+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
+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
+}
+
+void setup_cm_memory_region(struct resource *mem_resource)
+{
+ resource_size_t mask;
+ if (mips_cps_numiocu(0)) {
+ /* FIXME: hardware doesn't accept mask values with 1s after
+ 0s (e.g. 0xffef), so it would be great to warn if that's
+ about to happen */
+ mask = ~(mem_resource->end - mem_resource->start);
+
+ write_gcr_reg1_base(mem_resource->start);
+ write_gcr_reg1_mask(mask | CM_GCR_REGn_MASK_CMTGT_IOCU0);
+ printk("PCI coherence region base: 0x%08lx, mask/settings: 0x%08lx\n",
+ read_gcr_reg1_base(),
+ read_gcr_reg1_mask());
+ }
+}
+
+static int mt7621_pci_probe(struct platform_device *pdev)
+{
+ unsigned long val = 0;
+ int i;
+
+ for (i = 0; i < 3; i++)
+ pcie_irq[i] = irq_of_parse_and_map(pdev->dev.of_node, i);
+
+ 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
+ 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 ((*(unsigned int *)(0xbe00000c)&0xFFFF) == 0x0101) // MT7621 E2
+ bypass_pipe_rst();
+ set_phy_for_ssc();
+ printk("release PCIe RST: RALINK_RSTCTRL = %x\n", RALINK_RSTCTRL);
+
+#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 = mt7621_res_pci_io1.start;
+ ioport_resource.end = mt7621_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);
+ read_config(0, 2, 0, 0x70c, &val);
+ val &= ~(0xff)<<8;
+ val |= 0x50<<8;
+ write_config(0, 2, 0, 0x70c, val);
+ 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);
+ read_config(0, 1, 0, 0x70c, &val);
+ val &= ~(0xff)<<8;
+ val |= 0x50<<8;
+ write_config(0, 1, 0, 0x70c, val);
+ 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
+ read_config(0, 0, 0, 0x70c, &val);
+ val &= ~(0xff)<<8;
+ val |= 0x50<<8;
+ write_config(0, 0, 0, 0x70c, val);
+ }
+
+ pci_load_of_ranges(&mt7621_controller, pdev->dev.of_node);
+ setup_cm_memory_region(mt7621_controller.mem_resource);
+ register_pci_controller(&mt7621_controller);
+ return 0;
+
+}
+
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ return 0;
+}
+
+static const struct of_device_id mt7621_pci_ids[] = {
+ { .compatible = "mediatek,mt7621-pci" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, mt7621_pci_ids);
+
+static struct platform_driver mt7621_pci_driver = {
+ .probe = mt7621_pci_probe,
+ .driver = {
+ .name = "mt7621-pci",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(mt7621_pci_ids),
+ },
+};
+
+static int __init mt7621_pci_init(void)
+{
+ return platform_driver_register(&mt7621_pci_driver);
+}
+
+arch_initcall(mt7621_pci_init);

View File

@ -179,7 +179,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+ /* register clock event */
systick.dev.irq = irq_of_parse_and_map(np, 0);
if (!systick.dev.irq) {
pr_err("%s: request_irq failed", np->name);
pr_err("%pOFn: request_irq failed", np);
return -EINVAL;
}
@ -196,5 +196,5 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+ systick.dev.cpumask = cpumask_of(0);
+ clockevents_config_and_register(&systick.dev, SYSTICK_FREQ, 0x3, 0x7fff);
pr_info("%s: running - mult: %d, shift: %d\n",
np->name, systick.dev.mult, systick.dev.shift);
pr_info("%pOFn: running - mult: %d, shift: %d\n",
np, systick.dev.mult, systick.dev.shift);

View File

@ -10,7 +10,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
--- a/arch/mips/ralink/of.c
+++ b/arch/mips/ralink/of.c
@@ -82,6 +82,8 @@ void __init plat_mem_setup(void)
@@ -80,6 +80,8 @@ void __init plat_mem_setup(void)
__dt_setup_arch(dtb);

View File

@ -1,28 +0,0 @@
From 7768798964eb0e4f95eaecffb93b5d0ca28a38af Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Sat, 3 Jun 2017 20:00:03 +0200
Subject: [PATCH] MIPS: pci-mt7620: enabled PCIe on MT7688
To: linux-mips@linux-mips.org,
John Crispin <john@phrozen.org>
Cc: Wei Yongjun <yongjun_wei@trendmicro.com.cn>,
Ralf Baechle <ralf@linux-mips.org>,
linux-mediatek@lists.infradead.org
Use PCIe support for MT7628AN also on MT7688.
Tested on WRTNODE2R.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
arch/mips/pci/pci-mt7620.c | 1 +
1 file changed, 1 insertion(+)
--- a/arch/mips/pci/pci-mt7620.c
+++ b/arch/mips/pci/pci-mt7620.c
@@ -316,6 +316,7 @@ static int mt7620_pci_probe(struct platf
break;
case MT762X_SOC_MT7628AN:
+ case MT762X_SOC_MT7688:
if (mt7628_pci_hw_init(pdev))
return -1;
break;

View File

@ -10,15 +10,15 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -910,7 +910,6 @@ static void __init arch_mem_init(char **
crashk_res.end - crashk_res.start + 1,
BOOTMEM_DEFAULT);
@@ -652,7 +652,6 @@ static void __init arch_mem_init(char **
memblock_reserve(crashk_res.start,
crashk_res.end - crashk_res.start + 1);
#endif
- device_tree_init();
sparse_init();
plat_swiotlb_setup();
@@ -1026,6 +1025,7 @@ void __init setup_arch(char **cmdline_p)
@@ -760,6 +759,7 @@ void __init setup_arch(char **cmdline_p)
cpu_cache_init();
paging_init();

View File

@ -13,7 +13,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
@@ -23,6 +23,8 @@
@@ -19,6 +19,8 @@
#include <linux/pinctrl/pinctrl.h>
#include <linux/slab.h>
#include <linux/gpio/machine.h>
@ -21,9 +21,9 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+#include <linux/platform_device.h>
#include "gpiolib.h"
@@ -513,3 +515,68 @@ void of_gpiochip_remove(struct gpio_chip
gpiochip_remove_pin_ranges(chip);
#include "gpiolib-of.h"
@@ -915,3 +917,68 @@ void of_gpiochip_remove(struct gpio_chip
{
of_node_put(chip->of_node);
}
+
@ -93,7 +93,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+module_platform_driver(gpio_export_driver);
--- a/drivers/gpio/gpiolib-sysfs.c
+++ b/drivers/gpio/gpiolib-sysfs.c
@@ -553,7 +553,7 @@ static struct class gpio_class = {
@@ -563,7 +563,7 @@ static struct class gpio_class = {
*
* Returns zero on success, else an error.
*/
@ -102,7 +102,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
{
struct gpio_chip *chip;
struct gpio_device *gdev;
@@ -615,6 +615,8 @@ int gpiod_export(struct gpio_desc *desc,
@@ -625,6 +625,8 @@ int gpiod_export(struct gpio_desc *desc,
offset = gpio_chip_hwgpio(desc);
if (chip->names && chip->names[offset])
ioname = chip->names[offset];
@ -111,7 +111,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
dev = device_create_with_groups(&gpio_class, &gdev->dev,
MKDEV(0, 0), data, gpio_groups,
@@ -636,6 +638,12 @@ err_unlock:
@@ -646,6 +648,12 @@ err_unlock:
gpiod_dbg(desc, "%s: status %d\n", __func__, status);
return status;
}
@ -141,7 +141,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
{
--- a/include/linux/gpio/consumer.h
+++ b/include/linux/gpio/consumer.h
@@ -451,6 +451,7 @@ struct gpio_desc *devm_fwnode_get_gpiod_
@@ -668,6 +668,7 @@ static inline void devm_acpi_dev_remove_
#if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_GPIO_SYSFS)
@ -149,7 +149,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
int gpiod_export(struct gpio_desc *desc, bool direction_may_change);
int gpiod_export_link(struct device *dev, const char *name,
struct gpio_desc *desc);
@@ -458,6 +459,13 @@ void gpiod_unexport(struct gpio_desc *de
@@ -675,6 +676,13 @@ void gpiod_unexport(struct gpio_desc *de
#else /* CONFIG_GPIOLIB && CONFIG_GPIO_SYSFS */

View File

@ -1,524 +0,0 @@
From 7adbe9a88c33c6e362a10b109d963b5500a21f00 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Sun, 27 Jul 2014 09:34:05 +0100
Subject: [PATCH 25/53] pinctrl: ralink: add pinctrl driver
Signed-off-by: John Crispin <blogic@openwrt.org>
---
arch/mips/Kconfig | 2 +
drivers/pinctrl/Kconfig | 5 +
drivers/pinctrl/Makefile | 1 +
drivers/pinctrl/pinctrl-rt2880.c | 474 ++++++++++++++++++++++++++++++++++++++
4 files changed, 482 insertions(+)
create mode 100644 drivers/pinctrl/pinctrl-rt2880.c
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -629,6 +629,8 @@ config RALINK
select CLKDEV_LOOKUP
select ARCH_HAS_RESET_CONTROLLER
select RESET_CONTROLLER
+ select PINCTRL
+ select PINCTRL_RT2880
config SGI_IP22
bool "SGI IP22 (Indy/Indigo2)"
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -143,6 +143,11 @@ config PINCTRL_LPC18XX
help
Pinctrl driver for NXP LPC18xx/43xx System Control Unit (SCU).
+config PINCTRL_RT2880
+ bool
+ depends on RALINK
+ select PINMUX
+
config PINCTRL_FALCON
bool
depends on SOC_FALCON
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_PINCTRL_PALMAS) += pinctrl-
obj-$(CONFIG_PINCTRL_PIC32) += pinctrl-pic32.o
obj-$(CONFIG_PINCTRL_PISTACHIO) += pinctrl-pistachio.o
obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o
+obj-$(CONFIG_PINCTRL_RT2880) += pinctrl-rt2880.o
obj-$(CONFIG_PINCTRL_RZA1) += pinctrl-rza1.o
obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o
obj-$(CONFIG_PINCTRL_SIRF) += sirf/
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-rt2880.c
@@ -0,0 +1,472 @@
+/*
+ * linux/drivers/pinctrl/pinctrl-rt2880.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
+ * publishhed by the Free Software Foundation.
+ *
+ * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/pinctrl/machine.h>
+
+#include <asm/mach-ralink/ralink_regs.h>
+#include <asm/mach-ralink/pinmux.h>
+#include <asm/mach-ralink/mt7620.h>
+
+#include "core.h"
+
+#define SYSC_REG_GPIO_MODE 0x60
+#define SYSC_REG_GPIO_MODE2 0x64
+
+struct rt2880_priv {
+ struct device *dev;
+
+ struct pinctrl_pin_desc *pads;
+ struct pinctrl_desc *desc;
+
+ struct rt2880_pmx_func **func;
+ int func_count;
+
+ struct rt2880_pmx_group *groups;
+ const char **group_names;
+ int group_count;
+
+ uint8_t *gpio;
+ int max_pins;
+};
+
+static int rt2880_get_group_count(struct pinctrl_dev *pctrldev)
+{
+ struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev);
+
+ return p->group_count;
+}
+
+static const char *rt2880_get_group_name(struct pinctrl_dev *pctrldev,
+ unsigned group)
+{
+ struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev);
+
+ if (group >= p->group_count)
+ return NULL;
+
+ return p->group_names[group];
+}
+
+static int rt2880_get_group_pins(struct pinctrl_dev *pctrldev,
+ unsigned group,
+ const unsigned **pins,
+ unsigned *num_pins)
+{
+ struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev);
+
+ if (group >= p->group_count)
+ return -EINVAL;
+
+ *pins = p->groups[group].func[0].pins;
+ *num_pins = p->groups[group].func[0].pin_count;
+
+ return 0;
+}
+
+static void rt2880_pinctrl_dt_free_map(struct pinctrl_dev *pctrldev,
+ struct pinctrl_map *map, unsigned num_maps)
+{
+ int i;
+
+ for (i = 0; i < num_maps; i++)
+ if (map[i].type == PIN_MAP_TYPE_CONFIGS_PIN ||
+ map[i].type == PIN_MAP_TYPE_CONFIGS_GROUP)
+ kfree(map[i].data.configs.configs);
+ kfree(map);
+}
+
+static void rt2880_pinctrl_pin_dbg_show(struct pinctrl_dev *pctrldev,
+ struct seq_file *s,
+ unsigned offset)
+{
+ seq_printf(s, "ralink pio");
+}
+
+static void rt2880_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctrldev,
+ struct device_node *np,
+ struct pinctrl_map **map)
+{
+ const char *function;
+ int func = of_property_read_string(np, "ralink,function", &function);
+ int grps = of_property_count_strings(np, "ralink,group");
+ int i;
+
+ if (func || !grps)
+ return;
+
+ for (i = 0; i < grps; i++) {
+ const char *group;
+
+ of_property_read_string_index(np, "ralink,group", i, &group);
+
+ (*map)->type = PIN_MAP_TYPE_MUX_GROUP;
+ (*map)->name = function;
+ (*map)->data.mux.group = group;
+ (*map)->data.mux.function = function;
+ (*map)++;
+ }
+}
+
+static int rt2880_pinctrl_dt_node_to_map(struct pinctrl_dev *pctrldev,
+ struct device_node *np_config,
+ struct pinctrl_map **map,
+ unsigned *num_maps)
+{
+ int max_maps = 0;
+ struct pinctrl_map *tmp;
+ struct device_node *np;
+
+ for_each_child_of_node(np_config, np) {
+ int ret = of_property_count_strings(np, "ralink,group");
+
+ if (ret >= 0)
+ max_maps += ret;
+ }
+
+ if (!max_maps)
+ return -EINVAL;
+
+ *map = kzalloc(max_maps * sizeof(struct pinctrl_map), GFP_KERNEL);
+ if (!*map)
+ return -ENOMEM;
+
+ tmp = *map;
+
+ for_each_child_of_node(np_config, np)
+ rt2880_pinctrl_dt_subnode_to_map(pctrldev, np, &tmp);
+ *num_maps = max_maps;
+
+ return 0;
+}
+
+static const struct pinctrl_ops rt2880_pctrl_ops = {
+ .get_groups_count = rt2880_get_group_count,
+ .get_group_name = rt2880_get_group_name,
+ .get_group_pins = rt2880_get_group_pins,
+ .pin_dbg_show = rt2880_pinctrl_pin_dbg_show,
+ .dt_node_to_map = rt2880_pinctrl_dt_node_to_map,
+ .dt_free_map = rt2880_pinctrl_dt_free_map,
+};
+
+static int rt2880_pmx_func_count(struct pinctrl_dev *pctrldev)
+{
+ struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev);
+
+ return p->func_count;
+}
+
+static const char *rt2880_pmx_func_name(struct pinctrl_dev *pctrldev,
+ unsigned func)
+{
+ struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev);
+
+ return p->func[func]->name;
+}
+
+static int rt2880_pmx_group_get_groups(struct pinctrl_dev *pctrldev,
+ unsigned func,
+ const char * const **groups,
+ unsigned * const num_groups)
+{
+ struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev);
+
+ if (p->func[func]->group_count == 1)
+ *groups = &p->group_names[p->func[func]->groups[0]];
+ else
+ *groups = p->group_names;
+
+ *num_groups = p->func[func]->group_count;
+
+ return 0;
+}
+
+static int rt2880_pmx_group_enable(struct pinctrl_dev *pctrldev,
+ unsigned func,
+ unsigned group)
+{
+ struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev);
+ u32 mode = 0;
+ u32 reg = SYSC_REG_GPIO_MODE;
+ int i;
+ int shift;
+
+ /* dont allow double use */
+ if (p->groups[group].enabled) {
+ dev_err(p->dev, "%s is already enabled\n", p->groups[group].name);
+ return -EBUSY;
+ }
+
+ p->groups[group].enabled = 1;
+ p->func[func]->enabled = 1;
+
+ shift = p->groups[group].shift;
+ if (shift >= 32) {
+ shift -= 32;
+ reg = SYSC_REG_GPIO_MODE2;
+ }
+ mode = rt_sysc_r32(reg);
+ mode &= ~(p->groups[group].mask << shift);
+
+ /* mark the pins as gpio */
+ for (i = 0; i < p->groups[group].func[0].pin_count; i++)
+ p->gpio[p->groups[group].func[0].pins[i]] = 1;
+
+ /* function 0 is gpio and needs special handling */
+ if (func == 0) {
+ mode |= p->groups[group].gpio << shift;
+ } else {
+ for (i = 0; i < p->func[func]->pin_count; i++)
+ p->gpio[p->func[func]->pins[i]] = 0;
+ mode |= p->func[func]->value << shift;
+ }
+ rt_sysc_w32(mode, reg);
+
+ return 0;
+}
+
+static int rt2880_pmx_group_gpio_request_enable(struct pinctrl_dev *pctrldev,
+ struct pinctrl_gpio_range *range,
+ unsigned pin)
+{
+ struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev);
+
+ if (!p->gpio[pin]) {
+ dev_err(p->dev, "pin %d is not set to gpio mux\n", pin);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct pinmux_ops rt2880_pmx_group_ops = {
+ .get_functions_count = rt2880_pmx_func_count,
+ .get_function_name = rt2880_pmx_func_name,
+ .get_function_groups = rt2880_pmx_group_get_groups,
+ .set_mux = rt2880_pmx_group_enable,
+ .gpio_request_enable = rt2880_pmx_group_gpio_request_enable,
+};
+
+static struct pinctrl_desc rt2880_pctrl_desc = {
+ .owner = THIS_MODULE,
+ .name = "rt2880-pinmux",
+ .pctlops = &rt2880_pctrl_ops,
+ .pmxops = &rt2880_pmx_group_ops,
+};
+
+static struct rt2880_pmx_func gpio_func = {
+ .name = "gpio",
+};
+
+static int rt2880_pinmux_index(struct rt2880_priv *p)
+{
+ struct rt2880_pmx_func **f;
+ struct rt2880_pmx_group *mux = p->groups;
+ int i, j, c = 0;
+
+ /* count the mux functions */
+ while (mux->name) {
+ p->group_count++;
+ mux++;
+ }
+
+ /* allocate the group names array needed by the gpio function */
+ p->group_names = devm_kzalloc(p->dev, sizeof(char *) * p->group_count, GFP_KERNEL);
+ if (!p->group_names)
+ return -1;
+
+ for (i = 0; i < p->group_count; i++) {
+ p->group_names[i] = p->groups[i].name;
+ p->func_count += p->groups[i].func_count;
+ }
+
+ /* we have a dummy function[0] for gpio */
+ p->func_count++;
+
+ /* allocate our function and group mapping index buffers */
+ f = p->func = devm_kzalloc(p->dev, sizeof(struct rt2880_pmx_func) * p->func_count, GFP_KERNEL);
+ gpio_func.groups = devm_kzalloc(p->dev, sizeof(int) * p->group_count, GFP_KERNEL);
+ if (!f || !gpio_func.groups)
+ return -1;
+
+ /* add a backpointer to the function so it knows its group */
+ gpio_func.group_count = p->group_count;
+ for (i = 0; i < gpio_func.group_count; i++)
+ gpio_func.groups[i] = i;
+
+ f[c] = &gpio_func;
+ c++;
+
+ /* add remaining functions */
+ for (i = 0; i < p->group_count; i++) {
+ for (j = 0; j < p->groups[i].func_count; j++) {
+ f[c] = &p->groups[i].func[j];
+ f[c]->groups = devm_kzalloc(p->dev, sizeof(int), GFP_KERNEL);
+ f[c]->groups[0] = i;
+ f[c]->group_count = 1;
+ c++;
+ }
+ }
+ return 0;
+}
+
+static int rt2880_pinmux_pins(struct rt2880_priv *p)
+{
+ int i, j;
+
+ /* loop over the functions and initialize the pins array. also work out the highest pin used */
+ for (i = 0; i < p->func_count; i++) {
+ int pin;
+
+ if (!p->func[i]->pin_count)
+ continue;
+
+ p->func[i]->pins = devm_kzalloc(p->dev, sizeof(int) * p->func[i]->pin_count, GFP_KERNEL);
+ for (j = 0; j < p->func[i]->pin_count; j++)
+ p->func[i]->pins[j] = p->func[i]->pin_first + j;
+
+ pin = p->func[i]->pin_first + p->func[i]->pin_count;
+ if (pin > p->max_pins)
+ p->max_pins = pin;
+ }
+
+ /* the buffer that tells us which pins are gpio */
+ p->gpio = devm_kzalloc(p->dev,sizeof(uint8_t) * p->max_pins,
+ GFP_KERNEL);
+ /* the pads needed to tell pinctrl about our pins */
+ p->pads = devm_kzalloc(p->dev,
+ sizeof(struct pinctrl_pin_desc) * p->max_pins,
+ GFP_KERNEL);
+ if (!p->pads || !p->gpio ) {
+ dev_err(p->dev, "Failed to allocate gpio data\n");
+ return -ENOMEM;
+ }
+
+ memset(p->gpio, 1, sizeof(uint8_t) * p->max_pins);
+ for (i = 0; i < p->func_count; i++) {
+ if (!p->func[i]->pin_count)
+ continue;
+
+ for (j = 0; j < p->func[i]->pin_count; j++)
+ p->gpio[p->func[i]->pins[j]] = 0;
+ }
+
+ /* pin 0 is always a gpio */
+ p->gpio[0] = 1;
+
+ /* set the pads */
+ for (i = 0; i < p->max_pins; i++) {
+ /* strlen("ioXY") + 1 = 5 */
+ char *name = devm_kzalloc(p->dev, 5, GFP_KERNEL);
+
+ if (!name) {
+ dev_err(p->dev, "Failed to allocate pad name\n");
+ return -ENOMEM;
+ }
+ snprintf(name, 5, "io%d", i);
+ p->pads[i].number = i;
+ p->pads[i].name = name;
+ }
+ p->desc->pins = p->pads;
+ p->desc->npins = p->max_pins;
+
+ return 0;
+}
+
+static int rt2880_pinmux_probe(struct platform_device *pdev)
+{
+ struct rt2880_priv *p;
+ struct pinctrl_dev *dev;
+ struct device_node *np;
+
+ if (!rt2880_pinmux_data)
+ return -ENOSYS;
+
+ /* setup the private data */
+ p = devm_kzalloc(&pdev->dev, sizeof(struct rt2880_priv), GFP_KERNEL);
+ if (!p)
+ return -ENOMEM;
+
+ p->dev = &pdev->dev;
+ p->desc = &rt2880_pctrl_desc;
+ p->groups = rt2880_pinmux_data;
+ platform_set_drvdata(pdev, p);
+
+ /* init the device */
+ if (rt2880_pinmux_index(p)) {
+ dev_err(&pdev->dev, "failed to load index\n");
+ return -EINVAL;
+ }
+ if (rt2880_pinmux_pins(p)) {
+ dev_err(&pdev->dev, "failed to load pins\n");
+ return -EINVAL;
+ }
+ dev = pinctrl_register(p->desc, &pdev->dev, p);
+ if (IS_ERR(dev))
+ return PTR_ERR(dev);
+
+ /* finalize by adding gpio ranges for enables gpio controllers */
+ for_each_compatible_node(np, NULL, "ralink,rt2880-gpio") {
+ const __be32 *ngpio, *gpiobase;
+ struct pinctrl_gpio_range *range;
+ char *name;
+
+ if (!of_device_is_available(np))
+ continue;
+
+ ngpio = of_get_property(np, "ralink,nr-gpio", NULL);
+ gpiobase = of_get_property(np, "ralink,gpio-base", NULL);
+ if (!ngpio || !gpiobase) {
+ dev_err(&pdev->dev, "failed to load chip info\n");
+ return -EINVAL;
+ }
+
+ range = devm_kzalloc(p->dev, sizeof(struct pinctrl_gpio_range) + 4, GFP_KERNEL);
+ range->name = name = (char *) &range[1];
+ sprintf(name, "pio");
+ range->npins = __be32_to_cpu(*ngpio);
+ range->base = __be32_to_cpu(*gpiobase);
+ range->pin_base = range->base;
+ pinctrl_add_gpio_range(dev, range);
+ }
+
+ return 0;
+}
+
+static const struct of_device_id rt2880_pinmux_match[] = {
+ { .compatible = "ralink,rt2880-pinmux" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, rt2880_pinmux_match);
+
+static struct platform_driver rt2880_pinmux_driver = {
+ .probe = rt2880_pinmux_probe,
+ .driver = {
+ .name = "rt2880-pinmux",
+ .owner = THIS_MODULE,
+ .of_match_table = rt2880_pinmux_match,
+ },
+};
+
+int __init rt2880_pinmux_init(void)
+{
+ return platform_driver_register(&rt2880_pinmux_driver);
+}
+
+core_initcall_sync(rt2880_pinmux_init);

View File

@ -47,9 +47,9 @@ Cc: linux-gpio@vger.kernel.org
+#endif /* __ASM_MACH_RALINK_GPIO_H */
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -398,6 +398,12 @@ config GPIO_REG
A 32-bit single register GPIO fixed in/out implementation. This
can be used to represent any register as a set of GPIO signals.
@@ -471,6 +471,12 @@ config GPIO_SNPS_CREG
where only several fields in register belong to GPIO lines and
each GPIO line owns a field with different length and on/off value.
+config GPIO_RALINK
+ bool "Ralink GPIO Support"
@ -62,17 +62,17 @@ Cc: linux-gpio@vger.kernel.org
depends on PLAT_SPEAR
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -98,6 +98,7 @@ obj-$(CONFIG_GPIO_PCI_IDIO_16) += gpio-p
obj-$(CONFIG_GPIO_PISOSR) += gpio-pisosr.o
obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o
obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o
+obj-$(CONFIG_GPIO_RALINK) += gpio-ralink.o
obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t583.o
obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o
obj-$(CONFIG_GPIO_RCAR) += gpio-rcar.o
@@ -112,6 +112,7 @@ obj-$(CONFIG_GPIO_PISOSR) += gpio-pisos
obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o
obj-$(CONFIG_GPIO_PMIC_EIC_SPRD) += gpio-pmic-eic-sprd.o
obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o
+obj-$(CONFIG_GPIO_RALINK) += gpio-ralink.o
obj-$(CONFIG_GPIO_RASPBERRYPI_EXP) += gpio-raspberrypi-exp.o
obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t583.o
obj-$(CONFIG_GPIO_RCAR) += gpio-rcar.o
--- /dev/null
+++ b/drivers/gpio/gpio-ralink.c
@@ -0,0 +1,355 @@
@@ -0,0 +1,341 @@
+/*
+ * 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
@ -328,20 +328,6 @@ Cc: linux-gpio@vger.kernel.org
+ dev_info(rg->chip.parent, "registering %d irq handlers\n", rg->chip.ngpio);
+}
+
+static int ralink_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+ int gpio = chip->base + offset;
+
+ return pinctrl_request_gpio(gpio);
+}
+
+static void ralink_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+ int gpio = chip->base + offset;
+
+ pinctrl_free_gpio(gpio);
+}
+
+static int ralink_gpio_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
@ -393,9 +379,9 @@ Cc: linux-gpio@vger.kernel.org
+ rg->chip.direction_output = ralink_gpio_direction_output;
+ rg->chip.get = ralink_gpio_get;
+ rg->chip.set = ralink_gpio_set;
+ rg->chip.request = ralink_gpio_request;
+ rg->chip.request = gpiochip_generic_request;
+ rg->chip.to_irq = ralink_gpio_to_irq;
+ rg->chip.free = ralink_gpio_free;
+ rg->chip.free = gpiochip_generic_free;
+
+ /* set polarity to low for all lines */
+ rt_gpio_w32(rg, GPIO_REG_POL, 0);

View File

@ -1,405 +0,0 @@
From 61ac7d9b4228de8c332900902c2b93189b042eab Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Sun, 27 Jul 2014 11:00:32 +0100
Subject: [PATCH 28/53] GPIO: ralink: add mt7621 gpio controller
Signed-off-by: John Crispin <blogic@openwrt.org>
---
arch/mips/Kconfig | 3 +
drivers/gpio/Kconfig | 6 +
drivers/gpio/Makefile | 1 +
drivers/gpio/gpio-mt7621.c | 354 ++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 364 insertions(+)
create mode 100644 drivers/gpio/gpio-mt7621.c
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -631,6 +631,9 @@ config RALINK
select RESET_CONTROLLER
select PINCTRL
select PINCTRL_RT2880
+ select ARCH_HAS_RESET_CONTROLLER
+ select RESET_CONTROLLER
+ select ARCH_REQUIRE_GPIOLIB
config SGI_IP22
bool "SGI IP22 (Indy/Indigo2)"
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -298,6 +298,12 @@ config GPIO_MENZ127
help
Say yes here to support the MEN 16Z127 GPIO Controller
+config GPIO_MT7621
+ bool "Mediatek GPIO Support"
+ depends on SOC_MT7620 || SOC_MT7621
+ help
+ Say yes here to support the Mediatek SoC GPIO device
+
config GPIO_MM_LANTIQ
bool "Lantiq Memory mapped GPIOs"
depends on LANTIQ && SOC_XWAY
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -152,3 +152,4 @@ obj-$(CONFIG_GPIO_ZEVIO) += gpio-zevio.o
obj-$(CONFIG_GPIO_ZYNQ) += gpio-zynq.o
obj-$(CONFIG_GPIO_ZX) += gpio-zx.o
obj-$(CONFIG_GPIO_LOONGSON1) += gpio-loongson1.o
+obj-$(CONFIG_GPIO_MT7621) += gpio-mt7621.o
--- /dev/null
+++ b/drivers/gpio/gpio-mt7621.c
@@ -0,0 +1,354 @@
+/*
+ * 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_MAX_BANK 3
+#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,
+ GPIO_REG_REDGE,
+ GPIO_REG_FEDGE,
+ GPIO_REG_HLVL,
+ GPIO_REG_LLVL,
+ GPIO_REG_STAT,
+ GPIO_REG_EDGE,
+};
+
+static void __iomem *mediatek_gpio_membase;
+static int mediatek_gpio_irq;
+static struct irq_domain *mediatek_gpio_irq_domain;
+static atomic_t irq_refcount = ATOMIC_INIT(0);
+
+struct mtk_gc {
+ struct gpio_chip chip;
+ spinlock_t lock;
+ int bank;
+ u32 rising;
+ u32 falling;
+} *gc_map[MTK_MAX_BANK];
+
+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, mediatek_gpio_membase + (reg * 0x10) + (rg->bank * 0x4));
+}
+
+static inline u32
+mtk_gpio_r32(struct mtk_gc *rg, u8 reg)
+{
+ return ioread32(mediatek_gpio_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_get_direction(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);
+ spin_unlock_irqrestore(&rg->lock, flags);
+
+ if (t & BIT(offset))
+ return 0;
+
+ return 1;
+}
+
+static int
+mediatek_gpio_to_irq(struct gpio_chip *chip, unsigned pin)
+{
+ struct mtk_gc *rg = to_mediatek_gpio(chip);
+
+ return irq_create_mapping(mediatek_gpio_irq_domain, pin + (rg->bank * MTK_BANK_WIDTH));
+}
+
+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 || be32_to_cpu(*id) > MTK_MAX_BANK)
+ return -ENOMEM;
+
+ gc_map[be32_to_cpu(*id)] = rg;
+
+ memset(rg, 0, sizeof(struct mtk_gc));
+
+ spin_lock_init(&rg->lock);
+
+ rg->chip.parent = &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_direction = mediatek_gpio_get_direction;
+ rg->chip.get = mediatek_gpio_get;
+ rg->chip.set = mediatek_gpio_set;
+ if (mediatek_gpio_irq_domain)
+ rg->chip.to_irq = mediatek_gpio_to_irq;
+ rg->bank = be32_to_cpu(*id);
+
+ /* 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 void
+mediatek_gpio_irq_handler(struct irq_desc *desc)
+{
+ int i;
+
+ for (i = 0; i < MTK_MAX_BANK; i++) {
+ struct mtk_gc *rg = gc_map[i];
+ unsigned long pending;
+ int bit;
+
+ if (!rg)
+ continue;
+
+ pending = mtk_gpio_r32(rg, GPIO_REG_STAT);
+
+ for_each_set_bit(bit, &pending, MTK_BANK_WIDTH) {
+ u32 map = irq_find_mapping(mediatek_gpio_irq_domain, (MTK_BANK_WIDTH * i) + bit);
+
+ generic_handle_irq(map);
+ mtk_gpio_w32(rg, GPIO_REG_STAT, BIT(bit));
+ }
+ }
+}
+
+static void
+mediatek_gpio_irq_unmask(struct irq_data *d)
+{
+ int pin = d->hwirq;
+ int bank = pin / 32;
+ struct mtk_gc *rg = gc_map[bank];
+ unsigned long flags;
+ u32 rise, fall;
+
+ if (!rg)
+ return;
+
+ rise = mtk_gpio_r32(rg, GPIO_REG_REDGE);
+ fall = mtk_gpio_r32(rg, GPIO_REG_FEDGE);
+
+ spin_lock_irqsave(&rg->lock, flags);
+ mtk_gpio_w32(rg, GPIO_REG_REDGE, rise | (BIT(d->hwirq) & rg->rising));
+ mtk_gpio_w32(rg, GPIO_REG_FEDGE, fall | (BIT(d->hwirq) & rg->falling));
+ spin_unlock_irqrestore(&rg->lock, flags);
+}
+
+static void
+mediatek_gpio_irq_mask(struct irq_data *d)
+{
+ int pin = d->hwirq;
+ int bank = pin / 32;
+ struct mtk_gc *rg = gc_map[bank];
+ unsigned long flags;
+ u32 rise, fall;
+
+ if (!rg)
+ return;
+
+ rise = mtk_gpio_r32(rg, GPIO_REG_REDGE);
+ fall = mtk_gpio_r32(rg, GPIO_REG_FEDGE);
+
+ spin_lock_irqsave(&rg->lock, flags);
+ mtk_gpio_w32(rg, GPIO_REG_FEDGE, fall & ~BIT(d->hwirq));
+ mtk_gpio_w32(rg, GPIO_REG_REDGE, rise & ~BIT(d->hwirq));
+ spin_unlock_irqrestore(&rg->lock, flags);
+}
+
+static int
+mediatek_gpio_irq_type(struct irq_data *d, unsigned int type)
+{
+ int pin = d->hwirq;
+ int bank = pin / 32;
+ struct mtk_gc *rg = gc_map[bank];
+ u32 mask = BIT(d->hwirq);
+
+ if (!rg)
+ return -1;
+
+ if (type == IRQ_TYPE_PROBE) {
+ if ((rg->rising | rg->falling) & mask)
+ return 0;
+
+ type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
+ }
+
+ if (type & IRQ_TYPE_EDGE_RISING)
+ rg->rising |= mask;
+ else
+ rg->rising &= ~mask;
+
+ if (type & IRQ_TYPE_EDGE_FALLING)
+ rg->falling |= mask;
+ else
+ rg->falling &= ~mask;
+
+ return 0;
+}
+
+static struct irq_chip mediatek_gpio_irq_chip = {
+ .name = "GPIO",
+ .irq_unmask = mediatek_gpio_irq_unmask,
+ .irq_mask = mediatek_gpio_irq_mask,
+ .irq_mask_ack = mediatek_gpio_irq_mask,
+ .irq_set_type = mediatek_gpio_irq_type,
+};
+
+static int
+mediatek_gpio_gpio_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
+{
+ irq_set_chip_and_handler(irq, &mediatek_gpio_irq_chip, handle_level_irq);
+ irq_set_handler_data(irq, d);
+
+ return 0;
+}
+
+static const struct irq_domain_ops irq_domain_ops = {
+ .xlate = irq_domain_xlate_onecell,
+ .map = mediatek_gpio_gpio_map,
+};
+
+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);
+
+ mediatek_gpio_membase = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(mediatek_gpio_membase))
+ return PTR_ERR(mediatek_gpio_membase);
+
+ mediatek_gpio_irq = irq_of_parse_and_map(np, 0);
+ if (mediatek_gpio_irq) {
+ mediatek_gpio_irq_domain = irq_domain_add_linear(np,
+ MTK_MAX_BANK * MTK_BANK_WIDTH,
+ &irq_domain_ops, NULL);
+ if (!mediatek_gpio_irq_domain)
+ dev_err(&pdev->dev, "irq_domain_add_linear failed\n");
+ }
+
+ for_each_child_of_node(np, bank)
+ if (of_device_is_compatible(bank, "mtk,mt7621-gpio-bank"))
+ mediatek_gpio_bank_probe(pdev, bank);
+
+ if (mediatek_gpio_irq_domain)
+ irq_set_chained_handler(mediatek_gpio_irq, mediatek_gpio_irq_handler);
+
+ 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);

View File

@ -13,10 +13,10 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -2749,6 +2749,18 @@ static const struct usb_device_id uvc_id
@@ -2908,6 +2908,18 @@ static const struct usb_device_id uvc_id
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 0,
.driver_info = UVC_QUIRK_FORCE_Y8 },
.driver_info = UVC_INFO_META(V4L2_META_FMT_D4XX) },
+ /* iPassion iP2970 */
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
+ | USB_DEVICE_ID_MATCH_INT_INFO,
@ -34,15 +34,15 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
{ USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, UVC_PC_PROTOCOL_15) },
--- a/drivers/media/usb/uvc/uvc_status.c
+++ b/drivers/media/usb/uvc/uvc_status.c
@@ -139,6 +139,7 @@ static void uvc_status_complete(struct u
switch (dev->status[0] & 0x0f) {
case UVC_STATUS_TYPE_CONTROL:
uvc_event_control(dev, dev->status, len);
@@ -223,6 +223,7 @@ static void uvc_status_complete(struct u
if (uvc_event_control(urb, status, len))
/* The URB will be resubmitted in work context. */
return;
+ dev->motion = 1;
break;
}
case UVC_STATUS_TYPE_STREAMING:
@@ -182,6 +183,7 @@ int uvc_status_init(struct uvc_device *d
@@ -271,6 +272,7 @@ int uvc_status_init(struct uvc_device *d
}
pipe = usb_rcvintpipe(dev->udev, ep->desc.bEndpointAddress);
@ -52,7 +52,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
* an exponent of two. Some developers forgot about it.
--- a/drivers/media/usb/uvc/uvc_video.c
+++ b/drivers/media/usb/uvc/uvc_video.c
@@ -21,6 +21,11 @@
@@ -16,6 +16,11 @@
#include <linux/wait.h>
#include <linux/atomic.h>
#include <asm/unaligned.h>
@ -64,8 +64,8 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
#include <media/v4l2-common.h>
@@ -1101,9 +1106,149 @@ static void uvc_video_decode_data(struct
}
@@ -1156,9 +1161,149 @@ static void uvc_video_decode_data(struct
uvc_urb->async_operations++;
}
+struct bh_priv {
@ -196,7 +196,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+
+#define MOTION_FLAG_OFFSET 4
static void uvc_video_decode_end(struct uvc_streaming *stream,
struct uvc_buffer *buf, const __u8 *data, int len)
struct uvc_buffer *buf, const u8 *data, int len)
{
+ if ((stream->dev->quirks & UVC_QUIRK_MOTION) &&
+ (data[len - 2] == 0xff) && (data[len - 1] == 0xd9)) {
@ -214,7 +214,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
/* Mark the buffer as done if the EOF marker is set. */
if (data[1] & UVC_STREAM_EOF && buf->bytesused != 0) {
uvc_trace(UVC_TRACE_FRAME, "Frame complete (EOF found).\n");
@@ -1518,6 +1663,8 @@ static int uvc_init_video_isoc(struct uv
@@ -1715,6 +1860,8 @@ static int uvc_init_video_isoc(struct uv
if (npackets == 0)
return -ENOMEM;
@ -222,13 +222,13 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+ npackets = 1;
size = npackets * psize;
for (i = 0; i < UVC_URBS; ++i) {
for_each_uvc_urb(uvc_urb, stream) {
--- a/drivers/media/usb/uvc/uvcvideo.h
+++ b/drivers/media/usb/uvc/uvcvideo.h
@@ -186,7 +186,9 @@
#define UVC_QUIRK_RESTRICT_FRAME_RATE 0x00000200
@@ -199,7 +199,9 @@
#define UVC_QUIRK_RESTORE_CTRLS_ON_INIT 0x00000400
#define UVC_QUIRK_FORCE_Y8 0x00000800
#define UVC_QUIRK_FORCE_BPP 0x00001000
-
+#define UVC_QUIRK_MOTION 0x00001000
+#define UVC_QUIRK_SINGLE_ISO 0x00002000
@ -236,11 +236,11 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
/* Format flags */
#define UVC_FMT_FLAG_COMPRESSED 0x00000001
#define UVC_FMT_FLAG_STREAM 0x00000002
@@ -584,6 +586,7 @@ struct uvc_device {
__u8 *status;
@@ -666,6 +668,7 @@ struct uvc_device {
u8 *status;
struct input_dev *input;
char input_phys[64];
+ int motion;
};
enum uvc_handle_state {
struct uvc_ctrl_work {
struct work_struct work;

View File

@ -10,7 +10,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -48,6 +48,7 @@
@@ -49,6 +49,7 @@
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/usb.h>
@ -18,12 +18,12 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
#include <linux/usb/hcd.h>
#include <linux/usb/ch11.h>
@@ -5215,6 +5216,8 @@ int dwc2_hcd_init(struct dwc2_hsotg *hso
@@ -5023,6 +5024,8 @@ int dwc2_hcd_init(struct dwc2_hsotg *hso
retval = -ENOMEM;
+ device_reset(hsotg->dev);
+
hcfg = dwc2_readl(hsotg->regs + HCFG);
hcfg = dwc2_readl(hsotg, HCFG);
dev_dbg(hsotg->dev, "hcfg=%08x\n", hcfg);

View File

@ -1,59 +0,0 @@
From 0b6eb1e68290243d439ee330ea8d0b239a5aec69 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Sun, 27 Jul 2014 09:38:50 +0100
Subject: [PATCH 34/53] NET: multi phy support
Signed-off-by: John Crispin <blogic@openwrt.org>
---
drivers/net/phy/phy.c | 9 ++++++---
include/linux/phy.h | 1 +
2 files changed, 7 insertions(+), 3 deletions(-)
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -913,7 +913,10 @@ void phy_state_machine(struct work_struc
/* If the link is down, give up on negotiation for now */
if (!phydev->link) {
phydev->state = PHY_NOLINK;
- phy_link_down(phydev, true);
+ if (!phydev->no_auto_carrier_off)
+ phy_link_down(phydev, true);
+ else
+ phy_link_down(phydev, false);
break;
}
@@ -1000,7 +1003,10 @@ void phy_state_machine(struct work_struc
phy_link_up(phydev);
} else {
phydev->state = PHY_NOLINK;
- phy_link_down(phydev, true);
+ if (!phydev->no_auto_carrier_off)
+ phy_link_down(phydev, true);
+ else
+ phy_link_down(phydev, false);
}
if (phy_interrupt_is_valid(phydev))
@@ -1010,7 +1016,10 @@ void phy_state_machine(struct work_struc
case PHY_HALTED:
if (phydev->link) {
phydev->link = 0;
- phy_link_down(phydev, true);
+ if (!phydev->no_auto_carrier_off)
+ phy_link_down(phydev, true);
+ else
+ phy_link_down(phydev, false);
do_suspend = true;
}
break;
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -412,6 +412,7 @@ struct phy_device {
bool suspended;
bool sysfs_links;
bool loopback_enabled;
+ bool no_auto_carrier_off;
enum phy_state state;

View File

@ -18,53 +18,3 @@ Subject: [PATCH 37/53] mtd: cfi cmdset 0002 force word write
#define MAX_RETRIES 3
@@ -51,7 +51,9 @@
static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
+#if !FORCE_WORD_WRITE
static int cfi_amdstd_write_buffers(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
+#endif
static int cfi_amdstd_erase_chip(struct mtd_info *, struct erase_info *);
static int cfi_amdstd_erase_varsize(struct mtd_info *, struct erase_info *);
static void cfi_amdstd_sync (struct mtd_info *);
@@ -202,6 +204,7 @@ static void fixup_amd_bootblock(struct m
}
#endif
+#if !FORCE_WORD_WRITE
static void fixup_use_write_buffers(struct mtd_info *mtd)
{
struct map_info *map = mtd->priv;
@@ -211,6 +214,7 @@ static void fixup_use_write_buffers(stru
mtd->_write = cfi_amdstd_write_buffers;
}
}
+#endif /* !FORCE_WORD_WRITE */
/* Atmel chips don't use the same PRI format as AMD chips */
static void fixup_convert_atmel_pri(struct mtd_info *mtd)
@@ -1798,6 +1802,7 @@ static int cfi_amdstd_write_words(struct
/*
* FIXME: interleaved mode not tested, and probably not supported!
*/
+#if !FORCE_WORD_WRITE
static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
unsigned long adr, const u_char *buf,
int len)
@@ -1926,7 +1931,6 @@ static int __xipram do_write_buffer(stru
return ret;
}
-
static int cfi_amdstd_write_buffers(struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const u_char *buf)
{
@@ -2001,6 +2005,7 @@ static int cfi_amdstd_write_buffers(stru
return 0;
}
+#endif /* !FORCE_WORD_WRITE */
/*
* Wait for the flash chip to become ready to write data

View File

@ -1,67 +0,0 @@
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
Subject: [PATCH] Revert "mtd: nand: Remove unused chip->write_page() hook"
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This reverts commit f107d7a43923a83d837b3ea3c7b7de58cd014bbd.
OpenWrt's downstream driver mtk_nand2 still uses that callback.
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
---
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -2577,7 +2577,7 @@ static int nand_write_page_syndrome(stru
}
/**
- * nand_write_page - write one page
+ * nand_write_page - [REPLACEABLE] write one page
* @mtd: MTD device structure
* @chip: NAND chip descriptor
* @offset: address offset within the page
@@ -2761,9 +2761,9 @@ static int nand_do_write_ops(struct mtd_
memset(chip->oob_poi, 0xff, mtd->oobsize);
}
- ret = nand_write_page(mtd, chip, column, bytes, wbuf,
- oob_required, page,
- (ops->mode == MTD_OPS_RAW));
+ ret = chip->write_page(mtd, chip, column, bytes, wbuf,
+ oob_required, page,
+ (ops->mode == MTD_OPS_RAW));
if (ret)
break;
@@ -4719,6 +4719,9 @@ int nand_scan_tail(struct mtd_info *mtd)
}
}
+ if (!chip->write_page)
+ chip->write_page = nand_write_page;
+
/*
* Check ECC mode, default to software if 3byte/512byte hardware ECC is
* selected and we have 256 byte pagesize fallback to software ECC
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -862,6 +862,7 @@ struct nand_manufacturer_ops {
* structure which is shared among multiple independent
* devices.
* @priv: [OPTIONAL] pointer to private chip data
+ * @write_page: [REPLACEABLE] High-level page write function
* @manufacturer: [INTERN] Contains manufacturer information
*/
@@ -885,6 +886,9 @@ struct nand_chip {
int(*waitfunc)(struct mtd_info *mtd, struct nand_chip *this);
int (*erase)(struct mtd_info *mtd, int page);
int (*scan_bbt)(struct mtd_info *mtd);
+ int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
+ uint32_t offset, int data_len, const uint8_t *buf,
+ int oob_required, int page, int raw);
int (*onfi_set_features)(struct mtd_info *mtd, struct nand_chip *chip,
int feature_addr, uint8_t *subfeature_para);
int (*onfi_get_features)(struct mtd_info *mtd, struct nand_chip *chip,

View File

@ -1,32 +0,0 @@
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -1908,6 +1908,9 @@ static int nand_do_read_ops(struct mtd_i
__func__, buf);
read_retry:
+#ifdef CONFIG_MTK_MTD_NAND
+ ret = chip->read_page(mtd, chip, bufpoi, page);
+#else
if (nand_standard_page_accessors(&chip->ecc))
chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
@@ -1927,6 +1930,7 @@ read_retry:
else
ret = chip->ecc.read_page(mtd, chip, bufpoi,
oob_required, page);
+#endif
if (ret < 0) {
if (use_bufpoi)
/* Invalidate page cache */
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -897,6 +897,9 @@ struct nand_chip {
int (*setup_data_interface)(struct mtd_info *mtd, int chipnr,
const struct nand_data_interface *conf);
+#ifdef CONFIG_MTK_MTD_NAND
+ int (*read_page)(struct mtd_info *mtd, struct nand_chip *chip, u8 *buf, int page);
+#endif /* CONFIG_MTK_MTD_NAND */
int chip_delay;
unsigned int options;

View File

@ -16,9 +16,9 @@ Acked-by: John Crispin <blogic@openwrt.org>
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -563,6 +563,12 @@ config SPI_QUP
@@ -605,6 +605,12 @@ config SPI_QCOM_GENI
This driver can also be built as a module. If so, the module
will be called spi_qup.
will be called spi-geni-qcom.
+config SPI_RT2880
+ tristate "Ralink RT288x SPI Controller"
@ -31,7 +31,7 @@ Acked-by: John Crispin <blogic@openwrt.org>
depends on ARCH_S3C24XX
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -81,6 +81,7 @@ obj-$(CONFIG_SPI_QUP) += spi-qup.o
@@ -87,6 +87,7 @@ obj-$(CONFIG_SPI_QUP) += spi-qup.o
obj-$(CONFIG_SPI_ROCKCHIP) += spi-rockchip.o
obj-$(CONFIG_SPI_RB4XX) += spi-rb4xx.o
obj-$(CONFIG_SPI_RSPI) += spi-rspi.o

View File

@ -1,487 +0,0 @@
From cbd66c626e16743b05af807ad48012c0a097b9fb Mon Sep 17 00:00:00 2001
From: Stefan Roese <sr@denx.de>
Date: Mon, 25 Mar 2019 09:29:25 +0100
Subject: [PATCH] spi: mt7621: Move SPI driver out of staging
This patch moves the MT7621 SPI driver, which is used on some Ralink /
MediaTek MT76xx MIPS SoC's, out of the staging directory. No changes to
the source code are done in this patch.
This driver version was tested successfully on an MT7688 based platform
with an SPI NOR on CS0 and an SPI NAND on CS1 without any issues (so
far).
This patch also documents the devicetree bindings for the MT7621 SPI
device driver.
Signed-off-by: Stefan Roese <sr@denx.de>
Cc: Rob Herring <robh@kernel.org>
Cc: Mark Brown <broonie@kernel.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: NeilBrown <neil@brown.name>
Cc: Sankalp Negi <sankalpnegi2310@gmail.com>
Cc: Chuanhong Guo <gch981213@gmail.com>
Cc: John Crispin <john@phrozen.org>
Cc: Armando Miraglia <arma2ff0@gmail.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
.../devicetree/bindings/spi/spi-mt7621.txt | 26 ++++++
drivers/spi/Kconfig | 6 ++
drivers/spi/Makefile | 1 +
.../{staging/mt7621-spi => spi}/spi-mt7621.c | 83 +++++++++----------
drivers/staging/Kconfig | 2 -
drivers/staging/Makefile | 1 -
drivers/staging/mt7621-spi/Kconfig | 6 --
drivers/staging/mt7621-spi/Makefile | 1 -
drivers/staging/mt7621-spi/TODO | 5 --
9 files changed, 74 insertions(+), 57 deletions(-)
create mode 100644 Documentation/devicetree/bindings/spi/spi-mt7621.txt
rename drivers/{staging/mt7621-spi => spi}/spi-mt7621.c (88%)
delete mode 100644 drivers/staging/mt7621-spi/Kconfig
delete mode 100644 drivers/staging/mt7621-spi/Makefile
delete mode 100644 drivers/staging/mt7621-spi/TODO
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -569,6 +569,12 @@ config SPI_RT2880
help
This selects a driver for the Ralink RT288x/RT305x SPI Controller.
+config SPI_MT7621
+ tristate "MediaTek MT7621 SPI Controller"
+ depends on RALINK
+ help
+ This selects a driver for the MediaTek MT7621 SPI Controller.
+
config SPI_S3C24XX
tristate "Samsung S3C24XX series SPI"
depends on ARCH_S3C24XX
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -60,6 +60,7 @@ obj-$(CONFIG_SPI_MPC512x_PSC) += spi-mp
obj-$(CONFIG_SPI_MPC52xx_PSC) += spi-mpc52xx-psc.o
obj-$(CONFIG_SPI_MPC52xx) += spi-mpc52xx.o
obj-$(CONFIG_SPI_MT65XX) += spi-mt65xx.o
+obj-$(CONFIG_SPI_MT7621) += spi-mt7621.o
obj-$(CONFIG_SPI_MXS) += spi-mxs.o
obj-$(CONFIG_SPI_NUC900) += spi-nuc900.o
obj-$(CONFIG_SPI_OC_TINY) += spi-oc-tiny.o
--- /dev/null
+++ b/drivers/spi/spi-mt7621.c
@@ -0,0 +1,416 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// spi-mt7621.c -- MediaTek MT7621 SPI controller driver
+//
+// Copyright (C) 2011 Sergiy <piratfm@gmail.com>
+// Copyright (C) 2011-2013 Gabor Juhos <juhosg@openwrt.org>
+// Copyright (C) 2014-2015 Felix Fietkau <nbd@nbd.name>
+//
+// Some parts are based on spi-orion.c:
+// Author: Shadi Ammouri <shadi@marvell.com>
+// Copyright (C) 2007-2008 Marvell Ltd.
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/reset.h>
+#include <linux/spi/spi.h>
+
+#define DRIVER_NAME "spi-mt7621"
+
+/* in usec */
+#define RALINK_SPI_WAIT_MAX_LOOP 2000
+
+/* SPISTAT register bit field */
+#define SPISTAT_BUSY BIT(0)
+
+#define MT7621_SPI_TRANS 0x00
+#define SPITRANS_BUSY BIT(16)
+
+#define MT7621_SPI_OPCODE 0x04
+#define MT7621_SPI_DATA0 0x08
+#define MT7621_SPI_DATA4 0x18
+#define SPI_CTL_TX_RX_CNT_MASK 0xff
+#define SPI_CTL_START BIT(8)
+
+#define MT7621_SPI_MASTER 0x28
+#define MASTER_MORE_BUFMODE BIT(2)
+#define MASTER_FULL_DUPLEX BIT(10)
+#define MASTER_RS_CLK_SEL GENMASK(27, 16)
+#define MASTER_RS_CLK_SEL_SHIFT 16
+#define MASTER_RS_SLAVE_SEL GENMASK(31, 29)
+
+#define MT7621_SPI_MOREBUF 0x2c
+#define MT7621_SPI_POLAR 0x38
+#define MT7621_SPI_SPACE 0x3c
+
+#define MT7621_CPHA BIT(5)
+#define MT7621_CPOL BIT(4)
+#define MT7621_LSB_FIRST BIT(3)
+
+struct mt7621_spi {
+ struct spi_controller *master;
+ void __iomem *base;
+ unsigned int sys_freq;
+ unsigned int speed;
+ struct clk *clk;
+ int pending_write;
+};
+
+static inline struct mt7621_spi *spidev_to_mt7621_spi(struct spi_device *spi)
+{
+ return spi_controller_get_devdata(spi->master);
+}
+
+static inline u32 mt7621_spi_read(struct mt7621_spi *rs, u32 reg)
+{
+ return ioread32(rs->base + reg);
+}
+
+static inline void mt7621_spi_write(struct mt7621_spi *rs, u32 reg, u32 val)
+{
+ iowrite32(val, rs->base + reg);
+}
+
+static void mt7621_spi_set_cs(struct spi_device *spi, int enable)
+{
+ struct mt7621_spi *rs = spidev_to_mt7621_spi(spi);
+ int cs = spi->chip_select;
+ u32 polar = 0;
+ u32 master;
+
+ /*
+ * Select SPI device 7, enable "more buffer mode" and disable
+ * full-duplex (only half-duplex really works on this chip
+ * reliably)
+ */
+ master = mt7621_spi_read(rs, MT7621_SPI_MASTER);
+ master |= MASTER_RS_SLAVE_SEL | MASTER_MORE_BUFMODE;
+ master &= ~MASTER_FULL_DUPLEX;
+ mt7621_spi_write(rs, MT7621_SPI_MASTER, master);
+
+ rs->pending_write = 0;
+
+ if (enable)
+ polar = BIT(cs);
+ mt7621_spi_write(rs, MT7621_SPI_POLAR, polar);
+}
+
+static int mt7621_spi_prepare(struct spi_device *spi, unsigned int speed)
+{
+ struct mt7621_spi *rs = spidev_to_mt7621_spi(spi);
+ u32 rate;
+ u32 reg;
+
+ dev_dbg(&spi->dev, "speed:%u\n", speed);
+
+ rate = DIV_ROUND_UP(rs->sys_freq, speed);
+ dev_dbg(&spi->dev, "rate-1:%u\n", rate);
+
+ if (rate > 4097)
+ return -EINVAL;
+
+ if (rate < 2)
+ rate = 2;
+
+ reg = mt7621_spi_read(rs, MT7621_SPI_MASTER);
+ reg &= ~MASTER_RS_CLK_SEL;
+ reg |= (rate - 2) << MASTER_RS_CLK_SEL_SHIFT;
+ rs->speed = speed;
+
+ reg &= ~MT7621_LSB_FIRST;
+ if (spi->mode & SPI_LSB_FIRST)
+ reg |= MT7621_LSB_FIRST;
+
+ /*
+ * This SPI controller seems to be tested on SPI flash only and some
+ * bits are swizzled under other SPI modes probably due to incorrect
+ * wiring inside the silicon. Only mode 0 works correctly.
+ */
+ reg &= ~(MT7621_CPHA | MT7621_CPOL);
+
+ mt7621_spi_write(rs, MT7621_SPI_MASTER, reg);
+
+ return 0;
+}
+
+static inline int mt7621_spi_wait_till_ready(struct mt7621_spi *rs)
+{
+ int i;
+
+ for (i = 0; i < RALINK_SPI_WAIT_MAX_LOOP; i++) {
+ u32 status;
+
+ status = mt7621_spi_read(rs, MT7621_SPI_TRANS);
+ if ((status & SPITRANS_BUSY) == 0)
+ return 0;
+ cpu_relax();
+ udelay(1);
+ }
+
+ return -ETIMEDOUT;
+}
+
+static void mt7621_spi_read_half_duplex(struct mt7621_spi *rs,
+ int rx_len, u8 *buf)
+{
+ int tx_len;
+
+ /*
+ * Combine with any pending write, and perform one or more half-duplex
+ * transactions reading 'len' bytes. Data to be written is already in
+ * MT7621_SPI_DATA.
+ */
+ tx_len = rs->pending_write;
+ rs->pending_write = 0;
+
+ while (rx_len || tx_len) {
+ int i;
+ u32 val = (min(tx_len, 4) * 8) << 24;
+ int rx = min(rx_len, 32);
+
+ if (tx_len > 4)
+ val |= (tx_len - 4) * 8;
+ val |= (rx * 8) << 12;
+ mt7621_spi_write(rs, MT7621_SPI_MOREBUF, val);
+
+ tx_len = 0;
+
+ val = mt7621_spi_read(rs, MT7621_SPI_TRANS);
+ val |= SPI_CTL_START;
+ mt7621_spi_write(rs, MT7621_SPI_TRANS, val);
+
+ mt7621_spi_wait_till_ready(rs);
+
+ for (i = 0; i < rx; i++) {
+ if ((i % 4) == 0)
+ val = mt7621_spi_read(rs, MT7621_SPI_DATA0 + i);
+ *buf++ = val & 0xff;
+ val >>= 8;
+ }
+
+ rx_len -= i;
+ }
+}
+
+static inline void mt7621_spi_flush(struct mt7621_spi *rs)
+{
+ mt7621_spi_read_half_duplex(rs, 0, NULL);
+}
+
+static void mt7621_spi_write_half_duplex(struct mt7621_spi *rs,
+ int tx_len, const u8 *buf)
+{
+ int len = rs->pending_write;
+ int val = 0;
+
+ if (len & 3) {
+ val = mt7621_spi_read(rs, MT7621_SPI_OPCODE + (len & ~3));
+ if (len < 4) {
+ val <<= (4 - len) * 8;
+ val = swab32(val);
+ }
+ }
+
+ while (tx_len > 0) {
+ if (len >= 36) {
+ rs->pending_write = len;
+ mt7621_spi_flush(rs);
+ len = 0;
+ }
+
+ val |= *buf++ << (8 * (len & 3));
+ len++;
+ if ((len & 3) == 0) {
+ if (len == 4)
+ /* The byte-order of the opcode is weird! */
+ val = swab32(val);
+ mt7621_spi_write(rs, MT7621_SPI_OPCODE + len - 4, val);
+ val = 0;
+ }
+ tx_len -= 1;
+ }
+
+ if (len & 3) {
+ if (len < 4) {
+ val = swab32(val);
+ val >>= (4 - len) * 8;
+ }
+ mt7621_spi_write(rs, MT7621_SPI_OPCODE + (len & ~3), val);
+ }
+
+ rs->pending_write = len;
+}
+
+static int mt7621_spi_transfer_one_message(struct spi_controller *master,
+ struct spi_message *m)
+{
+ struct mt7621_spi *rs = spi_controller_get_devdata(master);
+ struct spi_device *spi = m->spi;
+ unsigned int speed = spi->max_speed_hz;
+ struct spi_transfer *t = NULL;
+ int status = 0;
+
+ mt7621_spi_wait_till_ready(rs);
+
+ list_for_each_entry(t, &m->transfers, transfer_list)
+ if (t->speed_hz < speed)
+ speed = t->speed_hz;
+
+ if (mt7621_spi_prepare(spi, speed)) {
+ status = -EIO;
+ goto msg_done;
+ }
+
+ /* Assert CS */
+ mt7621_spi_set_cs(spi, 1);
+
+ m->actual_length = 0;
+ list_for_each_entry(t, &m->transfers, transfer_list) {
+ if ((t->rx_buf) && (t->tx_buf)) {
+ /*
+ * This controller will shift some extra data out
+ * of spi_opcode if (mosi_bit_cnt > 0) &&
+ * (cmd_bit_cnt == 0). So the claimed full-duplex
+ * support is broken since we have no way to read
+ * the MISO value during that bit.
+ */
+ status = -EIO;
+ goto msg_done;
+ } else if (t->rx_buf) {
+ mt7621_spi_read_half_duplex(rs, t->len, t->rx_buf);
+ } else if (t->tx_buf) {
+ mt7621_spi_write_half_duplex(rs, t->len, t->tx_buf);
+ }
+ m->actual_length += t->len;
+ }
+
+ /* Flush data and deassert CS */
+ mt7621_spi_flush(rs);
+ mt7621_spi_set_cs(spi, 0);
+
+msg_done:
+ m->status = status;
+ spi_finalize_current_message(master);
+
+ return 0;
+}
+
+static int mt7621_spi_setup(struct spi_device *spi)
+{
+ struct mt7621_spi *rs = spidev_to_mt7621_spi(spi);
+
+ if ((spi->max_speed_hz == 0) ||
+ (spi->max_speed_hz > (rs->sys_freq / 2)))
+ spi->max_speed_hz = (rs->sys_freq / 2);
+
+ if (spi->max_speed_hz < (rs->sys_freq / 4097)) {
+ dev_err(&spi->dev, "setup: requested speed is too low %d Hz\n",
+ spi->max_speed_hz);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct of_device_id mt7621_spi_match[] = {
+ { .compatible = "ralink,mt7621-spi" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, mt7621_spi_match);
+
+static int mt7621_spi_probe(struct platform_device *pdev)
+{
+ const struct of_device_id *match;
+ struct spi_controller *master;
+ struct mt7621_spi *rs;
+ void __iomem *base;
+ struct resource *r;
+ int status = 0;
+ struct clk *clk;
+ int ret;
+
+ match = of_match_device(mt7621_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))
+ return PTR_ERR(base);
+
+ clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(clk)) {
+ dev_err(&pdev->dev, "unable to get SYS clock, err=%d\n",
+ status);
+ return PTR_ERR(clk);
+ }
+
+ status = clk_prepare_enable(clk);
+ if (status)
+ return status;
+
+ master = spi_alloc_master(&pdev->dev, sizeof(*rs));
+ if (!master) {
+ dev_info(&pdev->dev, "master allocation failed\n");
+ return -ENOMEM;
+ }
+
+ master->mode_bits = SPI_LSB_FIRST;
+ master->flags = SPI_CONTROLLER_HALF_DUPLEX;
+ master->setup = mt7621_spi_setup;
+ master->transfer_one_message = mt7621_spi_transfer_one_message;
+ master->bits_per_word_mask = SPI_BPW_MASK(8);
+ master->dev.of_node = pdev->dev.of_node;
+ master->num_chipselect = 2;
+
+ dev_set_drvdata(&pdev->dev, master);
+
+ rs = spi_controller_get_devdata(master);
+ rs->base = base;
+ rs->clk = clk;
+ rs->master = master;
+ rs->sys_freq = clk_get_rate(rs->clk);
+ rs->pending_write = 0;
+ dev_info(&pdev->dev, "sys_freq: %u\n", rs->sys_freq);
+
+ ret = device_reset(&pdev->dev);
+ if (ret) {
+ dev_err(&pdev->dev, "SPI reset failed!\n");
+ return ret;
+ }
+
+ return devm_spi_register_controller(&pdev->dev, master);
+}
+
+static int mt7621_spi_remove(struct platform_device *pdev)
+{
+ struct spi_controller *master;
+ struct mt7621_spi *rs;
+
+ master = dev_get_drvdata(&pdev->dev);
+ rs = spi_controller_get_devdata(master);
+
+ clk_disable_unprepare(rs->clk);
+
+ return 0;
+}
+
+MODULE_ALIAS("platform:" DRIVER_NAME);
+
+static struct platform_driver mt7621_spi_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .of_match_table = mt7621_spi_match,
+ },
+ .probe = mt7621_spi_probe,
+ .remove = mt7621_spi_remove,
+};
+
+module_platform_driver(mt7621_spi_driver);
+
+MODULE_DESCRIPTION("MT7621 SPI driver");
+MODULE_AUTHOR("Felix Fietkau <nbd@nbd.name>");
+MODULE_LICENSE("GPL");

View File

@ -45,7 +45,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+};
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -864,6 +864,11 @@ config I2C_RK3X
@@ -922,6 +922,11 @@ config I2C_RK3X
This driver can also be built as a module. If so, the module will
be called i2c-rk3x.
@ -59,14 +59,14 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
help
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -84,6 +84,7 @@ obj-$(CONFIG_I2C_PNX) += i2c-pnx.o
@@ -91,6 +91,7 @@ obj-$(CONFIG_I2C_PNX) += i2c-pnx.o
obj-$(CONFIG_I2C_PUV3) += i2c-puv3.o
obj-$(CONFIG_I2C_PXA) += i2c-pxa.o
obj-$(CONFIG_I2C_PXA_PCI) += i2c-pxa-pci.o
+obj-$(CONFIG_I2C_RALINK) += i2c-ralink.o
obj-$(CONFIG_I2C_QCOM_GENI) += i2c-qcom-geni.o
obj-$(CONFIG_I2C_QUP) += i2c-qup.o
obj-$(CONFIG_I2C_RIIC) += i2c-riic.o
obj-$(CONFIG_I2C_RK3X) += i2c-rk3x.o
--- /dev/null
+++ b/drivers/i2c/busses/i2c-ralink.c
@@ -0,0 +1,435 @@

View File

@ -1,473 +0,0 @@
From d5c54ff3d1db0a4348fa04d8e78f3bf6063e3afc Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Mon, 7 Dec 2015 17:21:27 +0100
Subject: [PATCH 45/53] i2c: add mt7621 driver
Signed-off-by: John Crispin <blogic@openwrt.org>
---
drivers/i2c/busses/Kconfig | 4 +
drivers/i2c/busses/Makefile | 1 +
drivers/i2c/busses/i2c-mt7621.c | 303 +++++++++++++++++++++++++++++++++++++++
3 files changed, 308 insertions(+)
create mode 100644 drivers/i2c/busses/i2c-mt7621.c
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -869,6 +869,11 @@ config I2C_RALINK
depends on RALINK && !SOC_MT7621
select OF_I2C
+config I2C_MT7621
+ tristate "MT7621/MT7628 I2C Controller"
+ depends on RALINK && (SOC_MT7620 || SOC_MT7621)
+ select OF_I2C
+
config HAVE_S3C2410_I2C
bool
help
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -85,6 +85,7 @@ obj-$(CONFIG_I2C_PUV3) += i2c-puv3.o
obj-$(CONFIG_I2C_PXA) += i2c-pxa.o
obj-$(CONFIG_I2C_PXA_PCI) += i2c-pxa-pci.o
obj-$(CONFIG_I2C_RALINK) += i2c-ralink.o
+obj-$(CONFIG_I2C_MT7621) += i2c-mt7621.o
obj-$(CONFIG_I2C_QUP) += i2c-qup.o
obj-$(CONFIG_I2C_RIIC) += i2c-riic.o
obj-$(CONFIG_I2C_RK3X) += i2c-rk3x.o
--- /dev/null
+++ b/drivers/i2c/busses/i2c-mt7621.c
@@ -0,0 +1,433 @@
+/*
+ * drivers/i2c/busses/i2c-mt7621.c
+ *
+ * Copyright (C) 2013 Steven Liu <steven_liu@mediatek.com>
+ * Copyright (C) 2016 Michael Lee <igvtee@gmail.com>
+ *
+ * Improve driver for i2cdetect from i2c-tools to detect i2c devices on the bus.
+ * (C) 2014 Sittisak <sittisaks@hotmail.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/reset.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/of_platform.h>
+#include <linux/i2c.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+
+#define REG_SM0CFG0 0x08
+#define REG_SM0DOUT 0x10
+#define REG_SM0DIN 0x14
+#define REG_SM0ST 0x18
+#define REG_SM0AUTO 0x1C
+#define REG_SM0CFG1 0x20
+#define REG_SM0CFG2 0x28
+#define REG_SM0CTL0 0x40
+#define REG_SM0CTL1 0x44
+#define REG_SM0D0 0x50
+#define REG_SM0D1 0x54
+#define REG_PINTEN 0x5C
+#define REG_PINTST 0x60
+#define REG_PINTCL 0x64
+
+/* REG_SM0CFG0 */
+#define I2C_DEVADDR_MASK 0x7f
+
+/* REG_SM0ST */
+#define I2C_DATARDY BIT(2)
+#define I2C_SDOEMPTY BIT(1)
+#define I2C_BUSY BIT(0)
+
+/* REG_SM0AUTO */
+#define READ_CMD BIT(0)
+
+/* REG_SM0CFG1 */
+#define BYTECNT_MAX 64
+#define SET_BYTECNT(x) (x - 1)
+
+/* REG_SM0CFG2 */
+#define AUTOMODE_EN BIT(0)
+
+/* REG_SM0CTL0 */
+#define ODRAIN_HIGH_SM0 BIT(31)
+#define VSYNC_SHIFT 28
+#define VSYNC_MASK 0x3
+#define VSYNC_PULSE (0x1 << VSYNC_SHIFT)
+#define VSYNC_RISING (0x2 << VSYNC_SHIFT)
+#define CLK_DIV_SHIFT 16
+#define CLK_DIV_MASK 0xfff
+#define DEG_CNT_SHIFT 8
+#define DEG_CNT_MASK 0xff
+#define WAIT_HIGH BIT(6)
+#define DEG_EN BIT(5)
+#define CS_STATUA BIT(4)
+#define SCL_STATUS BIT(3)
+#define SDA_STATUS BIT(2)
+#define SM0_EN BIT(1)
+#define SCL_STRECH BIT(0)
+
+/* REG_SM0CTL1 */
+#define ACK_SHIFT 16
+#define ACK_MASK 0xff
+#define PGLEN_SHIFT 8
+#define PGLEN_MASK 0x7
+#define SM0_MODE_SHIFT 4
+#define SM0_MODE_MASK 0x7
+#define SM0_MODE_START 0x1
+#define SM0_MODE_WRITE 0x2
+#define SM0_MODE_STOP 0x3
+#define SM0_MODE_READ_NACK 0x4
+#define SM0_MODE_READ_ACK 0x5
+#define SM0_TRI_BUSY BIT(0)
+
+/* timeout waiting for I2C devices to respond (clock streching) */
+#define TIMEOUT_MS 1000
+#define DELAY_INTERVAL_US 100
+
+struct mtk_i2c {
+ void __iomem *base;
+ struct clk *clk;
+ struct device *dev;
+ struct i2c_adapter adap;
+ u32 cur_clk;
+ u32 clk_div;
+ u32 flags;
+};
+
+static void mtk_i2c_w32(struct mtk_i2c *i2c, u32 val, unsigned reg)
+{
+ iowrite32(val, i2c->base + reg);
+}
+
+static u32 mtk_i2c_r32(struct mtk_i2c *i2c, unsigned reg)
+{
+ return ioread32(i2c->base + reg);
+}
+
+static int poll_down_timeout(void __iomem *addr, u32 mask)
+{
+ unsigned long timeout = jiffies + msecs_to_jiffies(TIMEOUT_MS);
+
+ do {
+ if (!(readl_relaxed(addr) & mask))
+ return 0;
+
+ usleep_range(DELAY_INTERVAL_US, DELAY_INTERVAL_US + 50);
+ } while (time_before(jiffies, timeout));
+
+ return (readl_relaxed(addr) & mask) ? -EAGAIN : 0;
+}
+
+static int mtk_i2c_wait_idle(struct mtk_i2c *i2c)
+{
+ int ret;
+
+ ret = poll_down_timeout(i2c->base + REG_SM0ST, I2C_BUSY);
+ if (ret < 0)
+ dev_dbg(i2c->dev, "idle err(%d)\n", ret);
+
+ return ret;
+}
+
+static int poll_up_timeout(void __iomem *addr, u32 mask)
+{
+ unsigned long timeout = jiffies + msecs_to_jiffies(TIMEOUT_MS);
+ u32 status;
+
+ do {
+ status = readl_relaxed(addr);
+ if (status & mask)
+ return 0;
+ usleep_range(DELAY_INTERVAL_US, DELAY_INTERVAL_US + 50);
+ } while (time_before(jiffies, timeout));
+
+ return -ETIMEDOUT;
+}
+
+static int mtk_i2c_wait_rx_done(struct mtk_i2c *i2c)
+{
+ int ret;
+
+ ret = poll_up_timeout(i2c->base + REG_SM0ST, I2C_DATARDY);
+ if (ret < 0)
+ dev_dbg(i2c->dev, "rx err(%d)\n", ret);
+
+ return ret;
+}
+
+static int mtk_i2c_wait_tx_done(struct mtk_i2c *i2c)
+{
+ int ret;
+
+ ret = poll_up_timeout(i2c->base + REG_SM0ST, I2C_SDOEMPTY);
+ if (ret < 0)
+ dev_dbg(i2c->dev, "tx err(%d)\n", ret);
+
+ return ret;
+}
+
+static void mtk_i2c_reset(struct mtk_i2c *i2c)
+{
+ u32 reg;
+ device_reset(i2c->adap.dev.parent);
+ barrier();
+
+ /* ctrl0 */
+ reg = ODRAIN_HIGH_SM0 | VSYNC_PULSE | (i2c->clk_div << CLK_DIV_SHIFT) |
+ WAIT_HIGH | SM0_EN;
+ mtk_i2c_w32(i2c, reg, REG_SM0CTL0);
+
+ /* auto mode */
+ mtk_i2c_w32(i2c, AUTOMODE_EN, REG_SM0CFG2);
+}
+
+static void mtk_i2c_dump_reg(struct mtk_i2c *i2c)
+{
+ dev_dbg(i2c->dev, "cfg0 %08x, dout %08x, din %08x, " \
+ "status %08x, auto %08x, cfg1 %08x, " \
+ "cfg2 %08x, ctl0 %08x, ctl1 %08x\n",
+ mtk_i2c_r32(i2c, REG_SM0CFG0),
+ mtk_i2c_r32(i2c, REG_SM0DOUT),
+ mtk_i2c_r32(i2c, REG_SM0DIN),
+ mtk_i2c_r32(i2c, REG_SM0ST),
+ mtk_i2c_r32(i2c, REG_SM0AUTO),
+ mtk_i2c_r32(i2c, REG_SM0CFG1),
+ mtk_i2c_r32(i2c, REG_SM0CFG2),
+ mtk_i2c_r32(i2c, REG_SM0CTL0),
+ mtk_i2c_r32(i2c, REG_SM0CTL1));
+}
+
+static int mtk_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
+ int num)
+{
+ struct mtk_i2c *i2c;
+ struct i2c_msg *pmsg;
+ int i, j, ret;
+ u32 cmd;
+
+ i2c = i2c_get_adapdata(adap);
+
+ for (i = 0; i < num; i++) {
+ pmsg = &msgs[i];
+ cmd = 0;
+
+ dev_dbg(i2c->dev, "addr: 0x%x, len: %d, flags: 0x%x\n",
+ pmsg->addr, pmsg->len, pmsg->flags);
+
+ /* wait hardware idle */
+ if ((ret = mtk_i2c_wait_idle(i2c)))
+ goto err_timeout;
+
+ if (pmsg->flags & I2C_M_TEN) {
+ dev_dbg(i2c->dev, "10 bits addr not supported\n");
+ return -EINVAL;
+ } else {
+ /* 7 bits address */
+ mtk_i2c_w32(i2c, pmsg->addr & I2C_DEVADDR_MASK,
+ REG_SM0CFG0);
+ }
+
+ /* buffer length */
+ if (pmsg->len == 0) {
+ dev_dbg(i2c->dev, "length is 0\n");
+ return -EINVAL;
+ } else
+ mtk_i2c_w32(i2c, SET_BYTECNT(pmsg->len),
+ REG_SM0CFG1);
+
+ j = 0;
+ if (pmsg->flags & I2C_M_RD) {
+ cmd |= READ_CMD;
+ /* start transfer */
+ barrier();
+ mtk_i2c_w32(i2c, cmd, REG_SM0AUTO);
+ do {
+ /* wait */
+ if ((ret = mtk_i2c_wait_rx_done(i2c)))
+ goto err_timeout;
+ /* read data */
+ if (pmsg->len)
+ pmsg->buf[j] = mtk_i2c_r32(i2c,
+ REG_SM0DIN);
+ j++;
+ } while (j < pmsg->len);
+ } else {
+ do {
+ /* write data */
+ if (pmsg->len)
+ mtk_i2c_w32(i2c, pmsg->buf[j],
+ REG_SM0DOUT);
+ /* start transfer */
+ if (j == 0) {
+ barrier();
+ mtk_i2c_w32(i2c, cmd, REG_SM0AUTO);
+ }
+ /* wait */
+ if ((ret = mtk_i2c_wait_tx_done(i2c)))
+ goto err_timeout;
+ j++;
+ } while (j < pmsg->len);
+ }
+ }
+ /* the return value is number of executed messages */
+ ret = i;
+
+ return ret;
+
+err_timeout:
+ mtk_i2c_dump_reg(i2c);
+ mtk_i2c_reset(i2c);
+ return ret;
+}
+
+static u32 mtk_i2c_func(struct i2c_adapter *a)
+{
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static const struct i2c_algorithm mtk_i2c_algo = {
+ .master_xfer = mtk_i2c_master_xfer,
+ .functionality = mtk_i2c_func,
+};
+
+static const struct of_device_id i2c_mtk_dt_ids[] = {
+ { .compatible = "mediatek,mt7621-i2c" },
+ { /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, i2c_mtk_dt_ids);
+
+static struct i2c_adapter_quirks mtk_i2c_quirks = {
+ .max_write_len = BYTECNT_MAX,
+ .max_read_len = BYTECNT_MAX,
+};
+
+static void mtk_i2c_init(struct mtk_i2c *i2c)
+{
+ i2c->clk_div = clk_get_rate(i2c->clk) / i2c->cur_clk;
+ if (i2c->clk_div > CLK_DIV_MASK)
+ i2c->clk_div = CLK_DIV_MASK;
+
+ mtk_i2c_reset(i2c);
+}
+
+static int mtk_i2c_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ struct mtk_i2c *i2c;
+ struct i2c_adapter *adap;
+ const struct of_device_id *match;
+ int ret;
+
+ match = of_match_device(i2c_mtk_dt_ids, &pdev->dev);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "no memory resource found\n");
+ return -ENODEV;
+ }
+
+ i2c = devm_kzalloc(&pdev->dev, sizeof(struct mtk_i2c), GFP_KERNEL);
+ if (!i2c) {
+ dev_err(&pdev->dev, "failed to allocate i2c_adapter\n");
+ return -ENOMEM;
+ }
+
+ i2c->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(i2c->base))
+ return PTR_ERR(i2c->base);
+
+ i2c->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(i2c->clk)) {
+ dev_err(&pdev->dev, "no clock defined\n");
+ return -ENODEV;
+ }
+ clk_prepare_enable(i2c->clk);
+ i2c->dev = &pdev->dev;
+
+ if (of_property_read_u32(pdev->dev.of_node,
+ "clock-frequency", &i2c->cur_clk))
+ i2c->cur_clk = 100000;
+
+ adap = &i2c->adap;
+ adap->owner = THIS_MODULE;
+ adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
+ adap->algo = &mtk_i2c_algo;
+ adap->retries = 3;
+ adap->dev.parent = &pdev->dev;
+ i2c_set_adapdata(adap, i2c);
+ adap->dev.of_node = pdev->dev.of_node;
+ strlcpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name));
+ adap->quirks = &mtk_i2c_quirks;
+
+ platform_set_drvdata(pdev, i2c);
+
+ mtk_i2c_init(i2c);
+
+ ret = i2c_add_adapter(adap);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to add adapter\n");
+ clk_disable_unprepare(i2c->clk);
+ return ret;
+ }
+
+ dev_info(&pdev->dev, "clock %uKHz, re-start not support\n",
+ i2c->cur_clk/1000);
+
+ return ret;
+}
+
+static int mtk_i2c_remove(struct platform_device *pdev)
+{
+ struct mtk_i2c *i2c = platform_get_drvdata(pdev);
+
+ i2c_del_adapter(&i2c->adap);
+ clk_disable_unprepare(i2c->clk);
+
+ return 0;
+}
+
+static struct platform_driver mtk_i2c_driver = {
+ .probe = mtk_i2c_probe,
+ .remove = mtk_i2c_remove,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "i2c-mt7621",
+ .of_match_table = i2c_mtk_dt_ids,
+ },
+};
+
+static int __init i2c_mtk_init (void)
+{
+ return platform_driver_register(&mtk_i2c_driver);
+}
+subsys_initcall(i2c_mtk_init);
+
+static void __exit i2c_mtk_exit (void)
+{
+ platform_driver_unregister(&mtk_i2c_driver);
+}
+module_exit(i2c_mtk_exit);
+
+MODULE_AUTHOR("Steven Liu <steven_liu@mediatek.com>");
+MODULE_DESCRIPTION("MT7621 I2c host driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:MT7621-I2C");

View File

@ -25,9 +25,9 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -901,3 +901,5 @@ config MMC_SDHCI_XENON
This selects Marvell Xenon eMMC/SD/SDIO SDHCI.
@@ -1019,3 +1019,5 @@ config MMC_SDHCI_AM654
If you have a controller with this interface, say Y or M here.
If unsure, say N.
+
+source "drivers/mmc/host/mtk-mmc/Kconfig"

View File

@ -20,15 +20,15 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
--- a/arch/mips/ralink/of.c
+++ b/arch/mips/ralink/of.c
@@ -15,6 +15,7 @@
@@ -13,6 +13,7 @@
#include <linux/of_fdt.h>
#include <linux/kernel.h>
#include <linux/bootmem.h>
#include <linux/memblock.h>
+#include <linux/module.h>
#include <linux/of_platform.h>
#include <linux/of_address.h>
@@ -26,6 +27,7 @@
@@ -24,6 +25,7 @@
#include "common.h"
__iomem void *rt_sysc_membase;
@ -38,7 +38,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
__iomem void *plat_of_remap_node(const char *node)
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -59,6 +59,7 @@ source "sound/soc/mxs/Kconfig"
@@ -60,6 +60,7 @@ source "sound/soc/mxs/Kconfig"
source "sound/soc/pxa/Kconfig"
source "sound/soc/qcom/Kconfig"
source "sound/soc/rockchip/Kconfig"
@ -48,7 +48,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
source "sound/soc/sirf/Kconfig"
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -40,6 +40,7 @@ obj-$(CONFIG_SND_SOC) += kirkwood/
@@ -43,6 +43,7 @@ obj-$(CONFIG_SND_SOC) += kirkwood/
obj-$(CONFIG_SND_SOC) += pxa/
obj-$(CONFIG_SND_SOC) += qcom/
obj-$(CONFIG_SND_SOC) += rockchip/

View File

@ -10,7 +10,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -428,6 +428,9 @@ uart_get_baud_rate(struct uart_port *por
@@ -416,6 +416,9 @@ uart_get_baud_rate(struct uart_port *por
break;
}

View File

@ -13,7 +13,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -302,6 +302,15 @@ config PWM_MEDIATEK
@@ -316,6 +316,15 @@ config PWM_MEDIATEK
To compile this driver as a module, choose M here: the module
will be called pwm-mediatek.
@ -31,7 +31,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
depends on ARCH_MXS && OF
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_PWM_LPSS_PCI) += pwm-lpss-p
@@ -29,6 +29,7 @@ obj-$(CONFIG_PWM_LPSS_PCI) += pwm-lpss-p
obj-$(CONFIG_PWM_LPSS_PLATFORM) += pwm-lpss-platform.o
obj-$(CONFIG_PWM_MESON) += pwm-meson.o
obj-$(CONFIG_PWM_MEDIATEK) += pwm-mediatek.o

View File

@ -1,214 +0,0 @@
mtd: spi-nor: add support for switching between 3-byte and 4-byte addressing on w25q256 flash
On some devices the flash chip needs to be in 3-byte addressing mode during
reboot, otherwise the boot loader will fail to start.
This mode however does not allow regular reads/writes onto the upper 16M
half. W25Q256 has separate read commands for reading from >16M, however
it does not have any separate write commands.
This patch changes the code to leave the chip in 3-byte mode most of the
time and only switch during erase/write cycles that go to >16M
addresses.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -89,6 +89,10 @@ struct flash_info {
#define NO_CHIP_ERASE BIT(12) /* Chip does not support chip erase */
#define SPI_NOR_SKIP_SFDP BIT(13) /* Skip parsing of SFDP tables */
#define USE_CLSR BIT(14) /* use CLSR command */
+#define SPI_NOR_4B_READ_OP BIT(15) /*
+ * Like SPI_NOR_4B_OPCODES, but for read
+ * op code only.
+ */
};
#define JEDEC_MFR(info) ((info)->id[0])
@@ -240,6 +244,15 @@ static inline u8 spi_nor_convert_3to4_er
ARRAY_SIZE(spi_nor_3to4_erase));
}
+static void spi_nor_set_4byte_read(struct spi_nor *nor,
+ const struct flash_info *info)
+{
+ nor->addr_width = 3;
+ nor->ext_addr = 0;
+ nor->read_opcode = spi_nor_convert_3to4_read(nor->read_opcode);
+ nor->flags |= SNOR_F_4B_EXT_ADDR;
+}
+
static void spi_nor_set_4byte_opcodes(struct spi_nor *nor,
const struct flash_info *info)
{
@@ -467,6 +480,36 @@ static int spi_nor_erase_sector(struct s
return nor->write_reg(nor, nor->erase_opcode, buf, nor->addr_width);
}
+static int spi_nor_check_ext_addr(struct spi_nor *nor, u32 addr)
+{
+ bool ext_addr;
+ int ret;
+ u8 cmd;
+
+ if (!(nor->flags & SNOR_F_4B_EXT_ADDR))
+ return 0;
+
+ ext_addr = !!(addr & 0xff000000);
+ if (nor->ext_addr == ext_addr)
+ return 0;
+
+ cmd = ext_addr ? SPINOR_OP_EN4B : SPINOR_OP_EX4B;
+ write_enable(nor);
+ ret = nor->write_reg(nor, cmd, NULL, 0);
+ if (ret)
+ return ret;
+
+ cmd = 0;
+ ret = nor->write_reg(nor, SPINOR_OP_WREAR, &cmd, 1);
+ if (ret)
+ return ret;
+
+ nor->addr_width = 3 + ext_addr;
+ nor->ext_addr = ext_addr;
+ write_disable(nor);
+ return 0;
+}
+
/*
* Erase an address range on the nor chip. The address range may extend
* one or more erase sectors. Return an error is there is a problem erasing.
@@ -492,6 +535,10 @@ static int spi_nor_erase(struct mtd_info
if (ret)
return ret;
+ ret = spi_nor_check_ext_addr(nor, addr + len);
+ if (ret)
+ return ret;
+
/* whole-chip erase? */
if (len == mtd->size && !(nor->flags & SNOR_F_NO_OP_CHIP_ERASE)) {
unsigned long timeout;
@@ -542,6 +589,7 @@ static int spi_nor_erase(struct mtd_info
write_disable(nor);
erase_err:
+ spi_nor_check_ext_addr(nor, 0);
spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_ERASE);
instr->state = ret ? MTD_ERASE_FAILED : MTD_ERASE_DONE;
@@ -834,7 +882,9 @@ static int spi_nor_lock(struct mtd_info
if (ret)
return ret;
+ spi_nor_check_ext_addr(nor, ofs + len);
ret = nor->flash_lock(nor, ofs, len);
+ spi_nor_check_ext_addr(nor, 0);
spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_UNLOCK);
return ret;
@@ -849,7 +899,9 @@ static int spi_nor_unlock(struct mtd_inf
if (ret)
return ret;
+ spi_nor_check_ext_addr(nor, ofs + len);
ret = nor->flash_unlock(nor, ofs, len);
+ spi_nor_check_ext_addr(nor, 0);
spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_LOCK);
return ret;
@@ -1182,7 +1234,7 @@ static const struct flash_info spi_nor_i
{ "w25q80", INFO(0xef5014, 0, 64 * 1024, 16, SECT_4K) },
{ "w25q80bl", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) },
{ "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) },
- { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+ { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_READ_OP) },
{ "w25m512jv", INFO(0xef7119, 0, 64 * 1024, 1024,
SECT_4K | SPI_NOR_QUAD_READ | SPI_NOR_DUAL_READ) },
@@ -1245,6 +1297,9 @@ static int spi_nor_read(struct mtd_info
if (ret)
return ret;
+ if (nor->flags & SNOR_F_4B_EXT_ADDR)
+ nor->addr_width = 4;
+
while (len) {
loff_t addr = from;
@@ -1269,6 +1324,18 @@ static int spi_nor_read(struct mtd_info
ret = 0;
read_err:
+ if (nor->flags & SNOR_F_4B_EXT_ADDR) {
+ u8 val = 0;
+
+ if ((from + len) & 0xff000000) {
+ write_enable(nor);
+ nor->write_reg(nor, SPINOR_OP_WREAR, &val, 1);
+ write_disable(nor);
+ }
+
+ nor->addr_width = 3;
+ }
+
spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_READ);
return ret;
}
@@ -1370,6 +1437,10 @@ static int spi_nor_write(struct mtd_info
if (ret)
return ret;
+ ret = spi_nor_check_ext_addr(nor, to + len);
+ if (ret < 0)
+ return ret;
+
for (i = 0; i < len; ) {
ssize_t written;
loff_t addr = to + i;
@@ -1410,6 +1481,7 @@ static int spi_nor_write(struct mtd_info
}
write_err:
+ spi_nor_check_ext_addr(nor, 0);
spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_WRITE);
return ret;
}
@@ -2826,8 +2898,10 @@ int spi_nor_scan(struct spi_nor *nor, co
} else if (mtd->size > 0x1000000) {
/* enable 4-byte addressing if the device exceeds 16MiB */
nor->addr_width = 4;
- if (JEDEC_MFR(info) == SNOR_MFR_SPANSION ||
- info->flags & SPI_NOR_4B_OPCODES)
+ if (info->flags & SPI_NOR_4B_READ_OP)
+ spi_nor_set_4byte_read(nor, info);
+ else if (JEDEC_MFR(info) == SNOR_MFR_SPANSION ||
+ info->flags & SPI_NOR_4B_OPCODES)
spi_nor_set_4byte_opcodes(nor, info);
else
set_4byte(nor, info, 1);
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -102,6 +102,7 @@
/* Used for Macronix and Winbond flashes. */
#define SPINOR_OP_EN4B 0xb7 /* Enter 4-byte mode */
#define SPINOR_OP_EX4B 0xe9 /* Exit 4-byte mode */
+#define SPINOR_OP_WREAR 0xc5 /* Write extended address register */
/* Used for Spansion flashes only. */
#define SPINOR_OP_BRWR 0x17 /* Bank register write */
@@ -229,6 +230,7 @@ enum spi_nor_option_flags {
SNOR_F_S3AN_ADDR_DEFAULT = BIT(3),
SNOR_F_READY_XSR_RDY = BIT(4),
SNOR_F_USE_CLSR = BIT(5),
+ SNOR_F_4B_EXT_ADDR = BIT(6),
};
/**
@@ -280,6 +282,7 @@ struct spi_nor {
enum spi_nor_protocol reg_proto;
bool sst_write_second;
u32 flags;
+ u8 ext_addr;
u8 cmd_buf[SPI_NOR_MAX_CMD_SIZE];
int (*prepare)(struct spi_nor *nor, enum spi_nor_ops ops);

View File

@ -1,73 +0,0 @@
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -142,20 +142,29 @@ static int read_fsr(struct spi_nor *nor)
* location. Return the configuration register value.
* Returns negative if error occurred.
*/
-static int read_cr(struct spi_nor *nor)
+static int _read_cr(struct spi_nor *nor, u8 reg)
{
int ret;
u8 val;
- ret = nor->read_reg(nor, SPINOR_OP_RDCR, &val, 1);
+ ret = nor->read_reg(nor, reg, &val, 1);
if (ret < 0) {
- dev_err(nor->dev, "error %d reading CR\n", ret);
+ dev_err(nor->dev, "error %d reading %s\n", ret,
+ (reg==SPINOR_OP_RDCR)?"CR":"XCR");
return ret;
}
return val;
}
+static inline int read_cr(struct spi_nor *nor) {
+ return _read_cr(nor, SPINOR_OP_RDCR);
+}
+
+static inline int read_xcr(struct spi_nor *nor) {
+ return _read_cr(nor, SPINOR_OP_RDXCR);
+}
+
/*
* Write status register 1 byte
* Returns negative if error occurred.
@@ -2898,9 +2907,16 @@ int spi_nor_scan(struct spi_nor *nor, co
} else if (mtd->size > 0x1000000) {
/* enable 4-byte addressing if the device exceeds 16MiB */
nor->addr_width = 4;
- if (info->flags & SPI_NOR_4B_READ_OP)
- spi_nor_set_4byte_read(nor, info);
- else if (JEDEC_MFR(info) == SNOR_MFR_SPANSION ||
+ if (info->flags & SPI_NOR_4B_READ_OP) {
+ if (JEDEC_MFR(info) == SNOR_MFR_WINBOND) {
+ ret = read_xcr(nor);
+ if (!(ret > 0 && (ret & XCR_DEF_4B_ADDR_MODE)))
+ spi_nor_set_4byte_read(nor, info);
+ else
+ set_4byte(nor, info, 1);
+ } else
+ spi_nor_set_4byte_read(nor, info);
+ } else if (JEDEC_MFR(info) == SNOR_MFR_SPANSION ||
info->flags & SPI_NOR_4B_OPCODES)
spi_nor_set_4byte_opcodes(nor, info);
else
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -103,6 +103,7 @@
#define SPINOR_OP_EN4B 0xb7 /* Enter 4-byte mode */
#define SPINOR_OP_EX4B 0xe9 /* Exit 4-byte mode */
#define SPINOR_OP_WREAR 0xc5 /* Write extended address register */
+#define SPINOR_OP_RDXCR 0x15 /* Read extended configuration register */
/* Used for Spansion flashes only. */
#define SPINOR_OP_BRWR 0x17 /* Bank register write */
@@ -135,6 +136,7 @@
/* Configuration Register bits. */
#define CR_QUAD_EN_SPAN BIT(1) /* Spansion Quad I/O */
+#define XCR_DEF_4B_ADDR_MODE BIT(1) /* Winbond 4B mode default */
/* Status Register 2 bits. */
#define SR2_QUAD_EN_BIT7 BIT(7)

View File

@ -1,12 +1,12 @@
--- a/drivers/usb/dwc2/platform.c
+++ b/drivers/usb/dwc2/platform.c
@@ -406,6 +406,12 @@ static int dwc2_driver_probe(struct plat
if (retval)
return retval;
@@ -432,6 +432,12 @@ static int dwc2_driver_probe(struct plat
hsotg->needs_byte_swap = dwc2_check_core_endianness(hsotg);
+ /* Enable USB port before any regs access */
+ if (dwc2_readl(hsotg->regs + PCGCTL) & 0x0f) {
+ dwc2_writel(0x00, hsotg->regs + PCGCTL);
+ if (dwc2_readl(hsotg, PCGCTL) & 0x0f) {
+ dwc2_writel(0x00, hsotg, PCGCTL);
+ /* TODO: mdelay(25) here? vendor driver don't use it */
+ }
+

View File

@ -1,9 +1,9 @@
--- a/arch/mips/ralink/Kconfig
+++ b/arch/mips/ralink/Kconfig
@@ -58,6 +58,7 @@ choice
@@ -57,6 +57,7 @@ choice
select COMMON_CLK
select CLKSRC_MIPS_GIC
select HW_HAS_PCI
select HAVE_PCI if PCI_MT7621
+ select WEAK_REORDERING_BEYOND_LLSC
endchoice

View File

@ -1,6 +1,6 @@
--- a/arch/mips/kernel/mips-cm.c
+++ b/arch/mips/kernel/mips-cm.c
@@ -237,6 +237,7 @@ int mips_cm_probe(void)
@@ -233,6 +233,7 @@ int mips_cm_probe(void)
/* disable CM regions */
write_gcr_reg0_base(CM_GCR_REGn_BASE_BASEADDR);
@ -8,7 +8,7 @@
write_gcr_reg0_mask(CM_GCR_REGn_MASK_ADDRMASK);
write_gcr_reg1_base(CM_GCR_REGn_BASE_BASEADDR);
write_gcr_reg1_mask(CM_GCR_REGn_MASK_ADDRMASK);
@@ -244,7 +245,7 @@ int mips_cm_probe(void)
@@ -240,7 +241,7 @@ int mips_cm_probe(void)
write_gcr_reg2_mask(CM_GCR_REGn_MASK_ADDRMASK);
write_gcr_reg3_base(CM_GCR_REGn_BASE_BASEADDR);
write_gcr_reg3_mask(CM_GCR_REGn_MASK_ADDRMASK);

View File

@ -1,10 +0,0 @@
--- a/arch/mips/pci/pci-mt7620.c
+++ b/arch/mips/pci/pci-mt7620.c
@@ -33,7 +33,6 @@
#define RALINK_GPIOMODE 0x60
#define PPLL_CFG1 0x9c
-#define PDRV_SW_SET BIT(23)
#define PPLL_DRV 0xa0
#define PDRV_SW_SET (1<<31)

View File

@ -1,13 +1,13 @@
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -56,6 +56,7 @@ obj-$(CONFIG_CXL_BASE) += cxl/
obj-$(CONFIG_ASPEED_LPC_CTRL) += aspeed-lpc-ctrl.o
obj-$(CONFIG_ASPEED_LPC_SNOOP) += aspeed-lpc-snoop.o
@@ -52,6 +52,7 @@ obj-$(CONFIG_ECHO) += echo/
obj-$(CONFIG_VEXPRESS_SYSCFG) += vexpress-syscfg.o
obj-$(CONFIG_CXL_BASE) += cxl/
obj-$(CONFIG_PCI_ENDPOINT_TEST) += pci_endpoint_test.o
+obj-$(CONFIG_SOC_MT7620) += linkit.o
lkdtm-$(CONFIG_LKDTM) += lkdtm_core.o
lkdtm-$(CONFIG_LKDTM) += lkdtm_bugs.o
obj-$(CONFIG_OCXL) += ocxl/
obj-y += cardreader/
obj-$(CONFIG_PVPANIC) += pvpanic.o
--- /dev/null
+++ b/drivers/misc/linkit.c
@@ -0,0 +1,84 @@

View File

@ -7,7 +7,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
--- a/arch/mips/kernel/smp-cps.c
+++ b/arch/mips/kernel/smp-cps.c
@@ -47,6 +47,11 @@ static unsigned core_vpe_count(unsigned
@@ -43,6 +43,11 @@ static unsigned core_vpe_count(unsigned
return mips_cps_numvps(cluster, core);
}
@ -19,7 +19,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
static void __init cps_smp_setup(void)
{
unsigned int nclusters, ncores, nvpes, core_vpes;
@@ -64,6 +69,8 @@ static void __init cps_smp_setup(void)
@@ -60,6 +65,8 @@ static void __init cps_smp_setup(void)
ncores = mips_cps_numcores(cl);
for (c = 0; c < ncores; c++) {
@ -30,7 +30,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
if (c > 0)
--- a/arch/mips/ralink/mt7621.c
+++ b/arch/mips/ralink/mt7621.c
@@ -15,6 +15,7 @@
@@ -13,6 +13,7 @@
#include <asm/mips-cps.h>
#include <asm/mach-ralink/ralink_regs.h>
#include <asm/mach-ralink/mt7621.h>
@ -38,7 +38,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
#include <pinmux.h>
@@ -162,6 +163,20 @@ void __init ralink_of_remap(void)
@@ -160,6 +161,20 @@ void __init ralink_of_remap(void)
panic("Failed to remap core resources");
}

View File

@ -1,6 +1,6 @@
--- a/arch/mips/ralink/mt7621.c
+++ b/arch/mips/ralink/mt7621.c
@@ -9,6 +9,7 @@
@@ -7,6 +7,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
@ -8,7 +8,7 @@
#include <asm/mipsregs.h>
#include <asm/smp-ops.h>
@@ -16,6 +17,7 @@
@@ -14,6 +15,7 @@
#include <asm/mach-ralink/ralink_regs.h>
#include <asm/mach-ralink/mt7621.h>
#include <asm/mips-boards/launch.h>
@ -16,7 +16,7 @@
#include <pinmux.h>
@@ -177,6 +179,58 @@ bool plat_cpu_core_present(int core)
@@ -175,6 +177,58 @@ bool plat_cpu_core_present(int core)
return true;
}
@ -77,9 +77,9 @@
void __iomem *sysc = (void __iomem *) KSEG1ADDR(MT7621_SYSC_BASE);
--- a/arch/mips/ralink/Kconfig
+++ b/arch/mips/ralink/Kconfig
@@ -59,6 +59,7 @@ choice
@@ -58,6 +58,7 @@ choice
select CLKSRC_MIPS_GIC
select HW_HAS_PCI
select HAVE_PCI if PCI_MT7621
select WEAK_REORDERING_BEYOND_LLSC
+ select GENERIC_CLOCKEVENTS_BROADCAST
endchoice

View File

@ -1,6 +1,6 @@
--- a/arch/mips/include/asm/mach-ralink/mt7621.h
+++ b/arch/mips/include/asm/mach-ralink/mt7621.h
@@ -19,6 +19,10 @@
@@ -17,6 +17,10 @@
#define SYSC_REG_CHIP_REV 0x0c
#define SYSC_REG_SYSTEM_CONFIG0 0x10
#define SYSC_REG_SYSTEM_CONFIG1 0x14
@ -11,7 +11,7 @@
#define CHIP_REV_PKG_MASK 0x1
#define CHIP_REV_PKG_SHIFT 16
@@ -26,6 +30,22 @@
@@ -24,6 +28,22 @@
#define CHIP_REV_VER_SHIFT 8
#define CHIP_REV_ECO_MASK 0xf
@ -36,7 +36,7 @@
#define MT7621_DDR2_SIZE_MAX 256
--- a/arch/mips/ralink/mt7621.c
+++ b/arch/mips/ralink/mt7621.c
@@ -10,6 +10,10 @@
@@ -8,6 +8,10 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/jiffies.h>
@ -47,7 +47,7 @@
#include <asm/mipsregs.h>
#include <asm/smp-ops.h>
@@ -18,16 +22,12 @@
@@ -16,16 +20,12 @@
#include <asm/mach-ralink/mt7621.h>
#include <asm/mips-boards/launch.h>
#include <asm/delay.h>
@ -65,7 +65,7 @@
#define MT7621_GPIO_MODE_UART1 1
#define MT7621_GPIO_MODE_I2C 2
#define MT7621_GPIO_MODE_UART3_MASK 0x3
@@ -113,49 +113,89 @@ static struct rt2880_pmx_group mt7621_pi
@@ -111,49 +111,89 @@ static struct rt2880_pmx_group mt7621_pi
{ 0 }
};
@ -184,7 +184,7 @@
rt_sysc_membase = plat_of_remap_node("mtk,mt7621-sysc");
--- a/arch/mips/ralink/timer-gic.c
+++ b/arch/mips/ralink/timer-gic.c
@@ -11,14 +11,14 @@
@@ -9,14 +9,14 @@
#include <linux/of.h>
#include <linux/clk-provider.h>

View File

@ -28,7 +28,7 @@ Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
--- a/arch/mips/include/asm/mach-ralink/mt7621.h
+++ b/arch/mips/include/asm/mach-ralink/mt7621.h
@@ -46,9 +46,10 @@
@@ -44,9 +44,10 @@
#define CPU_PLL_FBDIV_MASK 0x7f
#define CPU_PLL_FBDIV_SHIFT 4
@ -44,7 +44,7 @@ Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
#define MT7621_CHIP_NAME1 0x20203132
--- a/arch/mips/ralink/mt7621.c
+++ b/arch/mips/ralink/mt7621.c
@@ -15,6 +15,7 @@
@@ -13,6 +13,7 @@
#include <linux/clk-provider.h>
#include <dt-bindings/clock/mt7621-clk.h>
@ -52,7 +52,7 @@ Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
#include <asm/mipsregs.h>
#include <asm/smp-ops.h>
#include <asm/mips-cps.h>
@@ -57,6 +58,8 @@
@@ -55,6 +56,8 @@
#define MT7621_GPIO_MODE_SDHCI_SHIFT 18
#define MT7621_GPIO_MODE_SDHCI_GPIO 1
@ -61,7 +61,7 @@ Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
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[] = {
@@ -141,6 +144,28 @@ static struct clk *__init mt7621_add_sys
@@ -139,6 +142,28 @@ static struct clk *__init mt7621_add_sys
return clk;
}
@ -90,7 +90,7 @@ Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
void __init ralink_clk_init(void)
{
u32 syscfg, xtal_sel, clkcfg, clk_sel, curclk, ffiv, ffrac;
@@ -319,10 +344,7 @@ void prom_soc_init(struct ralink_soc_inf
@@ -317,10 +342,7 @@ void prom_soc_init(struct ralink_soc_inf
(rev >> CHIP_REV_VER_SHIFT) & CHIP_REV_VER_MASK,
(rev & CHIP_REV_ECO_MASK));
@ -104,7 +104,7 @@ Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
--- a/arch/mips/ralink/common.h
+++ b/arch/mips/ralink/common.h
@@ -19,6 +19,7 @@ struct ralink_soc_info {
@@ -17,6 +17,7 @@ struct ralink_soc_info {
unsigned long mem_size;
unsigned long mem_size_min;
unsigned long mem_size_max;
@ -114,7 +114,7 @@ Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
--- a/arch/mips/ralink/of.c
+++ b/arch/mips/ralink/of.c
@@ -89,6 +89,8 @@ void __init plat_mem_setup(void)
@@ -87,6 +87,8 @@ void __init plat_mem_setup(void)
of_scan_flat_dt(early_init_dt_find_memory, NULL);
if (memory_dtb)
of_scan_flat_dt(early_init_dt_scan_memory, NULL);

View File

@ -1,6 +1,6 @@
--- a/arch/mips/ralink/irq-gic.c
+++ b/arch/mips/ralink/irq-gic.c
@@ -15,6 +15,12 @@
@@ -13,6 +13,12 @@
int get_c0_perfcount_int(void)
{

View File

@ -1,6 +1,6 @@
--- a/arch/mips/include/asm/mach-ralink/mt7620.h
+++ b/arch/mips/include/asm/mach-ralink/mt7620.h
@@ -137,4 +137,16 @@ static inline int mt7620_get_eco(void)
@@ -135,4 +135,16 @@ static inline int mt7620_get_eco(void)
return rt_sysc_r32(SYSC_REG_CHIP_REV) & CHIP_REV_ECO_MASK;
}

View File

@ -1,8 +1,8 @@
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -1066,6 +1066,11 @@ static const struct flash_info spi_nor_i
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
@@ -2238,6 +2238,11 @@ static const struct flash_info spi_nor_i
SPI_NOR_4B_OPCODES | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
.fixups = &gd25q256_fixups,
},
+ {
+ "gd25q512", INFO(0xc84020, 0, 64 * 1024, 1024,

View File

@ -1,72 +0,0 @@
This hack can be dropped after the next stable release from
v5.x-tree.
The problem was fixed upstream by
commit 2bffa65da43e ("mtd: spi-nor: Add a post BFPT fixup for MX25L25635E")
For reference see:
<https://github.com/openwrt/openwrt/pull/1743>
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -1103,6 +1103,7 @@ static const struct flash_info spi_nor_i
{ "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) },
{ "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) },
{ "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+ { "mx25l25635f", INFO(0xc22019, 0, 64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
{ "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_4B_OPCODES) },
{ "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
{ "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
@@ -1275,11 +1276,12 @@ static const struct flash_info spi_nor_i
{ },
};
-static const struct flash_info *spi_nor_read_id(struct spi_nor *nor)
+static const struct flash_info *spi_nor_read_id(struct spi_nor *nor,
+ const char *name)
{
int tmp;
u8 id[SPI_NOR_MAX_ID_LEN];
- const struct flash_info *info;
+ const struct flash_info *info, *first_match = NULL;
tmp = nor->read_reg(nor, SPINOR_OP_RDID, id, SPI_NOR_MAX_ID_LEN);
if (tmp < 0) {
@@ -1290,10 +1292,16 @@ static const struct flash_info *spi_nor_
for (tmp = 0; tmp < ARRAY_SIZE(spi_nor_ids) - 1; tmp++) {
info = &spi_nor_ids[tmp];
if (info->id_len) {
- if (!memcmp(info->id, id, info->id_len))
- return &spi_nor_ids[tmp];
+ if (!memcmp(info->id, id, info->id_len)) {
+ if (!name || !strcmp(name, info->name))
+ return info;
+ if (!first_match)
+ first_match = info;
+ }
}
}
+ if (first_match)
+ return first_match;
dev_err(nor->dev, "unrecognized JEDEC id bytes: %02x, %02x, %02x\n",
id[0], id[1], id[2]);
return ERR_PTR(-ENODEV);
@@ -2773,7 +2781,7 @@ int spi_nor_scan(struct spi_nor *nor, co
info = spi_nor_match_id(name);
/* Try to auto-detect if chip name wasn't specified or not found */
if (!info)
- info = spi_nor_read_id(nor);
+ info = spi_nor_read_id(nor, NULL);
if (IS_ERR_OR_NULL(info))
return -ENOENT;
@@ -2784,7 +2792,7 @@ int spi_nor_scan(struct spi_nor *nor, co
if (name && info->id_len) {
const struct flash_info *jinfo;
- jinfo = spi_nor_read_id(nor);
+ jinfo = spi_nor_read_id(nor, name);
if (IS_ERR(jinfo)) {
return PTR_ERR(jinfo);
} else if (jinfo != info) {

View File

@ -1,14 +1,14 @@
--- a/arch/mips/pci/pci-mt7620.c
+++ b/arch/mips/pci/pci-mt7620.c
@@ -35,6 +35,7 @@
@@ -32,6 +32,7 @@
#define PPLL_CFG1 0x9c
#define PPLL_DRV 0xa0
+#define PPLL_LD (1<<23)
#define PDRV_SW_SET (1<<31)
#define LC_CKDRVPD (1<<19)
#define LC_CKDRVOHZ (1<<18)
@@ -242,8 +243,8 @@ static int mt7620_pci_hw_init(struct pla
+#define PPLL_LD BIT(23)
#define PDRV_SW_SET BIT(31)
#define LC_CKDRVPD BIT(19)
#define LC_CKDRVOHZ BIT(18)
@@ -239,8 +240,8 @@ static int mt7620_pci_hw_init(struct pla
rt_sysc_m32(0, RALINK_PCIE0_CLK_EN, RALINK_CLKCFG1);
mdelay(100);