Commit 98231c4fc3b95a0e9d37ba3711ad993bb27605c8
Committed by
Greg Kroah-Hartman
1 parent
68b4aee35d
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
memory: emif: add one-time settings
Add settings that are not dependent on frequency or any other transient parameters. This includes - power managment control init - impedence calibration control - frequency independent phy configuration registers - initialization of temperature polling Signed-off-by: Aneesh V <aneesh@ti.com> Reviewed-by: Santosh Shilimkar <santosh.shilimkar@ti.com> Reviewed-by: Benoit Cousson <b-cousson@ti.com> [santosh.shilimkar@ti.com: Moved to drivers/memory from drivers/misc] Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com> Tested-by: Lokesh Vutla <lokeshvutla@ti.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Showing 1 changed file with 148 additions and 0 deletions Side-by-side Diff
drivers/memory/emif.c
... | ... | @@ -78,6 +78,24 @@ |
78 | 78 | } |
79 | 79 | |
80 | 80 | /* |
81 | + * Get bus width used by EMIF. Note that this may be different from the | |
82 | + * bus width of the DDR devices used. For instance two 16-bit DDR devices | |
83 | + * may be connected to a given CS of EMIF. In this case bus width as far | |
84 | + * as EMIF is concerned is 32, where as the DDR bus width is 16 bits. | |
85 | + */ | |
86 | +static u32 get_emif_bus_width(struct emif_data *emif) | |
87 | +{ | |
88 | + u32 width; | |
89 | + void __iomem *base = emif->base; | |
90 | + | |
91 | + width = (readl(base + EMIF_SDRAM_CONFIG) & NARROW_MODE_MASK) | |
92 | + >> NARROW_MODE_SHIFT; | |
93 | + width = width == 0 ? 32 : 16; | |
94 | + | |
95 | + return width; | |
96 | +} | |
97 | + | |
98 | +/* | |
81 | 99 | * Get the CL from SDRAM_CONFIG register |
82 | 100 | */ |
83 | 101 | static u32 get_cl(struct emif_data *emif) |
... | ... | @@ -372,6 +390,70 @@ |
372 | 390 | return tim3; |
373 | 391 | } |
374 | 392 | |
393 | +static u32 get_zq_config_reg(const struct lpddr2_addressing *addressing, | |
394 | + bool cs1_used, bool cal_resistors_per_cs) | |
395 | +{ | |
396 | + u32 zq = 0, val = 0; | |
397 | + | |
398 | + val = EMIF_ZQCS_INTERVAL_US * 1000 / addressing->tREFI_ns; | |
399 | + zq |= val << ZQ_REFINTERVAL_SHIFT; | |
400 | + | |
401 | + val = DIV_ROUND_UP(T_ZQCL_DEFAULT_NS, T_ZQCS_DEFAULT_NS) - 1; | |
402 | + zq |= val << ZQ_ZQCL_MULT_SHIFT; | |
403 | + | |
404 | + val = DIV_ROUND_UP(T_ZQINIT_DEFAULT_NS, T_ZQCL_DEFAULT_NS) - 1; | |
405 | + zq |= val << ZQ_ZQINIT_MULT_SHIFT; | |
406 | + | |
407 | + zq |= ZQ_SFEXITEN_ENABLE << ZQ_SFEXITEN_SHIFT; | |
408 | + | |
409 | + if (cal_resistors_per_cs) | |
410 | + zq |= ZQ_DUALCALEN_ENABLE << ZQ_DUALCALEN_SHIFT; | |
411 | + else | |
412 | + zq |= ZQ_DUALCALEN_DISABLE << ZQ_DUALCALEN_SHIFT; | |
413 | + | |
414 | + zq |= ZQ_CS0EN_MASK; /* CS0 is used for sure */ | |
415 | + | |
416 | + val = cs1_used ? 1 : 0; | |
417 | + zq |= val << ZQ_CS1EN_SHIFT; | |
418 | + | |
419 | + return zq; | |
420 | +} | |
421 | + | |
422 | +static u32 get_temp_alert_config(const struct lpddr2_addressing *addressing, | |
423 | + const struct emif_custom_configs *custom_configs, bool cs1_used, | |
424 | + u32 sdram_io_width, u32 emif_bus_width) | |
425 | +{ | |
426 | + u32 alert = 0, interval, devcnt; | |
427 | + | |
428 | + if (custom_configs && (custom_configs->mask & | |
429 | + EMIF_CUSTOM_CONFIG_TEMP_ALERT_POLL_INTERVAL)) | |
430 | + interval = custom_configs->temp_alert_poll_interval_ms; | |
431 | + else | |
432 | + interval = TEMP_ALERT_POLL_INTERVAL_DEFAULT_MS; | |
433 | + | |
434 | + interval *= 1000000; /* Convert to ns */ | |
435 | + interval /= addressing->tREFI_ns; /* Convert to refresh cycles */ | |
436 | + alert |= (interval << TA_REFINTERVAL_SHIFT); | |
437 | + | |
438 | + /* | |
439 | + * sdram_io_width is in 'log2(x) - 1' form. Convert emif_bus_width | |
440 | + * also to this form and subtract to get TA_DEVCNT, which is | |
441 | + * in log2(x) form. | |
442 | + */ | |
443 | + emif_bus_width = __fls(emif_bus_width) - 1; | |
444 | + devcnt = emif_bus_width - sdram_io_width; | |
445 | + alert |= devcnt << TA_DEVCNT_SHIFT; | |
446 | + | |
447 | + /* DEVWDT is in 'log2(x) - 3' form */ | |
448 | + alert |= (sdram_io_width - 2) << TA_DEVWDT_SHIFT; | |
449 | + | |
450 | + alert |= 1 << TA_SFEXITEN_SHIFT; | |
451 | + alert |= 1 << TA_CS0EN_SHIFT; | |
452 | + alert |= (cs1_used ? 1 : 0) << TA_CS1EN_SHIFT; | |
453 | + | |
454 | + return alert; | |
455 | +} | |
456 | + | |
375 | 457 | static u32 get_read_idle_ctrl_shdw(u8 volt_ramp) |
376 | 458 | { |
377 | 459 | u32 idle = 0, val = 0; |
... | ... | @@ -815,6 +897,71 @@ |
815 | 897 | |
816 | 898 | } |
817 | 899 | |
900 | +static void __init_or_module emif_onetime_settings(struct emif_data *emif) | |
901 | +{ | |
902 | + u32 pwr_mgmt_ctrl, zq, temp_alert_cfg; | |
903 | + void __iomem *base = emif->base; | |
904 | + const struct lpddr2_addressing *addressing; | |
905 | + const struct ddr_device_info *device_info; | |
906 | + | |
907 | + device_info = emif->plat_data->device_info; | |
908 | + addressing = get_addressing_table(device_info); | |
909 | + | |
910 | + /* | |
911 | + * Init power management settings | |
912 | + * We don't know the frequency yet. Use a high frequency | |
913 | + * value for a conservative timeout setting | |
914 | + */ | |
915 | + pwr_mgmt_ctrl = get_pwr_mgmt_ctrl(1000000000, emif, | |
916 | + emif->plat_data->ip_rev); | |
917 | + emif->lpmode = (pwr_mgmt_ctrl & LP_MODE_MASK) >> LP_MODE_SHIFT; | |
918 | + writel(pwr_mgmt_ctrl, base + EMIF_POWER_MANAGEMENT_CONTROL); | |
919 | + | |
920 | + /* Init ZQ calibration settings */ | |
921 | + zq = get_zq_config_reg(addressing, device_info->cs1_used, | |
922 | + device_info->cal_resistors_per_cs); | |
923 | + writel(zq, base + EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG); | |
924 | + | |
925 | + /* Check temperature level temperature level*/ | |
926 | + get_temperature_level(emif); | |
927 | + if (emif->temperature_level == SDRAM_TEMP_VERY_HIGH_SHUTDOWN) | |
928 | + dev_emerg(emif->dev, "SDRAM temperature exceeds operating limit.. Needs shut down!!!\n"); | |
929 | + | |
930 | + /* Init temperature polling */ | |
931 | + temp_alert_cfg = get_temp_alert_config(addressing, | |
932 | + emif->plat_data->custom_configs, device_info->cs1_used, | |
933 | + device_info->io_width, get_emif_bus_width(emif)); | |
934 | + writel(temp_alert_cfg, base + EMIF_TEMPERATURE_ALERT_CONFIG); | |
935 | + | |
936 | + /* | |
937 | + * Program external PHY control registers that are not frequency | |
938 | + * dependent | |
939 | + */ | |
940 | + if (emif->plat_data->phy_type != EMIF_PHY_TYPE_INTELLIPHY) | |
941 | + return; | |
942 | + writel(EMIF_EXT_PHY_CTRL_1_VAL, base + EMIF_EXT_PHY_CTRL_1_SHDW); | |
943 | + writel(EMIF_EXT_PHY_CTRL_5_VAL, base + EMIF_EXT_PHY_CTRL_5_SHDW); | |
944 | + writel(EMIF_EXT_PHY_CTRL_6_VAL, base + EMIF_EXT_PHY_CTRL_6_SHDW); | |
945 | + writel(EMIF_EXT_PHY_CTRL_7_VAL, base + EMIF_EXT_PHY_CTRL_7_SHDW); | |
946 | + writel(EMIF_EXT_PHY_CTRL_8_VAL, base + EMIF_EXT_PHY_CTRL_8_SHDW); | |
947 | + writel(EMIF_EXT_PHY_CTRL_9_VAL, base + EMIF_EXT_PHY_CTRL_9_SHDW); | |
948 | + writel(EMIF_EXT_PHY_CTRL_10_VAL, base + EMIF_EXT_PHY_CTRL_10_SHDW); | |
949 | + writel(EMIF_EXT_PHY_CTRL_11_VAL, base + EMIF_EXT_PHY_CTRL_11_SHDW); | |
950 | + writel(EMIF_EXT_PHY_CTRL_12_VAL, base + EMIF_EXT_PHY_CTRL_12_SHDW); | |
951 | + writel(EMIF_EXT_PHY_CTRL_13_VAL, base + EMIF_EXT_PHY_CTRL_13_SHDW); | |
952 | + writel(EMIF_EXT_PHY_CTRL_14_VAL, base + EMIF_EXT_PHY_CTRL_14_SHDW); | |
953 | + writel(EMIF_EXT_PHY_CTRL_15_VAL, base + EMIF_EXT_PHY_CTRL_15_SHDW); | |
954 | + writel(EMIF_EXT_PHY_CTRL_16_VAL, base + EMIF_EXT_PHY_CTRL_16_SHDW); | |
955 | + writel(EMIF_EXT_PHY_CTRL_17_VAL, base + EMIF_EXT_PHY_CTRL_17_SHDW); | |
956 | + writel(EMIF_EXT_PHY_CTRL_18_VAL, base + EMIF_EXT_PHY_CTRL_18_SHDW); | |
957 | + writel(EMIF_EXT_PHY_CTRL_19_VAL, base + EMIF_EXT_PHY_CTRL_19_SHDW); | |
958 | + writel(EMIF_EXT_PHY_CTRL_20_VAL, base + EMIF_EXT_PHY_CTRL_20_SHDW); | |
959 | + writel(EMIF_EXT_PHY_CTRL_21_VAL, base + EMIF_EXT_PHY_CTRL_21_SHDW); | |
960 | + writel(EMIF_EXT_PHY_CTRL_22_VAL, base + EMIF_EXT_PHY_CTRL_22_SHDW); | |
961 | + writel(EMIF_EXT_PHY_CTRL_23_VAL, base + EMIF_EXT_PHY_CTRL_23_SHDW); | |
962 | + writel(EMIF_EXT_PHY_CTRL_24_VAL, base + EMIF_EXT_PHY_CTRL_24_SHDW); | |
963 | +} | |
964 | + | |
818 | 965 | static void get_default_timings(struct emif_data *emif) |
819 | 966 | { |
820 | 967 | struct emif_platform_data *pd = emif->plat_data; |
... | ... | @@ -1027,6 +1174,7 @@ |
1027 | 1174 | goto error; |
1028 | 1175 | } |
1029 | 1176 | |
1177 | + emif_onetime_settings(emif); | |
1030 | 1178 | disable_and_clear_all_interrupts(emif); |
1031 | 1179 | setup_interrupts(emif, irq); |
1032 | 1180 |