diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/core/ofnode.c | 22 | ||||
-rw-r--r-- | drivers/firmware/firmware-zynqmp.c | 8 | ||||
-rw-r--r-- | drivers/mailbox/zynqmp-ipi.c | 2 | ||||
-rw-r--r-- | drivers/misc/Kconfig | 7 | ||||
-rw-r--r-- | drivers/mmc/sdhci.c | 3 | ||||
-rw-r--r-- | drivers/mmc/zynq_sdhci.c | 406 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/Kconfig | 3 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/pxa3xx_nand.c | 180 | ||||
-rw-r--r-- | drivers/mtd/spi/sf_internal.h | 2 | ||||
-rw-r--r-- | drivers/phy/marvell/comphy_cp110.c | 1270 | ||||
-rw-r--r-- | drivers/serial/serial_pl01x.c | 13 | ||||
-rw-r--r-- | drivers/spi/xilinx_spi.c | 8 | ||||
-rw-r--r-- | drivers/spi/zynq_qspi.c | 84 | ||||
-rw-r--r-- | drivers/spi/zynq_spi.c | 35 |
14 files changed, 729 insertions, 1314 deletions
diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index 7d1b89514c..a68076bf35 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -476,6 +476,28 @@ ofnode ofnode_get_chosen_node(const char *name) return ofnode_path(prop); } +const void *ofnode_read_aliases_prop(const char *propname, int *sizep) +{ + ofnode node; + + node = ofnode_path("/aliases"); + + return ofnode_read_prop(node, propname, sizep); +} + +ofnode ofnode_get_aliases_node(const char *name) +{ + const char *prop; + + prop = ofnode_read_aliases_prop(name, NULL); + if (!prop) + return ofnode_null(); + + debug("%s: node_path: %s\n", __func__, prop); + + return ofnode_path(prop); +} + int ofnode_get_child_count(ofnode parent) { ofnode child; diff --git a/drivers/firmware/firmware-zynqmp.c b/drivers/firmware/firmware-zynqmp.c index 7583f24a20..d4dc856baf 100644 --- a/drivers/firmware/firmware-zynqmp.c +++ b/drivers/firmware/firmware-zynqmp.c @@ -165,6 +165,14 @@ int __maybe_unused xilinx_pm_request(u32 api_id, u32 arg0, u32 arg1, u32 arg2, */ u32 regs[] = {api_id, arg0, arg1, arg2, arg3}; + if (api_id == PM_FPGA_LOAD) { + /* Swap addr_hi/low because of incompatibility */ + u32 temp = regs[1]; + + regs[1] = regs[2]; + regs[2] = temp; + } + ipi_req(regs, PAYLOAD_ARG_CNT, ret_payload, PAYLOAD_ARG_CNT); #else return -EPERM; diff --git a/drivers/mailbox/zynqmp-ipi.c b/drivers/mailbox/zynqmp-ipi.c index 9483ed9cef..847a03648b 100644 --- a/drivers/mailbox/zynqmp-ipi.c +++ b/drivers/mailbox/zynqmp-ipi.c @@ -56,7 +56,7 @@ static int zynqmp_ipi_send(struct mbox_chan *chan, const void *data) /* Wait until observation bit is cleared */ ret = wait_for_bit_le32(&ipi_int_apu->obs, IPI_BIT_MASK_PMU0, false, - 100, false); + 1000, false); debug("%s, send %ld bytes\n", __func__, msg->len); return ret; diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index b67e906a76..29432ae7eb 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -376,13 +376,6 @@ config SPL_I2C_EEPROM This option is an SPL-variant of the I2C_EEPROM option. See the help of I2C_EEPROM for details. -config ZYNQ_GEM_I2C_MAC_OFFSET - hex "Set the I2C MAC offset" - default 0x0 - depends on DM_I2C - help - Set the MAC offset for i2C. - if I2C_EEPROM config SYS_I2C_EEPROM_ADDR diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index d549a264d7..0628934312 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -812,7 +812,8 @@ int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host, cfg->host_caps &= ~MMC_MODE_HS_52MHz; } - if (!(cfg->voltages & MMC_VDD_165_195)) + if (!(cfg->voltages & MMC_VDD_165_195) || + (host->quirks & SDHCI_QUIRK_NO_1_8_V)) caps_1 &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_DDR50); diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c index 775c17baac..147ecc0d70 100644 --- a/drivers/mmc/zynq_sdhci.c +++ b/drivers/mmc/zynq_sdhci.c @@ -19,6 +19,20 @@ #include <sdhci.h> #include <zynqmp_tap_delay.h> +#define SDHCI_ARASAN_ITAPDLY_REGISTER 0xF0F8 +#define SDHCI_ARASAN_OTAPDLY_REGISTER 0xF0FC +#define SDHCI_ITAPDLY_CHGWIN 0x200 +#define SDHCI_ITAPDLY_ENABLE 0x100 +#define SDHCI_OTAPDLY_ENABLE 0x40 + +#define SDHCI_TUNING_LOOP_COUNT 40 +#define MMC_BANK2 0x2 + +struct arasan_sdhci_clk_data { + int clk_phase_in[MMC_TIMING_MMC_HS400 + 1]; + int clk_phase_out[MMC_TIMING_MMC_HS400 + 1]; +}; + struct arasan_sdhci_plat { struct mmc_config cfg; struct mmc mmc; @@ -26,29 +40,35 @@ struct arasan_sdhci_plat { struct arasan_sdhci_priv { struct sdhci_host *host; + struct arasan_sdhci_clk_data clk_data; u8 deviceid; u8 bank; + u8 no_1p8; }; -#if defined(CONFIG_ARCH_ZYNQMP) -#define MMC_HS200_BUS_SPEED 5 +#if defined(CONFIG_ARCH_ZYNQMP) || defined(CONFIG_ARCH_VERSAL) +/* Default settings for ZynqMP Clock Phases */ +const u32 zynqmp_iclk_phases[] = {0, 63, 63, 0, 63, 0, 0, 183, 54, 0, 0}; +const u32 zynqmp_oclk_phases[] = {0, 72, 60, 0, 60, 72, 135, 48, 72, 135, 0}; + +/* Default settings for Versal Clock Phases */ +const u32 versal_iclk_phases[] = {0, 132, 132, 0, 132, 0, 0, 162, 90, 0, 0}; +const u32 versal_oclk_phases[] = {0, 60, 48, 0, 48, 72, 90, 36, 60, 90, 0}; static const u8 mode2timing[] = { - [MMC_LEGACY] = UHS_SDR12_BUS_SPEED, - [MMC_HS] = HIGH_SPEED_BUS_SPEED, - [SD_HS] = HIGH_SPEED_BUS_SPEED, - [MMC_HS_52] = HIGH_SPEED_BUS_SPEED, - [MMC_DDR_52] = HIGH_SPEED_BUS_SPEED, - [UHS_SDR12] = UHS_SDR12_BUS_SPEED, - [UHS_SDR25] = UHS_SDR25_BUS_SPEED, - [UHS_SDR50] = UHS_SDR50_BUS_SPEED, - [UHS_DDR50] = UHS_DDR50_BUS_SPEED, - [UHS_SDR104] = UHS_SDR104_BUS_SPEED, - [MMC_HS_200] = MMC_HS200_BUS_SPEED, + [MMC_LEGACY] = MMC_TIMING_LEGACY, + [MMC_HS] = MMC_TIMING_MMC_HS, + [SD_HS] = MMC_TIMING_SD_HS, + [MMC_HS_52] = MMC_TIMING_UHS_SDR50, + [MMC_DDR_52] = MMC_TIMING_UHS_DDR50, + [UHS_SDR12] = MMC_TIMING_UHS_SDR12, + [UHS_SDR25] = MMC_TIMING_UHS_SDR25, + [UHS_SDR50] = MMC_TIMING_UHS_SDR50, + [UHS_DDR50] = MMC_TIMING_UHS_DDR50, + [UHS_SDR104] = MMC_TIMING_UHS_SDR104, + [MMC_HS_200] = MMC_TIMING_MMC_HS200, }; -#define SDHCI_TUNING_LOOP_COUNT 40 - static void arasan_zynqmp_dll_reset(struct sdhci_host *host, u8 deviceid) { u16 clk; @@ -156,17 +176,352 @@ static int arasan_sdhci_execute_tuning(struct mmc *mmc, u8 opcode) return 0; } +/** + * sdhci_zynqmp_sdcardclk_set_phase - Set the SD Output Clock Tap Delays + * + * Set the SD Output Clock Tap Delays for Output path + * + * @host: Pointer to the sdhci_host structure. + * @degrees: The clock phase shift between 0 - 359. + * Return: 0 on success and error value on error + */ +static int sdhci_zynqmp_sdcardclk_set_phase(struct sdhci_host *host, + int degrees) +{ + struct arasan_sdhci_priv *priv = dev_get_priv(host->mmc->dev); + struct mmc *mmc = (struct mmc *)host->mmc; + u8 tap_delay, tap_max = 0; + int ret; + int timing = mode2timing[mmc->selected_mode]; + + /* + * This is applicable for SDHCI_SPEC_300 and above + * ZynqMP does not set phase for <=25MHz clock. + * If degrees is zero, no need to do anything. + */ + if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300 || + timing == MMC_TIMING_LEGACY || + timing == MMC_TIMING_UHS_SDR12 || !degrees) + return 0; + + switch (timing) { + case MMC_TIMING_MMC_HS: + case MMC_TIMING_SD_HS: + case MMC_TIMING_UHS_SDR25: + case MMC_TIMING_UHS_DDR50: + case MMC_TIMING_MMC_DDR52: + /* For 50MHz clock, 30 Taps are available */ + tap_max = 30; + break; + case MMC_TIMING_UHS_SDR50: + /* For 100MHz clock, 15 Taps are available */ + tap_max = 15; + break; + case MMC_TIMING_UHS_SDR104: + case MMC_TIMING_MMC_HS200: + /* For 200MHz clock, 8 Taps are available */ + tap_max = 8; + default: + break; + } + + tap_delay = (degrees * tap_max) / 360; + + arasan_zynqmp_set_tapdelay(priv->deviceid, 0, tap_delay); + + return ret; +} + +/** + * sdhci_zynqmp_sampleclk_set_phase - Set the SD Input Clock Tap Delays + * + * Set the SD Input Clock Tap Delays for Input path + * + * @host: Pointer to the sdhci_host structure. + * @degrees: The clock phase shift between 0 - 359. + * Return: 0 on success and error value on error + */ +static int sdhci_zynqmp_sampleclk_set_phase(struct sdhci_host *host, + int degrees) +{ + struct arasan_sdhci_priv *priv = dev_get_priv(host->mmc->dev); + struct mmc *mmc = (struct mmc *)host->mmc; + u8 tap_delay, tap_max = 0; + int ret; + int timing = mode2timing[mmc->selected_mode]; + + /* + * This is applicable for SDHCI_SPEC_300 and above + * ZynqMP does not set phase for <=25MHz clock. + * If degrees is zero, no need to do anything. + */ + if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300 || + timing == MMC_TIMING_LEGACY || + timing == MMC_TIMING_UHS_SDR12 || !degrees) + return 0; + + switch (timing) { + case MMC_TIMING_MMC_HS: + case MMC_TIMING_SD_HS: + case MMC_TIMING_UHS_SDR25: + case MMC_TIMING_UHS_DDR50: + case MMC_TIMING_MMC_DDR52: + /* For 50MHz clock, 120 Taps are available */ + tap_max = 120; + break; + case MMC_TIMING_UHS_SDR50: + /* For 100MHz clock, 60 Taps are available */ + tap_max = 60; + break; + case MMC_TIMING_UHS_SDR104: + case MMC_TIMING_MMC_HS200: + /* For 200MHz clock, 30 Taps are available */ + tap_max = 30; + default: + break; + } + + tap_delay = (degrees * tap_max) / 360; + + arasan_zynqmp_set_tapdelay(priv->deviceid, tap_delay, 0); + + return ret; +} + +/** + * sdhci_versal_sdcardclk_set_phase - Set the SD Output Clock Tap Delays + * + * Set the SD Output Clock Tap Delays for Output path + * + * @host: Pointer to the sdhci_host structure. + * @degrees The clock phase shift between 0 - 359. + * Return: 0 on success and error value on error + */ +static int sdhci_versal_sdcardclk_set_phase(struct sdhci_host *host, + int degrees) +{ + struct mmc *mmc = (struct mmc *)host->mmc; + u8 tap_delay, tap_max = 0; + int ret; + int timing = mode2timing[mmc->selected_mode]; + + /* + * This is applicable for SDHCI_SPEC_300 and above + * Versal does not set phase for <=25MHz clock. + * If degrees is zero, no need to do anything. + */ + if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300 || + timing == MMC_TIMING_LEGACY || + timing == MMC_TIMING_UHS_SDR12 || !degrees) + return 0; + + switch (timing) { + case MMC_TIMING_MMC_HS: + case MMC_TIMING_SD_HS: + case MMC_TIMING_UHS_SDR25: + case MMC_TIMING_UHS_DDR50: + case MMC_TIMING_MMC_DDR52: + /* For 50MHz clock, 30 Taps are available */ + tap_max = 30; + break; + case MMC_TIMING_UHS_SDR50: + /* For 100MHz clock, 15 Taps are available */ + tap_max = 15; + break; + case MMC_TIMING_UHS_SDR104: + case MMC_TIMING_MMC_HS200: + /* For 200MHz clock, 8 Taps are available */ + tap_max = 8; + default: + break; + } + + tap_delay = (degrees * tap_max) / 360; + + /* Set the Clock Phase */ + if (tap_delay) { + u32 regval; + + regval = sdhci_readl(host, SDHCI_ARASAN_OTAPDLY_REGISTER); + regval |= SDHCI_OTAPDLY_ENABLE; + sdhci_writel(host, regval, SDHCI_ARASAN_OTAPDLY_REGISTER); + regval |= tap_delay; + sdhci_writel(host, regval, SDHCI_ARASAN_OTAPDLY_REGISTER); + } + + return ret; +} + +/** + * sdhci_versal_sampleclk_set_phase - Set the SD Input Clock Tap Delays + * + * Set the SD Input Clock Tap Delays for Input path + * + * @host: Pointer to the sdhci_host structure. + * @degrees The clock phase shift between 0 - 359. + * Return: 0 on success and error value on error + */ +static int sdhci_versal_sampleclk_set_phase(struct sdhci_host *host, + int degrees) +{ + struct mmc *mmc = (struct mmc *)host->mmc; + u8 tap_delay, tap_max = 0; + int ret; + int timing = mode2timing[mmc->selected_mode]; + + /* + * This is applicable for SDHCI_SPEC_300 and above + * Versal does not set phase for <=25MHz clock. + * If degrees is zero, no need to do anything. + */ + if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300 || + timing == MMC_TIMING_LEGACY || + timing == MMC_TIMING_UHS_SDR12 || !degrees) + return 0; + + switch (timing) { + case MMC_TIMING_MMC_HS: + case MMC_TIMING_SD_HS: + case MMC_TIMING_UHS_SDR25: + case MMC_TIMING_UHS_DDR50: + case MMC_TIMING_MMC_DDR52: + /* For 50MHz clock, 120 Taps are available */ + tap_max = 120; + break; + case MMC_TIMING_UHS_SDR50: + /* For 100MHz clock, 60 Taps are available */ + tap_max = 60; + break; + case MMC_TIMING_UHS_SDR104: + case MMC_TIMING_MMC_HS200: + /* For 200MHz clock, 30 Taps are available */ + tap_max = 30; + default: + break; + } + + tap_delay = (degrees * tap_max) / 360; + + /* Set the Clock Phase */ + if (tap_delay) { + u32 regval; + + regval = sdhci_readl(host, SDHCI_ARASAN_ITAPDLY_REGISTER); + regval |= SDHCI_ITAPDLY_CHGWIN; + sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER); + regval |= SDHCI_ITAPDLY_ENABLE; + sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER); + regval |= tap_delay; + sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER); + regval &= ~SDHCI_ITAPDLY_CHGWIN; + sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER); + } + + return ret; +} + static void arasan_sdhci_set_tapdelay(struct sdhci_host *host) { struct arasan_sdhci_priv *priv = dev_get_priv(host->mmc->dev); + struct arasan_sdhci_clk_data *clk_data = &priv->clk_data; struct mmc *mmc = (struct mmc *)host->mmc; - u8 uhsmode; + struct udevice *dev = mmc->dev; + u8 timing = mode2timing[mmc->selected_mode]; + u32 iclk_phase = clk_data->clk_phase_in[timing]; + u32 oclk_phase = clk_data->clk_phase_out[timing]; + + dev_dbg(dev, "%s, host:%s, mode:%d\n", __func__, host->name, timing); + + if (IS_ENABLED(CONFIG_ARCH_ZYNQMP) && + device_is_compatible(dev, "xlnx,zynqmp-8.9a")) { + sdhci_zynqmp_sampleclk_set_phase(host, iclk_phase); + sdhci_zynqmp_sdcardclk_set_phase(host, oclk_phase); + } else if (IS_ENABLED(CONFIG_ARCH_VERSAL) && + device_is_compatible(dev, "xlnx,versal-8.9a")) { + sdhci_versal_sampleclk_set_phase(host, iclk_phase); + sdhci_versal_sdcardclk_set_phase(host, oclk_phase); + } +} - uhsmode = mode2timing[mmc->selected_mode]; +static void arasan_dt_read_clk_phase(struct udevice *dev, unsigned char timing, + const char *prop) +{ + struct arasan_sdhci_priv *priv = dev_get_priv(dev); + struct arasan_sdhci_clk_data *clk_data = &priv->clk_data; + u32 clk_phase[2] = {0}; + + /* + * Read Tap Delay values from DT, if the DT does not contain the + * Tap Values then use the pre-defined values + */ + if (dev_read_u32_array(dev, prop, &clk_phase[0], 2)) { + dev_dbg(dev, "Using predefined clock phase for %s = %d %d\n", + prop, clk_data->clk_phase_in[timing], + clk_data->clk_phase_out[timing]); + return; + } - if (uhsmode >= UHS_SDR25_BUS_SPEED) - arasan_zynqmp_set_tapdelay(priv->deviceid, uhsmode, - priv->bank); + /* The values read are Input and Output Clock Delays in order */ + clk_data->clk_phase_in[timing] = clk_phase[0]; + clk_data->clk_phase_out[timing] = clk_phase[1]; +} + +/** + * arasan_dt_parse_clk_phases - Read Tap Delay values from DT + * + * Called at initialization to parse the values of Tap Delays. + * + * @dev: Pointer to our struct udevice. + */ +static void arasan_dt_parse_clk_phases(struct udevice *dev) +{ + struct arasan_sdhci_priv *priv = dev_get_priv(dev); + struct arasan_sdhci_clk_data *clk_data = &priv->clk_data; + int i; + + if (IS_ENABLED(CONFIG_ARCH_ZYNQMP) && + device_is_compatible(dev, "xlnx,zynqmp-8.9a")) { + for (i = 0; i <= MMC_TIMING_MMC_HS400; i++) { + clk_data->clk_phase_in[i] = zynqmp_iclk_phases[i]; + clk_data->clk_phase_out[i] = zynqmp_oclk_phases[i]; + } + + if (priv->bank == MMC_BANK2) { + clk_data->clk_phase_out[MMC_TIMING_UHS_SDR104] = 90; + clk_data->clk_phase_out[MMC_TIMING_MMC_HS200] = 90; + } + } + + if (IS_ENABLED(CONFIG_ARCH_VERSAL) && + device_is_compatible(dev, "xlnx,versal-8.9a")) { + for (i = 0; i <= MMC_TIMING_MMC_HS400; i++) { + clk_data->clk_phase_in[i] = versal_iclk_phases[i]; + clk_data->clk_phase_out[i] = versal_oclk_phases[i]; + } + } + + arasan_dt_read_clk_phase(dev, MMC_TIMING_LEGACY, + "clk-phase-legacy"); + arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_HS, + "clk-phase-mmc-hs"); + arasan_dt_read_clk_phase(dev, MMC_TIMING_SD_HS, + "clk-phase-sd-hs"); + arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR12, + "clk-phase-uhs-sdr12"); + arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR25, + "clk-phase-uhs-sdr25"); + arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR50, + "clk-phase-uhs-sdr50"); + arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR104, + "clk-phase-uhs-sdr104"); + arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_DDR50, + "clk-phase-uhs-ddr50"); + arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_DDR52, + "clk-phase-mmc-ddr52"); + arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_HS200, + "clk-phase-mmc-hs200"); + arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_HS400, + "clk-phase-mmc-hs400"); } static void arasan_sdhci_set_control_reg(struct sdhci_host *host) @@ -184,12 +539,10 @@ static void arasan_sdhci_set_control_reg(struct sdhci_host *host) } if (mmc->selected_mode > SD_HS && - mmc->selected_mode <= UHS_DDR50) + mmc->selected_mode <= MMC_HS_200) sdhci_set_uhs_timing(host); } -#endif -#if defined(CONFIG_ARCH_ZYNQMP) const struct sdhci_ops arasan_ops = { .platform_execute_tuning = &arasan_sdhci_execute_tuning, .set_delay = &arasan_sdhci_set_tapdelay, @@ -236,6 +589,9 @@ static int arasan_sdhci_probe(struct udevice *dev) host->quirks |= SDHCI_QUIRK_BROKEN_HISPD_MODE; #endif + if (priv->no_1p8) + host->quirks |= SDHCI_QUIRK_NO_1_8_V; + plat->cfg.f_max = CONFIG_ZYNQ_SDHCI_MAX_FREQ; ret = mmc_of_parse(dev, &plat->cfg); @@ -267,8 +623,9 @@ static int arasan_sdhci_ofdata_to_platdata(struct udevice *dev) priv->host->name = dev->name; -#if defined(CONFIG_ARCH_ZYNQMP) +#if defined(CONFIG_ARCH_ZYNQMP) || defined(CONFIG_ARCH_VERSAL) priv->host->ops = &arasan_ops; + arasan_dt_parse_clk_phases(dev); #endif priv->host->ioaddr = (void *)dev_read_addr(dev); @@ -277,6 +634,7 @@ static int arasan_sdhci_ofdata_to_platdata(struct udevice *dev) priv->deviceid = dev_read_u32_default(dev, "xlnx,device_id", -1); priv->bank = dev_read_u32_default(dev, "xlnx,mio-bank", 0); + priv->no_1p8 = dev_read_bool(dev, "no-1-8-v"); return 0; } diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig index cd7e598aa8..3cf3b14f05 100644 --- a/drivers/mtd/nand/raw/Kconfig +++ b/drivers/mtd/nand/raw/Kconfig @@ -195,6 +195,9 @@ endif config NAND_PXA3XX bool "Support for NAND on PXA3xx and Armada 370/XP/38x" select SYS_NAND_SELF_INIT + select DM_MTD + select REGMAP + select SYSCON imply CMD_NAND help This enables the driver for the NAND flash device found on diff --git a/drivers/mtd/nand/raw/pxa3xx_nand.c b/drivers/mtd/nand/raw/pxa3xx_nand.c index 5fb3081c83..361a9e3293 100644 --- a/drivers/mtd/nand/raw/pxa3xx_nand.c +++ b/drivers/mtd/nand/raw/pxa3xx_nand.c @@ -22,6 +22,10 @@ #include <linux/mtd/mtd.h> #include <linux/mtd/rawnand.h> #include <linux/types.h> +#include <syscon.h> +#include <regmap.h> +#include <dm/uclass.h> +#include <dm/read.h> #include "pxa3xx_nand.h" @@ -117,6 +121,10 @@ DECLARE_GLOBAL_DATA_PTR; #define EXT_CMD_TYPE_LAST_RW 1 /* Last naked read/write */ #define EXT_CMD_TYPE_MONO 0 /* Monolithic read/write */ +/* System control register and bit to enable NAND on some SoCs */ +#define GENCONF_SOC_DEVICE_MUX 0x208 +#define GENCONF_SOC_DEVICE_MUX_NFC_EN BIT(0) + /* * This should be large enough to read 'ONFI' and 'JEDEC'. * Let's use 7 bytes, which is the maximum ID count supported @@ -157,6 +165,7 @@ enum { enum pxa3xx_nand_variant { PXA3XX_NAND_VARIANT_PXA, PXA3XX_NAND_VARIANT_ARMADA370, + PXA3XX_NAND_VARIANT_ARMADA_8K, }; struct pxa3xx_nand_host { @@ -417,10 +426,21 @@ static struct nand_ecclayout ecc_layout_8KB_bch8bit = { /* convert nano-seconds to nand flash controller clock cycles */ #define ns2cycle(ns, clk) (int)((ns) * (clk / 1000000) / 1000) -static enum pxa3xx_nand_variant pxa3xx_nand_get_variant(void) +static const struct udevice_id pxa3xx_nand_dt_ids[] = { + { + .compatible = "marvell,mvebu-pxa3xx-nand", + .data = PXA3XX_NAND_VARIANT_ARMADA370, + }, + { + .compatible = "marvell,armada-8k-nand-controller", + .data = PXA3XX_NAND_VARIANT_ARMADA_8K, + }, + {} +}; + +static enum pxa3xx_nand_variant pxa3xx_nand_get_variant(struct udevice *dev) { - /* We only support the Armada 370/XP/38x for now */ - return PXA3XX_NAND_VARIANT_ARMADA370; + return dev_get_driver_data(dev); } static void pxa3xx_nand_set_timing(struct pxa3xx_nand_host *host, @@ -697,7 +717,8 @@ static irqreturn_t pxa3xx_nand_irq(struct pxa3xx_nand_info *info) info->retcode = ERR_UNCORERR; if (status & NDSR_CORERR) { info->retcode = ERR_CORERR; - if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370 && + if ((info->variant == PXA3XX_NAND_VARIANT_ARMADA370 || + info->variant == PXA3XX_NAND_VARIANT_ARMADA_8K) && info->ecc_bch) info->ecc_err_cnt = NDSR_ERR_CNT(status); else @@ -752,7 +773,8 @@ static irqreturn_t pxa3xx_nand_irq(struct pxa3xx_nand_info *info) nand_writel(info, NDCB0, info->ndcb2); /* NDCB3 register is available in NFCv2 (Armada 370/XP SoC) */ - if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370) + if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370 || + info->variant == PXA3XX_NAND_VARIANT_ARMADA_8K) nand_writel(info, NDCB0, info->ndcb3); } @@ -1666,7 +1688,8 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) } /* Device detection must be done with ECC disabled */ - if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370) + if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370 || + info->variant == PXA3XX_NAND_VARIANT_ARMADA_8K) nand_writel(info, NDECCCTRL, 0x0); if (nand_scan_ident(mtd, 1, NULL)) @@ -1716,7 +1739,8 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) * (aka split) command handling, */ if (mtd->writesize > info->chunk_size) { - if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370) { + if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370 || + info->variant == PXA3XX_NAND_VARIANT_ARMADA_8K) { chip->cmdfunc = nand_cmdfunc_extended; } else { dev_err(mtd->dev, @@ -1752,19 +1776,19 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) return nand_scan_tail(mtd); } -static int alloc_nand_resource(struct pxa3xx_nand_info *info) +static int alloc_nand_resource(struct udevice *dev, struct pxa3xx_nand_info *info) { struct pxa3xx_nand_platform_data *pdata; struct pxa3xx_nand_host *host; struct nand_chip *chip = NULL; struct mtd_info *mtd; - int ret, cs; + int cs; pdata = info->pdata; if (pdata->num_cs <= 0) return -ENODEV; - info->variant = pxa3xx_nand_get_variant(); + info->variant = pxa3xx_nand_get_variant(dev); for (cs = 0; cs < pdata->num_cs; cs++) { chip = (struct nand_chip *) ((u8 *)&info[1] + sizeof(*host) * cs); @@ -1794,97 +1818,87 @@ static int alloc_nand_resource(struct pxa3xx_nand_info *info) /* Allocate a buffer to allow flash detection */ info->buf_size = INIT_BUFFER_SIZE; info->data_buff = kmalloc(info->buf_size, GFP_KERNEL); - if (info->data_buff == NULL) { - ret = -ENOMEM; - goto fail_disable_clk; - } + if (info->data_buff == NULL) + return -ENOMEM; /* initialize all interrupts to be disabled */ disable_int(info, NDSR_MASK); - return 0; + /* + * Some SoCs like A7k/A8k need to enable manually the NAND + * controller to avoid being bootloader dependent. This is done + * through the use of a single bit in the System Functions registers. + */ + if (pxa3xx_nand_get_variant(dev) == PXA3XX_NAND_VARIANT_ARMADA_8K) { + struct regmap *sysctrl_base = syscon_regmap_lookup_by_phandle( + dev, "marvell,system-controller"); + u32 reg; - kfree(info->data_buff); -fail_disable_clk: - return ret; + if (IS_ERR(sysctrl_base)) + return PTR_ERR(sysctrl_base); + + regmap_read(sysctrl_base, GENCONF_SOC_DEVICE_MUX, ®); + reg |= GENCONF_SOC_DEVICE_MUX_NFC_EN; + regmap_write(sysctrl_base, GENCONF_SOC_DEVICE_MUX, reg); + } + + return 0; } -static int pxa3xx_nand_probe_dt(struct pxa3xx_nand_info *info) +static int pxa3xx_nand_probe_dt(struct udevice *dev, struct pxa3xx_nand_info *info) { struct pxa3xx_nand_platform_data *pdata; - const void *blob = gd->fdt_blob; - int node = -1; pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); if (!pdata) return -ENOMEM; - /* Get address decoding nodes from the FDT blob */ - do { - node = fdt_node_offset_by_compatible(blob, node, - "marvell,mvebu-pxa3xx-nand"); - if (node < 0) - break; - - /* Bypass disabeld nodes */ - if (!fdtdec_get_is_enabled(blob, node)) - continue; - - /* Get the first enabled NAND controler base address */ - info->mmio_base = - (void __iomem *)fdtdec_get_addr_size_auto_noparent( - blob, node, "reg", 0, NULL, true); + info->mmio_base = dev_read_addr_ptr(dev); - pdata->num_cs = fdtdec_get_int(blob, node, "num-cs", 1); - if (pdata->num_cs != 1) { - pr_err("pxa3xx driver supports single CS only\n"); - break; - } - - if (fdtdec_get_bool(blob, node, "nand-enable-arbiter")) - pdata->enable_arbiter = 1; - - if (fdtdec_get_bool(blob, node, "nand-keep-config")) - pdata->keep_config = 1; + pdata->num_cs = dev_read_u32_default(dev, "num-cs", 1); + if (pdata->num_cs != 1) { + pr_err("pxa3xx driver supports single CS only\n"); + return -EINVAL; + } - /* - * ECC parameters. - * If these are not set, they will be selected according - * to the detected flash type. - */ - /* ECC strength */ - pdata->ecc_strength = fdtdec_get_int(blob, node, - "nand-ecc-strength", 0); + if (dev_read_bool(dev, "nand-enable-arbiter")) + pdata->enable_arbiter = 1; - /* ECC step size */ - pdata->ecc_step_size = fdtdec_get_int(blob, node, - "nand-ecc-step-size", 0); + if (dev_read_bool(dev, "nand-keep-config")) + pdata->keep_config = 1; - info->pdata = pdata; + /* + * ECC parameters. + * If these are not set, they will be selected according + * to the detected flash type. + */ + /* ECC strength */ + pdata->ecc_strength = dev_read_u32_default(dev, "nand-ecc-strength", 0); - /* Currently support only a single NAND controller */ - return 0; + /* ECC step size */ + pdata->ecc_step_size = dev_read_u32_default(dev, "nand-ecc-step-size", + 0); - } while (node >= 0); + info->pdata = pdata; - return -EINVAL; + return 0; } -static int pxa3xx_nand_probe(struct pxa3xx_nand_info *info) +static int pxa3xx_nand_probe(struct udevice *dev) { - struct mtd_info *mtd = &info->controller.active->mtd; struct pxa3xx_nand_platform_data *pdata; int ret, cs, probe_success; + struct pxa3xx_nand_info *info = dev_get_priv(dev); - ret = pxa3xx_nand_probe_dt(info); + ret = pxa3xx_nand_probe_dt(dev, info); if (ret) return ret; pdata = info->pdata; - ret = alloc_nand_resource(info); + ret = alloc_nand_resource(dev, info); if (ret) { - dev_err(mtd->dev, "alloc nand resource failed\n"); + dev_err(dev, "alloc nand resource failed\n"); return ret; } @@ -1918,22 +1932,24 @@ static int pxa3xx_nand_probe(struct pxa3xx_nand_info *info) return 0; } -/* - * Main initialization routine - */ +U_BOOT_DRIVER(pxa3xx_nand) = { + .name = "pxa3xx-nand", + .id = UCLASS_MTD, + .of_match = pxa3xx_nand_dt_ids, + .probe = pxa3xx_nand_probe, + .priv_auto_alloc_size = sizeof(struct pxa3xx_nand_info) + + sizeof(struct pxa3xx_nand_host) * CONFIG_SYS_MAX_NAND_DEVICE, +}; + void board_nand_init(void) { - struct pxa3xx_nand_info *info; - struct pxa3xx_nand_host *host; + struct udevice *dev; int ret; - info = kzalloc(sizeof(*info) + - sizeof(*host) * CONFIG_SYS_MAX_NAND_DEVICE, - GFP_KERNEL); - if (!info) - return; - - ret = pxa3xx_nand_probe(info); - if (ret) - return; + ret = uclass_get_device_by_driver(UCLASS_MTD, + DM_GET_DRIVER(pxa3xx_nand), &dev); + if (ret && ret != -ENODEV) { + pr_err("Failed to initialize %s. (error %d)\n", dev->name, + ret); + } } diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index dabd40a4cc..9ceff0e7c1 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -67,7 +67,7 @@ struct flash_info { #define SPI_NOR_SKIP_SFDP BIT(13) /* Skip parsing of SFDP tables */ #define USE_CLSR BIT(14) /* use CLSR command */ #define SPI_NOR_HAS_SST26LOCK BIT(15) /* Flash supports lock/unlock via BPR */ -#define SPI_NOR_OCTAL_READ BIT(16) /* Flash supports Octal Read */ +#define SPI_NOR_OCTAL_READ BIT(16) /* Flash supports Octal Read */ }; extern const struct flash_info spi_nor_ids[]; diff --git a/drivers/phy/marvell/comphy_cp110.c b/drivers/phy/marvell/comphy_cp110.c index 15e80049de..b0fcb13f1c 100644 --- a/drivers/phy/marvell/comphy_cp110.c +++ b/drivers/phy/marvell/comphy_cp110.c @@ -7,6 +7,7 @@ #include <fdtdec.h> #include <log.h> #include <asm/io.h> +#include <asm/ptrace.h> #include <asm/arch/cpu.h> #include <asm/arch/soc.h> #include <linux/delay.h> @@ -22,6 +23,40 @@ DECLARE_GLOBAL_DATA_PTR; #define HPIPE_ADDR(base, lane) (SD_ADDR(base, lane) + 0x800) #define COMPHY_ADDR(base, lane) (base + 0x28 * lane) +/* Firmware related definitions used for SMC calls */ +#define MV_SIP_COMPHY_POWER_ON 0x82000001 +#define MV_SIP_COMPHY_POWER_OFF 0x82000002 +#define MV_SIP_COMPHY_PLL_LOCK 0x82000003 + +/* Used to distinguish between different possible callers (U-boot/Linux) */ +#define COMPHY_CALLER_UBOOT (0x1 << 21) + +#define COMPHY_FW_MODE_FORMAT(mode) ((mode) << 12) +#define COMPHY_FW_FORMAT(mode, idx, speeds) \ + (((mode) << 12) | ((idx) << 8) | ((speeds) << 2)) + +#define COMPHY_FW_PCIE_FORMAT(pcie_width, clk_src, mode, speeds) \ + (COMPHY_CALLER_UBOOT | ((pcie_width) << 18) | \ + ((clk_src) << 17) | COMPHY_FW_FORMAT(mode, 0, speeds)) + +#define COMPHY_SATA_MODE 0x1 +#define COMPHY_SGMII_MODE 0x2 /* SGMII 1G */ +#define COMPHY_HS_SGMII_MODE 0x3 /* SGMII 2.5G */ +#define COMPHY_USB3H_MODE 0x4 +#define COMPHY_USB3D_MODE 0x5 +#define COMPHY_PCIE_MODE 0x6 +#define COMPHY_RXAUI_MODE 0x7 +#define COMPHY_XFI_MODE 0x8 +#define COMPHY_SFI_MODE 0x9 +#define COMPHY_USB3_MODE 0xa +#define COMPHY_AP_MODE 0xb + +/* Comphy unit index macro */ +#define COMPHY_UNIT_ID0 0 +#define COMPHY_UNIT_ID1 1 +#define COMPHY_UNIT_ID2 2 +#define COMPHY_UNIT_ID3 3 + struct utmi_phy_data { void __iomem *utmi_base_addr; void __iomem *usb_cfg_addr; @@ -85,441 +120,6 @@ static u32 polling_with_timeout(void __iomem *addr, u32 val, return 0; } -static int comphy_pcie_power_up(u32 lane, u32 pcie_width, bool clk_src, - bool is_end_point, void __iomem *hpipe_base, - void __iomem *comphy_base) -{ - u32 mask, data, ret = 1; - void __iomem *hpipe_addr = HPIPE_ADDR(hpipe_base, lane); - void __iomem *comphy_addr = COMPHY_ADDR(comphy_base, lane); - void __iomem *addr; - u32 pcie_clk = 0; /* set input by default */ - - debug_enter(); - - /* - * ToDo: - * Add SAR (Sample-At-Reset) configuration for the PCIe clock - * direction. SAR code is currently not ported from Marvell - * U-Boot to mainline version. - * - * SerDes Lane 4/5 got the PCIe ref-clock #1, - * and SerDes Lane 0 got PCIe ref-clock #0 - */ - debug("PCIe clock = %x\n", pcie_clk); - debug("PCIe RC = %d\n", !is_end_point); - debug("PCIe width = %d\n", pcie_width); - - /* enable PCIe by4 and by2 */ - if (lane == 0) { - if (pcie_width == 4) { - reg_set(comphy_base + COMMON_PHY_SD_CTRL1, - 0x1 << COMMON_PHY_SD_CTRL1_PCIE_X4_EN_OFFSET, - COMMON_PHY_SD_CTRL1_PCIE_X4_EN_MASK); - } else if (pcie_width == 2) { - reg_set(comphy_base + COMMON_PHY_SD_CTRL1, - 0x1 << COMMON_PHY_SD_CTRL1_PCIE_X2_EN_OFFSET, - COMMON_PHY_SD_CTRL1_PCIE_X2_EN_MASK); - } - } - - /* - * If PCIe clock is output and clock source from SerDes lane 5, - * we need to configure the clock-source MUX. - * By default, the clock source is from lane 4 - */ - if (pcie_clk && clk_src && (lane == 5)) { - reg_set((void __iomem *)DFX_DEV_GEN_CTRL12, - 0x3 << DFX_DEV_GEN_PCIE_CLK_SRC_OFFSET, - DFX_DEV_GEN_PCIE_CLK_SRC_MASK); - } - - debug("stage: RFU configurations - hard reset comphy\n"); - /* RFU configurations - hard reset comphy */ - mask = COMMON_PHY_CFG1_PWR_UP_MASK; - data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET; - mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK; - data |= 0x1 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET; - mask |= COMMON_PHY_CFG1_PWR_ON_RESET_MASK; - data |= 0x0 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET; - mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK; - data |= 0x0 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET; - mask |= COMMON_PHY_PHY_MODE_MASK; - data |= 0x0 << COMMON_PHY_PHY_MODE_OFFSET; - reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); - - /* release from hard reset */ - mask = COMMON_PHY_CFG1_PWR_ON_RESET_MASK; - data = 0x1 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET; - mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK; - data |= 0x1 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET; - reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); - - /* Wait 1ms - until band gap and ref clock ready */ - mdelay(1); - /* Start comphy Configuration */ - debug("stage: Comphy configuration\n"); - /* Set PIPE soft reset */ - mask = HPIPE_RST_CLK_CTRL_PIPE_RST_MASK; - data = 0x1 << HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET; - /* Set PHY datapath width mode for V0 */ - mask |= HPIPE_RST_CLK_CTRL_FIXED_PCLK_MASK; - data |= 0x1 << HPIPE_RST_CLK_CTRL_FIXED_PCLK_OFFSET; - /* Set Data bus width USB mode for V0 */ - mask |= HPIPE_RST_CLK_CTRL_PIPE_WIDTH_MASK; - data |= 0x0 << HPIPE_RST_CLK_CTRL_PIPE_WIDTH_OFFSET; - /* Set CORE_CLK output frequency for 250Mhz */ - mask |= HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_MASK; - data |= 0x0 << HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_OFFSET; - reg_set(hpipe_addr + HPIPE_RST_CLK_CTRL_REG, data, mask); - /* Set PLL ready delay for 0x2 */ - data = 0x2 << HPIPE_CLK_SRC_LO_PLL_RDY_DL_OFFSET; - mask = HPIPE_CLK_SRC_LO_PLL_RDY_DL_MASK; - if (pcie_width != 1) { - data |= 0x1 << HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SEL_OFFSET; - mask |= HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SEL_MASK; - data |= 0x1 << HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SCALE_OFFSET; - mask |= HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SCALE_MASK; - } - reg_set(hpipe_addr + HPIPE_CLK_SRC_LO_REG, data, mask); - - /* Set PIPE mode interface to PCIe3 - 0x1 & set lane order */ - data = 0x1 << HPIPE_CLK_SRC_HI_MODE_PIPE_OFFSET; - mask = HPIPE_CLK_SRC_HI_MODE_PIPE_MASK; - if (pcie_width != 1) { - mask |= HPIPE_CLK_SRC_HI_LANE_STRT_MASK; - mask |= HPIPE_CLK_SRC_HI_LANE_MASTER_MASK; - mask |= HPIPE_CLK_SRC_HI_LANE_BREAK_MASK; - if (lane == 0) { - data |= 0x1 << HPIPE_CLK_SRC_HI_LANE_STRT_OFFSET; - data |= 0x1 << HPIPE_CLK_SRC_HI_LANE_MASTER_OFFSET; - } else if (lane == (pcie_width - 1)) { - data |= 0x1 << HPIPE_CLK_SRC_HI_LANE_BREAK_OFFSET; - } - } - reg_set(hpipe_addr + HPIPE_CLK_SRC_HI_REG, data, mask); - /* Config update polarity equalization */ - reg_set(hpipe_addr + HPIPE_LANE_EQ_CFG1_REG, - 0x1 << HPIPE_CFG_UPDATE_POLARITY_OFFSET, - HPIPE_CFG_UPDATE_POLARITY_MASK); - /* Set PIPE version 4 to mode enable */ - reg_set(hpipe_addr + HPIPE_DFE_CTRL_28_REG, - 0x1 << HPIPE_DFE_CTRL_28_PIPE4_OFFSET, - HPIPE_DFE_CTRL_28_PIPE4_MASK); - /* TODO: check if pcie clock is output/input - for bringup use input*/ - /* Enable PIN clock 100M_125M */ - mask = 0; - data = 0; - /* Only if clock is output, configure the clock-source mux */ - if (pcie_clk) { - mask |= HPIPE_MISC_CLK100M_125M_MASK; - data |= 0x1 << HPIPE_MISC_CLK100M_125M_OFFSET; - } - /* - * Set PIN_TXDCLK_2X Clock Frequency Selection for outputs 500MHz - * clock - */ - mask |= HPIPE_MISC_TXDCLK_2X_MASK; - data |= 0x0 << HPIPE_MISC_TXDCLK_2X_OFFSET; - /* Enable 500MHz Clock */ - mask |= HPIPE_MISC_CLK500_EN_MASK; - data |= 0x1 << HPIPE_MISC_CLK500_EN_OFFSET; - if (pcie_clk) { /* output */ - /* Set reference clock comes from group 1 */ - mask |= HPIPE_MISC_REFCLK_SEL_MASK; - data |= 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET; - } else { - /* Set reference clock comes from group 2 */ - mask |= HPIPE_MISC_REFCLK_SEL_MASK; - data |= 0x1 << HPIPE_MISC_REFCLK_SEL_OFFSET; - } - mask |= HPIPE_MISC_ICP_FORCE_MASK; - data |= 0x1 << HPIPE_MISC_ICP_FORCE_OFFSET; - reg_set(hpipe_addr + HPIPE_MISC_REG, data, mask); - if (pcie_clk) { /* output */ - /* Set reference frequcency select - 0x2 for 25MHz*/ - mask = HPIPE_PWR_PLL_REF_FREQ_MASK; - data = 0x2 << HPIPE_PWR_PLL_REF_FREQ_OFFSET; - } else { - /* Set reference frequcency select - 0x0 for 100MHz*/ - mask = HPIPE_PWR_PLL_REF_FREQ_MASK; - data = 0x0 << HPIPE_PWR_PLL_REF_FREQ_OFFSET; - } - /* Set PHY mode to PCIe */ - mask |= HPIPE_PWR_PLL_PHY_MODE_MASK; - data |= 0x3 << HPIPE_PWR_PLL_PHY_MODE_OFFSET; - reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask); - - /* ref clock alignment */ - if (pcie_width != 1) { - mask = HPIPE_LANE_ALIGN_OFF_MASK; - data = 0x0 << HPIPE_LANE_ALIGN_OFF_OFFSET; - reg_set(hpipe_addr + HPIPE_LANE_ALIGN_REG, data, mask); - } - - /* - * Set the amount of time spent in the LoZ state - set for 0x7 only if - * the PCIe clock is output - */ - if (pcie_clk) { - reg_set(hpipe_addr + HPIPE_GLOBAL_PM_CTRL, - 0x7 << HPIPE_GLOBAL_PM_RXDLOZ_WAIT_OFFSET, - HPIPE_GLOBAL_PM_RXDLOZ_WAIT_MASK); - } - - /* Set Maximal PHY Generation Setting(8Gbps) */ - mask = HPIPE_INTERFACE_GEN_MAX_MASK; - data = 0x2 << HPIPE_INTERFACE_GEN_MAX_OFFSET; - /* Bypass frame detection and sync detection for RX DATA */ - mask = HPIPE_INTERFACE_DET_BYPASS_MASK; - data = 0x1 << HPIPE_INTERFACE_DET_BYPASS_OFFSET; - /* Set Link Train Mode (Tx training control pins are used) */ - mask |= HPIPE_INTERFACE_LINK_TRAIN_MASK; - data |= 0x1 << HPIPE_INTERFACE_LINK_TRAIN_OFFSET; - reg_set(hpipe_addr + HPIPE_INTERFACE_REG, data, mask); - - /* Set Idle_sync enable */ - mask = HPIPE_PCIE_IDLE_SYNC_MASK; - data = 0x1 << HPIPE_PCIE_IDLE_SYNC_OFFSET; - /* Select bits for PCIE Gen3(32bit) */ - mask |= HPIPE_PCIE_SEL_BITS_MASK; - data |= 0x2 << HPIPE_PCIE_SEL_BITS_OFFSET; - reg_set(hpipe_addr + HPIPE_PCIE_REG0, data, mask); - - /* Enable Tx_adapt_g1 */ - mask = HPIPE_TX_TRAIN_CTRL_G1_MASK; - data = 0x1 << HPIPE_TX_TRAIN_CTRL_G1_OFFSET; - /* Enable Tx_adapt_gn1 */ - mask |= HPIPE_TX_TRAIN_CTRL_GN1_MASK; - data |= 0x1 << HPIPE_TX_TRAIN_CTRL_GN1_OFFSET; - /* Disable Tx_adapt_g0 */ - mask |= HPIPE_TX_TRAIN_CTRL_G0_MASK; - data |= 0x0 << HPIPE_TX_TRAIN_CTRL_G0_OFFSET; - reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_REG, data, mask); - - /* Set reg_tx_train_chk_init */ - mask = HPIPE_TX_TRAIN_CHK_INIT_MASK; - data = 0x0 << HPIPE_TX_TRAIN_CHK_INIT_OFFSET; - /* Enable TX_COE_FM_PIN_PCIE3_EN */ - mask |= HPIPE_TX_TRAIN_COE_FM_PIN_PCIE3_MASK; - data |= 0x1 << HPIPE_TX_TRAIN_COE_FM_PIN_PCIE3_OFFSET; - reg_set(hpipe_addr + HPIPE_TX_TRAIN_REG, data, mask); - - debug("stage: TRx training parameters\n"); - /* Set Preset sweep configurations */ - mask = HPIPE_TX_TX_STATUS_CHECK_MODE_MASK; - data = 0x1 << HPIPE_TX_STATUS_CHECK_MODE_OFFSET; - - mask |= HPIPE_TX_NUM_OF_PRESET_MASK; - data |= 0x7 << HPIPE_TX_NUM_OF_PRESET_OFFSET; - - mask |= HPIPE_TX_SWEEP_PRESET_EN_MASK; - data |= 0x1 << HPIPE_TX_SWEEP_PRESET_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_11_REG, data, mask); - - /* Tx train start configuration */ - mask = HPIPE_TX_TRAIN_START_SQ_EN_MASK; - data = 0x1 << HPIPE_TX_TRAIN_START_SQ_EN_OFFSET; - - mask |= HPIPE_TX_TRAIN_START_FRM_DET_EN_MASK; - data |= 0x0 << HPIPE_TX_TRAIN_START_FRM_DET_EN_OFFSET; - - mask |= HPIPE_TX_TRAIN_START_FRM_LOCK_EN_MASK; - data |= 0x0 << HPIPE_TX_TRAIN_START_FRM_LOCK_EN_OFFSET; - - mask |= HPIPE_TX_TRAIN_WAIT_TIME_EN_MASK; - data |= 0x1 << HPIPE_TX_TRAIN_WAIT_TIME_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_5_REG, data, mask); - - /* Enable Tx train P2P */ - mask = HPIPE_TX_TRAIN_P2P_HOLD_MASK; - data = 0x1 << HPIPE_TX_TRAIN_P2P_HOLD_OFFSET; - reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_0_REG, data, mask); - - /* Configure Tx train timeout */ - mask = HPIPE_TRX_TRAIN_TIMER_MASK; - data = 0x17 << HPIPE_TRX_TRAIN_TIMER_OFFSET; - reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_4_REG, data, mask); - - /* Disable G0/G1/GN1 adaptation */ - mask = HPIPE_TX_TRAIN_CTRL_G1_MASK | HPIPE_TX_TRAIN_CTRL_GN1_MASK - | HPIPE_TX_TRAIN_CTRL_G0_OFFSET; - data = 0; - reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_REG, data, mask); - - /* Disable DTL frequency loop */ - mask = HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK; - data = 0x0 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, data, mask); - - /* Configure G3 DFE */ - mask = HPIPE_G3_DFE_RES_MASK; - data = 0x3 << HPIPE_G3_DFE_RES_OFFSET; - reg_set(hpipe_addr + HPIPE_G3_SETTING_4_REG, data, mask); - - /* Use TX/RX training result for DFE */ - mask = HPIPE_DFE_RES_FORCE_MASK; - data = 0x0 << HPIPE_DFE_RES_FORCE_OFFSET; - reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask); - - /* Configure initial and final coefficient value for receiver */ - mask = HPIPE_G3_SET_1_G3_RX_SELMUPI_MASK; - data = 0x1 << HPIPE_G3_SET_1_G3_RX_SELMUPI_OFFSET; - - mask |= HPIPE_G3_SET_1_G3_RX_SELMUPF_MASK; - data |= 0x1 << HPIPE_G3_SET_1_G3_RX_SELMUPF_OFFSET; - - mask |= HPIPE_G3_SET_1_G3_SAMPLER_INPAIRX2_EN_MASK; - data |= 0x0 << HPIPE_G3_SET_1_G3_SAMPLER_INPAIRX2_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_G3_SET_1_REG, data, mask); - - /* Trigger sampler enable pulse */ - mask = HPIPE_SMAPLER_MASK; - data = 0x1 << HPIPE_SMAPLER_OFFSET; - reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, data, mask); - udelay(5); - reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, 0, mask); - - /* FFE resistor tuning for different bandwidth */ - mask = HPIPE_G3_FFE_DEG_RES_LEVEL_MASK; - data = 0x1 << HPIPE_G3_FFE_DEG_RES_LEVEL_OFFSET; - - mask |= HPIPE_G3_FFE_LOAD_RES_LEVEL_MASK; - data |= 0x3 << HPIPE_G3_FFE_LOAD_RES_LEVEL_OFFSET; - reg_set(hpipe_addr + HPIPE_G3_SETTING_3_REG, data, mask); - - /* Pattern lock lost timeout disable */ - mask = HPIPE_PATTERN_LOCK_LOST_TIMEOUT_EN_MASK; - data = 0x0 << HPIPE_PATTERN_LOCK_LOST_TIMEOUT_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_FRAME_DETECT_CTRL_3_REG, data, mask); - - /* Configure DFE adaptations */ - mask = HPIPE_CDR_MAX_DFE_ADAPT_1_MASK; - data = 0x1 << HPIPE_CDR_MAX_DFE_ADAPT_1_OFFSET; - mask |= HPIPE_CDR_MAX_DFE_ADAPT_0_MASK; - data |= 0x0 << HPIPE_CDR_MAX_DFE_ADAPT_0_OFFSET; - mask |= HPIPE_CDR_RX_MAX_DFE_ADAPT_1_MASK; - data |= 0x0 << HPIPE_CDR_RX_MAX_DFE_ADAPT_1_OFFSET; - reg_set(hpipe_addr + HPIPE_CDR_CONTROL_REG, data, mask); - mask = HPIPE_DFE_TX_MAX_DFE_ADAPT_MASK; - data = 0x0 << HPIPE_DFE_TX_MAX_DFE_ADAPT_OFFSET; - reg_set(hpipe_addr + HPIPE_DFE_CONTROL_REG, data, mask); - - /* Genration 2 setting 1*/ - mask = HPIPE_G2_SET_1_G2_RX_SELMUPI_MASK; - data = 0x0 << HPIPE_G2_SET_1_G2_RX_SELMUPI_OFFSET; - mask |= HPIPE_G2_SET_1_G2_RX_SELMUPP_MASK; - data |= 0x1 << HPIPE_G2_SET_1_G2_RX_SELMUPP_OFFSET; - mask |= HPIPE_G2_SET_1_G2_RX_SELMUFI_MASK; - data |= 0x0 << HPIPE_G2_SET_1_G2_RX_SELMUFI_OFFSET; - reg_set(hpipe_addr + HPIPE_G2_SET_1_REG, data, mask); - - /* DFE enable */ - mask = HPIPE_G2_DFE_RES_MASK; - data = 0x3 << HPIPE_G2_DFE_RES_OFFSET; - reg_set(hpipe_addr + HPIPE_G2_SETTINGS_4_REG, data, mask); - - /* Configure DFE Resolution */ - mask = HPIPE_LANE_CFG4_DFE_EN_SEL_MASK; - data = 0x1 << HPIPE_LANE_CFG4_DFE_EN_SEL_OFFSET; - reg_set(hpipe_addr + HPIPE_LANE_CFG4_REG, data, mask); - - /* VDD calibration control */ - mask = HPIPE_EXT_SELLV_RXSAMPL_MASK; - data = 0x16 << HPIPE_EXT_SELLV_RXSAMPL_OFFSET; - reg_set(hpipe_addr + HPIPE_VDD_CAL_CTRL_REG, data, mask); - - /* Set PLL Charge-pump Current Control */ - mask = HPIPE_G3_SETTING_5_G3_ICP_MASK; - data = 0x4 << HPIPE_G3_SETTING_5_G3_ICP_OFFSET; - reg_set(hpipe_addr + HPIPE_G3_SETTING_5_REG, data, mask); - - /* Set lane rqualization remote setting */ - mask = HPIPE_LANE_CFG_FOM_DIRN_OVERRIDE_MASK; - data = 0x1 << HPIPE_LANE_CFG_FOM_DIRN_OVERRIDE_OFFSET; - mask |= HPIPE_LANE_CFG_FOM_ONLY_MODE_MASK; - data |= 0x1 << HPIPE_LANE_CFG_FOM_ONLY_MODE_OFFFSET; - mask |= HPIPE_LANE_CFG_FOM_PRESET_VECTOR_MASK; - data |= 0x2 << HPIPE_LANE_CFG_FOM_PRESET_VECTOR_OFFSET; - reg_set(hpipe_addr + HPIPE_LANE_EQ_REMOTE_SETTING_REG, data, mask); - - if (!is_end_point) { - /* Set phy in root complex mode */ - mask = HPIPE_CFG_PHY_RC_EP_MASK; - data = 0x1 << HPIPE_CFG_PHY_RC_EP_OFFSET; - reg_set(hpipe_addr + HPIPE_LANE_EQU_CONFIG_0_REG, data, mask); - } - - debug("stage: Comphy power up\n"); - - /* - * For PCIe by4 or by2 - release from reset only after finish to - * configure all lanes - */ - if ((pcie_width == 1) || (lane == (pcie_width - 1))) { - u32 i, start_lane, end_lane; - - if (pcie_width != 1) { - /* allows writing to all lanes in one write */ - reg_set(comphy_base + COMMON_PHY_SD_CTRL1, - 0x0 << - COMMON_PHY_SD_CTRL1_COMPHY_0_4_PORT_OFFSET, - COMMON_PHY_SD_CTRL1_COMPHY_0_4_PORT_MASK); - start_lane = 0; - end_lane = pcie_width; - - /* - * Release from PIPE soft reset - * for PCIe by4 or by2 - release from soft reset - * all lanes - can't use read modify write - */ - reg_set(HPIPE_ADDR(hpipe_base, 0) + - HPIPE_RST_CLK_CTRL_REG, 0x24, 0xffffffff); - } else { - start_lane = lane; - end_lane = lane + 1; - - /* - * Release from PIPE soft reset - * for PCIe by4 or by2 - release from soft reset - * all lanes - */ - reg_set(hpipe_addr + HPIPE_RST_CLK_CTRL_REG, - 0x0 << HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET, - HPIPE_RST_CLK_CTRL_PIPE_RST_MASK); - } - - - if (pcie_width != 1) { - /* disable writing to all lanes with one write */ - reg_set(comphy_base + COMMON_PHY_SD_CTRL1, - 0x3210 << - COMMON_PHY_SD_CTRL1_COMPHY_0_4_PORT_OFFSET, - COMMON_PHY_SD_CTRL1_COMPHY_0_4_PORT_MASK); - } - - debug("stage: Check PLL\n"); - /* Read lane status */ - for (i = start_lane; i < end_lane; i++) { - addr = HPIPE_ADDR(hpipe_base, i) + - HPIPE_LANE_STATUS1_REG; - data = HPIPE_LANE_STATUS1_PCLK_EN_MASK; - mask = data; - data = polling_with_timeout(addr, data, mask, 15000); - if (data != 0) { - debug("Read from reg = %p - value = 0x%x\n", - hpipe_addr + HPIPE_LANE_STATUS1_REG, - data); - pr_err("HPIPE_LANE_STATUS1_PCLK_EN_MASK is 0\n"); - ret = 0; - } - } - } - - debug_exit(); - return ret; -} - static int comphy_usb3_power_up(u32 lane, void __iomem *hpipe_base, void __iomem *comphy_base) { @@ -642,15 +242,31 @@ static int comphy_usb3_power_up(u32 lane, void __iomem *hpipe_base, return ret; } +static int comphy_smc(u32 function_id, void __iomem *comphy_base_addr, + u32 lane, u32 mode) +{ + struct pt_regs pregs = {0}; + + pregs.regs[0] = function_id; + pregs.regs[1] = (unsigned long)comphy_base_addr; + pregs.regs[2] = lane; + pregs.regs[3] = mode; + + smc_call(&pregs); + + /* + * TODO: Firmware return 0 on success, temporary map it to u-boot + * convention, but after all comphy will be reworked the convention in + * u-boot should be change and this conversion removed + */ + return pregs.regs[0] ? 0 : 1; +} + static int comphy_sata_power_up(u32 lane, void __iomem *hpipe_base, - void __iomem *comphy_base, int cp_index, - u32 invert) + void __iomem *comphy_base_addr, int cp_index, + u32 type) { u32 mask, data, i, ret = 1; - void __iomem *hpipe_addr = HPIPE_ADDR(hpipe_base, lane); - void __iomem *sd_ip_addr = SD_ADDR(hpipe_base, lane); - void __iomem *comphy_addr = COMPHY_ADDR(comphy_base, lane); - void __iomem *addr; void __iomem *sata_base = NULL; int sata_node = -1; /* Set to -1 in order to read the first sata node */ @@ -703,255 +319,8 @@ static int comphy_sata_power_up(u32 lane, void __iomem *hpipe_base, data |= 0x0 << SATA3_CTRL_SATA_SSU_OFFSET; reg_set(sata_base + SATA3_VENDOR_DATA, data, mask); - debug("stage: RFU configurations - hard reset comphy\n"); - /* RFU configurations - hard reset comphy */ - mask = COMMON_PHY_CFG1_PWR_UP_MASK; - data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET; - mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK; - data |= 0x0 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET; - mask |= COMMON_PHY_CFG1_PWR_ON_RESET_MASK; - data |= 0x0 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET; - mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK; - data |= 0x0 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET; - reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); - - /* Set select data width 40Bit - SATA mode only */ - reg_set(comphy_addr + COMMON_PHY_CFG6_REG, - 0x1 << COMMON_PHY_CFG6_IF_40_SEL_OFFSET, - COMMON_PHY_CFG6_IF_40_SEL_MASK); - - /* release from hard reset in SD external */ - mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; - data = 0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; - mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; - data |= 0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); - - /* Wait 1ms - until band gap and ref clock ready */ - mdelay(1); + ret = comphy_smc(MV_SIP_COMPHY_POWER_ON, comphy_base_addr, lane, type); - debug("stage: Comphy configuration\n"); - /* Start comphy Configuration */ - /* Set reference clock to comes from group 1 - choose 25Mhz */ - reg_set(hpipe_addr + HPIPE_MISC_REG, - 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET, - HPIPE_MISC_REFCLK_SEL_MASK); - /* Reference frequency select set 1 (for SATA = 25Mhz) */ - mask = HPIPE_PWR_PLL_REF_FREQ_MASK; - data = 0x1 << HPIPE_PWR_PLL_REF_FREQ_OFFSET; - /* PHY mode select (set SATA = 0x0 */ - mask |= HPIPE_PWR_PLL_PHY_MODE_MASK; - data |= 0x0 << HPIPE_PWR_PLL_PHY_MODE_OFFSET; - reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask); - /* Set max PHY generation setting - 6Gbps */ - reg_set(hpipe_addr + HPIPE_INTERFACE_REG, - 0x2 << HPIPE_INTERFACE_GEN_MAX_OFFSET, - HPIPE_INTERFACE_GEN_MAX_MASK); - /* Set select data width 40Bit (SEL_BITS[2:0]) */ - reg_set(hpipe_addr + HPIPE_LOOPBACK_REG, - 0x2 << HPIPE_LOOPBACK_SEL_OFFSET, HPIPE_LOOPBACK_SEL_MASK); - - debug("stage: Analog paramters from ETP(HW)\n"); - /* Set analog parameters from ETP(HW) */ - /* G1 settings */ - mask = HPIPE_G1_SET_1_G1_RX_SELMUPI_MASK; - data = 0x0 << HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET; - mask |= HPIPE_G1_SET_1_G1_RX_SELMUPP_MASK; - data |= 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUPP_OFFSET; - mask |= HPIPE_G1_SET_1_G1_RX_SELMUFI_MASK; - data |= 0x0 << HPIPE_G1_SET_1_G1_RX_SELMUFI_OFFSET; - mask |= HPIPE_G1_SET_1_G1_RX_SELMUFF_MASK; - data |= 0x3 << HPIPE_G1_SET_1_G1_RX_SELMUFF_OFFSET; - mask |= HPIPE_G1_SET_1_G1_RX_DIGCK_DIV_MASK; - data |= 0x1 << HPIPE_G1_SET_1_G1_RX_DIGCK_DIV_OFFSET; - reg_set(hpipe_addr + HPIPE_G1_SET_1_REG, data, mask); - - mask = HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_MASK; - data = 0xf << HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_OFFSET; - mask |= HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_MASK; - data |= 0x2 << HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_OFFSET; - mask |= HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_MASK; - data |= 0x1 << HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_OFFSET; - mask |= HPIPE_G1_SETTINGS_3_G1_FFE_DEG_RES_LEVEL_MASK; - data |= 0x1 << HPIPE_G1_SETTINGS_3_G1_FFE_DEG_RES_LEVEL_OFFSET; - mask |= HPIPE_G1_SETTINGS_3_G1_FFE_LOAD_RES_LEVEL_MASK; - data |= 0x1 << HPIPE_G1_SETTINGS_3_G1_FFE_LOAD_RES_LEVEL_OFFSET; - reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask); - - /* G2 settings */ - mask = HPIPE_G2_SET_1_G2_RX_SELMUPI_MASK; - data = 0x0 << HPIPE_G2_SET_1_G2_RX_SELMUPI_OFFSET; - mask |= HPIPE_G2_SET_1_G2_RX_SELMUPP_MASK; - data |= 0x1 << HPIPE_G2_SET_1_G2_RX_SELMUPP_OFFSET; - mask |= HPIPE_G2_SET_1_G2_RX_SELMUFI_MASK; - data |= 0x0 << HPIPE_G2_SET_1_G2_RX_SELMUFI_OFFSET; - mask |= HPIPE_G2_SET_1_G2_RX_SELMUFF_MASK; - data |= 0x3 << HPIPE_G2_SET_1_G2_RX_SELMUFF_OFFSET; - mask |= HPIPE_G2_SET_1_G2_RX_DIGCK_DIV_MASK; - data |= 0x1 << HPIPE_G2_SET_1_G2_RX_DIGCK_DIV_OFFSET; - reg_set(hpipe_addr + HPIPE_G2_SET_1_REG, data, mask); - - /* G3 settings */ - mask = HPIPE_G3_SET_1_G3_RX_SELMUPI_MASK; - data = 0x2 << HPIPE_G3_SET_1_G3_RX_SELMUPI_OFFSET; - mask |= HPIPE_G3_SET_1_G3_RX_SELMUPF_MASK; - data |= 0x2 << HPIPE_G3_SET_1_G3_RX_SELMUPF_OFFSET; - mask |= HPIPE_G3_SET_1_G3_RX_SELMUFI_MASK; - data |= 0x3 << HPIPE_G3_SET_1_G3_RX_SELMUFI_OFFSET; - mask |= HPIPE_G3_SET_1_G3_RX_SELMUFF_MASK; - data |= 0x3 << HPIPE_G3_SET_1_G3_RX_SELMUFF_OFFSET; - mask |= HPIPE_G3_SET_1_G3_RX_DFE_EN_MASK; - data |= 0x1 << HPIPE_G3_SET_1_G3_RX_DFE_EN_OFFSET; - mask |= HPIPE_G3_SET_1_G3_RX_DIGCK_DIV_MASK; - data |= 0x2 << HPIPE_G3_SET_1_G3_RX_DIGCK_DIV_OFFSET; - mask |= HPIPE_G3_SET_1_G3_SAMPLER_INPAIRX2_EN_MASK; - data |= 0x0 << HPIPE_G3_SET_1_G3_SAMPLER_INPAIRX2_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_G3_SET_1_REG, data, mask); - - /* DTL Control */ - mask = HPIPE_PWR_CTR_DTL_SQ_DET_EN_MASK; - data = 0x1 << HPIPE_PWR_CTR_DTL_SQ_DET_EN_OFFSET; - mask |= HPIPE_PWR_CTR_DTL_SQ_PLOOP_EN_MASK; - data |= 0x1 << HPIPE_PWR_CTR_DTL_SQ_PLOOP_EN_OFFSET; - mask |= HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK; - data |= 0x1 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET; - mask |= HPIPE_PWR_CTR_DTL_CLAMPING_SEL_MASK; - data |= 0x1 << HPIPE_PWR_CTR_DTL_CLAMPING_SEL_OFFSET; - mask |= HPIPE_PWR_CTR_DTL_INTPCLK_DIV_FORCE_MASK; - data |= 0x1 << HPIPE_PWR_CTR_DTL_INTPCLK_DIV_FORCE_OFFSET; - mask |= HPIPE_PWR_CTR_DTL_CLK_MODE_MASK; - data |= 0x1 << HPIPE_PWR_CTR_DTL_CLK_MODE_OFFSET; - mask |= HPIPE_PWR_CTR_DTL_CLK_MODE_FORCE_MASK; - data |= 0x1 << HPIPE_PWR_CTR_DTL_CLK_MODE_FORCE_OFFSET; - reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, data, mask); - - /* Trigger sampler enable pulse (by toggleing the bit) */ - mask = HPIPE_SMAPLER_MASK; - data = 0x1 << HPIPE_SMAPLER_OFFSET; - reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, data, mask); - mask = HPIPE_SMAPLER_MASK; - data = 0x0 << HPIPE_SMAPLER_OFFSET; - reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, data, mask); - - /* VDD Calibration Control 3 */ - mask = HPIPE_EXT_SELLV_RXSAMPL_MASK; - data = 0x10 << HPIPE_EXT_SELLV_RXSAMPL_OFFSET; - reg_set(hpipe_addr + HPIPE_VDD_CAL_CTRL_REG, data, mask); - - /* DFE Resolution Control */ - mask = HPIPE_DFE_RES_FORCE_MASK; - data = 0x1 << HPIPE_DFE_RES_FORCE_OFFSET; - reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask); - - /* DFE F3-F5 Coefficient Control */ - mask = HPIPE_DFE_F3_F5_DFE_EN_MASK; - data = 0x0 << HPIPE_DFE_F3_F5_DFE_EN_OFFSET; - mask |= HPIPE_DFE_F3_F5_DFE_CTRL_MASK; - data = 0x0 << HPIPE_DFE_F3_F5_DFE_CTRL_OFFSET; - reg_set(hpipe_addr + HPIPE_DFE_F3_F5_REG, data, mask); - - /* G3 Setting 3 */ - mask = HPIPE_G3_FFE_CAP_SEL_MASK; - data = 0xf << HPIPE_G3_FFE_CAP_SEL_OFFSET; - mask |= HPIPE_G3_FFE_RES_SEL_MASK; - data |= 0x4 << HPIPE_G3_FFE_RES_SEL_OFFSET; - mask |= HPIPE_G3_FFE_SETTING_FORCE_MASK; - data |= 0x1 << HPIPE_G3_FFE_SETTING_FORCE_OFFSET; - mask |= HPIPE_G3_FFE_DEG_RES_LEVEL_MASK; - data |= 0x1 << HPIPE_G3_FFE_DEG_RES_LEVEL_OFFSET; - mask |= HPIPE_G3_FFE_LOAD_RES_LEVEL_MASK; - data |= 0x3 << HPIPE_G3_FFE_LOAD_RES_LEVEL_OFFSET; - reg_set(hpipe_addr + HPIPE_G3_SETTING_3_REG, data, mask); - - /* G3 Setting 4 */ - mask = HPIPE_G3_DFE_RES_MASK; - data = 0x2 << HPIPE_G3_DFE_RES_OFFSET; - reg_set(hpipe_addr + HPIPE_G3_SETTING_4_REG, data, mask); - - /* Offset Phase Control */ - mask = HPIPE_OS_PH_OFFSET_MASK; - data = 0x5c << HPIPE_OS_PH_OFFSET_OFFSET; - mask |= HPIPE_OS_PH_OFFSET_FORCE_MASK; - data |= 0x1 << HPIPE_OS_PH_OFFSET_FORCE_OFFSET; - reg_set(hpipe_addr + HPIPE_PHASE_CONTROL_REG, data, mask); - mask = HPIPE_OS_PH_VALID_MASK; - data = 0x1 << HPIPE_OS_PH_VALID_OFFSET; - reg_set(hpipe_addr + HPIPE_PHASE_CONTROL_REG, data, mask); - mask = HPIPE_OS_PH_VALID_MASK; - data = 0x0 << HPIPE_OS_PH_VALID_OFFSET; - reg_set(hpipe_addr + HPIPE_PHASE_CONTROL_REG, data, mask); - - /* Set G1 TX amplitude and TX post emphasis value */ - mask = HPIPE_G1_SET_0_G1_TX_AMP_MASK; - data = 0x8 << HPIPE_G1_SET_0_G1_TX_AMP_OFFSET; - mask |= HPIPE_G1_SET_0_G1_TX_AMP_ADJ_MASK; - data |= 0x1 << HPIPE_G1_SET_0_G1_TX_AMP_ADJ_OFFSET; - mask |= HPIPE_G1_SET_0_G1_TX_EMPH1_MASK; - data |= 0x1 << HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET; - mask |= HPIPE_G1_SET_0_G1_TX_EMPH1_EN_MASK; - data |= 0x1 << HPIPE_G1_SET_0_G1_TX_EMPH1_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_G1_SET_0_REG, data, mask); - - /* Set G2 TX amplitude and TX post emphasis value */ - mask = HPIPE_G2_SET_0_G2_TX_AMP_MASK; - data = 0xa << HPIPE_G2_SET_0_G2_TX_AMP_OFFSET; - mask |= HPIPE_G2_SET_0_G2_TX_AMP_ADJ_MASK; - data |= 0x1 << HPIPE_G2_SET_0_G2_TX_AMP_ADJ_OFFSET; - mask |= HPIPE_G2_SET_0_G2_TX_EMPH1_MASK; - data |= 0x2 << HPIPE_G2_SET_0_G2_TX_EMPH1_OFFSET; - mask |= HPIPE_G2_SET_0_G2_TX_EMPH1_EN_MASK; - data |= 0x1 << HPIPE_G2_SET_0_G2_TX_EMPH1_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_G2_SET_0_REG, data, mask); - - /* Set G3 TX amplitude and TX post emphasis value */ - mask = HPIPE_G3_SET_0_G3_TX_AMP_MASK; - data = 0xe << HPIPE_G3_SET_0_G3_TX_AMP_OFFSET; - mask |= HPIPE_G3_SET_0_G3_TX_AMP_ADJ_MASK; - data |= 0x1 << HPIPE_G3_SET_0_G3_TX_AMP_ADJ_OFFSET; - mask |= HPIPE_G3_SET_0_G3_TX_EMPH1_MASK; - data |= 0x6 << HPIPE_G3_SET_0_G3_TX_EMPH1_OFFSET; - mask |= HPIPE_G3_SET_0_G3_TX_EMPH1_EN_MASK; - data |= 0x1 << HPIPE_G3_SET_0_G3_TX_EMPH1_EN_OFFSET; - mask |= HPIPE_G3_SET_0_G3_TX_SLEW_RATE_SEL_MASK; - data |= 0x4 << HPIPE_G3_SET_0_G3_TX_SLEW_RATE_SEL_OFFSET; - mask |= HPIPE_G3_SET_0_G3_TX_SLEW_CTRL_EN_MASK; - data |= 0x0 << HPIPE_G3_SET_0_G3_TX_SLEW_CTRL_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_G3_SET_0_REG, data, mask); - - /* SERDES External Configuration 2 register */ - mask = SD_EXTERNAL_CONFIG2_SSC_ENABLE_MASK; - data = 0x1 << SD_EXTERNAL_CONFIG2_SSC_ENABLE_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG2_REG, data, mask); - - /* DFE reset sequence */ - reg_set(hpipe_addr + HPIPE_PWR_CTR_REG, - 0x1 << HPIPE_PWR_CTR_RST_DFE_OFFSET, - HPIPE_PWR_CTR_RST_DFE_MASK); - reg_set(hpipe_addr + HPIPE_PWR_CTR_REG, - 0x0 << HPIPE_PWR_CTR_RST_DFE_OFFSET, - HPIPE_PWR_CTR_RST_DFE_MASK); - - /* Set RX / TX swaps */ - data = mask = 0; - if (invert & PHY_POLARITY_TXD_INVERT) { - data |= (1 << HPIPE_SYNC_PATTERN_TXD_SWAP_OFFSET); - mask |= HPIPE_SYNC_PATTERN_TXD_SWAP_MASK; - } - if (invert & PHY_POLARITY_RXD_INVERT) { - data |= (1 << HPIPE_SYNC_PATTERN_RXD_SWAP_OFFSET); - mask |= HPIPE_SYNC_PATTERN_RXD_SWAP_MASK; - } - reg_set(hpipe_addr + HPIPE_SYNC_PATTERN_REG, data, mask); - - /* SW reset for interupt logic */ - reg_set(hpipe_addr + HPIPE_PWR_CTR_REG, - 0x1 << HPIPE_PWR_CTR_SFT_RST_OFFSET, - HPIPE_PWR_CTR_SFT_RST_MASK); - reg_set(hpipe_addr + HPIPE_PWR_CTR_REG, - 0x0 << HPIPE_PWR_CTR_SFT_RST_OFFSET, - HPIPE_PWR_CTR_SFT_RST_MASK); - - debug("stage: Comphy power up\n"); /* * MAC configuration power up comphy - power up PLL/TX/RX * use indirect address for vendor spesific SATA control register @@ -981,469 +350,7 @@ static int comphy_sata_power_up(u32 lane, void __iomem *hpipe_base, reg_set(sata_base + SATA3_VENDOR_DATA, 0x1 << SATA_MBUS_REGRET_EN_OFFSET, SATA_MBUS_REGRET_EN_MASK); - debug("stage: Check PLL\n"); - - addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG; - data = SD_EXTERNAL_STATUS0_PLL_TX_MASK & - SD_EXTERNAL_STATUS0_PLL_RX_MASK; - mask = data; - data = polling_with_timeout(addr, data, mask, 15000); - if (data != 0) { - debug("Read from reg = %p - value = 0x%x\n", - hpipe_addr + HPIPE_LANE_STATUS1_REG, data); - pr_err("SD_EXTERNAL_STATUS0_PLL_TX is %d, SD_EXTERNAL_STATUS0_PLL_RX is %d\n", - (data & SD_EXTERNAL_STATUS0_PLL_TX_MASK), - (data & SD_EXTERNAL_STATUS0_PLL_RX_MASK)); - ret = 0; - } - - debug_exit(); - return ret; -} - -static int comphy_sgmii_power_up(u32 lane, u32 sgmii_speed, - void __iomem *hpipe_base, - void __iomem *comphy_base) -{ - u32 mask, data, ret = 1; - void __iomem *hpipe_addr = HPIPE_ADDR(hpipe_base, lane); - void __iomem *sd_ip_addr = SD_ADDR(hpipe_base, lane); - void __iomem *comphy_addr = COMPHY_ADDR(comphy_base, lane); - void __iomem *addr; - - debug_enter(); - debug("stage: RFU configurations - hard reset comphy\n"); - /* RFU configurations - hard reset comphy */ - mask = COMMON_PHY_CFG1_PWR_UP_MASK; - data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET; - mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK; - data |= 0x0 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET; - reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); - - /* Select Baud Rate of Comphy And PD_PLL/Tx/Rx */ - mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK; - data = 0x0 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET; - mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_MASK; - mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_MASK; - if (sgmii_speed == PHY_SPEED_1_25G) { - data |= 0x6 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET; - data |= 0x6 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET; - } else { - /* 3.125G */ - data |= 0x8 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET; - data |= 0x8 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET; - } - mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK; - data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET; - mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK; - data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET; - mask |= SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_MASK; - data |= 1 << SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask); - - /* release from hard reset */ - mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; - data = 0x0 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; - mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; - data |= 0x0 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; - mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK; - data |= 0x0 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); - - /* release from hard reset */ - mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; - data = 0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; - mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; - data |= 0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); - - - /* Wait 1ms - until band gap and ref clock ready */ - mdelay(1); - - /* Start comphy Configuration */ - debug("stage: Comphy configuration\n"); - /* set reference clock */ - mask = HPIPE_MISC_REFCLK_SEL_MASK; - data = 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET; - reg_set(hpipe_addr + HPIPE_MISC_REG, data, mask); - /* Power and PLL Control */ - mask = HPIPE_PWR_PLL_REF_FREQ_MASK; - data = 0x1 << HPIPE_PWR_PLL_REF_FREQ_OFFSET; - mask |= HPIPE_PWR_PLL_PHY_MODE_MASK; - data |= 0x4 << HPIPE_PWR_PLL_PHY_MODE_OFFSET; - reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask); - /* Loopback register */ - mask = HPIPE_LOOPBACK_SEL_MASK; - data = 0x1 << HPIPE_LOOPBACK_SEL_OFFSET; - reg_set(hpipe_addr + HPIPE_LOOPBACK_REG, data, mask); - /* rx control 1 */ - mask = HPIPE_RX_CONTROL_1_RXCLK2X_SEL_MASK; - data = 0x1 << HPIPE_RX_CONTROL_1_RXCLK2X_SEL_OFFSET; - mask |= HPIPE_RX_CONTROL_1_CLK8T_EN_MASK; - data |= 0x0 << HPIPE_RX_CONTROL_1_CLK8T_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_RX_CONTROL_1_REG, data, mask); - /* DTL Control */ - mask = HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK; - data = 0x0 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, data, mask); - - /* Set analog paramters from ETP(HW) - for now use the default datas */ - debug("stage: Analog paramters from ETP(HW)\n"); - - reg_set(hpipe_addr + HPIPE_G1_SET_0_REG, - 0x1 << HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET, - HPIPE_G1_SET_0_G1_TX_EMPH1_MASK); - - debug("stage: RFU configurations- Power Up PLL,Tx,Rx\n"); - /* SERDES External Configuration */ - mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK; - data = 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET; - mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK; - data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET; - mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK; - data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask); - - /* check PLL rx & tx ready */ - addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG; - data = SD_EXTERNAL_STATUS0_PLL_RX_MASK | - SD_EXTERNAL_STATUS0_PLL_TX_MASK; - mask = data; - data = polling_with_timeout(addr, data, mask, 15000); - if (data != 0) { - debug("Read from reg = %p - value = 0x%x\n", - sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data); - pr_err("SD_EXTERNAL_STATUS0_PLL_RX is %d, SD_EXTERNAL_STATUS0_PLL_TX is %d\n", - (data & SD_EXTERNAL_STATUS0_PLL_RX_MASK), - (data & SD_EXTERNAL_STATUS0_PLL_TX_MASK)); - ret = 0; - } - - /* RX init */ - mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK; - data = 0x1 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); - - /* check that RX init done */ - addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG; - data = SD_EXTERNAL_STATUS0_RX_INIT_MASK; - mask = data; - data = polling_with_timeout(addr, data, mask, 100); - if (data != 0) { - debug("Read from reg = %p - value = 0x%x\n", sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data); - pr_err("SD_EXTERNAL_STATUS0_RX_INIT is 0\n"); - ret = 0; - } - - debug("stage: RF Reset\n"); - /* RF Reset */ - mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK; - data = 0x0 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET; - mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK; - data |= 0x1 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); - - debug_exit(); - return ret; -} - -static int comphy_sfi_power_up(u32 lane, void __iomem *hpipe_base, - void __iomem *comphy_base, u32 speed) -{ - u32 mask, data, ret = 1; - void __iomem *hpipe_addr = HPIPE_ADDR(hpipe_base, lane); - void __iomem *sd_ip_addr = SD_ADDR(hpipe_base, lane); - void __iomem *comphy_addr = COMPHY_ADDR(comphy_base, lane); - void __iomem *addr; - - debug_enter(); - debug("stage: RFU configurations - hard reset comphy\n"); - /* RFU configurations - hard reset comphy */ - mask = COMMON_PHY_CFG1_PWR_UP_MASK; - data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET; - mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK; - data |= 0x0 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET; - reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); - - /* Select Baud Rate of Comphy And PD_PLL/Tx/Rx */ - mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK; - data = 0x0 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET; - mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_MASK; - data |= 0xE << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET; - mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_MASK; - data |= 0xE << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET; - mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK; - data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET; - mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK; - data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET; - mask |= SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_MASK; - data |= 0 << SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask); - - /* release from hard reset */ - mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; - data = 0x0 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; - mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; - data |= 0x0 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; - mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK; - data |= 0x0 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); - - mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; - data = 0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; - mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; - data |= 0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); - - - /* Wait 1ms - until band gap and ref clock ready */ - mdelay(1); - - /* Start comphy Configuration */ - debug("stage: Comphy configuration\n"); - /* set reference clock */ - mask = HPIPE_MISC_ICP_FORCE_MASK; - data = (speed == PHY_SPEED_5_15625G) ? - (0x0 << HPIPE_MISC_ICP_FORCE_OFFSET) : - (0x1 << HPIPE_MISC_ICP_FORCE_OFFSET); - mask |= HPIPE_MISC_REFCLK_SEL_MASK; - data |= 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET; - reg_set(hpipe_addr + HPIPE_MISC_REG, data, mask); - /* Power and PLL Control */ - mask = HPIPE_PWR_PLL_REF_FREQ_MASK; - data = 0x1 << HPIPE_PWR_PLL_REF_FREQ_OFFSET; - mask |= HPIPE_PWR_PLL_PHY_MODE_MASK; - data |= 0x4 << HPIPE_PWR_PLL_PHY_MODE_OFFSET; - reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask); - /* Loopback register */ - mask = HPIPE_LOOPBACK_SEL_MASK; - data = 0x1 << HPIPE_LOOPBACK_SEL_OFFSET; - reg_set(hpipe_addr + HPIPE_LOOPBACK_REG, data, mask); - /* rx control 1 */ - mask = HPIPE_RX_CONTROL_1_RXCLK2X_SEL_MASK; - data = 0x1 << HPIPE_RX_CONTROL_1_RXCLK2X_SEL_OFFSET; - mask |= HPIPE_RX_CONTROL_1_CLK8T_EN_MASK; - data |= 0x1 << HPIPE_RX_CONTROL_1_CLK8T_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_RX_CONTROL_1_REG, data, mask); - /* DTL Control */ - mask = HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK; - data = 0x1 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, data, mask); - - /* Transmitter/Receiver Speed Divider Force */ - if (speed == PHY_SPEED_5_15625G) { - mask = HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_MASK; - data = 1 << HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_OFFSET; - mask |= HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_FORCE_MASK; - data |= 1 << HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_FORCE_OFFSET; - mask |= HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_MASK; - data |= 1 << HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_OFFSET; - mask |= HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_FORCE_MASK; - data |= 1 << HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_FORCE_OFFSET; - } else { - mask = HPIPE_TXDIGCK_DIV_FORCE_MASK; - data = 0x1 << HPIPE_TXDIGCK_DIV_FORCE_OFFSET; - } - reg_set(hpipe_addr + HPIPE_SPD_DIV_FORCE_REG, data, mask); - - /* Set analog paramters from ETP(HW) */ - debug("stage: Analog paramters from ETP(HW)\n"); - /* SERDES External Configuration 2 */ - mask = SD_EXTERNAL_CONFIG2_PIN_DFE_EN_MASK; - data = 0x1 << SD_EXTERNAL_CONFIG2_PIN_DFE_EN_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG2_REG, data, mask); - /* 0x7-DFE Resolution control */ - mask = HPIPE_DFE_RES_FORCE_MASK; - data = 0x1 << HPIPE_DFE_RES_FORCE_OFFSET; - reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask); - /* 0xd-G1_Setting_0 */ - if (speed == PHY_SPEED_5_15625G) { - mask = HPIPE_G1_SET_0_G1_TX_EMPH1_MASK; - data = 0x6 << HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET; - } else { - mask = HPIPE_G1_SET_0_G1_TX_AMP_MASK; - data = 0x1c << HPIPE_G1_SET_0_G1_TX_AMP_OFFSET; - mask |= HPIPE_G1_SET_0_G1_TX_EMPH1_MASK; - data |= 0xe << HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET; - } - reg_set(hpipe_addr + HPIPE_G1_SET_0_REG, data, mask); - /* Genration 1 setting 2 (G1_Setting_2) */ - mask = HPIPE_G1_SET_2_G1_TX_EMPH0_MASK; - data = 0x0 << HPIPE_G1_SET_2_G1_TX_EMPH0_OFFSET; - mask |= HPIPE_G1_SET_2_G1_TX_EMPH0_EN_MASK; - data |= 0x1 << HPIPE_G1_SET_2_G1_TX_EMPH0_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_G1_SET_2_REG, data, mask); - /* Transmitter Slew Rate Control register (tx_reg1) */ - mask = HPIPE_TX_REG1_TX_EMPH_RES_MASK; - data = 0x3 << HPIPE_TX_REG1_TX_EMPH_RES_OFFSET; - mask |= HPIPE_TX_REG1_SLC_EN_MASK; - data |= 0x3f << HPIPE_TX_REG1_SLC_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_TX_REG1_REG, data, mask); - /* Impedance Calibration Control register (cal_reg1) */ - mask = HPIPE_CAL_REG_1_EXT_TXIMP_MASK; - data = 0xe << HPIPE_CAL_REG_1_EXT_TXIMP_OFFSET; - mask |= HPIPE_CAL_REG_1_EXT_TXIMP_EN_MASK; - data |= 0x1 << HPIPE_CAL_REG_1_EXT_TXIMP_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_CAL_REG1_REG, data, mask); - /* Generation 1 Setting 5 (g1_setting_5) */ - mask = HPIPE_G1_SETTING_5_G1_ICP_MASK; - data = 0 << HPIPE_CAL_REG_1_EXT_TXIMP_OFFSET; - reg_set(hpipe_addr + HPIPE_G1_SETTING_5_REG, data, mask); - /* 0xE-G1_Setting_1 */ - mask = HPIPE_G1_SET_1_G1_RX_DFE_EN_MASK; - data = 0x1 << HPIPE_G1_SET_1_G1_RX_DFE_EN_OFFSET; - if (speed == PHY_SPEED_5_15625G) { - mask |= HPIPE_G1_SET_1_G1_RX_SELMUPI_MASK; - data |= 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET; - mask |= HPIPE_G1_SET_1_G1_RX_SELMUPP_MASK; - data |= 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUPP_OFFSET; - } else { - mask |= HPIPE_G1_SET_1_G1_RX_SELMUPI_MASK; - data |= 0x2 << HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET; - mask |= HPIPE_G1_SET_1_G1_RX_SELMUPP_MASK; - data |= 0x2 << HPIPE_G1_SET_1_G1_RX_SELMUPP_OFFSET; - mask |= HPIPE_G1_SET_1_G1_RX_SELMUFI_MASK; - data |= 0x0 << HPIPE_G1_SET_1_G1_RX_SELMUFI_OFFSET; - mask |= HPIPE_G1_SET_1_G1_RX_SELMUFF_MASK; - data |= 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUFF_OFFSET; - mask |= HPIPE_G1_SET_1_G1_RX_DIGCK_DIV_MASK; - data |= 0x3 << HPIPE_G1_SET_1_G1_RX_DIGCK_DIV_OFFSET; - } - reg_set(hpipe_addr + HPIPE_G1_SET_1_REG, data, mask); - - /* 0xA-DFE_Reg3 */ - mask = HPIPE_DFE_F3_F5_DFE_EN_MASK; - data = 0x0 << HPIPE_DFE_F3_F5_DFE_EN_OFFSET; - mask |= HPIPE_DFE_F3_F5_DFE_CTRL_MASK; - data |= 0x0 << HPIPE_DFE_F3_F5_DFE_CTRL_OFFSET; - reg_set(hpipe_addr + HPIPE_DFE_F3_F5_REG, data, mask); - - /* 0x111-G1_Setting_4 */ - mask = HPIPE_G1_SETTINGS_4_G1_DFE_RES_MASK; - data = 0x1 << HPIPE_G1_SETTINGS_4_G1_DFE_RES_OFFSET; - reg_set(hpipe_addr + HPIPE_G1_SETTINGS_4_REG, data, mask); - /* Genration 1 setting 3 (G1_Setting_3) */ - mask = HPIPE_G1_SETTINGS_3_G1_FBCK_SEL_MASK; - data = 0x1 << HPIPE_G1_SETTINGS_3_G1_FBCK_SEL_OFFSET; - if (speed == PHY_SPEED_5_15625G) { - /* Force FFE (Feed Forward Equalization) to 5G */ - mask |= HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_MASK; - data |= 0xf << HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_OFFSET; - mask |= HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_MASK; - data |= 0x4 << HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_OFFSET; - mask |= HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_MASK; - data |= 0x1 << HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_OFFSET; - } - reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask); - - /* Connfigure RX training timer */ - mask = HPIPE_RX_TRAIN_TIMER_MASK; - data = 0x13 << HPIPE_RX_TRAIN_TIMER_OFFSET; - reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_5_REG, data, mask); - - /* Enable TX train peak to peak hold */ - mask = HPIPE_TX_TRAIN_P2P_HOLD_MASK; - data = 0x1 << HPIPE_TX_TRAIN_P2P_HOLD_OFFSET; - reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_0_REG, data, mask); - - /* Configure TX preset index */ - mask = HPIPE_TX_PRESET_INDEX_MASK; - data = 0x2 << HPIPE_TX_PRESET_INDEX_OFFSET; - reg_set(hpipe_addr + HPIPE_TX_PRESET_INDEX_REG, data, mask); - - /* Disable pattern lock lost timeout */ - mask = HPIPE_PATTERN_LOCK_LOST_TIMEOUT_EN_MASK; - data = 0x0 << HPIPE_PATTERN_LOCK_LOST_TIMEOUT_EN_OFFSET; - reg_set(hpipe_addr + HPIPE_FRAME_DETECT_CTRL_3_REG, data, mask); - - /* Configure TX training pattern and TX training 16bit auto */ - mask = HPIPE_TX_TRAIN_16BIT_AUTO_EN_MASK; - data = 0x1 << HPIPE_TX_TRAIN_16BIT_AUTO_EN_OFFSET; - mask |= HPIPE_TX_TRAIN_PAT_SEL_MASK; - data |= 0x1 << HPIPE_TX_TRAIN_PAT_SEL_OFFSET; - reg_set(hpipe_addr + HPIPE_TX_TRAIN_REG, data, mask); - - /* Configure Training patten number */ - mask = HPIPE_TRAIN_PAT_NUM_MASK; - data = 0x88 << HPIPE_TRAIN_PAT_NUM_OFFSET; - reg_set(hpipe_addr + HPIPE_FRAME_DETECT_CTRL_0_REG, data, mask); - - /* Configure differencial manchester encoter to ethernet mode */ - mask = HPIPE_DME_ETHERNET_MODE_MASK; - data = 0x1 << HPIPE_DME_ETHERNET_MODE_OFFSET; - reg_set(hpipe_addr + HPIPE_DME_REG, data, mask); - - /* Configure VDD Continuous Calibration */ - mask = HPIPE_CAL_VDD_CONT_MODE_MASK; - data = 0x1 << HPIPE_CAL_VDD_CONT_MODE_OFFSET; - reg_set(hpipe_addr + HPIPE_VDD_CAL_0_REG, data, mask); - - /* Trigger sampler enable pulse (by toggleing the bit) */ - mask = HPIPE_RX_SAMPLER_OS_GAIN_MASK; - data = 0x3 << HPIPE_RX_SAMPLER_OS_GAIN_OFFSET; - mask |= HPIPE_SMAPLER_MASK; - data |= 0x1 << HPIPE_SMAPLER_OFFSET; - reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, data, mask); - mask = HPIPE_SMAPLER_MASK; - data = 0x0 << HPIPE_SMAPLER_OFFSET; - reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, data, mask); - - /* Set External RX Regulator Control */ - mask = HPIPE_EXT_SELLV_RXSAMPL_MASK; - data = 0x1A << HPIPE_EXT_SELLV_RXSAMPL_OFFSET; - reg_set(hpipe_addr + HPIPE_VDD_CAL_CTRL_REG, data, mask); - - debug("stage: RFU configurations- Power Up PLL,Tx,Rx\n"); - /* SERDES External Configuration */ - mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK; - data = 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET; - mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK; - data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET; - mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK; - data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask); - - - /* check PLL rx & tx ready */ - addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG; - data = SD_EXTERNAL_STATUS0_PLL_RX_MASK | - SD_EXTERNAL_STATUS0_PLL_TX_MASK; - mask = data; - data = polling_with_timeout(addr, data, mask, 15000); - if (data != 0) { - debug("Read from reg = %p - value = 0x%x\n", sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data); - pr_err("SD_EXTERNAL_STATUS0_PLL_RX is %d, SD_EXTERNAL_STATUS0_PLL_TX is %d\n", - (data & SD_EXTERNAL_STATUS0_PLL_RX_MASK), - (data & SD_EXTERNAL_STATUS0_PLL_TX_MASK)); - ret = 0; - } - - /* RX init */ - mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK; - data = 0x1 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); - - - /* check that RX init done */ - addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG; - data = SD_EXTERNAL_STATUS0_RX_INIT_MASK; - mask = data; - data = polling_with_timeout(addr, data, mask, 100); - if (data != 0) { - debug("Read from reg = %p - value = 0x%x\n", - sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data); - pr_err("SD_EXTERNAL_STATUS0_RX_INIT is 0\n"); - ret = 0; - } - - debug("stage: RF Reset\n"); - /* RF Reset */ - mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK; - data = 0x0 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET; - mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK; - data |= 0x1 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET; - reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + ret = comphy_smc(MV_SIP_COMPHY_PLL_LOCK, comphy_base_addr, lane, type); debug_exit(); return ret; @@ -1973,6 +880,7 @@ int comphy_cp110_init(struct chip_serdes_phy_config *ptr_chip_cfg, void __iomem *comphy_base_addr, *hpipe_base_addr; u32 comphy_max_count, lane, ret = 0; u32 pcie_width = 0; + u32 mode; debug_enter(); @@ -2011,19 +919,23 @@ int comphy_cp110_init(struct chip_serdes_phy_config *ptr_chip_cfg, case PHY_TYPE_PEX1: case PHY_TYPE_PEX2: case PHY_TYPE_PEX3: - ret = comphy_pcie_power_up( - lane, pcie_width, ptr_comphy_map->clk_src, - serdes_map->end_point, - hpipe_base_addr, comphy_base_addr); + mode = COMPHY_FW_PCIE_FORMAT(pcie_width, + ptr_comphy_map->clk_src, + COMPHY_PCIE_MODE, + ptr_comphy_map->speed); + ret = comphy_smc(MV_SIP_COMPHY_POWER_ON, + ptr_chip_cfg->comphy_base_addr, lane, + mode); break; case PHY_TYPE_SATA0: case PHY_TYPE_SATA1: case PHY_TYPE_SATA2: case PHY_TYPE_SATA3: - ret = comphy_sata_power_up( - lane, hpipe_base_addr, comphy_base_addr, - ptr_chip_cfg->cp_index, - serdes_map[lane].invert); + mode = COMPHY_FW_MODE_FORMAT(COMPHY_SATA_MODE); + ret = comphy_sata_power_up(lane, hpipe_base_addr, + comphy_base_addr, + ptr_chip_cfg->cp_index, + mode); break; case PHY_TYPE_USB3_HOST0: case PHY_TYPE_USB3_HOST1: @@ -2033,6 +945,25 @@ int comphy_cp110_init(struct chip_serdes_phy_config *ptr_chip_cfg, break; case PHY_TYPE_SGMII0: case PHY_TYPE_SGMII1: + if (ptr_comphy_map->speed == PHY_SPEED_INVALID) { + debug("Warning: "); + debug("SGMII PHY speed in lane %d is invalid,", + lane); + debug(" set PHY speed to 1.25G\n"); + ptr_comphy_map->speed = PHY_SPEED_1_25G; + } + + /* + * UINIT_ID not relevant for SGMII0 and SGMII1 - will be + * ignored by firmware + */ + mode = COMPHY_FW_FORMAT(COMPHY_SGMII_MODE, + COMPHY_UNIT_ID0, + ptr_comphy_map->speed); + ret = comphy_smc(MV_SIP_COMPHY_POWER_ON, + ptr_chip_cfg->comphy_base_addr, lane, + mode); + break; case PHY_TYPE_SGMII2: case PHY_TYPE_SGMII3: if (ptr_comphy_map->speed == PHY_SPEED_INVALID) { @@ -2040,14 +971,21 @@ int comphy_cp110_init(struct chip_serdes_phy_config *ptr_chip_cfg, lane); ptr_comphy_map->speed = PHY_SPEED_1_25G; } - ret = comphy_sgmii_power_up( - lane, ptr_comphy_map->speed, hpipe_base_addr, - comphy_base_addr); + + mode = COMPHY_FW_FORMAT(COMPHY_SGMII_MODE, + COMPHY_UNIT_ID2, + ptr_comphy_map->speed); + ret = comphy_smc(MV_SIP_COMPHY_POWER_ON, + ptr_chip_cfg->comphy_base_addr, lane, + mode); break; case PHY_TYPE_SFI: - ret = comphy_sfi_power_up(lane, hpipe_base_addr, - comphy_base_addr, - ptr_comphy_map->speed); + mode = COMPHY_FW_FORMAT(COMPHY_SFI_MODE, + COMPHY_UNIT_ID0, + ptr_comphy_map->speed); + ret = comphy_smc(MV_SIP_COMPHY_POWER_ON, + ptr_chip_cfg->comphy_base_addr, lane, + mode); break; case PHY_TYPE_RXAUI0: case PHY_TYPE_RXAUI1: diff --git a/drivers/serial/serial_pl01x.c b/drivers/serial/serial_pl01x.c index 2772c25f1d..d9e35c6a2b 100644 --- a/drivers/serial/serial_pl01x.c +++ b/drivers/serial/serial_pl01x.c @@ -19,6 +19,7 @@ #include <watchdog.h> #include <asm/io.h> #include <serial.h> +#include <dm/device_compat.h> #include <dm/platform_data/serial_pl01x.h> #include <linux/compiler.h> #include "serial_pl01x_internal.h" @@ -362,8 +363,18 @@ int pl01x_serial_ofdata_to_platdata(struct udevice *dev) plat->clock = dev_read_u32_default(dev, "clock", CONFIG_PL011_CLOCK); ret = clk_get_by_index(dev, 0, &clk); if (!ret) { - clk_enable(&clk); + ret = clk_enable(&clk); + if (ret && ret != -ENOSYS) { + dev_err(dev, "failed to enable clock\n"); + return ret; + } + plat->clock = clk_get_rate(&clk); + if (IS_ERR_VALUE(plat->clock)) { + dev_err(dev, "failed to get rate\n"); + return plat->clock; + } + debug("%s: CLK %d\n", __func__, plat->clock); } plat->type = dev_get_driver_data(dev); plat->skip_init = dev_read_bool(dev, "skip-init"); diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c index 348630faf3..47a5571aec 100644 --- a/drivers/spi/xilinx_spi.c +++ b/drivers/spi/xilinx_spi.c @@ -214,7 +214,7 @@ static void xilinx_spi_startup_block(struct udevice *dev, unsigned int bytes, struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev); const unsigned char *txp = dout; unsigned char *rxp = din; - u32 reg, count; + u32 reg; u32 txbytes = bytes; u32 rxbytes = bytes; @@ -224,10 +224,10 @@ static void xilinx_spi_startup_block(struct udevice *dev, unsigned int bytes, * it sets txp to the initial value for the normal operation. */ for ( ; priv->startup < 2; priv->startup++) { - count = xilinx_spi_fill_txfifo(bus, txp, txbytes); + xilinx_spi_fill_txfifo(bus, txp, txbytes); reg = readl(®s->spicr) & ~SPICR_MASTER_INHIBIT; writel(reg, ®s->spicr); - count = xilinx_spi_read_rxfifo(bus, rxp, rxbytes); + xilinx_spi_read_rxfifo(bus, rxp, rxbytes); txp = din; if (priv->startup) { @@ -251,7 +251,7 @@ static int xilinx_spi_xfer(struct udevice *dev, unsigned int bitlen, unsigned char *rxp = din; u32 txbytes = bytes; u32 rxbytes = bytes; - u32 reg, count, timeout; + u32 reg, count; int ret; debug("spi_xfer: bus:%i cs:%i bitlen:%i bytes:%i flags:%lx\n", diff --git a/drivers/spi/zynq_qspi.c b/drivers/spi/zynq_qspi.c index 3f39ef05f2..f2eddec950 100644 --- a/drivers/spi/zynq_qspi.c +++ b/drivers/spi/zynq_qspi.c @@ -6,8 +6,10 @@ * Xilinx Zynq Quad-SPI(QSPI) controller driver (master mode only) */ +#include <clk.h> #include <common.h> #include <dm.h> +#include <dm/device_compat.h> #include <log.h> #include <malloc.h> #include <spi.h> @@ -105,17 +107,29 @@ static int zynq_qspi_ofdata_to_platdata(struct udevice *bus) plat->regs = (struct zynq_qspi_regs *)fdtdec_get_addr(blob, node, "reg"); - /* FIXME: Use 166MHz as a suitable default */ - plat->frequency = fdtdec_get_int(blob, node, "spi-max-frequency", - 166666666); - plat->speed_hz = plat->frequency / 2; - - debug("%s: regs=%p max-frequency=%d\n", __func__, - plat->regs, plat->frequency); - return 0; } +/** + * zynq_qspi_init_hw - Initialize the hardware + * @priv: Pointer to the zynq_qspi_priv structure + * + * The default settings of the QSPI controller's configurable parameters on + * reset are + * - Master mode + * - Baud rate divisor is set to 2 + * - Threshold value for TX FIFO not full interrupt is set to 1 + * - Flash memory interface mode enabled + * - Size of the word to be transferred as 8 bit + * This function performs the following actions + * - Disable and clear all the interrupts + * - Enable manual slave select + * - Enable auto start + * - Deselect all the chip select lines + * - Set the size of the word to be transferred as 32 bit + * - Set the little endian mode of TX FIFO and + * - Enable the QSPI controller + */ static void zynq_qspi_init_hw(struct zynq_qspi_priv *priv) { struct zynq_qspi_regs *regs = priv->regs; @@ -159,19 +173,45 @@ static int zynq_qspi_probe(struct udevice *bus) { struct zynq_qspi_platdata *plat = dev_get_platdata(bus); struct zynq_qspi_priv *priv = dev_get_priv(bus); + struct clk clk; + unsigned long clock; + int ret; priv->regs = plat->regs; priv->fifo_depth = ZYNQ_QSPI_FIFO_DEPTH; + ret = clk_get_by_name(bus, "ref_clk", &clk); + if (ret < 0) { + dev_err(bus, "failed to get clock\n"); + return ret; + } + + clock = clk_get_rate(&clk); + if (IS_ERR_VALUE(clock)) { + dev_err(bus, "failed to get rate\n"); + return clock; + } + + ret = clk_enable(&clk); + if (ret && ret != -ENOSYS) { + dev_err(bus, "failed to enable clock\n"); + return ret; + } + /* init the zynq spi hw */ zynq_qspi_init_hw(priv); + plat->frequency = clock; + plat->speed_hz = plat->frequency / 2; + + debug("%s: max-frequency=%d\n", __func__, plat->speed_hz); + return 0; } -/* +/** * zynq_qspi_read_data - Copy data to RX buffer - * @zqspi: Pointer to the zynq_qspi structure + * @priv: Pointer to the zynq_qspi_priv structure * @data: The 32 bit variable where data is stored * @size: Number of bytes to be copied from data to RX buffer */ @@ -214,9 +254,9 @@ static void zynq_qspi_read_data(struct zynq_qspi_priv *priv, u32 data, u8 size) priv->bytes_to_receive = 0; } -/* +/** * zynq_qspi_write_data - Copy data from TX buffer - * @zqspi: Pointer to the zynq_qspi structure + * @priv: Pointer to the zynq_qspi_priv structure * @data: Pointer to the 32 bit variable where data is to be copied * @size: Number of bytes to be copied from TX buffer to data */ @@ -263,6 +303,11 @@ static void zynq_qspi_write_data(struct zynq_qspi_priv *priv, priv->bytes_to_transfer = 0; } +/** + * zynq_qspi_chipselect - Select or deselect the chip select line + * @priv: Pointer to the zynq_qspi_priv structure + * @is_on: Select(1) or deselect (0) the chip select line + */ static void zynq_qspi_chipselect(struct zynq_qspi_priv *priv, int is_on) { u32 confr; @@ -282,9 +327,10 @@ static void zynq_qspi_chipselect(struct zynq_qspi_priv *priv, int is_on) writel(confr, ®s->cr); } -/* +/** * zynq_qspi_fill_tx_fifo - Fills the TX FIFO with as many bytes as possible - * @zqspi: Pointer to the zynq_qspi structure + * @priv: Pointer to the zynq_qspi_priv structure + * @size: Number of bytes to be copied to fifo */ static void zynq_qspi_fill_tx_fifo(struct zynq_qspi_priv *priv, u32 size) { @@ -322,9 +368,9 @@ static void zynq_qspi_fill_tx_fifo(struct zynq_qspi_priv *priv, u32 size) } } -/* +/** * zynq_qspi_irq_poll - Interrupt service routine of the QSPI controller - * @zqspi: Pointer to the zynq_qspi structure + * @priv: Pointer to the zynq_qspi structure * * This function handles TX empty and Mode Fault interrupts only. * On TX empty interrupt this function reads the received data from RX FIFO and @@ -410,11 +456,9 @@ static int zynq_qspi_irq_poll(struct zynq_qspi_priv *priv) return 0; } -/* +/** * zynq_qspi_start_transfer - Initiates the QSPI transfer - * @qspi: Pointer to the spi_device structure - * @transfer: Pointer to the spi_transfer structure which provide information - * about next transfer parameters + * @priv: Pointer to the zynq_qspi_priv structure * * This function fills the TX FIFO, starts the QSPI transfer, and waits for the * transfer to be completed. diff --git a/drivers/spi/zynq_spi.c b/drivers/spi/zynq_spi.c index 9923931e36..cb911c34f6 100644 --- a/drivers/spi/zynq_spi.c +++ b/drivers/spi/zynq_spi.c @@ -8,10 +8,12 @@ #include <common.h> #include <dm.h> +#include <dm/device_compat.h> #include <log.h> #include <malloc.h> #include <spi.h> #include <time.h> +#include <clk.h> #include <asm/io.h> #include <linux/bitops.h> #include <linux/delay.h> @@ -79,17 +81,10 @@ static int zynq_spi_ofdata_to_platdata(struct udevice *bus) plat->regs = dev_read_addr_ptr(bus); - /* FIXME: Use 250MHz as a suitable default */ - plat->frequency = fdtdec_get_int(blob, node, "spi-max-frequency", - 250000000); plat->deactivate_delay_us = fdtdec_get_int(blob, node, "spi-deactivate-delay", 0); plat->activate_delay_us = fdtdec_get_int(blob, node, "spi-activate-delay", 0); - plat->speed_hz = plat->frequency / 2; - - debug("%s: regs=%p max-frequency=%d\n", __func__, - plat->regs, plat->frequency); return 0; } @@ -128,13 +123,39 @@ static int zynq_spi_probe(struct udevice *bus) { struct zynq_spi_platdata *plat = dev_get_platdata(bus); struct zynq_spi_priv *priv = dev_get_priv(bus); + struct clk clk; + unsigned long clock; + int ret; priv->regs = plat->regs; priv->fifo_depth = ZYNQ_SPI_FIFO_DEPTH; + ret = clk_get_by_name(bus, "ref_clk", &clk); + if (ret < 0) { + dev_err(bus, "failed to get clock\n"); + return ret; + } + + clock = clk_get_rate(&clk); + if (IS_ERR_VALUE(clock)) { + dev_err(bus, "failed to get rate\n"); + return clock; + } + + ret = clk_enable(&clk); + if (ret && ret != -ENOSYS) { + dev_err(bus, "failed to enable clock\n"); + return ret; + } + /* init the zynq spi hw */ zynq_spi_init_hw(priv); + plat->frequency = clock; + plat->speed_hz = plat->frequency / 2; + + debug("%s: max-frequency=%d\n", __func__, plat->speed_hz); + return 0; } |