diff options
author | Aneesh V <aneesh@ti.com> | 2012-04-27 08:24:08 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-05-02 13:58:12 -0400 |
commit | 98231c4fc3b95a0e9d37ba3711ad993bb27605c8 (patch) | |
tree | a7411f99c7a9dba51095ae4f7fb1acf76666f268 /drivers/memory/emif.c | |
parent | 68b4aee35d1fb8399068aa6e6c908584690d0b06 (diff) |
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>
Diffstat (limited to 'drivers/memory/emif.c')
-rw-r--r-- | drivers/memory/emif.c | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c index a8dcf3515573..3dfffbb8ab40 100644 --- a/drivers/memory/emif.c +++ b/drivers/memory/emif.c | |||
@@ -78,6 +78,24 @@ static void set_ddr_clk_period(u32 freq) | |||
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 | * Get the CL from SDRAM_CONFIG register | 99 | * Get the CL from SDRAM_CONFIG register |
82 | */ | 100 | */ |
83 | static u32 get_cl(struct emif_data *emif) | 101 | static u32 get_cl(struct emif_data *emif) |
@@ -372,6 +390,70 @@ static u32 get_sdram_tim_3_shdw(const struct lpddr2_timings *timings, | |||
372 | return tim3; | 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 | static u32 get_read_idle_ctrl_shdw(u8 volt_ramp) | 457 | static u32 get_read_idle_ctrl_shdw(u8 volt_ramp) |
376 | { | 458 | { |
377 | u32 idle = 0, val = 0; | 459 | u32 idle = 0, val = 0; |
@@ -815,6 +897,71 @@ static int __init_or_module setup_interrupts(struct emif_data *emif, u32 irq) | |||
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 | static void get_default_timings(struct emif_data *emif) | 965 | static void get_default_timings(struct emif_data *emif) |
819 | { | 966 | { |
820 | struct emif_platform_data *pd = emif->plat_data; | 967 | struct emif_platform_data *pd = emif->plat_data; |
@@ -1027,6 +1174,7 @@ static int __init_or_module emif_probe(struct platform_device *pdev) | |||
1027 | goto error; | 1174 | goto error; |
1028 | } | 1175 | } |
1029 | 1176 | ||
1177 | emif_onetime_settings(emif); | ||
1030 | disable_and_clear_all_interrupts(emif); | 1178 | disable_and_clear_all_interrupts(emif); |
1031 | setup_interrupts(emif, irq); | 1179 | setup_interrupts(emif, irq); |
1032 | 1180 | ||