- MIPS: add support for Mediatek MT7620 SoCs

-----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEiQkHUH+J02LLC9InKPlOlyTyXBgFAmAN21EACgkQKPlOlyTy
 XBgzBw/+LUzGufIop4CimnEhqrfKRuoSKinRWhx8Lo4PyjF5SAwLgIyCWY95PoQf
 eDka+Ufyj1TbvqbPR+bhJbdL7wFrku3iKE7b0Ni8AamkmsyybxAVeyByen0Q1mSF
 q4KoPhKJmpdZOfrUVrXZBBwG7/T1WTHMrCc2ZSacR0G/IeimgLplT4sRk/uG1eFo
 uiKYf0/AjD28WNvlE9Dq0EZQA+KsTe/q7GQ79nOTuxYTOjbPA59WXTOtZMo1cPgc
 GhT1EJr4N7OcGvxgkiZ8Gs4mYMbFFVvMAUNW1Bsx4v1aYJyfgP0ua58gTnWSMn69
 OJNdxTs+JYBSIZd0B8gNf0P1ZQgrGACA1Vq4O3xJUImtkzp0tMID97ZwvAdhJQbo
 MhNrWcIxijrzWDHEGhnyZ0wyqWmSwznsrvIlS9hMuIxxmnYKveTwfkCeVcvkwvn7
 Nc1Pls1Lt2ViP8/Nygc+fAMg30vtp+NvSrbA53foka62sJMqmWAjPEprPPlJV0Z2
 qGJWCxIJ/1YAUjkNrEnSo/2A3SSAM8wA1ku6aT/Ju7NZCx/3m7sYXE+wQuxYlU2I
 zxQDO+2H0v0nlVVWebQZGZx8sn6Z4O+aGCLAkpJ9tqrViJYhy0Ti2QZi0Udcl1Ny
 lADQXQM2iPoQ2zJlO4AmzXCZ7DLrKVeS3hFFiVxRWK16apckz+o=
 =fKDK
 -----END PGP SIGNATURE-----

Merge tag 'mips-pull-2021-01-24' of https://gitlab.denx.de/u-boot/custodians/u-boot-mips

- MIPS: add support for Mediatek MT7620 SoCs
This commit is contained in:
Tom Rini 2021-01-25 14:38:40 -05:00
commit c99be953e7
61 changed files with 4477 additions and 72 deletions

View file

@ -812,6 +812,29 @@ F: drivers/spi/ca_sflash.c
F: drivers/i2c/i2c-cortina.c
F: drivers/i2c/i2c-cortina.h
MIPS MEDIATEK
M: Weijie Gao <weijie.gao@mediatek.com>
R: GSS_MTK_Uboot_upstream <GSS_MTK_Uboot_upstream@mediatek.com>
S: Maintained
F: arch/mips/mach-mtmips/
F: arch/mips/dts/mt7620.dtsi
F: arch/mips/dts/mt7620-u-boot.dtsi
F: include/configs/mt7620.h
F: include/dt-bindings/clock/mt7620-clk.h
F: include/dt-bindings/clock/mt7628-clk.h
F: include/dt-bindings/reset/mt7620-reset.h
F: include/dt-bindings/reset/mt7628-reset.h
F: drivers/clk/mtmips/
F: drivers/pinctrl/mtmips/
F: drivers/gpio/mt7620_gpio.c
F: drivers/net/mt7620-eth.c
F: drivers/phy/mt7620-usb-phy.c
F: drivers/reset/reset-mtmips.c
F: drivers/serial/serial_mt7620.c
F: drivers/spi/mt7620_spi.c
F: drivers/sysreset/sysreset_resetctl.c
F: drivers/watchdog/mt7620_wdt.c
MIPS MSCC
M: Gregory CLEMENT <gregory.clement@bootlin.com>
M: Lars Povlsen <lars.povlsen@microchip.com>

View file

@ -97,7 +97,6 @@ config ARCH_MTMIPS
select SUPPORTS_CPU_MIPS32_R1
select SUPPORTS_CPU_MIPS32_R2
select SUPPORTS_LITTLE_ENDIAN
select SYSRESET
select SUPPORT_SPL
config ARCH_JZ47XX

View file

@ -12,7 +12,7 @@
#include <asm/mipsregs.h>
#include <asm/reboot.h>
#ifndef CONFIG_SYSRESET
#if !CONFIG_IS_ENABLED(SYSRESET)
void __weak _machine_restart(void)
{
fprintf(stderr, "*** reset failed ***\n");

View file

@ -1,8 +1,5 @@
# SPDX-License-Identifier: GPL-2.0+
dtb-$(CONFIG_ARCH_MTMIPS) += \
gardena-smart-gateway-mt7688.dtb \
linkit-smart-7688.dtb
dtb-$(CONFIG_TARGET_AP121) += ap121.dtb
dtb-$(CONFIG_TARGET_AP143) += ap143.dtb
dtb-$(CONFIG_TARGET_AP152) += ap152.dtb
@ -17,7 +14,11 @@ dtb-$(CONFIG_BOARD_COMTREND_CT5361) += comtrend,ct-5361.dtb
dtb-$(CONFIG_BOARD_COMTREND_VR3032U) += comtrend,vr-3032u.dtb
dtb-$(CONFIG_BOARD_COMTREND_WAP5813N) += comtrend,wap-5813n.dtb
dtb-$(CONFIG_BOARD_HUAWEI_HG556A) += huawei,hg556a.dtb
dtb-$(CONFIG_BOARD_MT7620_RFB) += mediatek,mt7620-rfb.dtb
dtb-$(CONFIG_BOARD_MT7620_MT7530_RFB) += mediatek,mt7620-mt7530-rfb.dtb
dtb-$(CONFIG_BOARD_MT7628_RFB) += mediatek,mt7628-rfb.dtb
dtb-$(CONFIG_BOARD_GARDENA_SMART_GATEWAY_MT7688) += gardena-smart-gateway-mt7688.dtb
dtb-$(CONFIG_BOARD_LINKIT_SMART_7688) += linkit-smart-7688.dtb
dtb-$(CONFIG_TARGET_OCTEON_EBB7304) += mrvl,octeon-ebb7304.dtb
dtb-$(CONFIG_BOARD_NETGEAR_CG3100D) += netgear,cg3100d.dtb
dtb-$(CONFIG_BOARD_NETGEAR_DGND3700V2) += netgear,dgnd3700v2.dtb

View file

@ -0,0 +1,100 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2020 MediaTek Inc.
*
* Author: Weijie Gao <weijie.gao@mediatek.com>
*/
/dts-v1/;
#include <dt-bindings/gpio/gpio.h>
#include "mt7620.dtsi"
/ {
compatible = "mediatek,mt7620-mt7530-rfb", "mediatek,mt7620-soc";
model = "MediaTek MT7620-MT7530 RFB (MTKC712)";
aliases {
serial0 = &uartlite;
spi0 = &spi0;
};
chosen {
stdout-path = &uartlite;
};
};
&uartlite {
status = "okay";
};
&pinctrl {
state_default: pin_state {
pleds {
groups = "ephy led", "wled";
function = "led";
};
gpios {
groups = "pa", "uartf";
function = "gpio";
};
};
gsw_pins: gsw_pins {
mdio {
groups = "mdio";
function = "mdio";
};
rgmii1 {
groups = "rgmii1";
function = "rgmii1";
};
};
};
&spi0 {
status = "okay";
num-cs = <2>;
spi-flash@0 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "jedec,spi-nor";
spi-max-frequency = <25000000>;
reg = <0>;
};
};
&gpio0 {
pa0_pull_low {
gpio-hog;
output-low;
gpios = <20 GPIO_ACTIVE_HIGH>;
};
pa1_pull_low {
gpio-hog;
output-low;
gpios = <21 GPIO_ACTIVE_HIGH>;
};
};
&eth {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&gsw_pins>;
port5 {
phy-mode = "rgmii";
phy-addr = <5>;
fixed-link {
full-duplex;
speed = <1000>;
mediatek,mt7530;
mediatek,mt7530-reset = <&gpio0 10 GPIO_ACTIVE_HIGH>;
};
};
};

View file

@ -0,0 +1,97 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2020 MediaTek Inc.
*
* Author: Weijie Gao <weijie.gao@mediatek.com>
*/
/dts-v1/;
#include <dt-bindings/gpio/gpio.h>
#include "mt7620.dtsi"
/ {
compatible = "mediatek,mt7620-rfb", "mediatek,mt7620-soc";
model = "MediaTek MT7620 RFB (WS2120)";
aliases {
serial0 = &uartlite;
spi0 = &spi0;
};
chosen {
stdout-path = &uartlite;
};
};
&uartlite {
status = "okay";
};
&pinctrl {
state_default: pin_state {
pleds {
groups = "ephy led", "wled";
function = "led";
};
gpios {
groups = "uartf";
function = "gpio";
};
};
gsw_pins: gsw_pins {
mdio {
groups = "mdio";
function = "mdio";
};
rgmii1 {
groups = "rgmii1";
function = "rgmii1";
};
rgmii2 {
groups = "rgmii2";
function = "rgmii2";
};
};
};
&spi0 {
status = "okay";
num-cs = <2>;
spi-flash@0 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "jedec,spi-nor";
spi-max-frequency = <25000000>;
reg = <0>;
};
};
&eth {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&gsw_pins>;
port4 {
phy-mode = "rgmii";
phy-addr = <4>;
};
port5 {
phy-mode = "rgmii";
phy-addr = <5>;
};
};
&mmc {
bus-width = <4>;
cap-sd-highspeed;
status = "okay";
};

View file

@ -0,0 +1,14 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2020 MediaTek Inc.
*
* Author: Weijie Gao <weijie.gao@mediatek.com>
*/
&uartlite {
u-boot,dm-pre-reloc;
};
&uartfull {
u-boot,dm-pre-reloc;
};

296
arch/mips/dts/mt7620.dtsi Normal file
View file

@ -0,0 +1,296 @@
// SPDX-License-Identifier: GPL-2.0
#include <dt-bindings/clock/mt7620-clk.h>
#include <dt-bindings/reset/mt7620-reset.h>
/ {
#address-cells = <1>;
#size-cells = <1>;
compatible = "mediatek,mt7620-soc";
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
compatible = "mti,mips24KEc";
device_type = "cpu";
reg = <0>;
};
};
clk48m: clk48m@0 {
compatible = "fixed-clock";
clock-frequency = <48000000>;
#clock-cells = <0>;
};
sysc: sysc@10000000 {
compatible = "mediatek,mt7620-sysc";
reg = <0x10000000 0x100>;
};
clkctrl: clkctrl@10000030 {
compatible = "mediatek,mt7620-clk";
mediatek,sysc = <&sysc>;
#clock-cells = <1>;
};
rstctrl: rstctrl@10000034 {
compatible = "mediatek,mtmips-reset";
reg = <0x10000034 0x4>;
#reset-cells = <1>;
};
reboot: resetctl-reboot {
compatible = "resetctl-reboot";
resets = <&rstctrl SYS_RST>;
reset-names = "sysreset";
};
uartfull: uartfull@10000500 {
compatible = "mediatek,mt7620-uart";
reg = <10000500 0x100>;
pinctrl-names = "default";
pinctrl-0 = <&uartf_gpio_pins>;
clocks = <&clkctrl CLK_UARTF>;
resets = <&rstctrl UARTF_RST>;
reset-names = "uartf";
clock-frequency = <40000000>;
status = "disabled";
};
uartlite: uartlite@10000c00 {
compatible = "mediatek,mt7620-uart";
reg = <0x10000c00 0x100>;
pinctrl-names = "default";
pinctrl-0 = <&uartl_pins>;
clocks = <&clkctrl CLK_UARTL>;
resets = <&rstctrl UARTL_RST>;
reset-names = "uartl";
clock-frequency = <40000000>;
};
pinctrl: pinctrl@10000060 {
compatible = "mediatek,mt7620-pinctrl";
reg = <0x10000060 0x4>;
pinctrl-names = "default";
pinctrl-0 = <&state_default>;
state_default: pin_state {
sutif_pins {
groups = "sutif";
function = "none";
};
};
nand_pins: nand_pins {
groups = "nand";
function = "nand";
};
sd_pins: sd_pins {
groups = "nand";
function = "sd";
};
spi_single_pins: spi_single_pins {
groups = "spi";
function = "spi";
};
spi_dual_pins: spi_dual_pins {
spi_master_pins {
groups = "spi";
function = "spi";
};
spi_cs1_pin {
groups = "spi cs1";
function = "spi cs1";
};
};
uartl_pins: uartl_pins {
groups = "uartl";
function = "uartl";
};
uartf_pins: uartf_pins {
groups = "uartf";
function = "uartf";
};
uartf_pcm_pins: uartf_pcm_pins {
groups = "uartf";
function = "uartf pcm";
};
uartf_i2s_pins: uartf_i2s_pins {
groups = "uartf";
function = "i2s uartf";
};
uartf_gpio_pins: uartf_gpio_pins {
groups = "uartf";
function = "uartf gpio";
};
};
watchdog: watchdog@10000120 {
compatible = "mediatek,mt7620-wdt";
reg = <0x10000120 0x10>;
resets = <&rstctrl TIMER_RST>;
reset-names = "wdt";
};
gpio0: gpio0@10000600 {
compatible = "mediatek,mt7620-gpio";
reg = <0x10000600 0x34>;
resets = <&rstctrl PIO_RST>;
reset-names = "pio";
mediatek,bank-name = "PIOA";
mediatek,gpio-num = <24>;
mediatek,register-map = <0x20 0x24 0x2c 0x30>;
gpio-controller;
#gpio-cells = <2>;
};
gpio1: gpio1@10000638 {
compatible = "mediatek,mt7620-gpio";
reg = <0x10000638 0x24>;
resets = <&rstctrl PIO_RST>;
reset-names = "pio";
mediatek,bank-name = "PIOB";
mediatek,gpio-num = <16>;
mediatek,register-map = <0x10 0x14 0x1c 0x20>;
gpio-controller;
#gpio-cells = <2>;
};
gpio2: gpio2@10000660 {
compatible = "mediatek,mt7620-gpio";
reg = <0x10000660 0x24>;
resets = <&rstctrl PIO_RST>;
reset-names = "pio";
mediatek,bank-name = "PIOC";
mediatek,gpio-num = <32>;
mediatek,register-map = <0x10 0x14 0x1c 0x20>;
gpio-controller;
#gpio-cells = <2>;
};
gpio3: gpio3@10000688 {
compatible = "mediatek,mt7620-gpio";
reg = <0x10000688 0x24>;
resets = <&rstctrl PIO_RST>;
reset-names = "pio";
mediatek,bank-name = "PIOD";
mediatek,gpio-num = <1>;
mediatek,register-map = <0x10 0x14 0x1c 0x20>;
gpio-controller;
#gpio-cells = <2>;
};
spi0: spi@10000b00 {
compatible = "mediatek,mt7620-spi";
reg = <0x10000b00 0x100>;
pinctrl-names = "default";
pinctrl-0 = <&spi_single_pins>;
resets = <&rstctrl SPI_RST>;
reset-names = "spi";
#address-cells = <1>;
#size-cells = <0>;
clocks = <&clkctrl CLK_SPI>;
};
eth: eth@10100000 {
compatible = "mediatek,mt7620-eth";
reg = <0x10100000 0x10000
0x10110000 0x8000>;
reg-names = "fe", "esw";
mediatek,sysc = <&sysc>;
resets = <&rstctrl EPHY_RST>,
<&rstctrl ESW_RST>,
<&rstctrl FE_RST>;
reset-names = "ephy", "esw", "fe";
clocks = <&clkctrl CLK_EPHY>,
<&clkctrl CLK_ESW>,
<&clkctrl CLK_FE>;
clock-names = "ephy", "esw", "fe";
status = "disabled";
};
usb_phy: mt7620-usb-phy {
compatible = "mediatek,mt7620-usbphy";
#phy-cells = <0>;
mediatek,sysc = <&sysc>;
clocks = <&clkctrl CLK_UPHY_48M>, <&clkctrl CLK_UPHY_12M>;
clock-names = "uphy48m", "uphy12m";
resets = <&rstctrl UHST_RST>, <&rstctrl UDEV_RST>;
reset-names = "uhst", "udev";
};
ehci@101c0000 {
compatible = "generic-ehci";
reg = <0x101c0000 0x1000>;
phys = <&usb_phy>;
phy-names = "usb";
};
mmc: mmc@10130000 {
compatible = "mediatek,mt7620-mmc";
reg = <0x10130000 0x4000>;
builtin-cd = <1>;
r_smpl = <1>;
pinctrl-names = "default";
pinctrl-0 = <&sd_pins>;
clocks = <&clk48m>, <&clkctrl CLK_SDHC>;
clock-names = "source", "hclk";
resets = <&rstctrl SDHC_RST>;
status = "disabled";
};
};

