提交 e8b8c208 编写于 作者: T Tom Rini

Merge tag 'mips-pull-2021-04-22' of https://source.denx.de/u-boot/custodians/u-boot-mips

- net: fix traffic problems in MSCC Jaguar 2 network driver
- MIPS: mt7628: fix DDR memory init
- MIPS: octeon: add MMC and USB support
......@@ -134,6 +134,33 @@
clocks = <&clk OCTEON_CLK_IO>;
};
mmc: mmc@1180000002000 {
compatible = "cavium,octeon-7890-mmc",
"cavium,octeon-7360-mmc";
reg = <0x11800 0x00000000 0x0 0x2100>;
#address-cells = <1>;
#size-cells = <0>;
/* EMM_INT_BUF_DONE,
EMM_INT_CMD_DONE,
EMM_INT_DMA_DONE,
EMM_INT_CMD_ERR,
EMM_INT_DMA_ERR,
EMM_INT_SWITCH_DONE,
EMM_INT_SWITCH_ERR,
EMM_DMA_DONE,
EMM_DMA_FIFO*/
interrupts = <0x09040 1>,
<0x09041 1>,
<0x09042 1>,
<0x09043 1>,
<0x09044 1>,
<0x09045 1>,
<0x09046 1>,
<0x09000 1>,
<0x09001 1>;
clocks = <&clk OCTEON_CLK_IO>;
};
spi: spi@1070000001000 {
compatible = "cavium,octeon-3010-spi";
reg = <0x10700 0x00001000 0x0 0x100>;
......
......@@ -6,16 +6,36 @@
/dts-v1/;
#include "mrvl,cn73xx.dtsi"
#include <dt-bindings/gpio/gpio.h>
/ {
model = "cavium,ebb7304";
compatible = "cavium,ebb7304";
aliases {
mmc0 = &mmc0;
mmc1 = &mmc1;
serial0 = &uart0;
spi0 = &spi;
};
regulators {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <0>;
/* Power on GPIO 8, active high */
reg_mmc_3v3: regulator@0 {
compatible = "regulator-fixed";
reg = <0>;
regulator-name = "mmc-3v3";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
gpio = <&gpio 8 GPIO_ACTIVE_HIGH>;
enable-active-high;
};
};
chosen {
stdout-path = &uart0;
};
......@@ -137,3 +157,40 @@
*/
power = <&gpio 21 0>;
};
&mmc {
status = "okay";
/* The board has two MMC slots
* If both are occupied, the speed must be reduced,
* as extra data-line load increases slew time,
* and dat-skew adjustment does not help significantly.
*/
mmc0: mmc-slot@0 {
compatible = "cavium,octeon-6130-mmc-slot", "mmc-slot";
reg = <0>;
vqmmc-supply = <&reg_mmc_3v3>;
voltage-ranges = <3300 3300>;
//spi-max-frequency = <52000000>; // just one
spi-max-frequency = <37000000>; // both slots
/* bus width can be 1, 4 or 8 */
bus-width = <8>; /* new std property */
cavium,bus-max-width = <8>; /* custom property */
wp-gpios = <&gpio 22 0>; /* active high */
cd-gpios = <&gpio 23 1>; /* active low */
};
mmc1: mmc-slot@1 {
compatible = "cavium,octeon-6130-mmc-slot", "mmc-slot";
reg = <1>;
vqmmc-supply = <&reg_mmc_3v3>;
voltage-ranges = <3300 3300>;
//spi-max-frequency = <52000000>; // just one
spi-max-frequency = <37000000>; // both slots
/* bus width can be 1, 4 or 8 */
bus-width = <8>; /* new std property */
cavium,bus-max-width = <8>; /* custom property */
wp-gpios = <&gpio 24 0>; /* active high */
cd-gpios = <&gpio 25 1>; /* active low */
};
};
......@@ -243,7 +243,9 @@
<0x017d0000 0x10000>, // QFWD
<0x01020000 0x20000>, // QS
<0x017e0000 0x10000>, // QSYS
<0x01b00000 0x80000>; // REW
<0x01b00000 0x80000>, // REW
<0x01010000 0x100>, // GCB
<0x00000000 0x100>; // ICPU
reg-names = "port0", "port1", "port2", "port3", "port4",
"port5", "port6", "port7", "port8", "port9",
"port10", "port11", "port12", "port13",
......@@ -257,7 +259,7 @@
"port42", "port43", "port44", "port45",
"port46", "port47", "ana_ac", "ana_cl",
"ana_l2", "asm", "hsio", "lrn", "qfwd",
"qs", "qsys", "rew";
"qs", "qsys", "rew", "gcb", "icpu";
status = "okay";
ethernet-ports {
......
......@@ -140,6 +140,9 @@ void mt7628_ddr_init(void)
lspd = readl(sysc + SYSCTL_CLKCFG0_REG) &
(CPU_PLL_FROM_BBP | CPU_PLL_FROM_XTAL);
if (pkg_type == PKG_ID_KN)
ddr_type = DRAM_DDR1;
mt7628_memc_reset(1);
__udelay(200);
......@@ -152,9 +155,6 @@ void mt7628_ddr_init(void)
param.memsize = 0;
param.bus_width = 0;
if (pkg_type == PKG_ID_KN)
ddr_type = DRAM_DDR1;
if (ddr_type == DRAM_DDR1) {
if (lspd)
param.cfgs = ddr1_cfgs_160mhz;
......
......@@ -68,6 +68,9 @@ int print_cpuinfo(void)
val = readl(sysc + SYSCTL_EFUSE_CFG_REG);
ee = val & EFUSE_MT7688;
if (pkg == PKG_ID_KN)
ddr = DRAM_DDR1;
printf("CPU: MediaTek MT%u%c ver:%u eco:%u\n",
ee ? 7688 : 7628, pkg ? 'A' : 'K', ver, eco);
......
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2020 Marvell International Ltd.
*/
#ifndef __CVMX_MIO_EMM_DEFS_H__
#define __CVMX_MIO_EMM_DEFS_H__
static inline u64 MIO_EMM_DMA_FIFO_CFG(void)
{
return 0x160;
}
static inline u64 MIO_EMM_DMA_FIFO_ADR(void)
{
return 0x170;
}
static inline u64 MIO_EMM_DMA_FIFO_CMD(void)
{
return 0x178;
}
static inline u64 MIO_EMM_DMA_CFG(void)
{
return 0x180;
}
static inline u64 MIO_EMM_DMA_ADR(void)
{
return 0x188;
}
static inline u64 MIO_EMM_DMA_INT(void)
{
return 0x190;
}
static inline u64 MIO_EMM_CFG(void)
{
return 0x2000;
}
static inline u64 MIO_EMM_MODEX(u64 a)
{
return 0x2008 + 8 * a;
}
static inline u64 MIO_EMM_SWITCH(void)
{
return 0x2048;
}
static inline u64 MIO_EMM_DMA(void)
{
return 0x2050;
}
static inline u64 MIO_EMM_CMD(void)
{
return 0x2058;
}
static inline u64 MIO_EMM_RSP_STS(void)
{
return 0x2060;
}
static inline u64 MIO_EMM_RSP_LO(void)
{
return 0x2068;
}
static inline u64 MIO_EMM_RSP_HI(void)
{
return 0x2070;
}
static inline u64 MIO_EMM_INT(void)
{
return 0x2078;
}
static inline u64 MIO_EMM_WDOG(void)
{
return 0x2088;
}
static inline u64 MIO_EMM_SAMPLE(void)
{
return 0x2090;
}
static inline u64 MIO_EMM_STS_MASK(void)
{
return 0x2098;
}
static inline u64 MIO_EMM_RCA(void)
{
return 0x20a0;
}
static inline u64 MIO_EMM_BUF_IDX(void)
{
return 0x20e0;
}
static inline u64 MIO_EMM_BUF_DAT(void)
{
return 0x20e8;
}
/* Dummy implementation, not documented on MIPS Octeon */
static inline u64 MIO_EMM_DEBUG(void)
{
return 0x20f8;
}
/**
* mio_emm_access_wdog
*/
union mio_emm_access_wdog {
u64 u;
struct mio_emm_access_wdog_s {
uint64_t reserved_32_63 : 32;
uint64_t clk_cnt : 32;
} s;
};
/**
* mio_emm_buf_dat
*
* MIO_EMM_BUF_DAT = MIO EMMC Data buffer access Register
*
*/
union mio_emm_buf_dat {
u64 u;
struct mio_emm_buf_dat_s {
uint64_t dat : 64;
} s;
};
/**
* mio_emm_buf_idx
*
* MIO_EMM_BUF_IDX = MIO EMMC Data buffer address Register
*
*/
union mio_emm_buf_idx {
u64 u;
struct mio_emm_buf_idx_s {
uint64_t reserved_17_63 : 47;
uint64_t inc : 1;
uint64_t reserved_7_15 : 9;
uint64_t buf_num : 1;
uint64_t offset : 6;
} s;
};
/**
* mio_emm_cfg
*
* MIO_EMM_CFG = MIO EMMC Configuration Register
*
*/
union mio_emm_cfg {
u64 u;
struct mio_emm_cfg_s {
uint64_t reserved_17_63 : 47;
uint64_t boot_fail : 1;
uint64_t reserved_4_15 : 12;
uint64_t bus_ena : 4;
} s;
};
/**
* mio_emm_cmd
*
* MIO_EMM_CMD = MIO EMMC Command Register
*
*/
union mio_emm_cmd {
u64 u;
struct mio_emm_cmd_s {
uint64_t reserved_63_63 : 1;
uint64_t skip_busy : 1;
uint64_t bus_id : 2;
uint64_t cmd_val : 1;
uint64_t reserved_56_58 : 3;
uint64_t dbuf : 1;
uint64_t offset : 6;
uint64_t reserved_43_48 : 6;
uint64_t ctype_xor : 2;
uint64_t rtype_xor : 3;
uint64_t cmd_idx : 6;
uint64_t arg : 32;
} s;
};
/**
* mio_emm_dma
*
* MIO_EMM_DMA = MIO EMMC DMA config Register
*
*/
union mio_emm_dma {
u64 u;
struct mio_emm_dma_s {
uint64_t reserved_63_63 : 1;
uint64_t skip_busy : 1;
uint64_t bus_id : 2;
uint64_t dma_val : 1;
uint64_t sector : 1;
uint64_t dat_null : 1;
uint64_t thres : 6;
uint64_t rel_wr : 1;
uint64_t rw : 1;
uint64_t multi : 1;
uint64_t block_cnt : 16;
uint64_t card_addr : 32;
} s;
};
/**
* mio_emm_dma_adr
*
* This register sets the address for eMMC/SD flash transfers to/from memory. Sixty-four-bit
* operations must be used to access this register. This register is updated by the DMA
* hardware and can be reloaded by the values placed in the MIO_EMM_DMA_FIFO_ADR.
*/
union mio_emm_dma_adr {
u64 u;
struct mio_emm_dma_adr_s {
uint64_t reserved_42_63 : 22;
uint64_t adr : 42;
} s;
};
/**
* mio_emm_dma_cfg
*
* This register controls the internal DMA engine used with the eMMC/SD flash controller. Sixty-
* four-bit operations must be used to access this register. This register is updated by the
* hardware DMA engine and can also be reloaded by writes to the MIO_EMM_DMA_FIFO_CMD register.
*/
union mio_emm_dma_cfg {
u64 u;
struct mio_emm_dma_cfg_s {
uint64_t en : 1;
uint64_t rw : 1;
uint64_t clr : 1;
uint64_t reserved_60_60 : 1;
uint64_t swap32 : 1;
uint64_t swap16 : 1;
uint64_t swap8 : 1;
uint64_t endian : 1;
uint64_t size : 20;
uint64_t reserved_0_35 : 36;
} s;
};
/**
* mio_emm_dma_fifo_adr
*
* This register specifies the internal address that is loaded into the eMMC internal DMA FIFO.
* The FIFO is used to queue up operations for the MIO_EMM_DMA_CFG/MIO_EMM_DMA_ADR when the DMA
* completes successfully.
*/
union mio_emm_dma_fifo_adr {
u64 u;
struct mio_emm_dma_fifo_adr_s {
uint64_t reserved_42_63 : 22;
uint64_t adr : 39;
uint64_t reserved_0_2 : 3;
} s;
};
/**
* mio_emm_dma_fifo_cfg
*
* This register controls DMA FIFO operations.
*
*/
union mio_emm_dma_fifo_cfg {
u64 u;
struct mio_emm_dma_fifo_cfg_s {
uint64_t reserved_17_63 : 47;
uint64_t clr : 1;
uint64_t reserved_13_15 : 3;
uint64_t int_lvl : 5;
uint64_t reserved_5_7 : 3;
uint64_t count : 5;
} s;
};
/**
* mio_emm_dma_fifo_cmd
*
* This register specifies a command that is loaded into the eMMC internal DMA FIFO. The FIFO is
* used to queue up operations for the MIO_EMM_DMA_CFG/MIO_EMM_DMA_ADR when the DMA completes
* successfully. Writes to this register store both the MIO_EMM_DMA_FIFO_CMD and the
* MIO_EMM_DMA_FIFO_ADR contents into the FIFO and increment the MIO_EMM_DMA_FIFO_CFG[COUNT]
* field.
*
* Note: This register has a similar format to MIO_EMM_DMA_CFG with the exception
* that the EN and CLR fields are absent. These are supported in MIO_EMM_DMA_FIFO_CFG.
*/
union mio_emm_dma_fifo_cmd {
u64 u;
struct mio_emm_dma_fifo_cmd_s {
uint64_t reserved_63_63 : 1;
uint64_t rw : 1;
uint64_t reserved_61_61 : 1;
uint64_t intdis : 1;
uint64_t swap32 : 1;
uint64_t swap16 : 1;
uint64_t swap8 : 1;
uint64_t endian : 1;
uint64_t size : 20;
uint64_t reserved_0_35 : 36;
} s;
};
/**
* mio_emm_dma_int
*
* Sixty-four-bit operations must be used to access this register.
*
*/
union mio_emm_dma_int {
u64 u;
struct mio_emm_dma_int_s {
uint64_t reserved_2_63 : 62;
uint64_t fifo : 1;
uint64_t done : 1;
} s;
};
/**
* mio_emm_dma_int_w1s
*/
union mio_emm_dma_int_w1s {
u64 u;
struct mio_emm_dma_int_w1s_s {
uint64_t reserved_2_63 : 62;
uint64_t fifo : 1;
uint64_t done : 1;
} s;
};
/**
* mio_emm_int
*
* MIO_EMM_INT = MIO EMMC Interrupt Register
*
*/
union mio_emm_int {
u64 u;
struct mio_emm_int_s {
uint64_t reserved_7_63 : 57;
uint64_t switch_err : 1;
uint64_t switch_done : 1;
uint64_t dma_err : 1;
uint64_t cmd_err : 1;
uint64_t dma_done : 1;
uint64_t cmd_done : 1;
uint64_t buf_done : 1;
} s;
};
/**
* mio_emm_int_en
*
* MIO_EMM_INT_EN = MIO EMMC Interrupt enable Register
*
*/
union mio_emm_int_en {
u64 u;
struct mio_emm_int_en_s {
uint64_t reserved_7_63 : 57;
uint64_t switch_err : 1;
uint64_t switch_done : 1;
uint64_t dma_err : 1;
uint64_t cmd_err : 1;
uint64_t dma_done : 1;
uint64_t cmd_done : 1;
uint64_t buf_done : 1;
} s;
};
/**
* mio_emm_int_w1s
*/
union mio_emm_int_w1s {
u64 u;
struct mio_emm_int_w1s_s {
uint64_t reserved_7_63 : 57;
uint64_t switch_err : 1;
uint64_t switch_done : 1;
uint64_t dma_err : 1;
uint64_t cmd_err : 1;
uint64_t dma_done : 1;
uint64_t cmd_done : 1;
uint64_t buf_done : 1;
} s;
};
/**
* mio_emm_mode#
*
* MIO_EMM_MODE = MIO EMMC Operating mode Register
*
*/
union mio_emm_modex {
u64 u;
struct mio_emm_modex_s {
uint64_t reserved_49_63 : 15;
uint64_t hs_timing : 1;
uint64_t reserved_43_47 : 5;
uint64_t bus_width : 3;
uint64_t reserved_36_39 : 4;
uint64_t power_class : 4;
uint64_t clk_hi : 16;
uint64_t clk_lo : 16;
} s;
};
/**
* mio_emm_rca
*/
union mio_emm_rca {
u64 u;
struct mio_emm_rca_s {
uint64_t reserved_16_63 : 48;
uint64_t card_rca : 16;
} s;
};
/**
* mio_emm_rsp_hi
*
* MIO_EMM_RSP_HI = MIO EMMC Response data high Register
*
*/
union mio_emm_rsp_hi {
u64 u;
struct mio_emm_rsp_hi_s {
uint64_t dat : 64;
} s;
};
/**
* mio_emm_rsp_lo
*
* MIO_EMM_RSP_LO = MIO EMMC Response data low Register
*
*/
union mio_emm_rsp_lo {
u64 u;
struct mio_emm_rsp_lo_s {
uint64_t dat : 64;
} s;
};
/**
* mio_emm_rsp_sts
*
* MIO_EMM_RSP_STS = MIO EMMC Response status Register
*
*/
union mio_emm_rsp_sts {
u64 u;
struct mio_emm_rsp_sts_s {
uint64_t reserved_62_63 : 2;
uint64_t bus_id : 2;
uint64_t cmd_val : 1;
uint64_t switch_val : 1;
uint64_t dma_val : 1;
uint64_t dma_pend : 1;
uint64_t acc_timeout : 1;
uint64_t reserved_29_54 : 26;
uint64_t dbuf_err : 1;
uint64_t reserved_24_27 : 4;
uint64_t dbuf : 1;
uint64_t blk_timeout : 1;
uint64_t blk_crc_err : 1;
uint64_t rsp_busybit : 1;
uint64_t stp_timeout : 1;
uint64_t stp_crc_err : 1;
uint64_t stp_bad_sts : 1;
uint64_t stp_val : 1;
uint64_t rsp_timeout : 1;
uint64_t rsp_crc_err : 1;
uint64_t rsp_bad_sts : 1;
uint64_t rsp_val : 1;
uint64_t rsp_type : 3;
uint64_t cmd_type : 2;
uint64_t cmd_idx : 6;
uint64_t cmd_done : 1;
} s;
};
/**
* mio_emm_sample
*/
union mio_emm_sample {
u64 u;
struct mio_emm_sample_s {
uint64_t reserved_26_63 : 38;
uint64_t cmd_cnt : 10;
uint64_t reserved_10_15 : 6;
uint64_t dat_cnt : 10;
} s;
};
/**
* mio_emm_sts_mask
*/
union mio_emm_sts_mask {
u64 u;
struct mio_emm_sts_mask_s {
uint64_t reserved_32_63 : 32;
uint64_t sts_msk : 32;
} s;
};
/**
* mio_emm_switch
*
* MIO_EMM_SWITCH = MIO EMMC Operating mode switch Register
*
*/
union mio_emm_switch {
u64 u;
struct mio_emm_switch_s {
uint64_t reserved_62_63 : 2;
uint64_t bus_id : 2;
uint64_t switch_exe : 1;
uint64_t switch_err0 : 1;
uint64_t switch_err1 : 1;
uint64_t switch_err2 : 1;
uint64_t reserved_49_55 : 7;
uint64_t hs_timing : 1;
uint64_t reserved_43_47 : 5;
uint64_t bus_width : 3;
uint64_t reserved_36_39 : 4;
uint64_t power_class : 4;
uint64_t clk_hi : 16;
uint64_t clk_lo : 16;
} s;
};
/**
* mio_emm_wdog
*
* MIO_EMM_WDOG = MIO EMMC Watchdog Register
*
*/
union mio_emm_wdog {
u64 u;
struct mio_emm_wdog_s {
uint64_t reserved_26_63 : 38;
uint64_t clk_cnt : 26;
} s;
};
/*
* The following structs are only available to enable compilation of the common
* MMC driver. These registers do not exist on MIPS Octeon.
*/
/**
* Register (RSL) mio_emm_timing
*
* eMMC Timing Register This register determines the number of tap delays
* the EMM_DAT, EMM_DS, and EMM_CMD lines are transmitted or received in
* relation to EMM_CLK. These values should only be changed when the eMMC
* bus is idle.
*/
union mio_emm_timing {
u64 u;
struct mio_emm_timing_s {
u64 data_out_tap : 6;
u64 reserved_6_15 : 10;
u64 data_in_tap : 6;
u64 reserved_22_31 : 10;
u64 cmd_out_tap : 6;
u64 reserved_38_47 : 10;
u64 cmd_in_tap : 6;
u64 reserved_54_63 : 10;
} s;
};
/**
* Register (RSL) mio_emm_debug
*
* eMMC Debug Register
*/
union mio_emm_debug {
u64 u;
struct mio_emm_debug_s {
u64 clk_on : 1;
u64 reserved_1_7 : 7;
u64 cmd_sm : 4;
u64 data_sm : 4;
u64 dma_sm : 4;
u64 emmc_clk_disable : 1;
u64 rdsync_rst : 1;
u64 reserved_22_63 : 42;
} s;
};
#endif
......@@ -14,6 +14,7 @@ CONFIG_SYS_CONSOLE_INFO_QUIET=y
CONFIG_HUSH_PARSER=y
CONFIG_CMD_GPIO=y
CONFIG_CMD_I2C=y
CONFIG_CMD_MMC=y
CONFIG_CMD_MTD=y
CONFIG_CMD_PART=y
CONFIG_CMD_PCI=y
......@@ -24,12 +25,17 @@ CONFIG_CMD_TIME=y
CONFIG_CMD_EXT4=y
CONFIG_CMD_FAT=y
CONFIG_CMD_FS_GENERIC=y
# CONFIG_DOS_PARTITION is not set
CONFIG_AMIGA_PARTITION=y
CONFIG_EFI_PARTITION=y
CONFIG_PARTITION_TYPE_GUID=y
CONFIG_ENV_IS_IN_FLASH=y
CONFIG_ENV_ADDR=0x1FBFE000
CONFIG_BLK=y
CONFIG_CLK=y
# CONFIG_INPUT is not set
CONFIG_MISC=y
CONFIG_MMC=y
CONFIG_DM_MMC=y
CONFIG_MMC_OCTEONTX=y
CONFIG_MTD=y
CONFIG_DM_MTD=y
CONFIG_MTD_NOR_FLASH=y
......@@ -45,6 +51,8 @@ CONFIG_SPI_FLASH_STMICRO=y
# CONFIG_NETDEVICES is not set
CONFIG_PCI=y
CONFIG_DM_PCI=y
CONFIG_DM_REGULATOR=y
CONFIG_DM_REGULATOR_FIXED=y
CONFIG_RAM=y
CONFIG_RAM_OCTEON=y
CONFIG_RAM_OCTEON_DDR4=y
......@@ -59,6 +67,7 @@ CONFIG_USB=y
CONFIG_DM_USB=y
CONFIG_USB_XHCI_HCD=y
CONFIG_USB_XHCI_DWC3=y
CONFIG_USB_STORAGE=y
CONFIG_USB_HOST_ETHER=y
CONFIG_USB_ETHER_ASIX=y
CONFIG_USB_ETHER_ASIX88179=y
......
......@@ -317,13 +317,13 @@ config MMC_PCI
If you have an MMC controller on a PCI bus, say Y here.
config MMC_OCTEONTX
bool "Marvell OcteonTX Multimedia Card Interface support"
depends on (ARCH_OCTEONTX || ARCH_OCTEONTX2)
bool "Marvell Octeon Multimedia Card Interface support"
depends on (ARCH_OCTEON || ARCH_OCTEONTX || ARCH_OCTEONTX2)
depends on DM_MMC
help
This selects the OcteonTX Multimedia card Interface.
If you have an OcteonTX/TX2 board with a Multimedia Card slot,
say Y here.
This selects the Octeon Multimedia card Interface.
If you have an OcteonTX/TX2 or MIPS Octeon board with a
Multimedia Card slot, say Y here.
If unsure, say N.
......
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2019 Marvell International Ltd.
*
* https://spdx.org/licenses
*/
//#define DEBUG
#include <clk.h>
#include <cpu_func.h>
#include <dm.h>
#include <dm/device-internal.h>
#include <dm/lists.h>
#include <env.h>
#include <errno.h>
......@@ -19,23 +18,31 @@
#include <part.h>
#include <pci.h>
#include <pci_ids.h>
#include <power/regulator.h>
#include <time.h>
#include <watchdog.h>
#include <asm/io.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/libfdt.h>
#if defined(CONFIG_ARCH_OCTEON)
#include <mach/octeon-model.h>
#include <mach/cvmx-regs.h>
#include <mach/cvmx-mio-emm-defs.h>
#else
#include <asm/arch/board.h>
#include <asm/arch/clock.h>
#include <asm/arch/csrs/csrs-mio_emm.h>
#include <asm/io.h>
#include <dm/device-internal.h>
#include <power/regulator.h>
#endif
#include "octeontx_hsmmc.h"
/* Use dummy implementation for MIPS Octeon to always return false */
#if defined(CONFIG_ARCH_OCTEON)
#define otx_is_soc(ver) 0
#endif
#define MMC_TIMEOUT_SHORT 20 /* in ms */
#define MMC_TIMEOUT_LONG 1000
#define MMC_TIMEOUT_ERASE 10000
......@@ -71,16 +78,18 @@
#define MMC_DEFAULT_TAP_DELAY 4
#define TOTAL_NO_OF_TAPS 512
static void octeontx_mmc_switch_to(struct mmc *mmc);
static int octeontx_mmc_configure_delay(struct mmc *mmc);
static void octeontx_mmc_set_timing(struct mmc *mmc);
static void set_wdog(struct mmc *mmc, u64 us);
static void do_switch(struct mmc *mmc, union mio_emm_switch emm_switch);
static int octeontx_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
struct mmc_data *data);
static int octeontx2_mmc_calc_delay(struct mmc *mmc, int delay);
static int octeontx_mmc_configure_delay(struct mmc *mmc);
static int octeontx_mmc_calibrate_delay(struct mmc *mmc);
#if !defined(CONFIG_ARCH_OCTEON)
static int octeontx2_mmc_calc_delay(struct mmc *mmc, int delay);
static void octeontx_mmc_set_timing(struct mmc *mmc);
static int octeontx_mmc_set_input_bus_timing(struct mmc *mmc);
static int octeontx_mmc_set_output_bus_timing(struct mmc *mmc);
#endif
static bool host_probed;
......@@ -338,6 +347,7 @@ static void mmc_print_status(u32 status)
}
#endif
#if !defined(CONFIG_ARCH_OCTEON)
/**
* Print out all of the register values where mmc is optional
*
......@@ -687,6 +697,12 @@ static void octeontx_mmc_print_registers(struct mmc *mmc)
if (print)
octeontx_mmc_print_registers2(mmc, mmc_to_host(mmc));
}
#else
static void octeontx_mmc_print_registers(struct mmc *mmc)
{
return;
}
#endif
static const struct octeontx_sd_mods octeontx_cr_types[] = {
{ {0, 0}, {0, 0}, {0, 0} }, /* CMD0 */
......@@ -838,14 +854,17 @@ static void octeontx_mmc_track_switch(struct mmc *mmc, u32 cmd_arg)
break;
case EXT_CSD_HS_TIMING:
slot->want_switch.s.hs_timing = 0;
#if !defined(CONFIG_ARCH_OCTEON)
slot->want_switch.s.hs200_timing = 0;
slot->want_switch.s.hs400_timing = 0;
#endif
switch (val & 0xf) {
case 0:
break;
case 1:
slot->want_switch.s.hs_timing = 1;
break;
#if !defined(CONFIG_ARCH_OCTEON)
case 2:
if (!slot->is_asim && !slot->is_emul)
slot->want_switch.s.hs200_timing = 1;
......@@ -854,6 +873,7 @@ static void octeontx_mmc_track_switch(struct mmc *mmc, u32 cmd_arg)
if (!slot->is_asim && !slot->is_emul)
slot->want_switch.s.hs400_timing = 1;
break;
#endif
default:
pr_err("%s(%s): Unsupported timing mode 0x%x\n",
__func__, mmc->dev->name, val & 0xf);
......@@ -2413,7 +2433,10 @@ static u32 octeontx_mmc_calc_clk_period(struct mmc *mmc)
struct octeontx_mmc_slot *slot = mmc_to_slot(mmc);
struct octeontx_mmc_host *host = slot->host;
return DIV_ROUND_UP(host->sys_freq, mmc->clock);
if (mmc->clock)
return DIV_ROUND_UP(host->sys_freq, mmc->clock);
return 0;
}
static int octeontx_mmc_set_ios(struct udevice *dev)
......@@ -2489,14 +2512,18 @@ static int octeontx_mmc_set_ios(struct udevice *dev)
case UHS_SDR25:
case UHS_SDR50:
case UHS_SDR104:
#if !defined(CONFIG_ARCH_OCTEON)
emm_switch.s.hs200_timing = 1;
#endif
break;
case MMC_HS_400:
is_hs400 = true;
fallthrough;
case UHS_DDR50:
case MMC_DDR_52:
#if !defined(CONFIG_ARCH_OCTEON)
emm_switch.s.hs400_timing = 1;
#endif
break;
default:
pr_err("%s(%s): Unsupported mode 0x%x\n", __func__, dev->name,
......@@ -2522,17 +2549,21 @@ static int octeontx_mmc_set_ios(struct udevice *dev)
mmc->selected_mode);
}
#if !defined(CONFIG_ARCH_OCTEON)
debug(" Trying switch 0x%llx w%d hs:%d hs200:%d hs400:%d\n",
emm_switch.u, emm_switch.s.bus_width, emm_switch.s.hs_timing,
emm_switch.s.hs200_timing, emm_switch.s.hs400_timing);
#endif
set_wdog(mmc, 1000);
do_switch(mmc, emm_switch);
mdelay(100);
mode.u = read_csr(mmc, MIO_EMM_MODEX(slot->bus_id));
#if !defined(CONFIG_ARCH_OCTEON)
debug("%s(%s): mode: 0x%llx w:%d, hs:%d, hs200:%d, hs400:%d\n",
__func__, dev->name, mode.u, mode.s.bus_width,
mode.s.hs_timing, mode.s.hs200_timing, mode.s.hs400_timing);
#endif
err = octeontx_mmc_configure_delay(mmc);
......@@ -2578,6 +2609,26 @@ static int octeontx_mmc_get_wp(struct udevice *dev)
return val;
}
#if defined(CONFIG_ARCH_OCTEON)
static int octeontx_mmc_configure_delay(struct mmc *mmc)
{
struct octeontx_mmc_slot *slot = mmc_to_slot(mmc);
union mio_emm_sample emm_sample;
debug("%s(%s)\n", __func__, mmc->dev->name);
emm_sample.u = 0;
emm_sample.s.cmd_cnt = slot->cmd_cnt;
emm_sample.s.dat_cnt = slot->dat_cnt;
write_csr(mmc, MIO_EMM_SAMPLE(), emm_sample.u);
return 0;
}
static void octeontx_mmc_io_drive_setup(struct mmc *mmc)
{
}
#else
static void octeontx_mmc_set_timing(struct mmc *mmc)
{
union mio_emm_timing timing;
......@@ -2613,7 +2664,8 @@ static int octeontx_mmc_configure_delay(struct mmc *mmc)
debug("%s(%s)\n", __func__, mmc->dev->name);
if (IS_ENABLED(CONFIG_ARCH_OCTEONTX)) {
if (IS_ENABLED(CONFIG_ARCH_OCTEON) ||
IS_ENABLED(CONFIG_ARCH_OCTEONTX)) {
union mio_emm_sample emm_sample;
emm_sample.u = 0;
......@@ -2759,6 +2811,28 @@ static int octeontx_mmc_configure_delay(struct mmc *mmc)
return 0;
}
/**
* Set the IO drive strength and slew
*
* @param mmc mmc device
*/
static void octeontx_mmc_io_drive_setup(struct mmc *mmc)
{
if (IS_ENABLED(CONFIG_ARCH_OCTEONTX2)) {
struct octeontx_mmc_slot *slot = mmc_to_slot(mmc);
union mio_emm_io_ctl io_ctl;
if (slot->drive < 0 || slot->slew < 0)
return;
io_ctl.u = 0;
io_ctl.s.drive = slot->drive;
io_ctl.s.slew = slot->slew;
write_csr(mmc, MIO_EMM_IO_CTL(), io_ctl.u);
}
}
#endif
/**
* Sets the MMC watchdog timer in microseconds
*
......@@ -2784,27 +2858,6 @@ static void set_wdog(struct mmc *mmc, u64 us)
write_csr(mmc, MIO_EMM_WDOG(), wdog.u);
}
/**
* Set the IO drive strength and slew
*
* @param mmc mmc device
*/
static void octeontx_mmc_io_drive_setup(struct mmc *mmc)
{
if (!IS_ENABLED(CONFIG_ARCH_OCTEONTX)) {
struct octeontx_mmc_slot *slot = mmc_to_slot(mmc);
union mio_emm_io_ctl io_ctl;
if (slot->drive < 0 || slot->slew < 0)
return;
io_ctl.u = 0;
io_ctl.s.drive = slot->drive;
io_ctl.s.slew = slot->slew;
write_csr(mmc, MIO_EMM_IO_CTL(), io_ctl.u);
}
}
/**
* Print switch errors
*
......@@ -2858,6 +2911,31 @@ static void do_switch(struct mmc *mmc, union mio_emm_switch emm_switch)
read_csr(mmc, MIO_EMM_RSP_LO()));
}
/**
* Calibrates the delay based on the internal clock
*
* @param mmc Pointer to mmc data structure
*
* @return 0 for success or -ETIMEDOUT on error
*
* NOTE: On error a default value will be calculated.
*/
#if defined(CONFIG_ARCH_OCTEON)
static int octeontx_mmc_set_input_bus_timing(struct mmc *mmc)
{
return 0;
}
static int octeontx_mmc_set_output_bus_timing(struct mmc *mmc)
{
return 0;
}
static int octeontx_mmc_calibrate_delay(struct mmc *mmc)
{
return 0;
}
#else
/**
* Given a delay in ps, return the tap delay count
*
......@@ -2883,15 +2961,6 @@ static int octeontx2_mmc_calc_delay(struct mmc *mmc, int delay)
return min_t(int, DIV_ROUND_UP(delay, host->timing_taps), 63);
}
/**
* Calibrates the delay based on the internal clock
*
* @param mmc Pointer to mmc data structure
*
* @return 0 for success or -ETIMEDOUT on error
*
* NOTE: On error a default value will be calculated.
*/
static int octeontx_mmc_calibrate_delay(struct mmc *mmc)
{
union mio_emm_calb emm_calb;
......@@ -3141,6 +3210,7 @@ static int octeontx_mmc_set_output_bus_timing(struct mmc *mmc)
return 0;
}
#endif
static void octeontx_mmc_set_clock(struct mmc *mmc)
{
......@@ -3389,8 +3459,10 @@ static u32 xlate_voltage(u32 voltage)
{
u32 volt = 0;
/* Convert to millivolts */
voltage /= 1000;
/* Convert to millivolts. Only necessary on ARM Octeon TX/TX2 */
if (!IS_ENABLED(CONFIG_ARCH_OCTEON))
voltage /= 1000;
if (voltage >= 1650 && voltage <= 1950)
volt |= MMC_VDD_165_195;
if (voltage >= 2000 && voltage <= 2100)
......@@ -3736,6 +3808,8 @@ static int octeontx_mmc_host_probe(struct udevice *dev)
{
struct octeontx_mmc_host *host = dev_get_priv(dev);
union mio_emm_int emm_int;
struct clk clk;
int ret;
u8 rev;
debug("%s(%s): Entry host: %p\n", __func__, dev->name, host);
......@@ -3745,12 +3819,20 @@ static int octeontx_mmc_host_probe(struct udevice *dev)
return -ENODEV;
}
memset(host, 0, sizeof(*host));
host->base_addr = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0,
PCI_REGION_MEM);
if (!host->base_addr) {
pr_err("%s: Error: MMC base address not found\n", __func__);
return -1;
/* Octeon TX & TX2 use PCI based probing */
if (device_is_compatible(dev, "cavium,thunder-8890-mmc")) {
host->base_addr = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0,
PCI_REGION_MEM);
if (!host->base_addr) {
pr_err("%s: Error: MMC base address not found\n",
__func__);
return -1;
}
} else {
host->base_addr = dev_remap_addr(dev);
}
host->dev = dev;
debug("%s(%s): Base address: %p\n", __func__, dev->name,
host->base_addr);
......@@ -3760,10 +3842,12 @@ static int octeontx_mmc_host_probe(struct udevice *dev)
}
host->node = dev_ofnode(dev);
host->last_slotid = -1;
#if !defined(CONFIG_ARCH_OCTEON)
if (otx_is_platform(PLATFORM_ASIM))
host->is_asim = true;
if (otx_is_platform(PLATFORM_EMULATOR))
host->is_emul = true;
#endif
host->dma_wait_delay =
ofnode_read_u32_default(dev_ofnode(dev),
"marvell,dma-wait-delay", 1);
......@@ -3776,7 +3860,15 @@ static int octeontx_mmc_host_probe(struct udevice *dev)
writeq(emm_int.u, host->base_addr + MIO_EMM_INT());
debug("%s(%s): Getting I/O clock\n", __func__, dev->name);
host->sys_freq = octeontx_get_io_clock();
ret = clk_get_by_index(dev, 0, &clk);
if (ret < 0)
return ret;
ret = clk_enable(&clk);
if (ret)
return ret;
host->sys_freq = clk_get_rate(&clk);
debug("%s(%s): I/O clock %llu\n", __func__, dev->name, host->sys_freq);
if (IS_ENABLED(CONFIG_ARCH_OCTEONTX2)) {
......@@ -3882,6 +3974,7 @@ static int octeontx_mmc_host_child_pre_probe(struct udevice *dev)
static const struct udevice_id octeontx_hsmmc_host_ids[] = {
{ .compatible = "cavium,thunder-8890-mmc" },
{ .compatible = "cavium,octeon-7360-mmc" },
{ }
};
......
......@@ -235,7 +235,7 @@ static const char * const regs_names[] = {
"port36", "port37", "port38", "port39", "port40", "port41", "port42",
"port43", "port44", "port45", "port46", "port47",
"ana_ac", "ana_cl", "ana_l2", "asm", "hsio", "lrn",
"qfwd", "qs", "qsys", "rew",
"qfwd", "qs", "qsys", "rew", "gcb", "icpu",
};
#define REGS_NAMES_COUNT ARRAY_SIZE(regs_names) + 1
......@@ -252,6 +252,8 @@ enum jr2_ctrl_regs {
QS,
QSYS,
REW,
GCB,
ICPU,
};
#define JR2_MIIM_BUS_COUNT 3
......@@ -367,7 +369,6 @@ static void serdes6g_setup(void __iomem *base, uint32_t addr,
{
u32 ib_if_mode = 0;
u32 ib_qrate = 0;
u32 ib_cal_ena = 0;
u32 ib1_tsdet = 0;
u32 ob_lev = 0;
u32 ob_ena_cas = 0;
......@@ -379,7 +380,6 @@ static void serdes6g_setup(void __iomem *base, uint32_t addr,
case PHY_INTERFACE_MODE_SGMII:
ib_if_mode = 1;
ib_qrate = 1;
ib_cal_ena = 1;
ib1_tsdet = 3;
ob_lev = 48;
ob_ena_cas = 2;
......@@ -402,6 +402,12 @@ static void serdes6g_setup(void __iomem *base, uint32_t addr,
if (interface == PHY_INTERFACE_MODE_QSGMII)
writel(0xfff, base + HSIO_HW_CFGSTAT_HW_CFG);
writel(HSIO_ANA_SERDES6G_OB_CFG_RESISTOR_CTRL(1) |
HSIO_ANA_SERDES6G_OB_CFG_SR(7) |
HSIO_ANA_SERDES6G_OB_CFG_SR_H |
HSIO_ANA_SERDES6G_OB_CFG_ENA1V_MODE(ob_ena1v_mode) |
HSIO_ANA_SERDES6G_OB_CFG_POL, base + HSIO_ANA_SERDES6G_OB_CFG);
writel(HSIO_ANA_SERDES6G_COMMON_CFG_IF_MODE(3),
base + HSIO_ANA_SERDES6G_COMMON_CFG);
writel(HSIO_ANA_SERDES6G_PLL_CFG_FSM_CTRL_DATA(120) |
......@@ -431,6 +437,21 @@ static void serdes6g_setup(void __iomem *base, uint32_t addr,
HSIO_ANA_SERDES6G_IB_CFG1_TSDET(3) |
HSIO_ANA_SERDES6G_IB_CFG1_TJTAG(8),
base + HSIO_ANA_SERDES6G_IB_CFG1);
writel(HSIO_ANA_SERDES6G_IB_CFG2_UREG(4) |
HSIO_ANA_SERDES6G_IB_CFG2_UMAX(2) |
HSIO_ANA_SERDES6G_IB_CFG2_TCALV(12) |
HSIO_ANA_SERDES6G_IB_CFG2_OCALS(32) |
HSIO_ANA_SERDES6G_IB_CFG2_OINFS(7) |
HSIO_ANA_SERDES6G_IB_CFG2_OINFI(0x1f) |
HSIO_ANA_SERDES6G_IB_CFG2_TINFV(3),
base + HSIO_ANA_SERDES6G_IB_CFG2);
writel(HSIO_ANA_SERDES6G_IB_CFG3_INI_OFFSET(0x1f) |
HSIO_ANA_SERDES6G_IB_CFG3_INI_LP(1) |
HSIO_ANA_SERDES6G_IB_CFG3_INI_MID(0x1f),
base + HSIO_ANA_SERDES6G_IB_CFG3);
writel(HSIO_DIG_SERDES6G_MISC_CFG_LANE_RST,
base + HSIO_DIG_SERDES6G_MISC_CFG);
......@@ -505,7 +526,7 @@ static void serdes6g_setup(void __iomem *base, uint32_t addr,
writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA |
HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA |
HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA |
HSIO_ANA_SERDES6G_IB_CFG_CAL_ENA(ib_cal_ena) |
HSIO_ANA_SERDES6G_IB_CFG_CAL_ENA(1) |
HSIO_ANA_SERDES6G_IB_CFG_CONCUR |
HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA |
HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) |
......@@ -530,7 +551,7 @@ static void serdes6g_setup(void __iomem *base, uint32_t addr,
writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA |
HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA |
HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA |
HSIO_ANA_SERDES6G_IB_CFG_CAL_ENA(ib_cal_ena) |
HSIO_ANA_SERDES6G_IB_CFG_CAL_ENA(1) |
HSIO_ANA_SERDES6G_IB_CFG_CONCUR |
HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA |
HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) |
......@@ -850,6 +871,7 @@ static int jr2_probe(struct udevice *dev)
struct mii_dev *bus;
struct ofnode_phandle_args phandle;
struct phy_device *phy;
u32 val;
if (!priv)
return -EINVAL;
......@@ -865,6 +887,17 @@ static int jr2_probe(struct udevice *dev)
}
}
val = readl(priv->regs[ICPU] + ICPU_RESET);
val |= ICPU_RESET_CORE_RST_PROTECT;
writel(val, priv->regs[ICPU] + ICPU_RESET);
val = readl(priv->regs[GCB] + PERF_SOFT_RST);
val |= PERF_SOFT_RST_SOFT_SWC_RST;
writel(val, priv->regs[GCB] + PERF_SOFT_RST);
while (readl(priv->regs[GCB] + PERF_SOFT_RST) & PERF_SOFT_RST_SOFT_SWC_RST)
;
/* Initialize miim buses */
memset(&miim, 0x0, sizeof(struct mscc_miim_dev) * JR2_MIIM_BUS_COUNT);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册