mirror of
				https://source.denx.de/u-boot/u-boot.git
				synced 2025-10-31 08:21:36 +01:00 
			
		
		
		
	This patch adds support for MediaTek MT7621 SoC. All files are dedicated for u-boot. The default build target is u-boot-mt7621.bin. The specification of this chip: https://www.mediatek.com/products/homenetworking/mt7621 Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com> Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
		
			
				
	
	
		
			154 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			154 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| // SPDX-License-Identifier: GPL-2.0
 | |
| /*
 | |
|  * Copyright (C) 2022 MediaTek Inc. All rights reserved.
 | |
|  *
 | |
|  * Author: Weijie Gao <weijie.gao@mediatek.com>
 | |
|  */
 | |
| 
 | |
| #include <asm/io.h>
 | |
| #include <asm/addrspace.h>
 | |
| #include <asm/mipsregs.h>
 | |
| #include <asm/cm.h>
 | |
| #include <linux/bitfield.h>
 | |
| #include "../mt7621.h"
 | |
| 
 | |
| /* GIC Shared Register Bases */
 | |
| #define GIC_SH_POL_BASE		0x100
 | |
| #define GIC_SH_TRIG_BASE	0x180
 | |
| #define GIC_SH_RMASK_BASE	0x300
 | |
| #define GIC_SH_SMASK_BASE	0x380
 | |
| #define GIC_SH_MASK_BASE	0x400
 | |
| #define GIC_SH_PEND_BASE	0x480
 | |
| #define GIC_SH_MAP_PIN_BASE	0x500
 | |
| #define GIC_SH_MAP_VPE_BASE	0x2000
 | |
| 
 | |
| /* GIC Registers */
 | |
| #define GIC_SH_POL31_0		(GIC_SH_POL_BASE + 0x00)
 | |
| #define GIC_SH_POL63_32		(GIC_SH_POL_BASE + 0x04)
 | |
| 
 | |
| #define GIC_SH_TRIG31_0		(GIC_SH_TRIG_BASE + 0x00)
 | |
| #define GIC_SH_TRIG63_32	(GIC_SH_TRIG_BASE + 0x04)
 | |
| 
 | |
| #define GIC_SH_RMASK31_0	(GIC_SH_RMASK_BASE + 0x00)
 | |
| #define GIC_SH_RMASK63_32	(GIC_SH_RMASK_BASE + 0x04)
 | |
| 
 | |
| #define GIC_SH_SMASK31_0	(GIC_SH_SMASK_BASE + 0x00)
 | |
| #define GIC_SH_SMASK63_32	(GIC_SH_SMASK_BASE + 0x04)
 | |
| 
 | |
| #define GIC_SH_MAP_PIN(n)	(GIC_SH_MAP_PIN_BASE + (n) * 4)
 | |
| 
 | |
| #define GIC_SH_MAP_VPE(n, v)	(GIC_SH_MAP_VPE_BASE + (n) * 0x20 + ((v) / 32) * 4)
 | |
| #define GIC_SH_MAP_VPE31_0(n)	GIC_SH_MAP_VPE(n, 0)
 | |
| 
 | |
| /* GIC_SH_MAP_PIN fields */
 | |
| #define GIC_MAP_TO_PIN		BIT(31)
 | |
| #define GIC_MAP_TO_NMI		BIT(30)
 | |
| #define GIC_MAP			GENMASK(5, 0)
 | |
| #define GIC_MAP_SHIFT		0
 | |
| 
 | |
| static void cm_init(void __iomem *cm_base)
 | |
| {
 | |
| 	u32 gcrcfg, num_cores;
 | |
| 
 | |
| 	gcrcfg = readl(cm_base + GCR_CONFIG);
 | |
| 	num_cores = FIELD_GET(GCR_CONFIG_PCORES, gcrcfg) + 1;
 | |
| 
 | |
| 	writel((1 << num_cores) - 1, cm_base + GCR_ACCESS);
 | |
| 
 | |
| 	writel(GCR_REG0_BASE_VALUE, cm_base + GCR_REG0_BASE);
 | |
| 	writel(GCR_REG1_BASE_VALUE, cm_base + GCR_REG1_BASE);
 | |
| 	writel(GCR_REG2_BASE_VALUE, cm_base + GCR_REG2_BASE);
 | |
| 	writel(GCR_REG3_BASE_VALUE, cm_base + GCR_REG3_BASE);
 | |
| 
 | |
| 	clrsetbits_32(cm_base + GCR_REG0_MASK,
 | |
| 		      GCR_REGn_MASK_ADDRMASK | GCR_REGn_MASK_CMTGT,
 | |
| 		      FIELD_PREP(GCR_REGn_MASK_ADDRMASK, GCR_REG0_MASK_VALUE) |
 | |
| 		      GCR_REGn_MASK_CMTGT_IOCU0);
 | |
| 
 | |
| 	clrsetbits_32(cm_base + GCR_REG1_MASK,
 | |
| 		      GCR_REGn_MASK_ADDRMASK | GCR_REGn_MASK_CMTGT,
 | |
| 		      FIELD_PREP(GCR_REGn_MASK_ADDRMASK, GCR_REG1_MASK_VALUE) |
 | |
| 		      GCR_REGn_MASK_CMTGT_IOCU0);
 | |
| 
 | |
| 	clrsetbits_32(cm_base + GCR_REG2_MASK,
 | |
| 		      GCR_REGn_MASK_ADDRMASK | GCR_REGn_MASK_CMTGT,
 | |
| 		      FIELD_PREP(GCR_REGn_MASK_ADDRMASK, GCR_REG2_MASK_VALUE) |
 | |
| 		      GCR_REGn_MASK_CMTGT_IOCU0);
 | |
| 
 | |
| 	clrsetbits_32(cm_base + GCR_REG3_MASK,
 | |
| 		      GCR_REGn_MASK_ADDRMASK | GCR_REGn_MASK_CMTGT,
 | |
| 		      FIELD_PREP(GCR_REGn_MASK_ADDRMASK, GCR_REG3_MASK_VALUE) |
 | |
| 		      GCR_REGn_MASK_CMTGT_IOCU0);
 | |
| 
 | |
| 	clrbits_32(cm_base + GCR_BASE, CM_DEFAULT_TARGET_MASK);
 | |
| 	setbits_32(cm_base + GCR_CONTROL, GCR_CONTROL_SYNCCTL);
 | |
| }
 | |