View file

@ -5,6 +5,7 @@ config SYS_MALLOC_F_LEN
default 0x1000
config SYS_SOC
default "mt7620" if SOC_MT7620
default "mt7628" if SOC_MT7628
config SYS_DCACHE_SIZE
@ -31,10 +32,26 @@ config SPL_PAYLOAD
config BUILD_TARGET
default "u-boot-with-spl.bin" if SPL
default "u-boot.bin"
choice
prompt "MediaTek MIPS SoC select"
config SOC_MT7620
bool "MT7620"
select MIPS_L1_CACHE_SHIFT_5
select SYS_MIPS_CACHE_INIT_RAM_LOAD
select PINCTRL_MT7620
select MT7620_SERIAL
select MISC
select SPL_SEPARATE_BSS if SPL
select SPL_LOADER_SUPPORT if SPL
select SPL_OF_CONTROL if SPL_DM
select SPL_OF_PLATDATA if SPL_DM
select SPL_DM_SERIAL if SPL_DM
help
This supports MediaTek MT7620.
config SOC_MT7628
bool "MT7628"
select MIPS_L1_CACHE_SHIFT_5
@ -43,6 +60,7 @@ config SOC_MT7628
select SYS_MIPS_CACHE_INIT_RAM_LOAD
select PINCTRL_MT7628
select MTK_SERIAL
select SYSRESET
select SYSRESET_RESETCTL
select SPL_SEPARATE_BSS if SPL
select SPL_INIT_STACK_WITHOUT_MALLOC_F if SPL
@ -58,57 +76,7 @@ config SOC_MT7628
endchoice
choice
prompt "Board select"
config BOARD_GARDENA_SMART_GATEWAY_MT7688
bool "GARDENA smart Gateway"
depends on SOC_MT7628
select BOARD_LATE_INIT
help
GARDENA smart Gateway boards have a MT7688 SoC with 128 MiB of RAM
and 8 MiB of flash (SPI NOR) and additional SPI NAND storage.
config BOARD_LINKIT_SMART_7688
bool "LinkIt Smart 7688"
depends on SOC_MT7628
help
Seeed LinkIt Smart 7688 boards have a MT7688 SoC with 128 MiB of RAM
and 32 MiB of flash (SPI).
Between its different peripherals there's an integrated switch with 4
ethernet ports, 1 USB port, 1 UART, GPIO buttons and LEDs, and
a MT7688 (PCIe).
config BOARD_MT7628_RFB
bool "MediaTek MT7628 RFB"
depends on SOC_MT7628
help
The reference design of MT7628. The board has 128 MiB DDR2, 8 MiB
SPI-NOR flash, 1 built-in switch with 5 ports, 1 UART, 1 USB host,
1 SDXC, 1 PCIe socket and JTAG pins.
config BOARD_VOCORE2
bool "VoCore2"
depends on SOC_MT7628
select SPL_SERIAL_SUPPORT
select SPL_UART2_SPIS_PINMUX
help
VoCore VoCore2 board has a MT7628 SoC with 128 MiB of RAM
and 16 MiB of flash (SPI).
endchoice
config SPL_UART2_SPIS_PINMUX
bool "Use alternative pinmux for UART2 in SPL stage"
depends on SPL_SERIAL_SUPPORT
default n
help
Select this if the UART2 of your board is connected to GPIO 16/17
(shared with SPIS) rather than the usual GPIO 20/21.
source "board/gardena/smart-gateway-mt7688/Kconfig"
source "board/mediatek/mt7628/Kconfig"
source "board/seeed/linkit-smart-7688/Kconfig"
source "board/vocore/vocore2/Kconfig"
source "arch/mips/mach-mtmips/mt7620/Kconfig"
source "arch/mips/mach-mtmips/mt7628/Kconfig"
endmenu

View file

@ -5,4 +5,5 @@ obj-y += ddr_init.o
obj-y += ddr_cal.o
obj-$(CONFIG_SPL_BUILD) += spl.o
obj-$(CONFIG_SOC_MT7620) += mt7620/
obj-$(CONFIG_SOC_MT7628) += mt7628/

View file

@ -6,6 +6,7 @@
#include <common.h>
#include <init.h>
#include <malloc.h>
#include <asm/addrspace.h>
#include <linux/bitops.h>
#include <linux/io.h>
#include <linux/sizes.h>
@ -14,9 +15,7 @@ DECLARE_GLOBAL_DATA_PTR;
int dram_init(void)
{
#ifdef CONFIG_SKIP_LOWLEVEL_INIT
gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE, SZ_256M);
#endif
gd->ram_size = get_ram_size((void *)KSEG1, SZ_256M);
return 0;
}

View file

@ -15,6 +15,13 @@
#define DDR_BW_TEST_PAT 0xaa5555aa
static const u32 sdr_size_cfg1[] = {
[DRAM_8MB] = (1 << NUMROWS_S),
[DRAM_16MB] = (1 << NUMROWS_S) | (1 << NUMCOLS_S),
[DRAM_32MB] = (2 << NUMROWS_S) | (1 << NUMCOLS_S),
[DRAM_64MB] = (2 << NUMROWS_S) | (2 << NUMCOLS_S),
};
static const u32 dram_size[] = {
[DRAM_8MB] = SZ_8M,
[DRAM_16MB] = SZ_16M,
@ -193,3 +200,55 @@ void ddr2_init(struct mc_ddr_init_param *param)
param->memsize = dram_size[sz];
param->bus_width = bw;
}
static void mc_sdr_init(void __iomem *memc, mc_reset_t mc_reset, u32 cfg0,
u32 cfg1)
{
mc_reset(1);
__udelay(200);
mc_reset(0);
writel(cfg0, memc + MEMCTL_SDRAM_CFG0_REG);
writel(cfg1, memc + MEMCTL_SDRAM_CFG1_REG);
while (!(readl(memc + MEMCTL_SDRAM_CFG1_REG) & SDRAM_INIT_DONE))
;
clrsetbits_32(memc + MEMCTL_PWR_SAVE_CNT_REG, SR_TAR_CNT_M,
1 << SR_TAR_CNT_S);
setbits_32(memc + MEMCTL_DDR_SELF_REFRESH_REG, SR_AUTO_EN);
}
void sdr_init(struct mc_ddr_init_param *param)
{
enum mc_dram_size sz;
u32 cfg1;
cfg1 = param->sdr_cfg1 | SDRAM_INIT_START;
cfg1 &= ~(NUMCOLS_M | NUMROWS_M);
/* First initialization, determine SDR capacity */
mc_sdr_init(param->memc, param->mc_reset, param->sdr_cfg0,
cfg1 | sdr_size_cfg1[DRAM_64MB]);
if (dram_addr_test_bit(9)) {
sz = DRAM_8MB;
} else {
if (dram_addr_test_bit(10)) {
if (dram_addr_test_bit(23))
sz = DRAM_16MB;
else
sz = DRAM_32MB;
} else {
sz = DRAM_64MB;
}
}
/* Final initialization */
mc_sdr_init(param->memc, param->mc_reset, param->sdr_cfg0,
cfg1 | sdr_size_cfg1[sz]);
/* Return actual DDR configuration */
param->memsize = dram_size[sz];
}

View file

