diff options
author | Tom Rini <trini@konsulko.com> | 2022-04-05 20:45:22 +0300 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2022-04-05 20:45:22 +0300 |
commit | 59bffec43a657598b194b9eb30dc01eec06078c7 (patch) | |
tree | 80a668bc14a348be6be49a9808e811a7f4bb82c4 /drivers | |
parent | 037ef53cf01c522073a0a930c84c3ca858f032e1 (diff) | |
parent | da61ee662554f98fac0ab19c6b893edd82edb098 (diff) | |
download | u-boot-59bffec43a657598b194b9eb30dc01eec06078c7.tar.xz |
Merge branch '2022-04-04-platform-updates'
- Updates for exynos78x0 and TI K3 platforms
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/misc/k3_esm.c | 53 | ||||
-rw-r--r-- | drivers/ram/k3-am654-ddrss.c | 15 | ||||
-rw-r--r-- | drivers/ram/k3-ddrss/k3-ddrss.c | 138 |
3 files changed, 198 insertions, 8 deletions
diff --git a/drivers/misc/k3_esm.c b/drivers/misc/k3_esm.c index cc2a23dd66..41faeb3d85 100644 --- a/drivers/misc/k3_esm.c +++ b/drivers/misc/k3_esm.c @@ -16,17 +16,57 @@ #define ESM_SFT_RST 0x0c #define ESM_SFT_RST_KEY 0x0f +#define ESM_EN 0x08 +#define ESM_EN_KEY 0x0f #define ESM_STS(i) (0x404 + (i) / 32 * 0x20) +#define ESM_STS_MASK(i) (1 << ((i) % 32)) #define ESM_PIN_EN_SET_OFFSET(i) (0x414 + (i) / 32 * 0x20) -#define ESM_PIN_MASK(i) BIT((i) & 0x1f) +#define ESM_PIN_MASK(i) (1 << ((i) % 32)) +#define ESM_INTR_EN_SET_OFFSET(i) (0x408 + (i) / 32 * 0x20) +#define ESM_INTR_MASK(i) (1 << ((i) % 32)) +#define ESM_INTR_PRIO_SET_OFFSET(i) (0x410 + (i) / 32 * 0x20) +#define ESM_INTR_PRIO_MASK(i) (1 << ((i) % 32)) static void esm_pin_enable(void __iomem *base, int pin) { + u32 value; + + value = readl(base + ESM_PIN_EN_SET_OFFSET(pin)); + value |= ESM_PIN_MASK(pin); /* Enable event */ - writel(ESM_PIN_MASK(pin), base + ESM_PIN_EN_SET_OFFSET(pin)); + writel(value, base + ESM_PIN_EN_SET_OFFSET(pin)); +} + +static void esm_intr_enable(void __iomem *base, int pin) +{ + u32 value; + + value = readl(base + ESM_INTR_EN_SET_OFFSET(pin)); + value |= ESM_INTR_MASK(pin); + /* Enable Interrupt event */ + writel(value, base + ESM_INTR_EN_SET_OFFSET(pin)); +} + +static void esm_intr_prio_set(void __iomem *base, int pin) +{ + u32 value; + + value = readl(base + ESM_INTR_PRIO_SET_OFFSET(pin)); + value |= ESM_INTR_PRIO_MASK(pin); + /* Set to priority */ + writel(value, base + ESM_INTR_PRIO_SET_OFFSET(pin)); } +static void esm_clear_raw_status(void __iomem *base, int pin) +{ + u32 value; + + value = readl(base + ESM_STS(pin)); + value |= ESM_STS_MASK(pin); + /* Clear Event status */ + writel(value, base + ESM_STS(pin)); +} /** * k3_esm_probe: configures ESM based on DT data * @@ -67,8 +107,15 @@ static int k3_esm_probe(struct udevice *dev) /* Clear any pending events */ writel(ESM_SFT_RST_KEY, base + ESM_SFT_RST); - for (i = 0; i < num_pins; i++) + for (i = 0; i < num_pins; i++) { + esm_intr_prio_set(base, pins[i]); + esm_clear_raw_status(base, pins[i]); esm_pin_enable(base, pins[i]); + esm_intr_enable(base, pins[i]); + } + + /* Enable ESM */ + writel(ESM_EN_KEY, base + ESM_EN); free_pins: kfree(pins); diff --git a/drivers/ram/k3-am654-ddrss.c b/drivers/ram/k3-am654-ddrss.c index 4ec12bf42e..4453c247b2 100644 --- a/drivers/ram/k3-am654-ddrss.c +++ b/drivers/ram/k3-am654-ddrss.c @@ -265,6 +265,16 @@ static void am654_ddrss_phy_configuration(struct am654_ddrss_desc *ddrss) ddrss_phy_writel(DDRSS_DDRPHY_ACIOCR5, ioctl->ddrphy_aciocr5); ddrss_phy_writel(DDRSS_DDRPHY_IOVCR0, ioctl->ddrphy_iovcr0); + ddrss_phy_writel(DDRSS_DDRPHY_DX2GCR0, cfg->ddrphy_dx2gcr0); + ddrss_phy_writel(DDRSS_DDRPHY_DX2GCR1, cfg->ddrphy_dx2gcr1); + ddrss_phy_writel(DDRSS_DDRPHY_DX2GCR2, cfg->ddrphy_dx2gcr2); + ddrss_phy_writel(DDRSS_DDRPHY_DX2GCR3, cfg->ddrphy_dx2gcr3); + + ddrss_phy_writel(DDRSS_DDRPHY_DX3GCR0, cfg->ddrphy_dx3gcr0); + ddrss_phy_writel(DDRSS_DDRPHY_DX3GCR1, cfg->ddrphy_dx3gcr1); + ddrss_phy_writel(DDRSS_DDRPHY_DX3GCR2, cfg->ddrphy_dx3gcr2); + ddrss_phy_writel(DDRSS_DDRPHY_DX3GCR3, cfg->ddrphy_dx3gcr3); + ddrss_phy_writel(DDRSS_DDRPHY_DX4GCR0, cfg->ddrphy_dx4gcr0); ddrss_phy_writel(DDRSS_DDRPHY_DX4GCR1, cfg->ddrphy_dx4gcr1); ddrss_phy_writel(DDRSS_DDRPHY_DX4GCR2, cfg->ddrphy_dx4gcr2); @@ -874,9 +884,8 @@ static int am654_ddrss_power_on(struct am654_ddrss_desc *ddrss) device_get_supply_regulator(ddrss->dev, "vtt-supply", &ddrss->vtt_supply); ret = regulator_set_value(ddrss->vtt_supply, 3300000); - if (ret) - return ret; - debug("VTT regulator enabled\n"); + if (ret == 0) + debug("VTT regulator enabled\n"); #endif return 0; diff --git a/drivers/ram/k3-ddrss/k3-ddrss.c b/drivers/ram/k3-ddrss/k3-ddrss.c index 25e3976e65..2467f122a8 100644 --- a/drivers/ram/k3-ddrss/k3-ddrss.c +++ b/drivers/ram/k3-ddrss/k3-ddrss.c @@ -6,9 +6,12 @@ */ #include <common.h> +#include <config.h> #include <clk.h> +#include <div64.h> #include <dm.h> #include <dm/device_compat.h> +#include <fdt_support.h> #include <ram.h> #include <hang.h> #include <log.h> @@ -30,6 +33,19 @@ #define DDRSS_V2A_R1_MAT_REG 0x0020 #define DDRSS_ECC_CTRL_REG 0x0120 +#define DDRSS_ECC_CTRL_REG_ECC_EN BIT(0) +#define DDRSS_ECC_CTRL_REG_RMW_EN BIT(1) +#define DDRSS_ECC_CTRL_REG_ECC_CK BIT(2) +#define DDRSS_ECC_CTRL_REG_WR_ALLOC BIT(4) + +#define DDRSS_ECC_R0_STR_ADDR_REG 0x0130 +#define DDRSS_ECC_R0_END_ADDR_REG 0x0134 +#define DDRSS_ECC_R1_STR_ADDR_REG 0x0138 +#define DDRSS_ECC_R1_END_ADDR_REG 0x013c +#define DDRSS_ECC_R2_STR_ADDR_REG 0x0140 +#define DDRSS_ECC_R2_END_ADDR_REG 0x0144 +#define DDRSS_ECC_1B_ERR_CNT_REG 0x0150 + #define SINGLE_DDR_SUBSYSTEM 0x1 #define MULTI_DDR_SUBSYSTEM 0x2 @@ -102,10 +118,18 @@ struct k3_msmc { enum emif_active active; }; +#define K3_DDRSS_MAX_ECC_REGIONS 3 + +struct k3_ddrss_ecc_region { + u32 start; + u32 range; +}; + struct k3_ddrss_desc { struct udevice *dev; void __iomem *ddrss_ss_cfg; void __iomem *ddrss_ctrl_mmr; + void __iomem *ddrss_ctl_cfg; struct power_domain ddrcfg_pwrdmn; struct power_domain ddrdata_pwrdmn; struct clk ddr_clk; @@ -118,6 +142,9 @@ struct k3_ddrss_desc { lpddr4_obj *driverdt; lpddr4_config config; lpddr4_privatedata pd; + struct k3_ddrss_ecc_region ecc_regions[K3_DDRSS_MAX_ECC_REGIONS]; + u64 ecc_reserved_space; + bool ti_ecc_enabled; }; struct reginitdata { @@ -319,7 +346,7 @@ static int k3_ddrss_ofdata_to_priv(struct udevice *dev) dev_err(dev, "No reg property for DDRSS wrapper logic\n"); return -EINVAL; } - ddrss->ddrss_ss_cfg = (void *)reg; + ddrss->ddrss_ctl_cfg = (void *)reg; reg = dev_read_addr_name(dev, "ctrl_mmr_lp4"); if (reg == FDT_ADDR_T_NONE) { @@ -328,6 +355,14 @@ static int k3_ddrss_ofdata_to_priv(struct udevice *dev) } ddrss->ddrss_ctrl_mmr = (void *)reg; + reg = dev_read_addr_name(dev, "ss_cfg"); + if (reg == FDT_ADDR_T_NONE) { + dev_dbg(dev, "No reg property for SS Config region, but this is optional so continuing.\n"); + ddrss->ddrss_ss_cfg = NULL; + } else { + ddrss->ddrss_ss_cfg = (void *)reg; + } + ret = power_domain_get_by_index(dev, &ddrss->ddrcfg_pwrdmn, 0); if (ret) { dev_err(dev, "power_domain_get() failed: %d\n", ret); @@ -371,6 +406,8 @@ static int k3_ddrss_ofdata_to_priv(struct udevice *dev) if (ret) dev_err(dev, "ddr fhs cnt not populated %d\n", ret); + ddrss->ti_ecc_enabled = dev_read_bool(dev, "ti,ecc-enable"); + return ret; } @@ -403,7 +440,7 @@ void k3_lpddr4_init(struct k3_ddrss_desc *ddrss) hang(); } - config->ctlbase = (struct lpddr4_ctlregs_s *)ddrss->ddrss_ss_cfg; + config->ctlbase = (struct lpddr4_ctlregs_s *)ddrss->ddrss_ctl_cfg; config->infohandler = (lpddr4_infocallback) k3_lpddr4_info_handler; status = driverdt->init(pd, config); @@ -512,6 +549,60 @@ void k3_lpddr4_start(struct k3_ddrss_desc *ddrss) } } +static void k3_ddrss_set_ecc_range_r0(u32 base, u32 start_address, u32 size) +{ + writel((start_address) >> 16, base + DDRSS_ECC_R0_STR_ADDR_REG); + writel((start_address + size - 1) >> 16, base + DDRSS_ECC_R0_END_ADDR_REG); +} + +static void k3_ddrss_preload_ecc_mem_region(u32 *addr, u32 size, u32 word) +{ + int i; + + printf("ECC is enabled, priming DDR which will take several seconds.\n"); + + for (i = 0; i < (size / 4); i++) + addr[i] = word; +} + +static void k3_ddrss_lpddr4_ecc_calc_reserved_mem(struct k3_ddrss_desc *ddrss) +{ + fdtdec_setup_mem_size_base_lowest(); + + ddrss->ecc_reserved_space = gd->ram_size; + do_div(ddrss->ecc_reserved_space, 9); + + /* Round to clean number */ + ddrss->ecc_reserved_space = 1ull << (fls(ddrss->ecc_reserved_space)); +} + +static void k3_ddrss_lpddr4_ecc_init(struct k3_ddrss_desc *ddrss) +{ + u32 ecc_region_start = ddrss->ecc_regions[0].start; + u32 ecc_range = ddrss->ecc_regions[0].range; + u32 base = (u32)ddrss->ddrss_ss_cfg; + u32 val; + + /* Only Program region 0 which covers full ddr space */ + k3_ddrss_set_ecc_range_r0(base, ecc_region_start - gd->ram_base, ecc_range); + + /* Enable ECC, RMW, WR_ALLOC */ + writel(DDRSS_ECC_CTRL_REG_ECC_EN | DDRSS_ECC_CTRL_REG_RMW_EN | + DDRSS_ECC_CTRL_REG_WR_ALLOC, base + DDRSS_ECC_CTRL_REG); + + /* Preload ECC Mem region with 0's */ + k3_ddrss_preload_ecc_mem_region((u32 *)ecc_region_start, ecc_range, + 0x00000000); + + /* Clear Error Count Register */ + writel(0x1, base + DDRSS_ECC_1B_ERR_CNT_REG); + + /* Enable ECC Check */ + val = readl(base + DDRSS_ECC_CTRL_REG); + val |= DDRSS_ECC_CTRL_REG_ECC_CK; + writel(val, base + DDRSS_ECC_CTRL_REG); +} + static int k3_ddrss_probe(struct udevice *dev) { int ret; @@ -546,9 +637,52 @@ static int k3_ddrss_probe(struct udevice *dev) k3_lpddr4_start(ddrss); + if (ddrss->ti_ecc_enabled) { + if (!ddrss->ddrss_ss_cfg) { + printf("%s: ss_cfg is required if ecc is enabled but not provided.", + __func__); + return -EINVAL; + } + + k3_ddrss_lpddr4_ecc_calc_reserved_mem(ddrss); + + /* Always configure one region that covers full DDR space */ + ddrss->ecc_regions[0].start = gd->ram_base; + ddrss->ecc_regions[0].range = gd->ram_size - ddrss->ecc_reserved_space; + k3_ddrss_lpddr4_ecc_init(ddrss); + } + return ret; } +int k3_ddrss_ddr_fdt_fixup(struct udevice *dev, void *blob, struct bd_info *bd) +{ + struct k3_ddrss_desc *ddrss = dev_get_priv(dev); + u64 start[CONFIG_NR_DRAM_BANKS]; + u64 size[CONFIG_NR_DRAM_BANKS]; + int bank; + + if (ddrss->ecc_reserved_space == 0) + return 0; + + for (bank = CONFIG_NR_DRAM_BANKS - 1; bank >= 0; bank--) { + if (ddrss->ecc_reserved_space > bd->bi_dram[bank].size) { + ddrss->ecc_reserved_space -= bd->bi_dram[bank].size; + bd->bi_dram[bank].size = 0; + } else { + bd->bi_dram[bank].size -= ddrss->ecc_reserved_space; + break; + } + } + + for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) { + start[bank] = bd->bi_dram[bank].start; + size[bank] = bd->bi_dram[bank].size; + } + + return fdt_fixup_memory_banks(blob, start, size, CONFIG_NR_DRAM_BANKS); +} + static int k3_ddrss_get_info(struct udevice *dev, struct ram_info *info) { return 0; |