| 
 | |
| static void gic_init(void)
 | |
| {
 | |
| 	void __iomem *gic_base = (void *)KSEG1ADDR(MIPS_GIC_BASE);
 | |
| 	int i;
 | |
| 
 | |
| 	/* Interrupt 0..5: Level Trigger, Active High */
 | |
| 	writel(0, gic_base + GIC_SH_TRIG31_0);
 | |
| 	writel(0x3f, gic_base + GIC_SH_RMASK31_0);
 | |
| 	writel(0x3f, gic_base + GIC_SH_POL31_0);
 | |
| 	writel(0x3f, gic_base + GIC_SH_SMASK31_0);
 | |
| 
 | |
| 	/* Interrupt 56..63: Edge Trigger, Rising Edge */
 | |
| 	/* Hardcoded to set up the last 8 external interrupts for IPI. */
 | |
| 	writel(0xff000000, gic_base + GIC_SH_TRIG63_32);
 | |
| 	writel(0xff000000, gic_base + GIC_SH_RMASK63_32);
 | |
| 	writel(0xff000000, gic_base + GIC_SH_POL63_32);
 | |
| 	writel(0xff000000, gic_base + GIC_SH_SMASK63_32);
 | |
| 
 | |
| 	/* Map interrupt source to particular hardware interrupt pin */
 | |
| 	/* source {0,1,2,3,4,5} -> pin {0,0,4,3,0,5} */
 | |
| 	writel(GIC_MAP_TO_PIN | 0, gic_base + GIC_SH_MAP_PIN(0));
 | |
| 	writel(GIC_MAP_TO_PIN | 0, gic_base + GIC_SH_MAP_PIN(1));
 | |
| 	writel(GIC_MAP_TO_PIN | 4, gic_base + GIC_SH_MAP_PIN(2));
 | |
| 	writel(GIC_MAP_TO_PIN | 3, gic_base + GIC_SH_MAP_PIN(3));
 | |
| 	writel(GIC_MAP_TO_PIN | 0, gic_base + GIC_SH_MAP_PIN(4));
 | |
| 	writel(GIC_MAP_TO_PIN | 5, gic_base + GIC_SH_MAP_PIN(5));
 | |
| 
 | |
| 	/* source 56~59 -> pin 1, 60~63 -> pin 2 */
 | |
| 	writel(GIC_MAP_TO_PIN | 1, gic_base + GIC_SH_MAP_PIN(56));
 | |
| 	writel(GIC_MAP_TO_PIN | 1, gic_base + GIC_SH_MAP_PIN(57));
 | |
| 	writel(GIC_MAP_TO_PIN | 1, gic_base + GIC_SH_MAP_PIN(58));
 | |
| 	writel(GIC_MAP_TO_PIN | 1, gic_base + GIC_SH_MAP_PIN(59));
 | |
| 	writel(GIC_MAP_TO_PIN | 2, gic_base + GIC_SH_MAP_PIN(60));
 | |
| 	writel(GIC_MAP_TO_PIN | 2, gic_base + GIC_SH_MAP_PIN(61));
 | |
| 	writel(GIC_MAP_TO_PIN | 2, gic_base + GIC_SH_MAP_PIN(62));
 | |
| 	writel(GIC_MAP_TO_PIN | 2, gic_base + GIC_SH_MAP_PIN(63));
 | |
| 
 | |
| 	/* Interrupt map to VPE (bit mask) */
 | |
| 	for (i = 0; i < 32; i++)
 | |
| 		writel(BIT(0), gic_base + GIC_SH_MAP_VPE31_0(i));
 | |
| 
 | |
| 	/*
 | |
| 	 * Direct GIC_int 56..63 to vpe 0..3
 | |
| 	 * MIPS Linux convention that last 16 interrupts implemented be set
 | |
| 	 * aside for IPI signaling.
 | |
| 	 * The actual interrupts are tied low and software sends interrupts
 | |
| 	 * via GIC_SH_WEDGE writes.
 | |
| 	 */
 | |
| 	for (i = 0; i < 4; i++) {
 | |
| 		writel(BIT(i), gic_base + GIC_SH_MAP_VPE31_0(i + 56));
 | |
| 		writel(BIT(i), gic_base + GIC_SH_MAP_VPE31_0(i + 60));
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void mt7621_cps_init(void)
 | |
| {
 | |
| 	void __iomem *cm_base = (void *)KSEG1ADDR(CONFIG_MIPS_CM_BASE);
 | |
| 
 | |
| 	/* Enable GIC */
 | |
| 	writel(MIPS_GIC_BASE | GCR_GIC_EN, cm_base + GCR_GIC_BASE);
 | |
| 
 | |
| 	/* Enable CPC */
 | |
| 	writel(MIPS_CPC_BASE | GCR_CPC_EN, cm_base + GCR_CPC_BASE);
 | |
| 
 | |
| 	gic_init();
 | |
| 	cm_init(cm_base);
 | |
| }
 |