@ -35,6 +35,9 @@ typedef void (*mc_reset_t)(int assert);
struct mc_ddr_init_param {
void __iomem *memc;
u32 sdr_cfg0;
u32 sdr_cfg1;
u32 dq_dly;
u32 dqs_dly;
@ -45,6 +48,7 @@ struct mc_ddr_init_param {
u32 bus_width;
};
void sdr_init(struct mc_ddr_init_param *param);
void ddr1_init(struct mc_ddr_init_param *param);
void ddr2_init(struct mc_ddr_init_param *param);
void ddr_calibrate(void __iomem *memc, u32 memsize, u32 bw);

View file

@ -0,0 +1,54 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2020 MediaTek Inc.
*
* Author: Weijie Gao <weijie.gao@mediatek.com>
*
* Definitions of ioctl requests of MT7620 sysc driver
*/
#ifndef _MT7620_SYSC_H_
#define _MT7620_SYSC_H_
#include <linux/types.h>
enum mt7620_sysc_requests {
MT7620_SYSC_IOCTL_GET_CLK,
MT7620_SYSC_IOCTL_GET_CHIP_REV,
MT7620_SYSC_IOCTL_SET_GE1_MODE,
MT7620_SYSC_IOCTL_SET_GE2_MODE,
MT7620_SYSC_IOCTL_SET_USB_MODE,
MT7620_SYSC_IOCTL_SET_PCIE_MODE
};
struct mt7620_sysc_clks {
u32 cpu_clk;
u32 sys_clk;
u32 xtal_clk;
u32 peri_clk;
};
struct mt7620_sysc_chip_rev {
bool bga;
u32 ver : 4;
u32 eco : 4;
};
enum mt7620_sysc_ge_mode {
MT7620_SYSC_GE_RGMII,
MT7620_SYSC_GE_MII,
MT7620_SYSC_GE_RMII,
MT7620_SYSC_GE_ESW_PHY,
};
enum mt7620_sysc_usb_mode {
MT7620_SYSC_USB_DEVICE_MODE,
MT7620_SYSC_USB_HOST_MODE
};
enum mt7620_sysc_pcie_mode {
MT7620_SYSC_PCIE_EP_MODE,
MT7620_SYSC_PCIE_RC_MODE
};
#endif /* _MT7620_SYSC_H_ */

View file

@ -0,0 +1,71 @@
if SOC_MT7620
config DEBUG_UART_BOARD_INIT
default y
choice
prompt "Board select"
config BOARD_MT7620_RFB
bool "MediaTek MT7620 RFB"
help
The reference design of MT7620A (WS2120). The board has 64 MiB DDR2,
8 MiB SPI-NOR flash, 1 built-in 6 port switch (two GE PHYs and five
FE PHYs,one port can be configured to use either FE PHY or GE PHY),
1 UART, 1 USB host, 1 SDXC, 1 PCIe socket and JTAG pins.
config BOARD_MT7620_MT7530_RFB
bool "MediaTek MT7620-MT7530 RFB"
help
The reference design of MT7620DA (MTKC712). The board has 64 MiB
intergrated DDR2 KGD, 16 MiB SPI-NOR flash, an external 5-port giga
switch MT7530 and 1 UART.
endchoice
choice
prompt "CPU frequency select"
default CPU_FREQ_580MHZ
config CPU_FREQ_480MHZ
bool "480MHz"
config CPU_FREQ_500MHZ
bool "500MHz"
config CPU_FREQ_520MHZ
bool "520MHz"
config CPU_FREQ_540MHZ
bool "540MHz"
config CPU_FREQ_560MHZ
bool "560MHz"
config CPU_FREQ_580MHZ
bool "580MHz"
config CPU_FREQ_600MHZ
bool "600MHz"
config CPU_FREQ_620MHZ
bool "620MHz"
endchoice
config CPU_FREQ_MULTI
int
range 0 7
default 0 if CPU_FREQ_480MHZ
default 1 if CPU_FREQ_500MHZ
default 2 if CPU_FREQ_520MHZ
default 3 if CPU_FREQ_540MHZ
default 4 if CPU_FREQ_560MHZ
default 5 if CPU_FREQ_580MHZ
default 6 if CPU_FREQ_600MHZ
default 7 if CPU_FREQ_620MHZ
source "board/mediatek/mt7620/Kconfig"
endif

View file

@ -0,0 +1,10 @@
# SPDX-License-Identifier: GPL-2.0
obj-y += lowlevel_init.o
obj-y += init.o
obj-y += dram.o
obj-y += serial.o
ifndef CONFIG_SPL_BUILD
obj-y += sysc.o
endif

View file

@ -0,0 +1,113 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2020 MediaTek Inc. All Rights Reserved.
*
* Author: Weijie Gao <weijie.gao@mediatek.com>
*/
#include <asm/addrspace.h>
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/sizes.h>
#include <linux/io.h>
#include <mach/ddr.h>
#include <mach/mc.h>
#include "mt7620.h"
/* SDR parameters */
#define SDR_CFG0_VAL 0x51B283B3
#define SDR_CFG1_VAL 0xC00003A9
/* DDR2 DQ_DLY */
#define DDR2_DQ_DLY 0x88888888
/* DDR2 DQS_DLY */
#define DDR2_DQS_DLY 0x88888888
static const struct mc_ddr_cfg ddr1_cfgs_200mhz[] = {
[DRAM_8MB] = { 0x34A1EB94, 0x20262324, 0x28000033, 0x00000002, 0x00000000 },
[DRAM_16MB] = { 0x34A1EB94, 0x202A2324, 0x28000033, 0x00000002, 0x00000000 },
[DRAM_32MB] = { 0x34A1E5CA, 0x202E2324, 0x28000033, 0x00000002, 0x00000000 },
[DRAM_64MB] = { 0x3421E5CA, 0x20322324, 0x28000033, 0x00000002, 0x00000000 },
[DRAM_128MB] = { 0x241B05CA, 0x20362334, 0x28000033, 0x00000002, 0x00000000 },
};
static const struct mc_ddr_cfg ddr1_cfgs_160mhz[] = {
[DRAM_8MB] = { 0x239964A1, 0x20262323, 0x00000033, 0x00000002, 0x00000000 },
[DRAM_16MB] = { 0x239964A1, 0x202A2323, 0x00000033, 0x00000002, 0x00000000 },
[DRAM_32MB] = { 0x239964A1, 0x202E2323, 0x00000033, 0x00000002, 0x00000000 },
[DRAM_64MB] = { 0x239984A1, 0x20322323, 0x00000033, 0x00000002, 0x00000000 },
[DRAM_128MB] = { 0x239AB4A1, 0x20362333, 0x00000033, 0x00000002, 0x00000000 },
};
static const struct mc_ddr_cfg ddr2_cfgs_200mhz[] = {
[DRAM_32MB] = { 0x2519E2E5, 0x222E2323, 0x68000C43, 0x00000416, 0x0000000A },
[DRAM_64MB] = { 0x249AA2E5, 0x22322323, 0x68000C43, 0x00000416, 0x0000000A },
[DRAM_128MB] = { 0x249B42E5, 0x22362323, 0x68000C43, 0x00000416, 0x0000000A },
[DRAM_256MB] = { 0x249CE2E5, 0x223A2323, 0x68000C43, 0x00000416, 0x0000000A },
};
static const struct mc_ddr_cfg ddr2_cfgs_160mhz[] = {
[DRAM_32MB] = { 0x23918250, 0x222E2322, 0x40000A43, 0x00000416, 0x00000006 },
[DRAM_64MB] = { 0x239A2250, 0x22322322, 0x40000A43, 0x00000416, 0x00000008 },
[DRAM_128MB] = { 0x2392A250, 0x22362322, 0x40000A43, 0x00000416, 0x00000008 },
[DRAM_256MB] = { 0x24140250, 0x223A2322, 0x40000A43, 0x00000416, 0x00000008 },
};
static void mt7620_memc_reset(int assert)
{
void __iomem *sysc = ioremap_nocache(SYSCTL_BASE, SYSCTL_SIZE);
if (assert)
setbits_32(sysc + SYSCTL_RSTCTL_REG, MC_RST);
else
clrbits_32(sysc + SYSCTL_RSTCTL_REG, MC_RST);
}
void mt7620_dram_init(void)
{
void __iomem *sysc;
bool lspd = false;
int ddr_type, aux;
struct mc_ddr_init_param param;
sysc = ioremap_nocache(SYSCTL_BASE, SYSCTL_SIZE);
ddr_type = (readl(sysc + SYSCTL_SYSCFG0_REG) & DRAM_TYPE_M)
>> DRAM_TYPE_S;
aux = readl(sysc + SYSCTL_CPLL_CFG1_REG) &
(CPU_CLK_AUX1 | CPU_CLK_AUX0);
if (aux == CPU_CLK_AUX1 || aux == CPU_CLK_AUX0)
lspd = true;
mt7620_memc_reset(1);
__udelay(200);
param.memc = ioremap_nocache(MEMCTL_BASE, MEMCTL_SIZE);
param.dq_dly = DDR2_DQ_DLY;
param.dqs_dly = DDR2_DQS_DLY;
param.mc_reset = mt7620_memc_reset;
param.memsize = 0;
param.bus_width = 0;
if (ddr_type == DRAM_DDR1) {
if (lspd)
param.cfgs = ddr1_cfgs_160mhz;
else
param.cfgs = ddr1_cfgs_200mhz;
ddr1_init(&param);
} else if (ddr_type == DRAM_DDR2) {
if (lspd)
param.cfgs = ddr2_cfgs_160mhz;
else
param.cfgs = ddr2_cfgs_200mhz;
ddr2_init(&param);
} else {
param.sdr_cfg0 = SDR_CFG0_VAL;
param.sdr_cfg1 = SDR_CFG1_VAL;
sdr_init(&param);
}
}

View file

@ -0,0 +1,193 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2020 MediaTek Inc. All Rights Reserved.
*
* Author: Weijie Gao <weijie.gao@mediatek.com>
*/
#include <config.h>
#include <asm/global_data.h>
#include <linux/io.h>
#include "mt7620.h"
DECLARE_GLOBAL_DATA_PTR;
static const char * const dram_type[] = {
"SDRAM", "DDR", "DDR2", "SDRAM"
};
static const char * const boot_mode[(CHIP_MODE_M >> CHIP_MODE_S) + 1] = {
[1] = "NAND 4-cycles 2KB-page",
[2] = "SPI-NOR 3-Byte Addr",
[3] = "SPI-NOR 4-Byte Addr",
[10] = "NAND 4-cycles 512B-page",
[11] = "NAND 5-cycles 2KB-page",
[12] = "NAND 3-cycles 512B-page",
};
static void cpu_pll_init(void)
{
void __iomem *sysc = ioremap_nocache(SYSCTL_BASE, SYSCTL_SIZE);
u32 pllmul = CONFIG_CPU_FREQ_MULTI;
/* Make sure the pll multiplier is valid */
if (pllmul > 7)
pllmul = 7;
/* Set init CPU clock to 480MHz */
clrsetbits_32(sysc + SYSCTL_CPLL_CFG1_REG, CPU_CLK_AUX1, CPU_CLK_AUX0);
/* Enable software control of CPU PLL */
setbits_32(sysc + SYSCTL_CPLL_CFG0_REG, CPLL_SW_CFG);
/* CPU PLL power down */
setbits_32(sysc + SYSCTL_CPLL_CFG1_REG, CPLL_PD);
/* PLL configuration */
clrsetbits_32(sysc + SYSCTL_CPLL_CFG0_REG, PLL_MULT_RATIO_M |
PLL_DIV_RATIO_M | SSC_UP_BOUND_M | SSC_EN,
(pllmul << PLL_MULT_RATIO_S) | SSC_SWING_M);
/* CPU PLL power up */
clrbits_32(sysc + SYSCTL_CPLL_CFG1_REG, CPLL_PD);
/* Wait for CPU PLL locked */
while (!(readl(sysc + SYSCTL_CPLL_CFG1_REG) & CPLL_LD))
;
/* Set final CPU clock source */
clrbits_32(sysc + SYSCTL_CPLL_CFG1_REG, CPU_CLK_AUX1 | CPU_CLK_AUX0);
/* Adjust CPU clock */
clrsetbits_32(sysc + SYSCTL_CPU_SYS_CLKCFG_REG,
CPU_FDIV_M | CPU_FFRAC_M,
(1 << CPU_FDIV_S) | (1 << CPU_FFRAC_S));
}
void mt7620_init(void)
{
u32 cpu_clk;
cpu_pll_init();
/*
* Set timer freq, which will be used during DRAM initialization
* Note that this function is using a temporary gd which will be
* destroyed after leaving this function.
*/
mt7620_get_clks(&cpu_clk, NULL, NULL);
gd->arch.timer_freq = cpu_clk / 2;
mt7620_dram_init();
}
void mt7620_get_clks(u32 *cpu_clk, u32 *sys_clk, u32 *xtal_clk)
{
void __iomem *sysc = ioremap_nocache(SYSCTL_BASE, SYSCTL_SIZE);
u32 val, multi, div, fdiv, ffrac, dram_type, sys_div;
u32 cpu_freq, xtal_freq;
static const u32 div_ratio_table[] = {2, 3, 4, 8};
val = readl(sysc + SYSCTL_SYSCFG0_REG);
dram_type = (val & DRAM_TYPE_M) >> DRAM_TYPE_S;
if (val & XTAL_FREQ_SEL)
xtal_freq = 40000000;
else
xtal_freq = 20000000;
val = readl(sysc + SYSCTL_CPLL_CFG1_REG);
if (val & CPU_CLK_AUX1) {
cpu_freq = xtal_freq;
} else if (val & CPU_CLK_AUX0) {
cpu_freq = 480000000;
} else {
val = readl(sysc + SYSCTL_CPLL_CFG0_REG);
if (val & CPLL_SW_CFG) {
multi = (val & PLL_MULT_RATIO_M) >> PLL_MULT_RATIO_S;
div = (val & PLL_DIV_RATIO_M) >> PLL_DIV_RATIO_S;
cpu_freq = (multi + 24) * 40000000 /
div_ratio_table[div];
} else {
cpu_freq = 600000000;
}
}
val = readl(sysc + SYSCTL_CUR_CLK_STS_REG);
ffrac = (val & CUR_CPU_FFRAC_M) >> CUR_CPU_FFRAC_S;
fdiv = (val & CUR_CPU_FDIV_M) >> CUR_CPU_FDIV_S;
cpu_freq = (cpu_freq * ffrac) / fdiv;
switch (dram_type) {
case DRAM_SDRAM_E1:
sys_div = 4;
break;
case DRAM_DDR1:
case DRAM_DDR2:
sys_div = 3;
break;
case DRAM_SDRAM:
sys_div = 5;
break;
}
if (cpu_clk)
*cpu_clk = cpu_freq;
if (sys_clk)
*sys_clk = cpu_freq / sys_div;
if (xtal_clk)
*xtal_clk = xtal_freq;
}
int print_cpuinfo(void)
{
void __iomem *sysc = ioremap_nocache(SYSCTL_BASE, SYSCTL_SIZE);
u32 cpu_clk, bus_clk, xtal_clk;
u32 val, ver, eco, pkg, dram, chipmode;
const char *bootdev;
val = readl(sysc + SYSCTL_CHIP_REV_ID_REG);
ver = (val & VER_M) >> VER_S;
eco = (val & ECO_M) >> ECO_S;
pkg = !!(val & PKG_ID);
val = readl(sysc + SYSCTL_SYSCFG0_REG);
dram = (val & DRAM_TYPE_M) >> DRAM_TYPE_S;
chipmode = (val & CHIP_MODE_M) >> CHIP_MODE_S;
bootdev = boot_mode[chipmode];
if (!bootdev)
bootdev = "Unsupported boot mode";
printf("CPU: MediaTek MT7620%c ver:%u eco:%u\n",
pkg ? 'A' : 'N', ver, eco);
printf("Boot: %s, %s\n", dram_type[dram], bootdev);
mt7620_get_clks(&cpu_clk, &bus_clk, &xtal_clk);
/* Set final timer frequency */
gd->arch.timer_freq = cpu_clk / 2;
printf("Clock: CPU: %uMHz, Bus: %uMHz, XTAL: %uMHz\n",
cpu_clk / 1000000, bus_clk / 1000000, xtal_clk / 1000000);
return 0;
}
ulong notrace get_tbclk(void)
{
return gd->arch.timer_freq;
}
void _machine_restart(void)
{
void __iomem *sysc = ioremap_nocache(SYSCTL_BASE, SYSCTL_SIZE);
while (1)
writel(SYS_RST, sysc + SYSCTL_RSTCTL_REG);
}

View file

@ -0,0 +1,53 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2020 MediaTek Inc.
*
* Author: Weijie Gao <weijie.gao@mediatek.com>
*/
#include <config.h>
#include <asm-offsets.h>
#include <asm/regdef.h>
#include <asm/asm.h>
.set noreorder
NESTED(lowlevel_init, 0, ra)
/* Save ra and do real lowlevel initialization */
move s0, ra
/*
* Use SRAM from 802.11n MAC/BBP, 16KiB (0x10184000 ~ 0x10187fff)
* NOTE: non-word operations may fail in this SRAM.
* Use it as stack only for CPU/DRAM init which only has word operations.
*/
PTR_LI sp, 0xb0187f00
/* We still need a temporary gd for udelay */
PTR_SUBU \
sp, sp, GD_SIZE # reserve space for gd
li t0, -16
and sp, sp, t0 # force 16 byte alignment
move k0, sp # save gd pointer
move fp, sp
/* Clear gd */
move t0, k0
1:
PTR_S zero, 0(t0)
PTR_ADDIU t0, PTRSIZE
blt t0, t1, 1b
nop
/* Do CPU & DRAM initialization */
PTR_LA t9, mt7620_init
jalr t9
nop
/* Restore ra */
move ra, s0
jr ra
nop
END(lowlevel_init)

View file

@ -0,0 +1,103 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2020 MediaTek Inc. All Rights Reserved.
*
* Author: Weijie Gao <weijie.gao@mediatek.com>
*/
#ifndef _MT7620_H_
#define _MT7620_H_
#include <linux/bitops.h>
#define SYSCTL_BASE 0x10000000
#define SYSCTL_SIZE 0x100
#define MEMCTL_BASE 0x10000300
#define MEMCTL_SIZE 0x100
#define UARTFULL_BASE 0x10000500
#define UARTFULL_SIZE 0x100
#define UARTLITE_BASE 0x10000c00
#define UARTLITE_SIZE 0x100
#define SYSCTL_CHIP_REV_ID_REG 0x0c
#define PKG_ID BIT(16)
#define PKG_ID_A 1
#define PKG_ID_N 0
#define VER_S 8
#define VER_M GENMASK(11, 8)
#define ECO_S 0
#define ECO_M GENMASK(3, 0)
#define SYSCTL_SYSCFG0_REG 0x10
#define XTAL_FREQ_SEL BIT(6)
#define XTAL_40MHZ 1
#define XTAL_20MHZ 0
#define DRAM_TYPE_S 4
#define DRAM_TYPE_M GENMASK(5, 4)
#define DRAM_SDRAM 3
#define DRAM_DDR2 2
#define DRAM_DDR1 1
#define DRAM_SDRAM_E1 0
#define CHIP_MODE_S 0
#define CHIP_MODE_M GENMASK(3, 0)
#define SYSCTL_SYSCFG1_REG 0x14
#define GE2_MODE_S 14
#define GE2_MODE_M GENMASK(15, 14)
#define GE1_MODE_S 12
#define GE1_MODE_M GENMASK(13, 12)
#define USB0_HOST_MODE BIT(10)
#define PCIE_RC_MODE BIT(8)
#define GE_MODE_M GENMASK(1, 0)
#define SYSCTL_RSTCTL_REG 0x34
#define MC_RST BIT(10)
#define SYS_RST BIT(0)
#define SYSCTL_CLKCFG0_REG 0x2c
#define PERI_CLK_SEL BIT(4)
#define SYSCTL_CPU_SYS_CLKCFG_REG 0x3c
#define CPU_OCP_RATIO_S 16
#define CPU_OCP_RATIO_M GENMASK(19, 16)
#define CPU_FDIV_S 8
#define CPU_FDIV_M GENMASK(12, 8)
#define CPU_FFRAC_S 0
#define CPU_FFRAC_M GENMASK(4, 0)
#define SYSCTL_CUR_CLK_STS_REG 0x44
#define CUR_CPU_OCP_RATIO_S 16
#define CUR_CPU_OCP_RATIO_M GENMASK(19, 16)
#define CUR_CPU_FDIV_S 8
#define CUR_CPU_FDIV_M GENMASK(12, 8)
#define CUR_CPU_FFRAC_S 0
#define CUR_CPU_FFRAC_M GENMASK(4, 0)
#define SYSCTL_CPLL_CFG0_REG 0x54
#define CPLL_SW_CFG BIT(31)
#define PLL_MULT_RATIO_S 16
#define PLL_MULT_RATIO_M GENMASK(18, 16)
#define PLL_DIV_RATIO_S 10
#define PLL_DIV_RATIO_M GENMASK(11, 10)
#define SSC_UP_BOUND_S 8
#define SSC_UP_BOUND_M GENMASK(9, 8)
#define SSC_EN BIT(7)
#define SSC_SWING_S 4
#define SSC_SWING_M GENMASK(6, 4)
#define SYSCTL_CPLL_CFG1_REG 0x58
#define CPLL_PD BIT(26)
#define CPU_CLK_AUX1 BIT(25)
#define CPU_CLK_AUX0 BIT(24)
#define CPLL_LD BIT(23)
#define SYSCTL_GPIOMODE_REG 0x60
#define UARTL_GPIO_MODE BIT(5)
#define UARTF_SHARE_MODE_S 2
#define UARTF_SHARE_MODE_M GENMASK(4, 2)
#define UARTF_MODE_UARTF_GPIO 5
void mt7620_dram_init(void);
void mt7620_get_clks(u32 *cpu_clk, u32 *sys_clk, u32 *xtal_clk);
#endif /* _MT7620_H_ */

View file

@ -0,0 +1,36 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2020 MediaTek Inc.
*
* Author: Weijie Gao <weijie.gao@mediatek.com>
*/
#include <asm/io.h>
#include <asm/addrspace.h>
#include "mt7620.h"
void board_debug_uart_init(void)
{
void __iomem *base = ioremap_nocache(SYSCTL_BASE, SYSCTL_SIZE);
#if CONFIG_DEBUG_UART_BASE == 0xb0000500 /* KSEG1ADDR(UARTFULL_BASE) */
clrsetbits_32(base + SYSCTL_GPIOMODE_REG, UARTF_SHARE_MODE_M,
UARTF_MODE_UARTF_GPIO << UARTF_SHARE_MODE_S);
#else
clrbits_32(base + SYSCTL_GPIOMODE_REG, UARTL_GPIO_MODE);
#endif
}
void mtmips_spl_serial_init(void)
{
#ifdef CONFIG_SPL_SERIAL_SUPPORT
void __iomem *base = ioremap_nocache(SYSCTL_BASE, SYSCTL_SIZE);
#if CONFIG_CONS_INDEX == 1
clrbits_32(base + SYSCTL_GPIOMODE_REG, UARTL_GPIO_MODE);
#elif CONFIG_CONS_INDEX == 2
clrsetbits_32(base + SYSCTL_GPIOMODE_REG, UARTF_SHARE_MODE_M,
UARTF_MODE_UARTF_GPIO << UARTF_SHARE_MODE_S);
#endif
#endif /* CONFIG_SPL_SERIAL_SUPPORT */
}

View file

@ -0,0 +1,172 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2020 MediaTek Inc. All Rights Reserved.
*
* Author: Weijie Gao <weijie.gao@mediatek.com>
*
* Misc driver for manipulating System control registers
*/
#include <dm.h>
#include <misc.h>
#include <asm/io.h>
#include <asm/addrspace.h>
#include <dm/device_compat.h>
#include <mach/mt7620-sysc.h>
#include "mt7620.h"
struct mt7620_sysc_priv {
void __iomem *base;
};
static int mt7620_sysc_read(struct udevice *dev, int offset, void *buf,
int size)
{
struct mt7620_sysc_priv *priv = dev_get_priv(dev);
u32 val;
if (offset % sizeof(u32) || size != sizeof(u32) ||
offset >= SYSCTL_SIZE)
return -EINVAL;
val = readl(priv->base + offset);
if (buf)
*(u32 *)buf = val;
return 0;
}
static int mt7620_sysc_write(struct udevice *dev, int offset, const void *buf,
int size)
{
struct mt7620_sysc_priv *priv = dev_get_priv(dev);
u32 val;
if (offset % sizeof(u32) || size != sizeof(u32) ||
offset >= SYSCTL_SIZE || !buf)
return -EINVAL;
val = *(u32 *)buf;
writel(val, priv->base + offset);
return 0;
}
static int mt7620_sysc_ioctl(struct udevice *dev, unsigned long request,
void *buf)
{
struct mt7620_sysc_priv *priv = dev_get_priv(dev);
struct mt7620_sysc_chip_rev *chip_rev;
struct mt7620_sysc_clks *clks;
u32 val, shift;
if (!buf)
return -EINVAL;
switch (request) {
case MT7620_SYSC_IOCTL_GET_CLK:
clks = buf;
mt7620_get_clks(&clks->cpu_clk, &clks->sys_clk,
&clks->xtal_clk);
val = readl(priv->base + SYSCTL_CLKCFG0_REG);
if (val & PERI_CLK_SEL)
clks->peri_clk = clks->xtal_clk;
else
clks->peri_clk = 40000000;
return 0;
case MT7620_SYSC_IOCTL_GET_CHIP_REV:
chip_rev = buf;
val = readl(priv->base + SYSCTL_CHIP_REV_ID_REG);
chip_rev->bga = !!(val & PKG_ID);
chip_rev->ver = (val & VER_M) >> VER_S;
chip_rev->eco = (val & ECO_M) >> ECO_S;
return 0;
case MT7620_SYSC_IOCTL_SET_GE1_MODE:
case MT7620_SYSC_IOCTL_SET_GE2_MODE:
val = *(u32 *)buf;
if (val > MT7620_SYSC_GE_ESW_PHY)
return -EINVAL;
if (request == MT7620_SYSC_IOCTL_SET_GE1_MODE)
shift = GE1_MODE_S;
else
shift = GE2_MODE_S;
clrsetbits_32(priv->base + SYSCTL_SYSCFG1_REG,
GE_MODE_M << shift, val << shift);
return 0;
case MT7620_SYSC_IOCTL_SET_USB_MODE:
val = *(u32 *)buf;
if (val == MT7620_SYSC_USB_DEVICE_MODE)
val = 0;
else if (val == MT7620_SYSC_USB_HOST_MODE)
val = USB0_HOST_MODE;
clrsetbits_32(priv->base + SYSCTL_SYSCFG1_REG,
USB0_HOST_MODE, val);
return 0;
case MT7620_SYSC_IOCTL_SET_PCIE_MODE:
val = *(u32 *)buf;
if (val == MT7620_SYSC_PCIE_EP_MODE)
val = 0;
else if (val == MT7620_SYSC_PCIE_RC_MODE)
val = PCIE_RC_MODE;
clrsetbits_32(priv->base + SYSCTL_SYSCFG1_REG,
PCIE_RC_MODE, val);
return 0;
default:
return -EINVAL;
}
}
static int mt7620_sysc_probe(struct udevice *dev)
{
struct mt7620_sysc_priv *priv = dev_get_priv(dev);
priv->base = dev_remap_addr_index(dev, 0);
if (!priv->base) {
dev_err(dev, "failed to map sysc registers\n");
return -EINVAL;
}
return 0;
}
static struct misc_ops mt7620_sysc_ops = {
.read = mt7620_sysc_read,
.write = mt7620_sysc_write,
.ioctl = mt7620_sysc_ioctl,
};
static const struct udevice_id mt7620_sysc_ids[] = {
{ .compatible = "mediatek,mt7620-sysc" },
{ }
};
U_BOOT_DRIVER(mt7620_sysc) = {
.name = "mt7620_sysc",
.id = UCLASS_MISC,
.of_match = mt7620_sysc_ids,
.probe = mt7620_sysc_probe,
.ops = &mt7620_sysc_ops,
.priv_auto = sizeof(struct mt7620_sysc_priv),
.flags = DM_FLAG_PRE_RELOC,
};

View file

@ -0,0 +1,53 @@
if SOC_MT7628
choice
prompt "Board select"
config BOARD_GARDENA_SMART_GATEWAY_MT7688
bool "GARDENA smart Gateway"
select BOARD_LATE_INIT
help
GARDENA smart Gateway boards have a MT7688 SoC with 128 MiB of RAM
and 8 MiB of flash (SPI NOR) and additional SPI NAND storage.
config BOARD_LINKIT_SMART_7688
bool "LinkIt Smart 7688"
help
Seeed LinkIt Smart 7688 boards have a MT7688 SoC with 128 MiB of RAM
and 32 MiB of flash (SPI).
Between its different peripherals there's an integrated switch with 4
ethernet ports, 1 USB port, 1 UART, GPIO buttons and LEDs, and
a MT7688 (PCIe).
config BOARD_MT7628_RFB
bool "MediaTek MT7628 RFB"
help
The reference design of MT7628. The board has 128 MiB DDR2, 8 MiB
SPI-NOR flash, 1 built-in switch with 5 ports, 1 UART, 1 USB host,
1 SDXC, 1 PCIe socket and JTAG pins.
config BOARD_VOCORE2
bool "VoCore2"
select SPL_SERIAL_SUPPORT
select SPL_UART2_SPIS_PINMUX
help
VoCore VoCore2 board has a MT7628 SoC with 128 MiB of RAM
and 16 MiB of flash (SPI).
endchoice
config SPL_UART2_SPIS_PINMUX
bool "Use alternative pinmux for UART2 in SPL stage"
depends on SPL_SERIAL_SUPPORT
default n
help
Select this if the UART2 of your board is connected to GPIO 16/17
(shared with SPIS) rather than the usual GPIO 20/21.
source "board/gardena/smart-gateway-mt7688/Kconfig"
source "board/mediatek/mt7628/Kconfig"
source "board/seeed/linkit-smart-7688/Kconfig"
source "board/vocore/vocore2/Kconfig"
endif

View file

@ -0,0 +1,12 @@
if BOARD_MT7620_RFB || BOARD_MT7620_MT7530_RFB
config SYS_BOARD
default "mt7620"
config SYS_VENDOR
default "mediatek"
config SYS_CONFIG_NAME
default "mt7620"
endif

View file

@ -0,0 +1,9 @@
MT7620_RFB BOARD
M: Weijie Gao <weijie.gao@mediatek.com>
S: Maintained
F: board/mediatek/mt7620
F: include/configs/mt7620.h
F: configs/mt7620_rfb_defconfig
F: configs/mt7620_mt7530_rfb_defconfig
F: arch/mips/dts/mediatek,mt7620-rfb.dts
F: arch/mips/dts/mediatek,mt7620-mt7530-rfb.dts

View file

@ -0,0 +1,3 @@
# SPDX-License-Identifier: GPL-2.0
obj-y += board.o

View file

@ -0,0 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2020 MediaTek Inc. All Rights Reserved.
*
* Author: Weijie Gao <weijie.gao@mediatek.com>
*/

View file

@ -12,6 +12,7 @@ CONFIG_SPL=y
CONFIG_SYS_BOOTCOUNT_SINGLEWORD=y
CONFIG_ENV_OFFSET_REDUND=0xB0000
CONFIG_ARCH_MTMIPS=y
CONFIG_SOC_MT7628=y
CONFIG_DEFAULT_DEVICE_TREE="gardena-smart-gateway-mt7688"
CONFIG_RESTORE_EXCEPTION_VECTOR_BASE=y
# CONFIG_MIPS_BOOT_ENV_LEGACY is not set

View file

@ -9,6 +9,7 @@ CONFIG_SPL_SERIAL_SUPPORT=y
CONFIG_SPL_SYS_MALLOC_F_LEN=0x40000
CONFIG_SPL=y
CONFIG_ARCH_MTMIPS=y
CONFIG_SOC_MT7628=y
CONFIG_BOARD_LINKIT_SMART_7688=y
CONFIG_DEFAULT_DEVICE_TREE="linkit-smart-7688"
CONFIG_RESTORE_EXCEPTION_VECTOR_BASE=y

View file

@ -0,0 +1,58 @@
CONFIG_MIPS=y
CONFIG_SPL_LIBCOMMON_SUPPORT=y
CONFIG_SPL_LIBGENERIC_SUPPORT=y
CONFIG_NR_DRAM_BANKS=1
CONFIG_ENV_SIZE=0x1000
CONFIG_ENV_OFFSET=0x30000
CONFIG_ENV_SECT_SIZE=0x10000
CONFIG_SPL_SERIAL_SUPPORT=y
CONFIG_SPL_SYS_MALLOC_F_LEN=0x40000
CONFIG_SPL=y
CONFIG_DEBUG_UART_BASE=0xb0000c00
CONFIG_DEBUG_UART_CLOCK=40000000
CONFIG_ARCH_MTMIPS=y
CONFIG_BOARD_MT7620_MT7530_RFB=y
CONFIG_DEFAULT_DEVICE_TREE="mediatek,mt7620-mt7530-rfb"
CONFIG_RESTORE_EXCEPTION_VECTOR_BASE=y
CONFIG_MIPS_BOOT_FDT=y
CONFIG_DEBUG_UART=y
CONFIG_FIT=y
# CONFIG_ARCH_FIXUP_FDT_MEMORY is not set
CONFIG_SPL_SYS_MALLOC_SIMPLE=y
CONFIG_SPL_NOR_SUPPORT=y
# CONFIG_CMD_ELF is not set
# CONFIG_CMD_XIMG is not set
# CONFIG_CMD_CRC32 is not set
# CONFIG_CMD_DM is not set
CONFIG_CMD_GPIO=y
# CONFIG_CMD_LOADS is not set
CONFIG_CMD_SPI=y
# CONFIG_CMD_NFS is not set
CONFIG_CMD_MII=y
# CONFIG_CMD_MDIO is not set
# CONFIG_PARTITIONS is not set
CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clocks clock-names interrupt-parent interrupts resets reset-names"
CONFIG_ENV_IS_IN_SPI_FLASH=y
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_SPL_DM=y
# CONFIG_SIMPLE_BUS is not set
# CONFIG_SPL_SIMPLE_BUS is not set
CONFIG_GPIO_HOG=y
# CONFIG_INPUT is not set
CONFIG_SPI_FLASH_SFDP_SUPPORT=y
CONFIG_SPI_FLASH_EON=y
CONFIG_SPI_FLASH_GIGADEVICE=y
CONFIG_SPI_FLASH_ISSI=y
CONFIG_SPI_FLASH_MACRONIX=y
CONFIG_SPI_FLASH_SPANSION=y
CONFIG_SPI_FLASH_STMICRO=y
CONFIG_SPI_FLASH_WINBOND=y
CONFIG_SPI_FLASH_XMC=y
CONFIG_MT7620_ETH=y
CONFIG_SPECIFY_CONSOLE_INDEX=y
CONFIG_DEBUG_UART_SHIFT=2
CONFIG_SPI=y
CONFIG_MT7620_SPI=y
CONFIG_LZMA=y
CONFIG_SPL_LZMA=y

View file

@ -0,0 +1,76 @@
CONFIG_MIPS=y
CONFIG_SPL_LIBCOMMON_SUPPORT=y
CONFIG_SPL_LIBGENERIC_SUPPORT=y
CONFIG_NR_DRAM_BANKS=1
CONFIG_ENV_SIZE=0x1000
CONFIG_ENV_OFFSET=0x30000
CONFIG_ENV_SECT_SIZE=0x10000
CONFIG_SPL_SERIAL_SUPPORT=y
CONFIG_SPL_SYS_MALLOC_F_LEN=0x40000
CONFIG_SPL=y
CONFIG_DEBUG_UART_BASE=0xb0000c00
CONFIG_DEBUG_UART_CLOCK=40000000
CONFIG_ARCH_MTMIPS=y
CONFIG_DEFAULT_DEVICE_TREE="mediatek,mt7620-rfb"
CONFIG_RESTORE_EXCEPTION_VECTOR_BASE=y
CONFIG_MIPS_BOOT_FDT=y
CONFIG_DEBUG_UART=y
CONFIG_FIT=y
# CONFIG_ARCH_FIXUP_FDT_MEMORY is not set
CONFIG_SPL_SYS_MALLOC_SIMPLE=y
CONFIG_SPL_NOR_SUPPORT=y
# CONFIG_CMD_ELF is not set
# CONFIG_CMD_XIMG is not set
# CONFIG_CMD_CRC32 is not set
# CONFIG_CMD_DM is not set
CONFIG_CMD_GPIO=y
# CONFIG_CMD_LOADS is not set
CONFIG_CMD_MMC=y
CONFIG_CMD_SPI=y
CONFIG_CMD_USB=y
# CONFIG_CMD_NFS is not set
CONFIG_CMD_MII=y
# CONFIG_CMD_MDIO is not set
CONFIG_CMD_FAT=y
CONFIG_CMD_FS_GENERIC=y
# CONFIG_SPL_DOS_PARTITION is not set
# CONFIG_ISO_PARTITION is not set
CONFIG_EFI_PARTITION=y
# CONFIG_SPL_EFI_PARTITION is not set
CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clocks clock-names interrupt-parent interrupts resets reset-names"
CONFIG_ENV_IS_IN_SPI_FLASH=y
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_SPL_DM=y
# CONFIG_SIMPLE_BUS is not set
# CONFIG_SPL_SIMPLE_BUS is not set
# CONFIG_SPL_BLK is not set
CONFIG_GPIO_HOG=y
# CONFIG_INPUT is not set
CONFIG_MMC=y
CONFIG_DM_MMC=y
# CONFIG_MMC_QUIRKS is not set
# CONFIG_MMC_HW_PARTITIONING is not set
CONFIG_MMC_MTK=y
CONFIG_SPI_FLASH_SFDP_SUPPORT=y
CONFIG_SPI_FLASH_EON=y
CONFIG_SPI_FLASH_GIGADEVICE=y
CONFIG_SPI_FLASH_ISSI=y
CONFIG_SPI_FLASH_MACRONIX=y
CONFIG_SPI_FLASH_SPANSION=y
CONFIG_SPI_FLASH_STMICRO=y
CONFIG_SPI_FLASH_WINBOND=y
CONFIG_SPI_FLASH_XMC=y
CONFIG_MT7620_ETH=y
CONFIG_PHY=y
CONFIG_MT7620_USB_PHY=y
CONFIG_SPECIFY_CONSOLE_INDEX=y
CONFIG_DEBUG_UART_SHIFT=2
CONFIG_SPI=y
CONFIG_MT7620_SPI=y
CONFIG_USB=y
CONFIG_DM_USB=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_GENERIC=y
CONFIG_LZMA=y
CONFIG_SPL_LZMA=y

View file

@ -9,6 +9,7 @@ CONFIG_SPL_SERIAL_SUPPORT=y
CONFIG_SPL_SYS_MALLOC_F_LEN=0x40000
CONFIG_SPL=y
CONFIG_ARCH_MTMIPS=y
CONFIG_SOC_MT7628=y
CONFIG_BOARD_MT7628_RFB=y
CONFIG_DEFAULT_DEVICE_TREE="mediatek,mt7628-rfb"
CONFIG_RESTORE_EXCEPTION_VECTOR_BASE=y

View file

@ -10,6 +10,7 @@ CONFIG_SPL_SYS_MALLOC_F_LEN=0x40000
CONFIG_SPL=y
CONFIG_SYS_BOOTCOUNT_SINGLEWORD=y
CONFIG_ARCH_MTMIPS=y
CONFIG_SOC_MT7628=y
CONFIG_BOARD_VOCORE2=y
CONFIG_DEFAULT_DEVICE_TREE="vocore_vocore2"
CONFIG_RESTORE_EXCEPTION_VECTOR_BASE=y

View file

@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_SOC_MT7620) += clk-mt7620.o
obj-$(CONFIG_SOC_MT7628) += clk-mt7628.o

