From 8865f61ad2b24ff8566de86df4ef1b1a30bb0d89 Mon Sep 17 00:00:00 2001 From: YouMin Chen Date: Mon, 5 Feb 2018 10:58:07 +0800 Subject: [PATCH] PM / devfreq: rockchip_dmc: add support for px30 Change-Id: I225088ce179f9b9cd62fce256b87bccb591fd2b2 Signed-off-by: YouMin Chen --- .../bindings/devfreq/rockchip_dmc.txt | 1 + drivers/devfreq/rockchip_dmc.c | 311 ++++++++++++++++++ include/dt-bindings/clock/rockchip-ddr.h | 2 + include/dt-bindings/memory/px30-dram.h | 132 ++++++++ 4 files changed, 446 insertions(+) create mode 100644 include/dt-bindings/memory/px30-dram.h diff --git a/Documentation/devicetree/bindings/devfreq/rockchip_dmc.txt b/Documentation/devicetree/bindings/devfreq/rockchip_dmc.txt index 23ac503752a8..59a7c2b7ce15 100644 --- a/Documentation/devicetree/bindings/devfreq/rockchip_dmc.txt +++ b/Documentation/devicetree/bindings/devfreq/rockchip_dmc.txt @@ -2,6 +2,7 @@ Required properties: - compatible: Should be one of the following. + - "rockchip,px30-dmc" - for PX30 SoCs. - "rockchip,rk3128-dmc" - for RK3128 SoCs. - "rockchip,rk3228-dmc" - for RK3228 SoCs. - "rockchip,rk3288-dmc" - for RK3288 SoCs. diff --git a/drivers/devfreq/rockchip_dmc.c b/drivers/devfreq/rockchip_dmc.c index 69b57982e7e1..b8d821a74f4a 100644 --- a/drivers/devfreq/rockchip_dmc.c +++ b/drivers/devfreq/rockchip_dmc.c @@ -100,6 +100,158 @@ struct share_params { static struct share_params *ddr_psci_param; +/* hope this define can adapt all future platfor */ +static const char * const px30_dts_timing[] = { + "ddr2_speed_bin", + "ddr3_speed_bin", + "ddr4_speed_bin", + "pd_idle", + "sr_idle", + "sr_mc_gate_idle", + "srpd_lite_idle", + "standby_idle", + + "auto_pd_dis_freq", + "auto_sr_dis_freq", + "ddr2_dll_dis_freq", + "ddr3_dll_dis_freq", + "ddr4_dll_dis_freq", + "phy_dll_dis_freq", + + "ddr2_odt_dis_freq", + "phy_ddr2_odt_dis_freq", + "ddr2_drv", + "ddr2_odt", + "phy_ddr2_ca_drv", + "phy_ddr2_ck_drv", + "phy_ddr2_dq_drv", + "phy_ddr2_odt", + + "ddr3_odt_dis_freq", + "phy_ddr3_odt_dis_freq", + "ddr3_drv", + "ddr3_odt", + "phy_ddr3_ca_drv", + "phy_ddr3_ck_drv", + "phy_ddr3_dq_drv", + "phy_ddr3_odt", + + "phy_lpddr2_odt_dis_freq", + "lpddr2_drv", + "phy_lpddr2_ca_drv", + "phy_lpddr2_ck_drv", + "phy_lpddr2_dq_drv", + "phy_lpddr2_odt", + + "lpddr3_odt_dis_freq", + "phy_lpddr3_odt_dis_freq", + "lpddr3_drv", + "lpddr3_odt", + "phy_lpddr3_ca_drv", + "phy_lpddr3_ck_drv", + "phy_lpddr3_dq_drv", + "phy_lpddr3_odt", + + "lpddr4_odt_dis_freq", + "phy_lpddr4_odt_dis_freq", + "lpddr4_drv", + "lpddr4_dq_odt", + "lpddr4_ca_odt", + "phy_lpddr4_ca_drv", + "phy_lpddr4_ck_cs_drv", + "phy_lpddr4_dq_drv", + "phy_lpddr4_odt", + + "ddr4_odt_dis_freq", + "phy_ddr4_odt_dis_freq", + "ddr4_drv", + "ddr4_odt", + "phy_ddr4_ca_drv", + "phy_ddr4_ck_drv", + "phy_ddr4_dq_drv", + "phy_ddr4_odt", +}; + +struct px30_ddr_dts_config_timing { + unsigned int ddr2_speed_bin; + unsigned int ddr3_speed_bin; + unsigned int ddr4_speed_bin; + unsigned int pd_idle; + unsigned int sr_idle; + unsigned int sr_mc_gate_idle; + unsigned int srpd_lite_idle; + unsigned int standby_idle; + + unsigned int auto_pd_dis_freq; + unsigned int auto_sr_dis_freq; + /* for ddr2 only */ + unsigned int ddr2_dll_dis_freq; + /* for ddr3 only */ + unsigned int ddr3_dll_dis_freq; + /* for ddr4 only */ + unsigned int ddr4_dll_dis_freq; + unsigned int phy_dll_dis_freq; + + unsigned int ddr2_odt_dis_freq; + unsigned int phy_ddr2_odt_dis_freq; + unsigned int ddr2_drv; + unsigned int ddr2_odt; + unsigned int phy_ddr2_ca_drv; + unsigned int phy_ddr2_ck_drv; + unsigned int phy_ddr2_dq_drv; + unsigned int phy_ddr2_odt; + + unsigned int ddr3_odt_dis_freq; + unsigned int phy_ddr3_odt_dis_freq; + unsigned int ddr3_drv; + unsigned int ddr3_odt; + unsigned int phy_ddr3_ca_drv; + unsigned int phy_ddr3_ck_drv; + unsigned int phy_ddr3_dq_drv; + unsigned int phy_ddr3_odt; + + unsigned int phy_lpddr2_odt_dis_freq; + unsigned int lpddr2_drv; + unsigned int phy_lpddr2_ca_drv; + unsigned int phy_lpddr2_ck_drv; + unsigned int phy_lpddr2_dq_drv; + unsigned int phy_lpddr2_odt; + + unsigned int lpddr3_odt_dis_freq; + unsigned int phy_lpddr3_odt_dis_freq; + unsigned int lpddr3_drv; + unsigned int lpddr3_odt; + unsigned int phy_lpddr3_ca_drv; + unsigned int phy_lpddr3_ck_drv; + unsigned int phy_lpddr3_dq_drv; + unsigned int phy_lpddr3_odt; + + unsigned int lpddr4_odt_dis_freq; + unsigned int phy_lpddr4_odt_dis_freq; + unsigned int lpddr4_drv; + unsigned int lpddr4_dq_odt; + unsigned int lpddr4_ca_odt; + unsigned int phy_lpddr4_ca_drv; + unsigned int phy_lpddr4_ck_cs_drv; + unsigned int phy_lpddr4_dq_drv; + unsigned int phy_lpddr4_odt; + + unsigned int ddr4_odt_dis_freq; + unsigned int phy_ddr4_odt_dis_freq; + unsigned int ddr4_drv; + unsigned int ddr4_odt; + unsigned int phy_ddr4_ca_drv; + unsigned int phy_ddr4_ck_drv; + unsigned int phy_ddr4_dq_drv; + unsigned int phy_ddr4_odt; + + unsigned int ca_skew[15]; + unsigned int cs0_skew[44]; + unsigned int cs1_skew[44]; + + unsigned int available; +}; + static const char * const rk3128_dts_timing[] = { "ddr3_speed_bin", "pd_idle", @@ -643,6 +795,61 @@ struct rockchip_dmcfreq { int (*set_auto_self_refresh)(u32 en); }; +/* + * function: packaging de-skew setting to px30_ddr_dts_config_timing, + * px30_ddr_dts_config_timing will pass to trust firmware, and + * used direct to set register. + * input: de_skew + * output: tim + */ +static void px30_de_skew_set_2_reg(struct rk3328_ddr_de_skew_setting *de_skew, + struct px30_ddr_dts_config_timing *tim) +{ + u32 n; + u32 offset; + u32 shift; + + memset_io(tim->ca_skew, 0, sizeof(tim->ca_skew)); + memset_io(tim->cs0_skew, 0, sizeof(tim->cs0_skew)); + memset_io(tim->cs1_skew, 0, sizeof(tim->cs1_skew)); + + /* CA de-skew */ + for (n = 0; n < ARRAY_SIZE(de_skew->ca_de_skew); n++) { + offset = n / 2; + shift = n % 2; + /* 0 => 4; 1 => 0 */ + shift = (shift == 0) ? 4 : 0; + tim->ca_skew[offset] &= ~(0xf << shift); + tim->ca_skew[offset] |= (de_skew->ca_de_skew[n] << shift); + } + + /* CS0 data de-skew */ + for (n = 0; n < ARRAY_SIZE(de_skew->cs0_de_skew); n++) { + offset = ((n / 21) * 11) + ((n % 21) / 2); + shift = ((n % 21) % 2); + if ((n % 21) == 20) + shift = 0; + else + /* 0 => 4; 1 => 0 */ + shift = (shift == 0) ? 4 : 0; + tim->cs0_skew[offset] &= ~(0xf << shift); + tim->cs0_skew[offset] |= (de_skew->cs0_de_skew[n] << shift); + } + + /* CS1 data de-skew */ + for (n = 0; n < ARRAY_SIZE(de_skew->cs1_de_skew); n++) { + offset = ((n / 21) * 11) + ((n % 21) / 2); + shift = ((n % 21) % 2); + if ((n % 21) == 20) + shift = 0; + else + /* 0 => 4; 1 => 0 */ + shift = (shift == 0) ? 4 : 0; + tim->cs1_skew[offset] &= ~(0xf << shift); + tim->cs1_skew[offset] |= (de_skew->cs1_de_skew[n] << shift); + } +} + /* * function: packaging de-skew setting to rk3328_ddr_dts_config_timing, * rk3328_ddr_dts_config_timing will pass to trust firmware, and @@ -959,6 +1166,64 @@ static inline void reset_last_status(struct devfreq *devfreq) devfreq->last_status.busy_time = 1; } +static void of_get_px30_timings(struct device *dev, + struct device_node *np, uint32_t *timing) +{ + struct device_node *np_tim; + u32 *p; + struct px30_ddr_dts_config_timing *dts_timing; + struct rk3328_ddr_de_skew_setting *de_skew; + int ret = 0; + u32 i; + + dts_timing = + (struct px30_ddr_dts_config_timing *)(timing + + DTS_PAR_OFFSET / 4); + + np_tim = of_parse_phandle(np, "ddr_timing", 0); + if (!np_tim) { + ret = -EINVAL; + goto end; + } + de_skew = kmalloc(sizeof(*de_skew), GFP_KERNEL); + if (!de_skew) { + ret = -ENOMEM; + goto end; + } + p = (u32 *)dts_timing; + for (i = 0; i < ARRAY_SIZE(px30_dts_timing); i++) { + ret |= of_property_read_u32(np_tim, px30_dts_timing[i], + p + i); + } + p = (u32 *)de_skew->ca_de_skew; + for (i = 0; i < ARRAY_SIZE(rk3328_dts_ca_timing); i++) { + ret |= of_property_read_u32(np_tim, rk3328_dts_ca_timing[i], + p + i); + } + p = (u32 *)de_skew->cs0_de_skew; + for (i = 0; i < ARRAY_SIZE(rk3328_dts_cs0_timing); i++) { + ret |= of_property_read_u32(np_tim, rk3328_dts_cs0_timing[i], + p + i); + } + p = (u32 *)de_skew->cs1_de_skew; + for (i = 0; i < ARRAY_SIZE(rk3328_dts_cs1_timing); i++) { + ret |= of_property_read_u32(np_tim, rk3328_dts_cs1_timing[i], + p + i); + } + if (!ret) + px30_de_skew_set_2_reg(de_skew, dts_timing); + kfree(de_skew); +end: + if (!ret) { + dts_timing->available = 1; + } else { + dts_timing->available = 0; + dev_err(dev, "of_get_ddr_timings: fail\n"); + } + + of_node_put(np_tim); +} + static void of_get_rk3128_timings(struct device *dev, struct device_node *np, uint32_t *timing) { @@ -1303,6 +1568,51 @@ static int rockchip_ddr_set_auto_self_refresh(uint32_t en) return res.a0; } +static int px30_dmc_init(struct platform_device *pdev, + struct rockchip_dmcfreq *dmcfreq) +{ + struct arm_smccc_res res; + u32 size; + + res = sip_smc_dram(0, 0, + ROCKCHIP_SIP_CONFIG_DRAM_GET_VERSION); + dev_notice(&pdev->dev, "current ATF version 0x%lx!\n", res.a1); + if (res.a0 || res.a1 < 0x101) { + dev_err(&pdev->dev, + "trusted firmware need to update or is invalid!\n"); + return -ENXIO; + } + + dev_notice(&pdev->dev, "read tf version 0x%lx!\n", res.a1); + + /* + * first 4KB is used for interface parameters + * after 4KB * N is dts parameters + */ + size = sizeof(struct px30_ddr_dts_config_timing); + res = sip_smc_request_share_mem(DIV_ROUND_UP(size, 4096) + 1, + SHARE_PAGE_TYPE_DDR); + if (res.a0 != 0) { + dev_err(&pdev->dev, "no ATF memory for init\n"); + return -ENOMEM; + } + ddr_psci_param = (struct share_params *)res.a1; + of_get_px30_timings(&pdev->dev, pdev->dev.of_node, + (uint32_t *)ddr_psci_param); + + res = sip_smc_dram(SHARE_PAGE_TYPE_DDR, 0, + ROCKCHIP_SIP_CONFIG_DRAM_INIT); + if (res.a0) { + dev_err(&pdev->dev, "rockchip_sip_config_dram_init error:%lx\n", + res.a0); + return -ENOMEM; + } + + dmcfreq->set_auto_self_refresh = rockchip_ddr_set_auto_self_refresh; + + return 0; +} + static int rk3128_dmc_init(struct platform_device *pdev, struct rockchip_dmcfreq *dmcfreq) { @@ -1610,6 +1920,7 @@ static int rk3399_dmc_init(struct platform_device *pdev) } static const struct of_device_id rockchip_dmcfreq_of_match[] = { + { .compatible = "rockchip,px30-dmc", .data = px30_dmc_init }, { .compatible = "rockchip,rk3128-dmc", .data = rk3128_dmc_init }, { .compatible = "rockchip,rk3228-dmc", .data = rk3228_dmc_init }, { .compatible = "rockchip,rk3288-dmc", .data = rk3288_dmc_init }, diff --git a/include/dt-bindings/clock/rockchip-ddr.h b/include/dt-bindings/clock/rockchip-ddr.h index 08c7a850ae5b..b065432e7793 100644 --- a/include/dt-bindings/clock/rockchip-ddr.h +++ b/include/dt-bindings/clock/rockchip-ddr.h @@ -16,6 +16,8 @@ #ifndef _DT_BINDINGS_CLOCK_ROCKCHIP_DDR_H #define _DT_BINDINGS_CLOCK_ROCKCHIP_DDR_H +#define DDR2_DEFAULT (0) + #define DDR3_800D (0) /* 5-5-5 */ #define DDR3_800E (1) /* 6-6-6 */ #define DDR3_1066E (2) /* 6-6-6 */ diff --git a/include/dt-bindings/memory/px30-dram.h b/include/dt-bindings/memory/px30-dram.h new file mode 100644 index 000000000000..17d799d802d9 --- /dev/null +++ b/include/dt-bindings/memory/px30-dram.h @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2018 Fuzhou Rockchip Electronics Co., Ltd + * + * SPDX-License-Identifier: (GPL-2.0+ OR MIT) + */ + +#ifndef _DT_BINDINGS_DRAM_ROCKCHIP_PX30_H +#define _DT_BINDINGS_DRAM_ROCKCHIP_PX30_H + +#define DDR2_DS_FULL (0) +#define DDR2_DS_REDUCE (1) + +#define DDR2_ODT_DIS (0) +#define DDR2_ODT_50ohm (50) /* optional */ +#define DDR2_ODT_75ohm (75) +#define DDR2_ODT_150ohm (150) + +#define DDR3_DS_34ohm (34) +#define DDR3_DS_40ohm (40) + +#define DDR3_ODT_DIS (0) +#define DDR3_ODT_40ohm (40) +#define DDR3_ODT_60ohm (60) +#define DDR3_ODT_120ohm (120) + +#define LP2_DS_34ohm (34) +#define LP2_DS_40ohm (40) +#define LP2_DS_48ohm (48) +#define LP2_DS_60ohm (60) +#define LP2_DS_68_6ohm (68) /* optional */ +#define LP2_DS_80ohm (80) +#define LP2_DS_120ohm (120) /* optional */ + +#define LP3_DS_34ohm (34) +#define LP3_DS_40ohm (40) +#define LP3_DS_48ohm (48) +#define LP3_DS_60ohm (60) +#define LP3_DS_80ohm (80) +#define LP3_DS_34D_40U (3440) +#define LP3_DS_40D_48U (4048) +#define LP3_DS_34D_48U (3448) + +#define LP3_ODT_DIS (0) +#define LP3_ODT_60ohm (60) +#define LP3_ODT_120ohm (120) +#define LP3_ODT_240ohm (240) + +#define LP4_PDDS_40ohm (40) +#define LP4_PDDS_48ohm (48) +#define LP4_PDDS_60ohm (60) +#define LP4_PDDS_80ohm (80) +#define LP4_PDDS_120ohm (120) +#define LP4_PDDS_240ohm (240) + +#define LP4_DQ_ODT_40ohm (40) +#define LP4_DQ_ODT_48ohm (48) +#define LP4_DQ_ODT_60ohm (60) +#define LP4_DQ_ODT_80ohm (80) +#define LP4_DQ_ODT_120ohm (120) +#define LP4_DQ_ODT_240ohm (240) +#define LP4_DQ_ODT_DIS (0) + +#define LP4_CA_ODT_40ohm (40) +#define LP4_CA_ODT_48ohm (48) +#define LP4_CA_ODT_60ohm (60) +#define LP4_CA_ODT_80ohm (80) +#define LP4_CA_ODT_120ohm (120) +#define LP4_CA_ODT_240ohm (240) +#define LP4_CA_ODT_DIS (0) + +#define DDR4_DS_34ohm (34) +#define DDR4_DS_48ohm (48) +#define DDR4_RTT_NOM_DIS (0) +#define DDR4_RTT_NOM_60ohm (60) +#define DDR4_RTT_NOM_120ohm (120) +#define DDR4_RTT_NOM_40ohm (40) +#define DDR4_RTT_NOM_240ohm (240) +#define DDR4_RTT_NOM_48ohm (48) +#define DDR4_RTT_NOM_80ohm (80) +#define DDR4_RTT_NOM_34ohm (34) + +#define PHY_DDR3_RON_RTT_DISABLE (0) +#define PHY_DDR3_RON_RTT_451ohm (1) +#define PHY_DDR3_RON_RTT_225ohm (2) +#define PHY_DDR3_RON_RTT_150ohm (3) +#define PHY_DDR3_RON_RTT_112ohm (4) +#define PHY_DDR3_RON_RTT_90ohm (5) +#define PHY_DDR3_RON_RTT_75ohm (6) +#define PHY_DDR3_RON_RTT_64ohm (7) +#define PHY_DDR3_RON_RTT_56ohm (16) +#define PHY_DDR3_RON_RTT_50ohm (17) +#define PHY_DDR3_RON_RTT_45ohm (18) +#define PHY_DDR3_RON_RTT_41ohm (19) +#define PHY_DDR3_RON_RTT_37ohm (20) +#define PHY_DDR3_RON_RTT_34ohm (21) +#define PHY_DDR3_RON_RTT_33ohm (22) +#define PHY_DDR3_RON_RTT_30ohm (23) +#define PHY_DDR3_RON_RTT_28ohm (24) +#define PHY_DDR3_RON_RTT_26ohm (25) +#define PHY_DDR3_RON_RTT_25ohm (26) +#define PHY_DDR3_RON_RTT_23ohm (27) +#define PHY_DDR3_RON_RTT_22ohm (28) +#define PHY_DDR3_RON_RTT_21ohm (29) +#define PHY_DDR3_RON_RTT_20ohm (30) +#define PHY_DDR3_RON_RTT_19ohm (31) + +#define PHY_DDR4_LPDDR3_2_RON_RTT_DISABLE (0) +#define PHY_DDR4_LPDDR3_2_RON_RTT_480ohm (1) +#define PHY_DDR4_LPDDR3_2_RON_RTT_240ohm (2) +#define PHY_DDR4_LPDDR3_2_RON_RTT_160ohm (3) +#define PHY_DDR4_LPDDR3_2_RON_RTT_120ohm (4) +#define PHY_DDR4_LPDDR3_2_RON_RTT_96ohm (5) +#define PHY_DDR4_LPDDR3_2_RON_RTT_80ohm (6) +#define PHY_DDR4_LPDDR3_2_RON_RTT_68ohm (7) +#define PHY_DDR4_LPDDR3_2_RON_RTT_60ohm (16) +#define PHY_DDR4_LPDDR3_2_RON_RTT_53ohm (17) +#define PHY_DDR4_LPDDR3_2_RON_RTT_48ohm (18) +#define PHY_DDR4_LPDDR3_2_RON_RTT_43ohm (19) +#define PHY_DDR4_LPDDR3_2_RON_RTT_40ohm (20) +#define PHY_DDR4_LPDDR3_2_RON_RTT_37ohm (21) +#define PHY_DDR4_LPDDR3_2_RON_RTT_34ohm (22) +#define PHY_DDR4_LPDDR3_2_RON_RTT_32ohm (23) +#define PHY_DDR4_LPDDR3_2_RON_RTT_30ohm (24) +#define PHY_DDR4_LPDDR3_2_RON_RTT_28ohm (25) +#define PHY_DDR4_LPDDR3_2_RON_RTT_26ohm (26) +#define PHY_DDR4_LPDDR3_2_RON_RTT_25ohm (27) +#define PHY_DDR4_LPDDR3_2_RON_RTT_24ohm (28) +#define PHY_DDR4_LPDDR3_2_RON_RTT_22ohm (29) +#define PHY_DDR4_LPDDR3_2_RON_RTT_21ohm (30) +#define PHY_DDR4_LPDDR3_2_RON_RTT_20ohm (31) + +#endif /*_DT_BINDINGS_DRAM_ROCKCHIP_PX30_H*/