diff options
author | Tom Rini | 2019-10-24 07:32:21 -0400 |
---|---|---|
committer | Tom Rini | 2019-10-24 07:32:21 -0400 |
commit | c9e40996f916671d6c0b87207fdcd6aa85424c04 (patch) | |
tree | 3a04a1cefdf057bf0a902aa14edbe5800fd29fce /drivers | |
parent | 680023c5fab6b1777c0c6f2e76e5d2effb7903a0 (diff) | |
parent | a360e42216d5c43e28ed067b6e1c48d00cd4763f (diff) |
Merge https://gitlab.denx.de/u-boot/custodians/u-boot-marvell
- Add support for HyperBus Memory Controller of TI's J721e
and AM654 SoCs (Vignesh)
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mtd/Kconfig | 7 | ||||
-rw-r--r-- | drivers/mtd/Makefile | 1 | ||||
-rw-r--r-- | drivers/mtd/cfi_flash.c | 6 | ||||
-rw-r--r-- | drivers/mtd/hbmc-am654.c | 105 |
4 files changed, 117 insertions, 2 deletions
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig index 0050fb2b9bf..37f379d4780 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig @@ -94,6 +94,13 @@ config RENESAS_RPC_HF This enables access to Hyperflash memory through the Renesas RCar Gen3 RPC controller. +config HBMC_AM654 + bool "HyperBus controller driver for AM65x SoC" + depends on SYSCON + help + This is the driver for HyperBus controller on TI's AM65x and + other SoCs + source "drivers/mtd/nand/Kconfig" source "drivers/mtd/spi/Kconfig" diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile index 22ceda93c06..293079d709a 100644 --- a/drivers/mtd/Makefile +++ b/drivers/mtd/Makefile @@ -18,5 +18,6 @@ obj-$(CONFIG_FLASH_PIC32) += pic32_flash.o obj-$(CONFIG_ST_SMI) += st_smi.o obj-$(CONFIG_STM32_FLASH) += stm32_flash.o obj-$(CONFIG_RENESAS_RPC_HF) += renesas_rpc_hf.o +obj-$(CONFIG_HBMC_AM654) += hbmc-am654.o obj-y += nand/ diff --git a/drivers/mtd/cfi_flash.c b/drivers/mtd/cfi_flash.c index c59254c76e3..0574fa63a44 100644 --- a/drivers/mtd/cfi_flash.c +++ b/drivers/mtd/cfi_flash.c @@ -178,7 +178,8 @@ __maybe_weak u64 flash_read64(void *addr) /*----------------------------------------------------------------------- */ #if defined(CONFIG_ENV_IS_IN_FLASH) || defined(CONFIG_ENV_ADDR_REDUND) || \ - (CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE) + (defined(CONFIG_SYS_MONITOR_BASE) && \ + (CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE)) static flash_info_t *flash_get_info(ulong base) { int i; @@ -2329,7 +2330,8 @@ static void flash_protect_default(void) #endif /* Monitor protection ON by default */ -#if (CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE) && \ +#if defined(CONFIG_SYS_MONITOR_BASE) && \ + (CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE) && \ (!defined(CONFIG_MONITOR_IS_IN_RAM)) flash_protect(FLAG_PROTECT_SET, CONFIG_SYS_MONITOR_BASE, diff --git a/drivers/mtd/hbmc-am654.c b/drivers/mtd/hbmc-am654.c new file mode 100644 index 00000000000..5a560f1253b --- /dev/null +++ b/drivers/mtd/hbmc-am654.c @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/ +// Author: Vignesh Raghavendra <vigneshr@ti.com> + +#include <common.h> +#include <asm/io.h> +#include <dm.h> +#include <regmap.h> +#include <syscon.h> + +#define FSS_SYSC_REG 0x4 + +#define HYPERBUS_CALIB_COUNT 25 + +struct am654_hbmc_priv { + void __iomem *mmiobase; + bool calibrated; +}; + +/* Calibrate by looking for "QRY" string within the CFI space */ +static int am654_hyperbus_calibrate(struct udevice *dev) +{ + struct am654_hbmc_priv *priv = dev_get_priv(dev); + int count = HYPERBUS_CALIB_COUNT; + int pass_count = 0; + u16 qry[3]; + + if (priv->calibrated) + return 0; + + writew(0xF0, priv->mmiobase); + writew(0x98, priv->mmiobase + 0xaa); + + while (count--) { + qry[0] = readw(priv->mmiobase + 0x20); + qry[1] = readw(priv->mmiobase + 0x22); + qry[2] = readw(priv->mmiobase + 0x24); + + if (qry[0] == 'Q' && qry[1] == 'R' && qry[2] == 'Y') + pass_count++; + else + pass_count = 0; + if (pass_count == 5) + break; + } + writew(0xF0, priv->mmiobase); + writew(0xFF, priv->mmiobase); + + return pass_count == 5; +} + +static int am654_select_hbmc(struct udevice *dev) +{ + struct regmap *regmap = syscon_get_regmap(dev_get_parent(dev)); + + return regmap_update_bits(regmap, FSS_SYSC_REG, 0x2, 0x2); +} + +static int am654_hbmc_bind(struct udevice *dev) +{ + return dm_scan_fdt_dev(dev); +} + +static int am654_hbmc_probe(struct udevice *dev) +{ + struct am654_hbmc_priv *priv = dev_get_priv(dev); + int ret; + + priv->mmiobase = devfdt_remap_addr_index(dev, 1); + if (dev_read_bool(dev, "mux-controls")) { + ret = am654_select_hbmc(dev); + if (ret) { + dev_err(dev, "Failed to select HBMC mux\n"); + return ret; + } + } + + if (!priv->calibrated) { + ret = am654_hyperbus_calibrate(dev); + if (!ret) { + dev_err(dev, "Calibration Failed\n"); + return -EIO; + } + } + priv->calibrated = true; + + return 0; +} + +static const struct udevice_id am654_hbmc_dt_ids[] = { + { + .compatible = "ti,am654-hbmc", + }, + { /* end of table */ } +}; + +U_BOOT_DRIVER(hbmc_am654) = { + .name = "hbmc-am654", + .id = UCLASS_MTD, + .of_match = am654_hbmc_dt_ids, + .probe = am654_hbmc_probe, + .bind = am654_hbmc_bind, + .priv_auto_alloc_size = sizeof(struct am654_hbmc_priv), +}; |