View file

@ -0,0 +1,159 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2020 MediaTek Inc. All Rights Reserved.
*
* Author: Weijie Gao <weijie.gao@mediatek.com>
*/
#include <clk-uclass.h>
#include <dm.h>
#include <dm/device_compat.h>
#include <dt-bindings/clock/mt7620-clk.h>
#include <misc.h>
#include <mach/mt7620-sysc.h>
/* CLKCFG1 */
#define CLKCFG1_REG 0x30
#define CLK_SRC_CPU -1
#define CLK_SRC_CPU_D2 -2
#define CLK_SRC_SYS -3
#define CLK_SRC_XTAL -4
#define CLK_SRC_PERI -5
struct mt7620_clk_priv {
struct udevice *dev;
struct udevice *sysc;
struct mt7620_sysc_clks clks;
};
static const int mt7620_clks[] = {
[CLK_SYS] = CLK_SRC_SYS,
[CLK_CPU] = CLK_SRC_CPU,
[CLK_XTAL] = CLK_SRC_XTAL,
[CLK_MIPS_CNT] = CLK_SRC_CPU_D2,
[CLK_UARTF] = CLK_SRC_PERI,
[CLK_UARTL] = CLK_SRC_PERI,
[CLK_SPI] = CLK_SRC_SYS,
[CLK_I2C] = CLK_SRC_PERI,
[CLK_I2S] = CLK_SRC_PERI,
};
static ulong mt7620_clk_get_rate(struct clk *clk)
{
struct mt7620_clk_priv *priv = dev_get_priv(clk->dev);
if (clk->id >= ARRAY_SIZE(mt7620_clks))
return 0;
switch (mt7620_clks[clk->id]) {
case CLK_SRC_CPU:
return priv->clks.cpu_clk;
case CLK_SRC_CPU_D2:
return priv->clks.cpu_clk / 2;
case CLK_SRC_SYS:
return priv->clks.sys_clk;
case CLK_SRC_XTAL:
return priv->clks.xtal_clk;
case CLK_SRC_PERI:
return priv->clks.peri_clk;
default:
return mt7620_clks[clk->id];
}
}
static int mt7620_clkcfg1_rmw(struct mt7620_clk_priv *priv, u32 clr, u32 set)
{
u32 val;
int ret;
ret = misc_read(priv->sysc, CLKCFG1_REG, &val, sizeof(val));
if (ret) {
dev_err(priv->dev, "mt7620_clk: failed to read CLKCFG1\n");
return ret;
}
val &= ~clr;
val |= set;
ret = misc_write(priv->sysc, CLKCFG1_REG, &val, sizeof(val));
if (ret) {
dev_err(priv->dev, "mt7620_clk: failed to write CLKCFG1\n");
return ret;
}
return 0;
}
static int mt7620_clk_enable(struct clk *clk)
{
struct mt7620_clk_priv *priv = dev_get_priv(clk->dev);
if (clk->id > 30)
return -1;
return mt7620_clkcfg1_rmw(priv, 0, BIT(clk->id));
}
static int mt7620_clk_disable(struct clk *clk)
{
struct mt7620_clk_priv *priv = dev_get_priv(clk->dev);
if (clk->id > 30)
return -1;
return mt7620_clkcfg1_rmw(priv, BIT(clk->id), 0);
}
const struct clk_ops mt7620_clk_ops = {
.enable = mt7620_clk_enable,
.disable = mt7620_clk_disable,
.get_rate = mt7620_clk_get_rate,
};
static int mt7620_clk_probe(struct udevice *dev)
{
struct mt7620_clk_priv *priv = dev_get_priv(dev);
struct ofnode_phandle_args sysc_args;
int ret;
ret = ofnode_parse_phandle_with_args(dev_ofnode(dev), "mediatek,sysc", NULL,
0, 0, &sysc_args);
if (ret) {
dev_err(dev, "mt7620_clk: sysc property not found\n");
return ret;
}
ret = uclass_get_device_by_ofnode(UCLASS_MISC, sysc_args.node,
&priv->sysc);
if (ret) {
dev_err(dev, "mt7620_clk: failed to sysc device\n");
return ret;
}
ret = misc_ioctl(priv->sysc, MT7620_SYSC_IOCTL_GET_CLK,
&priv->clks);
if (ret) {
dev_err(dev, "mt7620_clk: failed to get base clocks\n");
return ret;
}
priv->dev = dev;
return 0;
}
static const struct udevice_id mt7620_clk_ids[] = {
{ .compatible = "mediatek,mt7620-clk" },
{ }
};
U_BOOT_DRIVER(mt7620_clk) = {
.name = "mt7620-clk",
.id = UCLASS_CLK,
.of_match = mt7620_clk_ids,
.probe = mt7620_clk_probe,
.priv_auto = sizeof(struct mt7620_clk_priv),
.ops = &mt7620_clk_ops,
.flags = DM_FLAG_PRE_RELOC,
};

