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>
This commit is contained in:
		 DENG Qingfang
					DENG Qingfang
				
			
				
					committed by
					
						 Chuanhong Guo
						Chuanhong Guo
					
				
			
			
				
	
			
			
			 Chuanhong Guo
						Chuanhong Guo
					
				
			
						parent
						
							d75c9b8f81
						
					
				
				
					commit
					6be0da90a1
				
			| @@ -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 } | ||||
|  }; | ||||
|   | ||||
| @@ -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; | ||||
|  } | ||||
| @@ -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; | ||||
| - | ||||
|   | ||||
| @@ -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); | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
|   | ||||
| @@ -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; | ||||
| @@ -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(); | ||||
|   | ||||
| @@ -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 */ | ||||
|   | ||||
|   | ||||
| @@ -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); | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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); | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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, | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -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; | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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"); | ||||
| @@ -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 @@ | ||||
|   | ||||
| @@ -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"); | ||||
| @@ -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" | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -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/ | ||||
|   | ||||
| @@ -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; | ||||
|  	} | ||||
|   | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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); | ||||
| @@ -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) | ||||
| @@ -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 */ | ||||
| +	} | ||||
| + | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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) | ||||
| @@ -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 @@ | ||||
|   | ||||
| @@ -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"); | ||||
|  } | ||||
|   | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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> | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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) | ||||
|  { | ||||
|   | ||||
| @@ -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; | ||||
|  } | ||||
|   | ||||
|   | ||||
| @@ -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, | ||||
|   | ||||
| @@ -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) { | ||||
| @@ -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); | ||||
|   | ||||
|   | ||||
		Reference in New Issue
	
	Block a user