| /* SPDX-License-Identifier: GPL-2.0-or-later */ |
| /* |
| * Copyright (C) 2024 PHYTEC Messtechnik GmbH |
| * Author: Wadim Egorov <w.egorov@phytec.de> |
| */ |
| |
| #include "k3_ddrss_patch.h" |
| |
| #include <fdt_support.h> |
| #include <linux/errno.h> |
| |
| #ifdef CONFIG_K3_AM64_DDRSS |
| #define LPDDR4_INTR_CTL_REG_COUNT (423U) |
| #define LPDDR4_INTR_PHY_INDEP_REG_COUNT (345U) |
| #define LPDDR4_INTR_PHY_REG_COUNT (1406U) |
| #endif |
| |
| static int fdt_setprop_inplace_idx_u32(void *fdt, int nodeoffset, |
| const char *name, uint32_t idx, u32 val) |
| { |
| val = cpu_to_be32(val); |
| return fdt_setprop_inplace_namelen_partial(fdt, nodeoffset, name, |
| strlen(name), |
| idx * sizeof(val), &val, |
| sizeof(val)); |
| } |
| |
| int fdt_apply_ddrss_timings_patch(void *fdt, struct ddrss *ddrss) |
| { |
| int i, j; |
| int ret; |
| int mem_offset; |
| |
| mem_offset = fdt_path_offset(fdt, "/memorycontroller@f300000"); |
| if (mem_offset < 0) |
| return -ENODEV; |
| |
| for (i = 0; i < LPDDR4_INTR_CTL_REG_COUNT; i++) |
| for (j = 0; j < ddrss->ctl_regs_num; j++) |
| if (i == ddrss->ctl_regs[j].off) { |
| ret = fdt_setprop_inplace_idx_u32(fdt, |
| mem_offset, "ti,ctl-data", i, |
| ddrss->ctl_regs[j].val); |
| if (ret) |
| return ret; |
| } |
| |
| for (i = 0; i < LPDDR4_INTR_PHY_INDEP_REG_COUNT; i++) |
| for (j = 0; j < ddrss->pi_regs_num; j++) |
| if (i == ddrss->pi_regs[j].off) { |
| ret = fdt_setprop_inplace_idx_u32(fdt, |
| mem_offset, "ti,pi-data", i, |
| ddrss->pi_regs[j].val); |
| if (ret) |
| return ret; |
| } |
| |
| for (i = 0; i < LPDDR4_INTR_PHY_REG_COUNT; i++) |
| for (j = 0; j < ddrss->phy_regs_num; j++) |
| if (i == ddrss->phy_regs[j].off) { |
| ret = fdt_setprop_inplace_idx_u32(fdt, |
| mem_offset, "ti,phy-data", i, |
| ddrss->phy_regs[j].val); |
| if (ret) |
| return ret; |
| } |
| |
| return 0; |
| } |