View file

@ -471,6 +471,14 @@ config MPC83XX_SPISEL_BOOT
This pin is typically used as spi chip select to a spi nor flash.
config MT7620_GPIO
bool "MediaTek MT7620 GPIO driver"
depends on DM_GPIO && SOC_MT7620
default y
help
Device model driver for GPIO controller present in MediaTek MT7620
and earlier SoCs.
config MT7621_GPIO
bool "MediaTek MT7621 GPIO driver"
depends on DM_GPIO && SOC_MT7628

View file

@ -64,6 +64,7 @@ obj-$(CONFIG_MVEBU_GPIO) += mvebu_gpio.o
obj-$(CONFIG_MSM_GPIO) += msm_gpio.o
obj-$(CONFIG_$(SPL_)PCF8575_GPIO) += pcf8575_gpio.o
obj-$(CONFIG_PM8916_GPIO) += pm8916_gpio.o
obj-$(CONFIG_MT7620_GPIO) += mt7620_gpio.o
obj-$(CONFIG_MT7621_GPIO) += mt7621_gpio.o
obj-$(CONFIG_MSCC_SGPIO) += mscc_sgpio.o
obj-$(CONFIG_NX_GPIO) += nx_gpio.o

146
drivers/gpio/mt7620_gpio.c Normal file
View file

@ -0,0 +1,146 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2020 MediaTek Inc. All Rights Reserved.
*
* Author: Weijie Gao <weijie.gao@mediatek.com>
*
* GPIO controller driver for MediaTek MT7620 SoC
*/
#include <dm.h>
#include <errno.h>
#include <dm/device_compat.h>
#include <linux/bitops.h>
#include <linux/io.h>
#include <asm/gpio.h>
enum mt7620_regs {
GPIO_REG_DATA,
GPIO_REG_DIR,
GPIO_REG_SET,
GPIO_REG_CLR,
__GPIO_REG_MAX
};
struct mt7620_gpio_priv {
void __iomem *base;
u32 regs[__GPIO_REG_MAX];
u32 count;
};
static int mt7620_gpio_get_value(struct udevice *dev, unsigned int offset)
{
struct mt7620_gpio_priv *priv = dev_get_priv(dev);
return !!(readl(priv->base + priv->regs[GPIO_REG_DATA]) & BIT(offset));
}
static int mt7620_gpio_set_value(struct udevice *dev, unsigned int offset,
int value)
{
struct mt7620_gpio_priv *priv = dev_get_priv(dev);
u32 reg;
reg = value ? priv->regs[GPIO_REG_SET] : priv->regs[GPIO_REG_CLR];
writel(BIT(offset), priv->base + reg);
return 0;
}
static int mt7620_gpio_direction_input(struct udevice *dev, unsigned int offset)
{
struct mt7620_gpio_priv *priv = dev_get_priv(dev);
clrbits_32(priv->base + priv->regs[GPIO_REG_DIR], BIT(offset));
return 0;
}
static int mt7620_gpio_direction_output(struct udevice *dev,
unsigned int offset, int value)
{
struct mt7620_gpio_priv *priv = dev_get_priv(dev);
/* Set value first */
mt7620_gpio_set_value(dev, offset, value);
setbits_32(priv->base + priv->regs[GPIO_REG_DIR], BIT(offset));
return 0;
}
static int mt7620_gpio_get_function(struct udevice *dev, unsigned int offset)
{
struct mt7620_gpio_priv *priv = dev_get_priv(dev);
return (readl(priv->base + priv->regs[GPIO_REG_DIR]) & BIT(offset)) ?
GPIOF_OUTPUT : GPIOF_INPUT;
}
static const struct dm_gpio_ops mt7620_gpio_ops = {
.direction_input = mt7620_gpio_direction_input,
.direction_output = mt7620_gpio_direction_output,
.get_value = mt7620_gpio_get_value,
.set_value = mt7620_gpio_set_value,
.get_function = mt7620_gpio_get_function,
};
static int mt7620_gpio_probe(struct udevice *dev)
{
struct mt7620_gpio_priv *priv = dev_get_priv(dev);
struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
const char *name;
name = dev_read_string(dev, "mediatek,bank-name");
if (!name)
name = dev->name;
uc_priv->gpio_count = priv->count;
uc_priv->bank_name = name;
return 0;
}
static int mt7620_gpio_of_to_plat(struct udevice *dev)
{
struct mt7620_gpio_priv *priv = dev_get_priv(dev);
int ret;
priv->base = dev_remap_addr_index(dev, 0);
if (!priv->base) {
dev_err(dev, "mt7620_gpio: unable to map registers\n");
return -EINVAL;
}
ret = dev_read_u32(dev, "mediatek,gpio-num", &priv->count);
if (ret) {
dev_err(dev, "mt7620_gpio: failed to get GPIO count\n");
return -EINVAL;
}
ret = dev_read_u32_array(dev, "mediatek,register-map", priv->regs,
__GPIO_REG_MAX);
if (ret) {
dev_err(dev, "mt7620_gpio: unable to get register map\n");
return -EINVAL;
}
return 0;
}
static const struct udevice_id mt7620_gpio_ids[] = {
{ .compatible = "mediatek,mt7620-gpio" },
{ }
};
U_BOOT_DRIVER(mt7620_gpio) = {
.name = "mt7620_gpio",
.id = UCLASS_GPIO,
.ops = &mt7620_gpio_ops,
.of_match = mt7620_gpio_ids,
.probe = mt7620_gpio_probe,
.of_to_plat = mt7620_gpio_of_to_plat,
.priv_auto = sizeof(struct mt7620_gpio_priv),
};

View file

@ -113,7 +113,51 @@
#define MSDC_PB2_RESPWAIT_M 0x0c
#define MSDC_PB2_RESPWAIT_S 2
/* MSDC_PAD_CTRL0 */
#define MSDC_PAD_CTRL0_CLKRDSEL_M 0xff000000
#define MSDC_PAD_CTRL0_CLKRDSEL_S 24
#define MSDC_PAD_CTRL0_CLKTDSEL BIT(20)
#define MSDC_PAD_CTRL0_CLKIES BIT(19)
#define MSDC_PAD_CTRL0_CLKSMT BIT(18)
#define MSDC_PAD_CTRL0_CLKPU BIT(17)
#define MSDC_PAD_CTRL0_CLKPD BIT(16)
#define MSDC_PAD_CTRL0_CLKSR BIT(8)
#define MSDC_PAD_CTRL0_CLKDRVP_M 0x70
#define MSDC_PAD_CTRL0_CLKDRVP_S 4
#define MSDC_PAD_CTRL0_CLKDRVN_M 0x7
#define MSDC_PAD_CTRL0_CLKDRVN_S 0
/* MSDC_PAD_CTRL1 */
#define MSDC_PAD_CTRL1_CMDRDSEL_M 0xff000000
#define MSDC_PAD_CTRL1_CMDRDSEL_S 24
#define MSDC_PAD_CTRL1_CMDTDSEL BIT(20)
#define MSDC_PAD_CTRL1_CMDIES BIT(19)
#define MSDC_PAD_CTRL1_CMDSMT BIT(18)
#define MSDC_PAD_CTRL1_CMDPU BIT(17)
#define MSDC_PAD_CTRL1_CMDPD BIT(16)
#define MSDC_PAD_CTRL1_CMDSR BIT(8)
#define MSDC_PAD_CTRL1_CMDDRVP_M 0x70
#define MSDC_PAD_CTRL1_CMDDRVP_S 4
#define MSDC_PAD_CTRL1_CMDDRVN_M 0x7
#define MSDC_PAD_CTRL1_CMDDRVN_S 0
/* MSDC_PAD_CTRL2 */
#define MSDC_PAD_CTRL2_DATRDSEL_M 0xff000000
#define MSDC_PAD_CTRL2_DATRDSEL_S 24
#define MSDC_PAD_CTRL2_DATTDSEL BIT(20)
#define MSDC_PAD_CTRL2_DATIES BIT(19)
#define MSDC_PAD_CTRL2_DATSMT BIT(18)
#define MSDC_PAD_CTRL2_DATPU BIT(17)
#define MSDC_PAD_CTRL2_DATPD BIT(16)
#define MSDC_PAD_CTRL2_DATSR BIT(8)
#define MSDC_PAD_CTRL2_DATDRVP_M 0x70
#define MSDC_PAD_CTRL2_DATDRVP_S 4
#define MSDC_PAD_CTRL2_DATDRVN_M 0x7
#define MSDC_PAD_CTRL2_DATDRVN_S 0
/* PAD_TUNE */
#define MSDC_PAD_TUNE_CLKTDLY_M 0xf8000000
#define MSDC_PAD_TUNE_CLKTDLY_S 27
#define MSDC_PAD_TUNE_CMDRRDLY_M 0x7c00000
#define MSDC_PAD_TUNE_CMDRRDLY_S 22
#define MSDC_PAD_TUNE_CMD_SEL BIT(21)
@ -129,6 +173,26 @@
#define PAD_CMD_TUNE_RX_DLY3 0x3E
#define PAD_CMD_TUNE_RX_DLY3_S 1
/* PAD_TUNE0 */
#define MSDC_PAD_TUNE0_DAT0RDDLY_M 0x1f000000
#define MSDC_PAD_TUNE0_DAT0RDDLY_S 24
#define MSDC_PAD_TUNE0_DAT1RDDLY_M 0x1f0000
#define MSDC_PAD_TUNE0_DAT1RDDLY_S 16
#define MSDC_PAD_TUNE0_DAT2RDDLY_M 0x1f00
#define MSDC_PAD_TUNE0_DAT2RDDLY_S 8
#define MSDC_PAD_TUNE0_DAT3RDDLY_M 0x1f
#define MSDC_PAD_TUNE0_DAT3RDDLY_S 0
/* PAD_TUNE1 */
#define MSDC_PAD_TUNE1_DAT4RDDLY_M 0x1f000000
#define MSDC_PAD_TUNE1_DAT4RDDLY_S 24
#define MSDC_PAD_TUNE1_DAT5RDDLY_M 0x1f0000
#define MSDC_PAD_TUNE1_DAT5RDDLY_S 16
#define MSDC_PAD_TUNE1_DAT6RDDLY_M 0x1f00
#define MSDC_PAD_TUNE1_DAT6RDDLY_S 8
#define MSDC_PAD_TUNE1_DAT7RDDLY_M 0x1f
#define MSDC_PAD_TUNE1_DAT7RDDLY_S 0
/* EMMC50_CFG0 */
#define EMMC50_CFG_CFCSTS_SEL BIT(4)
@ -166,6 +230,8 @@
#define DEFAULT_CD_DEBOUNCE 8
#define SCLK_CYCLES_SHIFT 20
#define CMD_INTS_MASK \
(MSDC_INT_CMDRDY | MSDC_INT_RSPCRCERR | MSDC_INT_CMDTMO)
@ -221,7 +287,10 @@ struct mtk_sd_regs {
u32 dat3_tune_crc;
u32 cmd_tune_crc;
u32 sdio_tune_wind;
u32 reserved4[5];
u32 reserved4[2];
u32 pad_ctrl0;
u32 pad_ctrl1;
u32 pad_ctrl2;
u32 pad_tune;
u32 pad_tune0;
u32 pad_tune1;
@ -256,13 +325,14 @@ struct msdc_top_regs {
struct msdc_compatible {
u8 clk_div_bits;
u8 sclk_cycle_shift;
bool pad_tune0;
bool async_fifo;
bool data_tune;
bool busy_check;
bool stop_clk_fix;
bool enhance_rx;
bool builtin_pad_ctrl;
bool default_pad_dly;
};
struct msdc_delay_phase {
@ -722,7 +792,7 @@ static int msdc_ops_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
static void msdc_set_timeout(struct msdc_host *host, u32 ns, u32 clks)
{
u32 timeout, clk_ns, shift;
u32 timeout, clk_ns, shift = SCLK_CYCLES_SHIFT;
u32 mode = 0;
host->timeout_ns = ns;
@ -731,7 +801,6 @@ static void msdc_set_timeout(struct msdc_host *host, u32 ns, u32 clks)
if (host->sclk == 0) {
timeout = 0;
} else {
shift = host->dev_comp->sclk_cycle_shift;
clk_ns = 1000000000UL / host->sclk;
timeout = (ns + clk_ns - 1) / clk_ns + clks;
/* unit is 1048576 sclk cycles */
@ -1391,9 +1460,14 @@ static void msdc_init_hw(struct msdc_host *host)
{
u32 val;
void __iomem *tune_reg = &host->base->pad_tune;
void __iomem *rd_dly0_reg = &host->base->pad_tune0;
void __iomem *rd_dly1_reg = &host->base->pad_tune1;
if (host->dev_comp->pad_tune0)
if (host->dev_comp->pad_tune0) {
tune_reg = &host->base->pad_tune0;
rd_dly0_reg = &host->base->dat_rd_dly[0];
rd_dly1_reg = &host->base->dat_rd_dly[1];
}
/* Configure to MMC/SD mode, clock free running */
setbits_le32(&host->base->msdc_cfg, MSDC_CFG_MODE);
@ -1479,6 +1553,45 @@ static void msdc_init_hw(struct msdc_host *host)
setbits_le32(tune_reg, MSDC_PAD_TUNE_RXDLYSEL);
}
if (host->dev_comp->builtin_pad_ctrl) {
/* Set pins driving strength */
writel(MSDC_PAD_CTRL0_CLKPD | MSDC_PAD_CTRL0_CLKSMT |
MSDC_PAD_CTRL0_CLKIES | (4 << MSDC_PAD_CTRL0_CLKDRVN_S) |
(4 << MSDC_PAD_CTRL0_CLKDRVP_S), &host->base->pad_ctrl0);
writel(MSDC_PAD_CTRL1_CMDPU | MSDC_PAD_CTRL1_CMDSMT |
MSDC_PAD_CTRL1_CMDIES | (4 << MSDC_PAD_CTRL1_CMDDRVN_S) |
(4 << MSDC_PAD_CTRL1_CMDDRVP_S), &host->base->pad_ctrl1);
writel(MSDC_PAD_CTRL2_DATPU | MSDC_PAD_CTRL2_DATSMT |
MSDC_PAD_CTRL2_DATIES | (4 << MSDC_PAD_CTRL2_DATDRVN_S) |
(4 << MSDC_PAD_CTRL2_DATDRVP_S), &host->base->pad_ctrl2);
}
if (host->dev_comp->default_pad_dly) {
/* Default pad delay may be needed if tuning not enabled */
clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_CLKTDLY_M |
MSDC_PAD_TUNE_CMDRRDLY_M |
MSDC_PAD_TUNE_CMDRDLY_M |
MSDC_PAD_TUNE_DATRRDLY_M |
MSDC_PAD_TUNE_DATWRDLY_M,
(0x10 << MSDC_PAD_TUNE_CLKTDLY_S) |
(0x10 << MSDC_PAD_TUNE_CMDRRDLY_S) |
(0x10 << MSDC_PAD_TUNE_CMDRDLY_S) |
(0x10 << MSDC_PAD_TUNE_DATRRDLY_S) |
(0x10 << MSDC_PAD_TUNE_DATWRDLY_S));
writel((0x10 << MSDC_PAD_TUNE0_DAT0RDDLY_S) |
(0x10 << MSDC_PAD_TUNE0_DAT1RDDLY_S) |
(0x10 << MSDC_PAD_TUNE0_DAT2RDDLY_S) |
(0x10 << MSDC_PAD_TUNE0_DAT3RDDLY_S),
rd_dly0_reg);
writel((0x10 << MSDC_PAD_TUNE1_DAT4RDDLY_S) |
(0x10 << MSDC_PAD_TUNE1_DAT5RDDLY_S) |
(0x10 << MSDC_PAD_TUNE1_DAT6RDDLY_S) |
(0x10 << MSDC_PAD_TUNE1_DAT7RDDLY_S),
rd_dly1_reg);
}
/* Configure to enable SDIO mode otherwise sdio cmd5 won't work */
setbits_le32(&host->base->sdc_cfg, SDC_CFG_SDIO);
@ -1526,12 +1639,14 @@ static int msdc_drv_probe(struct udevice *dev)
else
cfg->f_min = host->src_clk_freq / (4 * 4095);
cfg->f_max = host->src_clk_freq;
cfg->b_max = 1024;
cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
host->mmc = &plat->mmc;
host->timeout_ns = 100000000;
host->timeout_clks = 3 * (1 << host->dev_comp->sclk_cycle_shift);
host->timeout_clks = 3 * (1 << SCLK_CYCLES_SHIFT);
#ifdef CONFIG_PINCTRL
pinctrl_select_state(dev, "default");
@ -1615,13 +1730,14 @@ static const struct dm_mmc_ops msdc_ops = {
static const struct msdc_compatible mt7620_compat = {
.clk_div_bits = 8,
.sclk_cycle_shift = 16,
.pad_tune0 = false,
.async_fifo = false,
.data_tune = false,
.busy_check = false,
.stop_clk_fix = false,
.enhance_rx = false
.enhance_rx = false,
.builtin_pad_ctrl = true,
.default_pad_dly = true,
};
static const struct msdc_compatible mt7622_compat = {
@ -1635,7 +1751,6 @@ static const struct msdc_compatible mt7622_compat = {
static const struct msdc_compatible mt7623_compat = {
.clk_div_bits = 12,
.sclk_cycle_shift = 20,
.pad_tune0 = true,
.async_fifo = true,
.data_tune = true,
@ -1646,7 +1761,6 @@ static const struct msdc_compatible mt7623_compat = {
static const struct msdc_compatible mt8512_compat = {
.clk_div_bits = 12,
.sclk_cycle_shift = 20,
.pad_tune0 = true,
.async_fifo = true,
.data_tune = true,
@ -1656,7 +1770,6 @@ static const struct msdc_compatible mt8512_compat = {
static const struct msdc_compatible mt8516_compat = {
.clk_div_bits = 12,
.sclk_cycle_shift = 20,
.pad_tune0 = true,
.async_fifo = true,
.data_tune = true,
@ -1666,7 +1779,6 @@ static const struct msdc_compatible mt8516_compat = {
static const struct msdc_compatible mt8183_compat = {
.clk_div_bits = 12,
.sclk_cycle_shift = 20,
.pad_tune0 = true,
.async_fifo = true,
.data_tune = true,

View file

@ -399,6 +399,18 @@ config MACB_ZYNQ
The Cadence MACB ethernet interface was used on Zynq platform.
Say Y to enable support for the MACB/GEM in Zynq chip.
config MT7620_ETH
bool "MediaTek MT7620 Ethernet Interface"
depends on SOC_MT7620
select PHYLIB
select DM_RESET
select DM_GPIO
select CLK
help
The MediaTek MT7620 ethernet interface is used on MT7620 based
boards. It has a built-in switch with two configurable ports which
can connect to external PHY/MACs.
config MT7628_ETH
bool "MediaTek MT7628 Ethernet Interface"
depends on SOC_MT7628

View file

@ -44,6 +44,7 @@ obj-$(CONFIG_MDIO_IPQ4019) += mdio-ipq4019.o
obj-$(CONFIG_MDIO_MUX_I2CREG) += mdio_mux_i2creg.o
obj-$(CONFIG_MDIO_MUX_SANDBOX) += mdio_mux_sandbox.o
obj-$(CONFIG_MPC8XX_FEC) += mpc8xx_fec.o
obj-$(CONFIG_MT7620_ETH) += mt7620-eth.o
obj-$(CONFIG_MT7628_ETH) += mt7628-eth.o
obj-$(CONFIG_MVGBE) += mvgbe.o
obj-$(CONFIG_MVMDIO) += mvmdio.o

1222
drivers/net/mt7620-eth.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -218,6 +218,13 @@ config KEYSTONE_USB_PHY
This PHY is found on some Keystone (K2) devices supporting USB.
config MT7620_USB_PHY
bool "MediaTek MT7620 USB PHY support"
depends on PHY
depends on SOC_MT7620
help
Support the intergated USB PHY in MediaTek MT7620 SoC
config MT76X8_USB_PHY
bool "MediaTek MT76x8 (7628/88) USB PHY support"
depends on PHY

View file

@ -24,6 +24,7 @@ obj-$(CONFIG_MESON_G12A_USB_PHY) += meson-g12a-usb2.o meson-g12a-usb3-pcie.o
obj-$(CONFIG_MSM8916_USB_PHY) += msm8916-usbh-phy.o
obj-$(CONFIG_OMAP_USB2_PHY) += omap-usb2-phy.o
obj-$(CONFIG_KEYSTONE_USB_PHY) += keystone-usb-phy.o
obj-$(CONFIG_MT7620_USB_PHY) += mt7620-usb-phy.o
obj-$(CONFIG_MT76X8_USB_PHY) += mt76x8-usb-phy.o
obj-$(CONFIG_PHY_DA8XX_USB) += phy-da8xx-usb.o
obj-$(CONFIG_PHY_MTK_TPHY) += phy-mtk-tphy.o

View file

@ -0,0 +1,110 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2020 MediaTek Inc. All Rights Reserved.
*
* Author: Weijie Gao <weijie.gao@mediatek.com>
*/
#include <clk.h>
#include <dm.h>
#include <generic-phy.h>
#include <misc.h>
#include <reset.h>
#include <dm/device_compat.h>
#include <linux/delay.h>
#include <mach/mt7620-sysc.h>
struct mt7620_usb_phy {
struct udevice *sysc;
struct clk_bulk clocks;
struct reset_ctl_bulk resets;
};
static int mt7620_usb_phy_power_on(struct phy *_phy)
{
struct mt7620_usb_phy *phy = dev_get_priv(_phy->dev);
u32 mode = MT7620_SYSC_USB_HOST_MODE;
int ret;
reset_deassert_bulk(&phy->resets);
clk_enable_bulk(&phy->clocks);
mdelay(10);
ret = misc_ioctl(phy->sysc, MT7620_SYSC_IOCTL_SET_USB_MODE, &mode);
if (ret) {
dev_err(_phy->dev,
"mt7620_usbphy: failed to set USB host mode\n");
return ret;
}
mdelay(10);
return 0;
}
static int mt7620_usb_phy_power_off(struct phy *_phy)
{
struct mt7620_usb_phy *phy = dev_get_priv(_phy->dev);
clk_disable_bulk(&phy->clocks);
reset_assert_bulk(&phy->resets);
return 0;
}
static int mt7620_usb_phy_probe(struct udevice *dev)
{
struct mt7620_usb_phy *phy = dev_get_priv(dev);
struct ofnode_phandle_args sysc_args;
int ret;
ret = ofnode_parse_phandle_with_args(dev_ofnode(dev), "mediatek,sysc", NULL,
0, 0, &sysc_args);
if (ret) {
dev_err(dev, "mt7620_usbphy: sysc property not found\n");
return ret;
}
ret = uclass_get_device_by_ofnode(UCLASS_MISC, sysc_args.node,
&phy->sysc);
if (ret) {
dev_err(dev, "mt7620_usbphy: failed to sysc device\n");
return ret;
}
ret = clk_get_bulk(dev, &phy->clocks);
if (ret) {
dev_err(dev, "mt7620_usbphy: failed to get clocks\n");
return ret;
}
ret = reset_get_bulk(dev, &phy->resets);
if (ret) {
dev_err(dev, "mt7620_usbphy: failed to get reset control\n");
return ret;
}
return 0;
}
static struct phy_ops mt7620_usb_phy_ops = {
.power_on = mt7620_usb_phy_power_on,
.power_off = mt7620_usb_phy_power_off,
};
static const struct udevice_id mt7620_usb_phy_ids[] = {
{ .compatible = "mediatek,mt7620-usbphy" },
{ }
};
U_BOOT_DRIVER(mt7620_usb_phy) = {
.name = "mt7620_usb_phy",
.id = UCLASS_PHY,
.of_match = mt7620_usb_phy_ids,
.ops = &mt7620_usb_phy_ops,
.probe = mt7620_usb_phy_probe,
.priv_auto = sizeof(struct mt7620_usb_phy),
};

View file

@ -3,6 +3,15 @@ config PINCTRL_MTMIPS
depends on ARCH_MTMIPS
bool
config PINCTRL_MT7620
bool "MediaTek MT7620 pin control driver"
select PINCTRL_MTMIPS
depends on SOC_MT7620 && PINCTRL_GENERIC
help
Support pin multiplexing control on MediaTek MT7620.
The driver is controlled by a device tree node which contains
the pin mux functions for each available pin groups.
config PINCTRL_MT7628
bool "MediaTek MT7628 pin control driver"
select PINCTRL_MTMIPS

View file

@ -4,4 +4,5 @@
obj-$(CONFIG_PINCTRL_MTMIPS) += pinctrl-mtmips-common.o
# SoC Drivers
obj-$(CONFIG_PINCTRL_MT7620) += pinctrl-mt7620.o
obj-$(CONFIG_PINCTRL_MT7628) += pinctrl-mt7628.o

View file

@ -0,0 +1,200 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2020 MediaTek Inc. All Rights Reserved.
*
* Author: Weijie Gao <weijie.gao@mediatek.com>
*/
#include <dm.h>
#include <dm/pinctrl.h>
#include <linux/bitops.h>
#include <linux/io.h>
#include "pinctrl-mtmips-common.h"
#define SUTIF_SHIFT 30
#define WDT_RST_SHIFT 21
#define PA_G_SHIFT 20
#define NAND_SD_SHIFT 18
#define PERST_SHIFT 16
#define EPHY_LED_SHIFT 15
#define WLED_SHIFT 13
#define SPI_CS1_SHIFT 12
#define SPI_SHIFT 11
#define RGMII2_SHIFT 10
#define RGMII1_SHIFT 9
#define MDIO_SHIFT 7
#define UARTL_SHIFT 5
#define UARTF_SHIFT 2
#define I2C_SHIFT 0
#define GM4_MASK 3
#define GM8_MASK 7
#if CONFIG_IS_ENABLED(PINMUX)
static const struct mtmips_pmx_func sutif_grp[] = {
FUNC("i2c", 2),
FUNC("uartl", 1),
FUNC("none", 0),
};
static const struct mtmips_pmx_func wdt_rst_grp[] = {
FUNC("gpio", 2),
FUNC("refclk", 1),
FUNC("wdt rst", 0),
};
static const struct mtmips_pmx_func pa_g_grp[] = {
FUNC("gpio", 1),
FUNC("pa", 0),
};
static const struct mtmips_pmx_func nand_sd_grp[] = {
FUNC("gpio", 2),
FUNC("sd", 1),
FUNC("nand", 0),
};
static const struct mtmips_pmx_func perst_grp[] = {
FUNC("gpio", 2),
FUNC("refclk", 1),
FUNC("perst", 0),
};
static const struct mtmips_pmx_func ephy_led_grp[] = {
FUNC("gpio", 1),
FUNC("led", 0),
};
static const struct mtmips_pmx_func wled_grp[] = {
FUNC("gpio", 1),
FUNC("led", 0),
};
static const struct mtmips_pmx_func spi_cs1_grp[] = {
FUNC("refclk", 1),
FUNC("spi cs1", 0),
};
static const struct mtmips_pmx_func spi_grp[] = {
FUNC("gpio", 1),
FUNC("spi", 0),
};
static const struct mtmips_pmx_func rgmii2_grp[] = {
FUNC("gpio", 1),
FUNC("rgmii2", 0),
};
static const struct mtmips_pmx_func rgmii1_grp[] = {
FUNC("gpio", 1),
FUNC("rgmii1", 0),
};
static const struct mtmips_pmx_func mdio_grp[] = {
FUNC("gpio", 2),
FUNC("refclk", 1),
FUNC("mdio", 0),
};
static const struct mtmips_pmx_func uartl_grp[] = {
FUNC("gpio", 1),
FUNC("uartl", 0),
};
static const struct mtmips_pmx_func uartf_grp[] = {
FUNC("gpio", 7),
FUNC("i2s gpio", 6),
FUNC("uartf gpio", 5),
FUNC("gpio pcm", 4),
FUNC("i2s uartf", 3),
FUNC("i2s pcm", 2),
FUNC("uartf pcm", 1),
FUNC("uartf", 0),
};
static const struct mtmips_pmx_func i2c_grp[] = {
FUNC("gpio", 1),
FUNC("i2c", 0),
};
static const struct mtmips_pmx_group mt7620_pinmux_data[] = {
GRP("sutif", sutif_grp, 0, SUTIF_SHIFT, GM4_MASK),
GRP("wdt rst", wdt_rst_grp, 0, WDT_RST_SHIFT, GM4_MASK),
GRP("pa", pa_g_grp, 0, PA_G_SHIFT, 1),
GRP("nand", nand_sd_grp, 0, NAND_SD_SHIFT, GM4_MASK),
GRP("perst", perst_grp, 0, PERST_SHIFT, GM4_MASK),
GRP("ephy led", ephy_led_grp, 0, EPHY_LED_SHIFT, 1),
GRP("wled", wled_grp, 0, WLED_SHIFT, 1),
GRP("spi cs1", spi_cs1_grp, 0, SPI_CS1_SHIFT, 1),
GRP("spi", spi_grp, 0, SPI_SHIFT, 1),
GRP("rgmii2", rgmii2_grp, 0, RGMII2_SHIFT, 1),
GRP("rgmii1", rgmii1_grp, 0, RGMII1_SHIFT, 1),
GRP("mdio", mdio_grp, 0, MDIO_SHIFT, GM4_MASK),
GRP("uartl", uartl_grp, 0, UARTL_SHIFT, 1),
GRP("uartf", uartf_grp, 0, UARTF_SHIFT, GM8_MASK),
GRP("i2c", i2c_grp, 0, I2C_SHIFT, 1),
};
static int mt7620_get_groups_count(struct udevice *dev)
{
return ARRAY_SIZE(mt7620_pinmux_data);
}
static const char *mt7620_get_group_name(struct udevice *dev,
unsigned int selector)
{
return mt7620_pinmux_data[selector].name;
}
#endif /* CONFIG_IS_ENABLED(PINMUX) */
static int mt7620_pinctrl_probe(struct udevice *dev)
{
struct mtmips_pinctrl_priv *priv = dev_get_priv(dev);
int ret = 0;
#if CONFIG_IS_ENABLED(PINMUX)
ret = mtmips_pinctrl_probe(priv, ARRAY_SIZE(mt7620_pinmux_data),
mt7620_pinmux_data);
#endif /* CONFIG_IS_ENABLED(PINMUX) */
return ret;
}
static int mt7620_pinctrl_of_to_plat(struct udevice *dev)
{
struct mtmips_pinctrl_priv *priv = dev_get_priv(dev);
priv->base = dev_remap_addr_index(dev, 0);
if (!priv->base)
return -EINVAL;
return 0;
}
static const struct pinctrl_ops mt7620_pinctrl_ops = {
#if CONFIG_IS_ENABLED(PINMUX)
.get_groups_count = mt7620_get_groups_count,
.get_group_name = mt7620_get_group_name,
.get_functions_count = mtmips_get_functions_count,
.get_function_name = mtmips_get_function_name,
.pinmux_group_set = mtmips_pinmux_group_set,
#endif /* CONFIG_IS_ENABLED(PINMUX) */
.set_state = pinctrl_generic_set_state,
};
static const struct udevice_id mt7620_pinctrl_ids[] = {
{ .compatible = "mediatek,mt7620-pinctrl" },
{ }
};
U_BOOT_DRIVER(mt7620_pinctrl) = {
.name = "mt7620-pinctrl",
.id = UCLASS_PINCTRL,
.of_match = mt7620_pinctrl_ids,
.of_to_plat = mt7620_pinctrl_of_to_plat,
.ops = &mt7620_pinctrl_ops,
.probe = mt7620_pinctrl_probe,
.priv_auto = sizeof(struct mtmips_pinctrl_priv),
.flags = DM_FLAG_PRE_RELOC,
};

View file

@ -82,4 +82,5 @@ U_BOOT_DRIVER(mtmips_reset) = {
.probe = mtmips_reset_probe,
.priv_auto = sizeof(struct mtmips_reset_priv),
.ops = &mtmips_reset_ops,
.flags = DM_FLAG_PRE_RELOC,
};

View file

@ -417,6 +417,16 @@ config DEBUG_UART_MTK
driver will be available until the real driver model serial is
running.
config DEBUG_UART_MT7620
bool "UART driver for MediaTek MT7620 and earlier SoCs"
depends on MT7620_SERIAL
help
Select this to enable a debug UART using the UART driver for
MediaTek MT7620 and earlier SoCs.
You will need to provide parameters to make this work. The
driver will be available until the real driver model serial is
running.
endchoice
config DEBUG_UART_BASE
@ -833,6 +843,16 @@ config MTK_SERIAL
The High-speed UART is compatible with the ns16550a UART and have
its own high-speed registers.
config MT7620_SERIAL
bool "UART driver for MediaTek MT7620 and earlier SoCs"
depends on DM_SERIAL
help
Select this to enable UART support for MediaTek MT7620 and earlier
SoCs. This driver uses driver model and requires a device tree
binding to operate.
The UART driver for MediaTek MT7620 and earlier SoCs is *NOT*
compatible with the ns16550a UART.
config MPC8XX_CONS
bool "Console driver for MPC8XX"
depends on MPC8xx

View file

@ -69,6 +69,7 @@ obj-$(CONFIG_NULLDEV_SERIAL) += serial_nulldev.o
obj-$(CONFIG_OWL_SERIAL) += serial_owl.o
obj-$(CONFIG_OMAP_SERIAL) += serial_omap.o
obj-$(CONFIG_MTK_SERIAL) += serial_mtk.o
obj-$(CONFIG_MT7620_SERIAL) += serial_mt7620.o
obj-$(CONFIG_SIFIVE_SERIAL) += serial_sifive.o
obj-$(CONFIG_XEN_SERIAL) += serial_xen.o

View file

@ -0,0 +1,246 @@
// SPDX-License-Identifier: GPL-2.0
/*
* UART driver for MediaTek MT7620 and earlier SoCs
*
* Copyright (C) 2020 MediaTek Inc.
* Author: Weijie Gao <weijie.gao@mediatek.com>
*/
#include <clk.h>
#include <div64.h>
#include <dm.h>
#include <errno.h>
#include <log.h>
#include <reset.h>
#include <serial.h>
#include <watchdog.h>
#include <asm/io.h>
#include <asm/types.h>
#include <asm/addrspace.h>
#include <dm/device_compat.h>
#include <linux/err.h>
#if CONFIG_IS_ENABLED(OF_PLATDATA)
#include <dt-structs.h>
#endif
struct mt7620_serial_regs {
u32 rbr;
u32 thr;
u32 ier;
u32 iir;
u32 fcr;
u32 lcr;
u32 mcr;
u32 lsr;
u32 msr;
u32 scratch;
u32 dl;
u32 dll;
u32 dlm;
u32 ifctl;
};
#define UART_LCR_WLS_8 0x03 /* 8 bit character length */
#define UART_LSR_DR 0x01 /* Data ready */
#define UART_LSR_THRE 0x20 /* Xmit holding register empty */
#define UART_LSR_TEMT 0x40 /* Xmitter empty */
#define UART_MCR_DTR 0x01 /* DTR */
#define UART_MCR_RTS 0x02 /* RTS */
#define UART_FCR_FIFO_EN 0x01 /* Fifo enable */
#define UART_FCR_RXSR 0x02 /* Receiver soft reset */
#define UART_FCR_TXSR 0x04 /* Transmitter soft reset */
#define UART_MCRVAL (UART_MCR_DTR | \
UART_MCR_RTS)
/* Clear & enable FIFOs */
#define UART_FCRVAL (UART_FCR_FIFO_EN | \
UART_FCR_RXSR | \
UART_FCR_TXSR)
struct mt7620_serial_plat {
#if CONFIG_IS_ENABLED(OF_PLATDATA)
struct dtd_serial_mt7620 dtplat;
#endif
struct mt7620_serial_regs __iomem *regs;
u32 clock;
};
static void _mt7620_serial_setbrg(struct mt7620_serial_plat *plat, int baud)
{
u32 quot;
/* set divisor */
quot = DIV_ROUND_CLOSEST(plat->clock, 16 * baud);
writel(quot, &plat->regs->dl);
/* set character length and stop bits */
writel(UART_LCR_WLS_8, &plat->regs->lcr);
}
static int mt7620_serial_setbrg(struct udevice *dev, int baudrate)
{
struct mt7620_serial_plat *plat = dev_get_plat(dev);
_mt7620_serial_setbrg(plat, baudrate);
return 0;
}
static int mt7620_serial_putc(struct udevice *dev, const char ch)
{
struct mt7620_serial_plat *plat = dev_get_plat(dev);
if (!(readl(&plat->regs->lsr) & UART_LSR_THRE))
return -EAGAIN;
writel(ch, &plat->regs->thr);
if (ch == '\n')
WATCHDOG_RESET();
return 0;
}
static int mt7620_serial_getc(struct udevice *dev)
{
struct mt7620_serial_plat *plat = dev_get_plat(dev);
if (!(readl(&plat->regs->lsr) & UART_LSR_DR))
return -EAGAIN;
return readl(&plat->regs->rbr);
}
static int mt7620_serial_pending(struct udevice *dev, bool input)
{
struct mt7620_serial_plat *plat = dev_get_plat(dev);
if (input)
return (readl(&plat->regs->lsr) & UART_LSR_DR) ? 1 : 0;
return (readl(&plat->regs->lsr) & UART_LSR_THRE) ? 0 : 1;
}
static int mt7620_serial_probe(struct udevice *dev)
{
struct mt7620_serial_plat *plat = dev_get_plat(dev);
#if CONFIG_IS_ENABLED(OF_PLATDATA)
plat->regs = (void __iomem *)KSEG1ADDR(plat->dtplat.reg[0]);
plat->clock = plat->dtplat.clock_frequency;
#endif
/* Disable interrupt */
writel(0, &plat->regs->ier);
writel(UART_MCRVAL, &plat->regs->mcr);
writel(UART_FCRVAL, &plat->regs->fcr);
return 0;
}
#if !CONFIG_IS_ENABLED(OF_PLATDATA)
static int mt7620_serial_of_to_plat(struct udevice *dev)
{
struct mt7620_serial_plat *plat = dev_get_plat(dev);
struct reset_ctl reset_uart;
struct clk clk;
int err;
err = reset_get_by_index(dev, 0, &reset_uart);
if (!err)
reset_deassert(&reset_uart);
plat->regs = dev_remap_addr_index(dev, 0);
if (!plat->regs) {
dev_err(dev, "mt7620_serial: unable to map UART registers\n");
return -EINVAL;
}
err = clk_get_by_index(dev, 0, &clk);
if (!err) {
err = clk_get_rate(&clk);
if (!IS_ERR_VALUE(err))
plat->clock = err;
} else if (err != -ENOENT && err != -ENODEV && err != -ENOSYS) {
dev_err(dev, "mt7620_serial: failed to get clock\n");
return err;
}
if (!plat->clock)
plat->clock = dev_read_u32_default(dev, "clock-frequency", 0);
if (!plat->clock) {
dev_err(dev, "mt7620_serial: clock not defined\n");
return -EINVAL;
}
return 0;
}
static const struct udevice_id mt7620_serial_ids[] = {
{ .compatible = "mediatek,mt7620-uart" },
{ }
};
#endif
static const struct dm_serial_ops mt7620_serial_ops = {
.putc = mt7620_serial_putc,
.pending = mt7620_serial_pending,
.getc = mt7620_serial_getc,
.setbrg = mt7620_serial_setbrg,
};
U_BOOT_DRIVER(serial_mt7620) = {
.name = "serial_mt7620",
.id = UCLASS_SERIAL,
#if !CONFIG_IS_ENABLED(OF_PLATDATA)
.of_match = mt7620_serial_ids,
.of_to_plat = mt7620_serial_of_to_plat,
#endif
.plat_auto = sizeof(struct mt7620_serial_plat),
.probe = mt7620_serial_probe,
.ops = &mt7620_serial_ops,
.flags = DM_FLAG_PRE_RELOC,
};
DM_DRIVER_ALIAS(serial_mt7620, mediatek_mt7620_uart);
#ifdef CONFIG_DEBUG_UART_MT7620
#include <debug_uart.h>
static inline void _debug_uart_init(void)
{
struct mt7620_serial_plat plat;
plat.regs = (void *)CONFIG_DEBUG_UART_BASE;
plat.clock = CONFIG_DEBUG_UART_CLOCK;
writel(0, &plat.regs->ier);
writel(UART_MCRVAL, &plat.regs->mcr);
writel(UART_FCRVAL, &plat.regs->fcr);
_mt7620_serial_setbrg(&plat, CONFIG_BAUDRATE);
}
static inline void _debug_uart_putc(int ch)
{
struct mt7620_serial_regs __iomem *regs =
(void *)CONFIG_DEBUG_UART_BASE;
while (!(readl(&regs->lsr) & UART_LSR_THRE))
;
writel(ch, &regs->thr);
}
DEBUG_UART_FUNCS
#endif

View file

@ -210,6 +210,13 @@ config MSCC_BB_SPI
Enable MSCC bitbang SPI driver. This driver can be used on
MSCC SOCs.
config MT7620_SPI
bool "MediaTek MT7620 SPI driver"
depends on SOC_MT7620
help
Enable the MT7620 SPI driver. This driver can be used to access
generic SPI devices on MediaTek MT7620 SoC.
config MT7621_SPI
bool "MediaTek MT7621 SPI driver"
depends on SOC_MT7628

View file

@ -37,6 +37,7 @@ obj-$(CONFIG_MESON_SPIFC) += meson_spifc.o
obj-$(CONFIG_MPC8XX_SPI) += mpc8xx_spi.o
obj-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o
obj-$(CONFIG_MTK_SNFI_SPI) += mtk_snfi_spi.o
obj-$(CONFIG_MT7620_SPI) += mt7620_spi.o
obj-$(CONFIG_MT7621_SPI) += mt7621_spi.o
obj-$(CONFIG_MSCC_BB_SPI) += mscc_bb_spi.o
obj-$(CONFIG_MVEBU_A3700_SPI) += mvebu_a3700_spi.o

281
drivers/spi/mt7620_spi.c Normal file
View file

@ -0,0 +1,281 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2020 MediaTek Inc.
*
* Author: Weijie Gao <weijie.gao@mediatek.com>
*
* Generic SPI driver for MediaTek MT7620 SoC
*/
#include <clk.h>
#include <dm.h>
#include <dm/device_compat.h>
#include <spi.h>
#include <linux/bitops.h>
#include <linux/iopoll.h>
#include <linux/io.h>
#include <linux/log2.h>
#define MT7620_SPI_NUM_CS 2
#define MT7620_SPI_MASTER1_OFF 0x00
#define MT7620_SPI_MASTER2_OFF 0x40
/* SPI_STAT */
#define SPI_BUSY BIT(0)
/* SPI_CFG */
#define MSB_FIRST BIT(8)
#define SPI_CLK_POL BIT(6)
#define RX_CLK_EDGE BIT(5)
#define TX_CLK_EDGE BIT(4)
#define SPI_CLK_S 0
#define SPI_CLK_M GENMASK(2, 0)
/* SPI_CTL */
#define START_WR BIT(2)
#define START_RD BIT(1)
#define SPI_HIGH BIT(0)
#define SPI_ARB 0xf0
#define ARB_EN BIT(31)
#define POLLING_SCALE 10
#define POLLING_FRAC_USEC 100
struct mt7620_spi_master_regs {
u32 stat;
u32 reserved0[3];
u32 cfg;
u32 ctl;
u32 reserved1[2];
u32 data;
};
struct mt7620_spi {
void __iomem *regs;
struct mt7620_spi_master_regs *m[MT7620_SPI_NUM_CS];
unsigned int sys_freq;
u32 wait_us;
uint mode;
uint speed;
};
static void mt7620_spi_master_setup(struct mt7620_spi *ms, int cs)
{
u32 rate, prescale, freq, tmo, cfg;
/* Calculate the clock divsior */
rate = DIV_ROUND_UP(ms->sys_freq, ms->speed);
rate = roundup_pow_of_two(rate);
prescale = ilog2(rate / 2);
if (prescale > 6)
prescale = 6;
/* Calculate the real clock, and usecs for one byte transaction */
freq = ms->sys_freq >> (prescale + 1);
tmo = DIV_ROUND_UP(8 * 1000000, freq);
/* 10 times tolerance plus 100us */
ms->wait_us = POLLING_SCALE * tmo + POLLING_FRAC_USEC;
/* set SPI_CFG */
cfg = prescale << SPI_CLK_S;
switch (ms->mode & (SPI_CPOL | SPI_CPHA)) {
case SPI_MODE_0:
cfg |= TX_CLK_EDGE;
break;
case SPI_MODE_1:
cfg |= RX_CLK_EDGE;
break;
case SPI_MODE_2:
cfg |= SPI_CLK_POL | RX_CLK_EDGE;
break;
case SPI_MODE_3:
cfg |= SPI_CLK_POL | TX_CLK_EDGE;
break;
}
if (!(ms->mode & SPI_LSB_FIRST))
cfg |= MSB_FIRST;
writel(cfg, &ms->m[cs]->cfg);
writel(SPI_HIGH, &ms->m[cs]->ctl);
}
static void mt7620_spi_set_cs(struct mt7620_spi *ms, int cs, bool enable)
{
if (enable)
mt7620_spi_master_setup(ms, cs);
if (ms->mode & SPI_CS_HIGH)
enable = !enable;
if (enable)
clrbits_32(&ms->m[cs]->ctl, SPI_HIGH);
else
setbits_32(&ms->m[cs]->ctl, SPI_HIGH);
}
static int mt7620_spi_set_mode(struct udevice *bus, uint mode)
{
struct mt7620_spi *ms = dev_get_priv(bus);
ms->mode = mode;
/* Mode 0 is buggy. Force to use mode 3 */
if ((mode & SPI_MODE_3) == SPI_MODE_0)
ms->mode |= SPI_MODE_3;
return 0;
}
static int mt7620_spi_set_speed(struct udevice *bus, uint speed)
{
struct mt7620_spi *ms = dev_get_priv(bus);
ms->speed = speed;
return 0;
}
static inline int mt7620_spi_busy_poll(struct mt7620_spi *ms, int cs)
{
u32 val;
return readl_poll_timeout(&ms->m[cs]->stat, val, !(val & SPI_BUSY),
ms->wait_us);
}
static int mt7620_spi_read(struct mt7620_spi *ms, int cs, u8 *buf, size_t len)
{
int ret;
while (len) {
setbits_32(&ms->m[cs]->ctl, START_RD);
ret = mt7620_spi_busy_poll(ms, cs);
if (ret)
return ret;
*buf++ = (u8)readl(&ms->m[cs]->data);
len--;
}
return 0;
}
static int mt7620_spi_write(struct mt7620_spi *ms, int cs, const u8 *buf,
size_t len)
{
int ret;
while (len) {
writel(*buf++, &ms->m[cs]->data);
setbits_32(&ms->m[cs]->ctl, START_WR);
ret = mt7620_spi_busy_poll(ms, cs);
if (ret)
return ret;
len--;
}
return 0;
}
static int mt7620_spi_xfer(struct udevice *dev, unsigned int bitlen,
const void *dout, void *din, unsigned long flags)
{
struct udevice *bus = dev->parent;
struct mt7620_spi *ms = dev_get_priv(bus);
int total_size = bitlen >> 3;
int cs, ret = 0;
/*
* This driver only supports half-duplex, so complain and bail out
* upon full-duplex messages
*/
if (dout && din) {
dev_err(dev, "mt7620_spi: Only half-duplex is supported\n");
return -EIO;
}
cs = spi_chip_select(dev);
if (cs < 0 || cs >= MT7620_SPI_NUM_CS) {
dev_err(dev, "mt7620_spi: Invalid chip select %d\n", cs);
return -EINVAL;
}
if (flags & SPI_XFER_BEGIN)
mt7620_spi_set_cs(ms, cs, true);
if (din)
ret = mt7620_spi_read(ms, cs, din, total_size);
else if (dout)
ret = mt7620_spi_write(ms, cs, dout, total_size);
if (ret)
dev_err(dev, "mt7620_spi: %s transaction timeout\n",
din ? "read" : "write");
if (flags & SPI_XFER_END)
mt7620_spi_set_cs(ms, cs, false);
return ret;
}
static int mt7620_spi_probe(struct udevice *dev)
{
struct mt7620_spi *ms = dev_get_priv(dev);
struct clk clk;
int ret;
ms->regs = dev_remap_addr(dev);
if (!ms->regs)
return -EINVAL;
ms->m[0] = ms->regs + MT7620_SPI_MASTER1_OFF;
ms->m[1] = ms->regs + MT7620_SPI_MASTER2_OFF;
ret = clk_get_by_index(dev, 0, &clk);
if (ret < 0) {
dev_err(dev, "mt7620_spi: Please provide a clock!\n");
return ret;
}
clk_enable(&clk);
ms->sys_freq = clk_get_rate(&clk);
if (!ms->sys_freq) {
dev_err(dev, "mt7620_spi: Please provide a valid bus clock!\n");
return -EINVAL;
}
writel(ARB_EN, ms->regs + SPI_ARB);
return 0;
}
static const struct dm_spi_ops mt7620_spi_ops = {
.set_mode = mt7620_spi_set_mode,
.set_speed = mt7620_spi_set_speed,
.xfer = mt7620_spi_xfer,
};
static const struct udevice_id mt7620_spi_ids[] = {
{ .compatible = "mediatek,mt7620-spi" },
{ }
};
U_BOOT_DRIVER(mt7620_spi) = {
.name = "mt7620_spi",
.id = UCLASS_SPI,
.of_match = mt7620_spi_ids,
.ops = &mt7620_spi_ops,
.priv_auto = sizeof(struct mt7620_spi),
.probe = mt7620_spi_probe,
};

View file

@ -134,6 +134,13 @@ config WDT_MPC8xx
help
Select this to enable mpc8xx watchdog timer
config WDT_MT7620
bool "MediaTek MT7620 watchdog timer support"
depends on WDT && SOC_MT7620
help
Select this to enable watchdog timer on MediaTek MT7620 and earlier
SoC chips.
config WDT_MT7621
bool "MediaTek MT7621 watchdog timer support"
depends on WDT && SOC_MT7628

View file

@ -25,6 +25,7 @@ obj-$(CONFIG_WDT_CORTINA) += cortina_wdt.o
obj-$(CONFIG_WDT_ORION) += orion_wdt.o
obj-$(CONFIG_WDT_CDNS) += cdns_wdt.o
obj-$(CONFIG_WDT_MPC8xx) += mpc8xx_wdt.o
obj-$(CONFIG_WDT_MT7620) += mt7620_wdt.o
obj-$(CONFIG_WDT_MT7621) += mt7621_wdt.o
obj-$(CONFIG_WDT_MTK) += mtk_wdt.o
obj-$(CONFIG_WDT_OCTEONTX) += octeontx_wdt.o

View file

@ -0,0 +1,142 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2020 MediaTek Inc.
*
* Author: Weijie Gao <weijie.gao@mediatek.com>
*
* Watchdog timer for MT7620 and earlier SoCs
*/
#include <div64.h>
#include <dm.h>
#include <reset.h>
#include <wdt.h>
#include <linux/bitops.h>
#include <linux/io.h>
struct mt7620_wdt {
void __iomem *regs;
u64 timeout;
};
#define TIMER_FREQ 40000000
#define TIMER_MASK 0xffff
#define TIMER_PRESCALE 65536
#define TIMER_LOAD 0x00
#define TIMER_CTL 0x08
#define TIMER_ENABLE BIT(7)
#define TIMER_MODE_SHIFT 4
#define TIMER_MODE_WDT 3
#define TIMER_PRESCALE_SHIFT 0
#define TIMER_PRESCALE_65536 15
static void mt7620_wdt_ping(struct mt7620_wdt *priv)
{
u64 val;
val = (TIMER_FREQ / TIMER_PRESCALE) * priv->timeout;
do_div(val, 1000);
if (val > TIMER_MASK)
val = TIMER_MASK;
writel(val, priv->regs + TIMER_LOAD);
}
static int mt7620_wdt_start(struct udevice *dev, u64 ms, ulong flags)
{
struct mt7620_wdt *priv = dev_get_priv(dev);
priv->timeout = ms;
mt7620_wdt_ping(priv);
writel(TIMER_ENABLE | (TIMER_MODE_WDT << TIMER_MODE_SHIFT) |
(TIMER_PRESCALE_65536 << TIMER_PRESCALE_SHIFT),
priv->regs + TIMER_CTL);
return 0;
}
static int mt7620_wdt_stop(struct udevice *dev)
{
struct mt7620_wdt *priv = dev_get_priv(dev);
mt7620_wdt_ping(priv);
clrbits_32(priv->regs + TIMER_CTL, TIMER_ENABLE);
return 0;
}
static int mt7620_wdt_reset(struct udevice *dev)
{
struct mt7620_wdt *priv = dev_get_priv(dev);
mt7620_wdt_ping(priv);
return 0;
}
static int mt7620_wdt_expire_now(struct udevice *dev, ulong flags)
{
struct mt7620_wdt *priv = dev_get_priv(dev);
mt7620_wdt_start(dev, 1, flags);
/*
* 0 will disable the timer directly, a positive number must be used
* instead. Since the timer is a countdown timer, 1 (tick) is used.
*
* For a timer with input clock = 40MHz, 1 timer tick is short
* enough to trigger a timeout immediately.
*
* Restore prescale to 1, and load timer with 1 to trigger timeout.
*/
writel(TIMER_ENABLE | (TIMER_MODE_WDT << TIMER_MODE_SHIFT),
priv->regs + TIMER_CTL);
writel(1, priv->regs + TIMER_LOAD);
return 0;
}
static int mt7620_wdt_probe(struct udevice *dev)
{
struct mt7620_wdt *priv = dev_get_priv(dev);
struct reset_ctl reset_wdt;
int ret;
ret = reset_get_by_index(dev, 0, &reset_wdt);
if (!ret)
reset_deassert(&reset_wdt);
priv->regs = dev_remap_addr(dev);
if (!priv->regs)
return -EINVAL;
mt7620_wdt_stop(dev);
return 0;
}
static const struct wdt_ops mt7620_wdt_ops = {
.start = mt7620_wdt_start,
.reset = mt7620_wdt_reset,
.stop = mt7620_wdt_stop,
.expire_now = mt7620_wdt_expire_now,
};
static const struct udevice_id mt7620_wdt_ids[] = {
{ .compatible = "mediatek,mt7620-wdt" },
{}
};
U_BOOT_DRIVER(mt7620_wdt) = {
.name = "mt7620_wdt",
.id = UCLASS_WDT,
.of_match = mt7620_wdt_ids,
.probe = mt7620_wdt_probe,
.priv_auto = sizeof(struct mt7620_wdt),
.ops = &mt7620_wdt_ops,
};

46
include/configs/mt7620.h Normal file
View file

@ -0,0 +1,46 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2020 MediaTek Inc. All Rights Reserved.
*
* Author: Weijie Gao <weijie.gao@mediatek.com>
*/
#ifndef __CONFIG_MT7620_H
#define __CONFIG_MT7620_H
#define CONFIG_SYS_HZ 1000
#define CONFIG_SYS_MIPS_TIMER_FREQ 290000000
#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE
#define CONFIG_SYS_MALLOC_LEN 0x100000
#define CONFIG_SYS_BOOTPARAMS_LEN 0x20000
#define CONFIG_SYS_SDRAM_BASE 0x80000000
#define CONFIG_SYS_LOAD_ADDR 0x80010000
#define CONFIG_SYS_INIT_SP_OFFSET 0x400000
#define CONFIG_SYS_BOOTM_LEN 0x1000000
#define CONFIG_SYS_MAXARGS 16
#define CONFIG_SYS_CBSIZE 1024
/* Serial common */
#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 }
/* SPL */
#if defined(CONFIG_SPL) && !defined(CONFIG_SPL_BUILD)
#define CONFIG_SKIP_LOWLEVEL_INIT
#endif
#define CONFIG_SYS_UBOOT_START CONFIG_SYS_TEXT_BASE
#define CONFIG_SPL_BSS_START_ADDR 0x80010000
#define CONFIG_SPL_BSS_MAX_SIZE 0x10000
#define CONFIG_SPL_MAX_SIZE 0x10000
#define CONFIG_SPL_PAD_TO 0
/* Dummy value */
#define CONFIG_SYS_UBOOT_BASE 0
#endif /* __CONFIG_MT7620_H */

View file

@ -0,0 +1,40 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2020 MediaTek Inc.
*
* Author: Weijie Gao <weijie.gao@mediatek.com>
*/
#ifndef _DT_BINDINGS_MT7620_CLK_H_
#define _DT_BINDINGS_MT7620_CLK_H_
/* Base clocks */
#define CLK_SYS 34
#define CLK_CPU 33
#define CLK_XTAL 32
/* Peripheral clocks */
#define CLK_SDHC 30
#define CLK_MIPS_CNT 28
#define CLK_PCIE 26
#define CLK_UPHY_12M 25
#define CLK_EPHY 24
#define CLK_ESW 23
#define CLK_UPHY_48M 22
#define CLK_FE 21
#define CLK_UARTL 19
#define CLK_SPI 18
#define CLK_I2S 17
#define CLK_I2C 16
#define CLK_NAND 15
#define CLK_GDMA 14
#define CLK_PIO 13
#define CLK_UARTF 12
#define CLK_PCM 11
#define CLK_MC 10
#define CLK_INTC 9
#define CLK_TIMER 8
#define CLK_GE2 7
#define CLK_GE1 6
#endif /* _DT_BINDINGS_MT7620_CLK_H_ */

View file

@ -0,0 +1,35 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2020 MediaTek Inc.
*
* Author: Weijie Gao <weijie.gao@mediatek.com>
*/
#ifndef _DT_BINDINGS_MT7620_RESET_H_
#define _DT_BINDINGS_MT7620_RESET_H_
#define PPE_RST 31
#define SDHC_RST 30
#define MIPS_CNT_RST 28
#define PCIE_RST 26
#define UHST_RST 25
#define EPHY_RST 24
#define ESW_RST 23
#define UDEV_RST 22
#define FE_RST 21
#define WLAN_RST 20
#define UARTL_RST 19
#define SPI_RST 18
#define I2S_RST 17
#define I2C_RST 16
#define NAND_RST 15
#define DMA_RST 14
#define PIO_RST 13
#define UARTF_RST 12
#define PCM_RST 11
#define MC_RST 10
#define INTC_RST 9
#define TIMER_RST 8
#define SYS_RST 0
#endif /* _DT_BINDINGS_MT7620_RESET_H_ */