- materialized overwrites:
- `add-board-helios64.patch`
- `add-board-orangepi-r1-plus.patch`
- `add-driver-for-Motorcomm-YT85xx+PHYs.patch`
- `add-board-rk3328-roc-pc.patch`
- not touched: wifi patches, those still require work before rebase is consistent.
- `wifi-4003-uwe5622-adjust-for-rockchip.patch`
- this patch is done on top of the wifi drivers patches exclusively, and fails to apply out of tree.
- we should probably consider moving this into the wifi drivers patch harness, not in the rockchip tree.
2389 lines
67 KiB
Diff
2389 lines
67 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Paolo Sabatino <paolo.sabatino@gmail.com>
|
|
Date: Tue, 12 Oct 2021 18:45:05 +0000
|
|
Subject: rk3328 dmc driver
|
|
|
|
---
|
|
arch/arm64/boot/dts/rockchip/rk3328-dram-default-timing.dtsi | 311 ++++
|
|
arch/arm64/boot/dts/rockchip/rk3328.dtsi | 61 +
|
|
drivers/clk/rockchip/clk-ddr.c | 131 ++
|
|
drivers/clk/rockchip/clk-rk3328.c | 13 +-
|
|
drivers/clk/rockchip/clk.h | 3 +-
|
|
drivers/devfreq/Kconfig | 12 +
|
|
drivers/devfreq/Makefile | 1 +
|
|
drivers/devfreq/event/rockchip-dfi.c | 554 +++++-
|
|
drivers/devfreq/rk3328_dmc.c | 836 ++++++++++
|
|
include/dt-bindings/clock/rockchip-ddr.h | 63 +
|
|
include/dt-bindings/memory/rk3328-dram.h | 159 ++
|
|
include/soc/rockchip/rockchip_sip.h | 11 +
|
|
12 files changed, 2099 insertions(+), 56 deletions(-)
|
|
|
|
diff --git a/arch/arm64/boot/dts/rockchip/rk3328-dram-default-timing.dtsi b/arch/arm64/boot/dts/rockchip/rk3328-dram-default-timing.dtsi
|
|
new file mode 100644
|
|
index 000000000000..a3f5ff4bdc47
|
|
--- /dev/null
|
|
+++ b/arch/arm64/boot/dts/rockchip/rk3328-dram-default-timing.dtsi
|
|
@@ -0,0 +1,311 @@
|
|
+/*
|
|
+ * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd
|
|
+ *
|
|
+ * This file is dual-licensed: you can use it either under the terms
|
|
+ * of the GPL or the X11 license, at your option. Note that this dual
|
|
+ * licensing only applies to this file, and not this project as a
|
|
+ * whole.
|
|
+ *
|
|
+ * a) This library is free software; you can redistribute it and/or
|
|
+ * modify it under the terms of the GNU General Public License as
|
|
+ * published by the Free Software Foundation; either version 2 of the
|
|
+ * License, or (at your option) any later version.
|
|
+ *
|
|
+ * This library is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ * GNU General Public License for more details.
|
|
+ *
|
|
+ * Or, alternatively,
|
|
+ *
|
|
+ * b) Permission is hereby granted, free of charge, to any person
|
|
+ * obtaining a copy of this software and associated documentation
|
|
+ * files (the "Software"), to deal in the Software without
|
|
+ * restriction, including without limitation the rights to use,
|
|
+ * copy, modify, merge, publish, distribute, sublicense, and/or
|
|
+ * sell copies of the Software, and to permit persons to whom the
|
|
+ * Software is furnished to do so, subject to the following
|
|
+ * conditions:
|
|
+ *
|
|
+ * The above copyright notice and this permission notice shall be
|
|
+ * included in all copies or substantial portions of the Software.
|
|
+ *
|
|
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
+ * OTHER DEALINGS IN THE SOFTWARE.
|
|
+ */
|
|
+#include <dt-bindings/clock/rockchip-ddr.h>
|
|
+#include <dt-bindings/memory/rk3328-dram.h>
|
|
+
|
|
+/ {
|
|
+ ddr_timing: ddr_timing {
|
|
+ compatible = "rockchip,ddr-timing";
|
|
+ ddr3_speed_bin = <DDR3_DEFAULT>;
|
|
+ ddr4_speed_bin = <DDR4_DEFAULT>;
|
|
+ pd_idle = <0>;
|
|
+ sr_idle = <0>;
|
|
+ sr_mc_gate_idle = <0>;
|
|
+ srpd_lite_idle = <0>;
|
|
+ standby_idle = <0>;
|
|
+
|
|
+ auto_pd_dis_freq = <1066>;
|
|
+ auto_sr_dis_freq = <800>;
|
|
+ ddr3_dll_dis_freq = <300>;
|
|
+ ddr4_dll_dis_freq = <625>;
|
|
+ phy_dll_dis_freq = <400>;
|
|
+
|
|
+ ddr3_odt_dis_freq = <100>;
|
|
+ phy_ddr3_odt_dis_freq = <100>;
|
|
+ ddr3_drv = <DDR3_DS_40ohm>;
|
|
+ ddr3_odt = <DDR3_ODT_120ohm>;
|
|
+ phy_ddr3_ca_drv = <PHY_DDR3_RON_RTT_34ohm>;
|
|
+ phy_ddr3_ck_drv = <PHY_DDR3_RON_RTT_45ohm>;
|
|
+ phy_ddr3_dq_drv = <PHY_DDR3_RON_RTT_34ohm>;
|
|
+ phy_ddr3_odt = <PHY_DDR3_RON_RTT_225ohm>;
|
|
+
|
|
+ lpddr3_odt_dis_freq = <666>;
|
|
+ phy_lpddr3_odt_dis_freq = <666>;
|
|
+ lpddr3_drv = <LP3_DS_40ohm>;
|
|
+ lpddr3_odt = <LP3_ODT_240ohm>;
|
|
+ phy_lpddr3_ca_drv = <PHY_DDR4_LPDDR3_RON_RTT_34ohm>;
|
|
+ phy_lpddr3_ck_drv = <PHY_DDR4_LPDDR3_RON_RTT_43ohm>;
|
|
+ phy_lpddr3_dq_drv = <PHY_DDR4_LPDDR3_RON_RTT_34ohm>;
|
|
+ phy_lpddr3_odt = <PHY_DDR4_LPDDR3_RON_RTT_240ohm>;
|
|
+
|
|
+ lpddr4_odt_dis_freq = <800>;
|
|
+ phy_lpddr4_odt_dis_freq = <800>;
|
|
+ lpddr4_drv = <LP4_PDDS_60ohm>;
|
|
+ lpddr4_dq_odt = <LP4_DQ_ODT_40ohm>;
|
|
+ lpddr4_ca_odt = <LP4_CA_ODT_40ohm>;
|
|
+ phy_lpddr4_ca_drv = <PHY_DDR4_LPDDR3_RON_RTT_40ohm>;
|
|
+ phy_lpddr4_ck_cs_drv = <PHY_DDR4_LPDDR3_RON_RTT_80ohm>;
|
|
+ phy_lpddr4_dq_drv = <PHY_DDR4_LPDDR3_RON_RTT_80ohm>;
|
|
+ phy_lpddr4_odt = <PHY_DDR4_LPDDR3_RON_RTT_60ohm>;
|
|
+
|
|
+ ddr4_odt_dis_freq = <666>;
|
|
+ phy_ddr4_odt_dis_freq = <666>;
|
|
+ ddr4_drv = <DDR4_DS_34ohm>;
|
|
+ ddr4_odt = <DDR4_RTT_NOM_240ohm>;
|
|
+ phy_ddr4_ca_drv = <PHY_DDR4_LPDDR3_RON_RTT_34ohm>;
|
|
+ phy_ddr4_ck_drv = <PHY_DDR4_LPDDR3_RON_RTT_43ohm>;
|
|
+ phy_ddr4_dq_drv = <PHY_DDR4_LPDDR3_RON_RTT_34ohm>;
|
|
+ phy_ddr4_odt = <PHY_DDR4_LPDDR3_RON_RTT_240ohm>;
|
|
+
|
|
+ /* CA de-skew, one step is 47.8ps, range 0-15 */
|
|
+ ddr3a1_ddr4a9_de-skew = <7>;
|
|
+ ddr3a0_ddr4a10_de-skew = <7>;
|
|
+ ddr3a3_ddr4a6_de-skew = <8>;
|
|
+ ddr3a2_ddr4a4_de-skew = <8>;
|
|
+ ddr3a5_ddr4a8_de-skew = <7>;
|
|
+ ddr3a4_ddr4a5_de-skew = <9>;
|
|
+ ddr3a7_ddr4a11_de-skew = <7>;
|
|
+ ddr3a6_ddr4a7_de-skew = <9>;
|
|
+ ddr3a9_ddr4a0_de-skew = <8>;
|
|
+ ddr3a8_ddr4a13_de-skew = <7>;
|
|
+ ddr3a11_ddr4a3_de-skew = <9>;
|
|
+ ddr3a10_ddr4cs0_de-skew = <7>;
|
|
+ ddr3a13_ddr4a2_de-skew = <8>;
|
|
+ ddr3a12_ddr4ba1_de-skew = <7>;
|
|
+ ddr3a15_ddr4odt0_de-skew = <7>;
|
|
+ ddr3a14_ddr4a1_de-skew = <8>;
|
|
+ ddr3ba1_ddr4a15_de-skew = <7>;
|
|
+ ddr3ba0_ddr4bg0_de-skew = <7>;
|
|
+ ddr3ras_ddr4cke_de-skew = <7>;
|
|
+ ddr3ba2_ddr4ba0_de-skew = <8>;
|
|
+ ddr3we_ddr4bg1_de-skew = <8>;
|
|
+ ddr3cas_ddr4a12_de-skew = <7>;
|
|
+ ddr3ckn_ddr4ckn_de-skew = <8>;
|
|
+ ddr3ckp_ddr4ckp_de-skew = <8>;
|
|
+ ddr3cke_ddr4a16_de-skew = <8>;
|
|
+ ddr3odt0_ddr4a14_de-skew = <7>;
|
|
+ ddr3cs0_ddr4act_de-skew = <8>;
|
|
+ ddr3reset_ddr4reset_de-skew = <7>;
|
|
+ ddr3cs1_ddr4cs1_de-skew = <7>;
|
|
+ ddr3odt1_ddr4odt1_de-skew = <7>;
|
|
+
|
|
+ /* DATA de-skew
|
|
+ * RX one step is 25.1ps, range 0-15
|
|
+ * TX one step is 47.8ps, range 0-15
|
|
+ */
|
|
+ cs0_dm0_rx_de-skew = <7>;
|
|
+ cs0_dm0_tx_de-skew = <8>;
|
|
+ cs0_dq0_rx_de-skew = <7>;
|
|
+ cs0_dq0_tx_de-skew = <8>;
|
|
+ cs0_dq1_rx_de-skew = <7>;
|
|
+ cs0_dq1_tx_de-skew = <8>;
|
|
+ cs0_dq2_rx_de-skew = <7>;
|
|
+ cs0_dq2_tx_de-skew = <8>;
|
|
+ cs0_dq3_rx_de-skew = <7>;
|
|
+ cs0_dq3_tx_de-skew = <8>;
|
|
+ cs0_dq4_rx_de-skew = <7>;
|
|
+ cs0_dq4_tx_de-skew = <8>;
|
|
+ cs0_dq5_rx_de-skew = <7>;
|
|
+ cs0_dq5_tx_de-skew = <8>;
|
|
+ cs0_dq6_rx_de-skew = <7>;
|
|
+ cs0_dq6_tx_de-skew = <8>;
|
|
+ cs0_dq7_rx_de-skew = <7>;
|
|
+ cs0_dq7_tx_de-skew = <8>;
|
|
+ cs0_dqs0_rx_de-skew = <6>;
|
|
+ cs0_dqs0p_tx_de-skew = <9>;
|
|
+ cs0_dqs0n_tx_de-skew = <9>;
|
|
+
|
|
+ cs0_dm1_rx_de-skew = <7>;
|
|
+ cs0_dm1_tx_de-skew = <7>;
|
|
+ cs0_dq8_rx_de-skew = <7>;
|
|
+ cs0_dq8_tx_de-skew = <8>;
|
|
+ cs0_dq9_rx_de-skew = <7>;
|
|
+ cs0_dq9_tx_de-skew = <7>;
|
|
+ cs0_dq10_rx_de-skew = <7>;
|
|
+ cs0_dq10_tx_de-skew = <8>;
|
|
+ cs0_dq11_rx_de-skew = <7>;
|
|
+ cs0_dq11_tx_de-skew = <7>;
|
|
+ cs0_dq12_rx_de-skew = <7>;
|
|
+ cs0_dq12_tx_de-skew = <8>;
|
|
+ cs0_dq13_rx_de-skew = <7>;
|
|
+ cs0_dq13_tx_de-skew = <7>;
|
|
+ cs0_dq14_rx_de-skew = <7>;
|
|
+ cs0_dq14_tx_de-skew = <8>;
|
|
+ cs0_dq15_rx_de-skew = <7>;
|
|
+ cs0_dq15_tx_de-skew = <7>;
|
|
+ cs0_dqs1_rx_de-skew = <7>;
|
|
+ cs0_dqs1p_tx_de-skew = <9>;
|
|
+ cs0_dqs1n_tx_de-skew = <9>;
|
|
+
|
|
+ cs0_dm2_rx_de-skew = <7>;
|
|
+ cs0_dm2_tx_de-skew = <8>;
|
|
+ cs0_dq16_rx_de-skew = <7>;
|
|
+ cs0_dq16_tx_de-skew = <8>;
|
|
+ cs0_dq17_rx_de-skew = <7>;
|
|
+ cs0_dq17_tx_de-skew = <8>;
|
|
+ cs0_dq18_rx_de-skew = <7>;
|
|
+ cs0_dq18_tx_de-skew = <8>;
|
|
+ cs0_dq19_rx_de-skew = <7>;
|
|
+ cs0_dq19_tx_de-skew = <8>;
|
|
+ cs0_dq20_rx_de-skew = <7>;
|
|
+ cs0_dq20_tx_de-skew = <8>;
|
|
+ cs0_dq21_rx_de-skew = <7>;
|
|
+ cs0_dq21_tx_de-skew = <8>;
|
|
+ cs0_dq22_rx_de-skew = <7>;
|
|
+ cs0_dq22_tx_de-skew = <8>;
|
|
+ cs0_dq23_rx_de-skew = <7>;
|
|
+ cs0_dq23_tx_de-skew = <8>;
|
|
+ cs0_dqs2_rx_de-skew = <6>;
|
|
+ cs0_dqs2p_tx_de-skew = <9>;
|
|
+ cs0_dqs2n_tx_de-skew = <9>;
|
|
+
|
|
+ cs0_dm3_rx_de-skew = <7>;
|
|
+ cs0_dm3_tx_de-skew = <7>;
|
|
+ cs0_dq24_rx_de-skew = <7>;
|
|
+ cs0_dq24_tx_de-skew = <8>;
|
|
+ cs0_dq25_rx_de-skew = <7>;
|
|
+ cs0_dq25_tx_de-skew = <7>;
|
|
+ cs0_dq26_rx_de-skew = <7>;
|
|
+ cs0_dq26_tx_de-skew = <7>;
|
|
+ cs0_dq27_rx_de-skew = <7>;
|
|
+ cs0_dq27_tx_de-skew = <7>;
|
|
+ cs0_dq28_rx_de-skew = <7>;
|
|
+ cs0_dq28_tx_de-skew = <7>;
|
|
+ cs0_dq29_rx_de-skew = <7>;
|
|
+ cs0_dq29_tx_de-skew = <7>;
|
|
+ cs0_dq30_rx_de-skew = <7>;
|
|
+ cs0_dq30_tx_de-skew = <7>;
|
|
+ cs0_dq31_rx_de-skew = <7>;
|
|
+ cs0_dq31_tx_de-skew = <7>;
|
|
+ cs0_dqs3_rx_de-skew = <7>;
|
|
+ cs0_dqs3p_tx_de-skew = <9>;
|
|
+ cs0_dqs3n_tx_de-skew = <9>;
|
|
+
|
|
+ cs1_dm0_rx_de-skew = <7>;
|
|
+ cs1_dm0_tx_de-skew = <8>;
|
|
+ cs1_dq0_rx_de-skew = <7>;
|
|
+ cs1_dq0_tx_de-skew = <8>;
|
|
+ cs1_dq1_rx_de-skew = <7>;
|
|
+ cs1_dq1_tx_de-skew = <8>;
|
|
+ cs1_dq2_rx_de-skew = <7>;
|
|
+ cs1_dq2_tx_de-skew = <8>;
|
|
+ cs1_dq3_rx_de-skew = <7>;
|
|
+ cs1_dq3_tx_de-skew = <8>;
|
|
+ cs1_dq4_rx_de-skew = <7>;
|
|
+ cs1_dq4_tx_de-skew = <8>;
|
|
+ cs1_dq5_rx_de-skew = <7>;
|
|
+ cs1_dq5_tx_de-skew = <8>;
|
|
+ cs1_dq6_rx_de-skew = <7>;
|
|
+ cs1_dq6_tx_de-skew = <8>;
|
|
+ cs1_dq7_rx_de-skew = <7>;
|
|
+ cs1_dq7_tx_de-skew = <8>;
|
|
+ cs1_dqs0_rx_de-skew = <6>;
|
|
+ cs1_dqs0p_tx_de-skew = <9>;
|
|
+ cs1_dqs0n_tx_de-skew = <9>;
|
|
+
|
|
+ cs1_dm1_rx_de-skew = <7>;
|
|
+ cs1_dm1_tx_de-skew = <7>;
|
|
+ cs1_dq8_rx_de-skew = <7>;
|
|
+ cs1_dq8_tx_de-skew = <8>;
|
|
+ cs1_dq9_rx_de-skew = <7>;
|
|
+ cs1_dq9_tx_de-skew = <7>;
|
|
+ cs1_dq10_rx_de-skew = <7>;
|
|
+ cs1_dq10_tx_de-skew = <8>;
|
|
+ cs1_dq11_rx_de-skew = <7>;
|
|
+ cs1_dq11_tx_de-skew = <7>;
|
|
+ cs1_dq12_rx_de-skew = <7>;
|
|
+ cs1_dq12_tx_de-skew = <8>;
|
|
+ cs1_dq13_rx_de-skew = <7>;
|
|
+ cs1_dq13_tx_de-skew = <7>;
|
|
+ cs1_dq14_rx_de-skew = <7>;
|
|
+ cs1_dq14_tx_de-skew = <8>;
|
|
+ cs1_dq15_rx_de-skew = <7>;
|
|
+ cs1_dq15_tx_de-skew = <7>;
|
|
+ cs1_dqs1_rx_de-skew = <7>;
|
|
+ cs1_dqs1p_tx_de-skew = <9>;
|
|
+ cs1_dqs1n_tx_de-skew = <9>;
|
|
+
|
|
+ cs1_dm2_rx_de-skew = <7>;
|
|
+ cs1_dm2_tx_de-skew = <8>;
|
|
+ cs1_dq16_rx_de-skew = <7>;
|
|
+ cs1_dq16_tx_de-skew = <8>;
|
|
+ cs1_dq17_rx_de-skew = <7>;
|
|
+ cs1_dq17_tx_de-skew = <8>;
|
|
+ cs1_dq18_rx_de-skew = <7>;
|
|
+ cs1_dq18_tx_de-skew = <8>;
|
|
+ cs1_dq19_rx_de-skew = <7>;
|
|
+ cs1_dq19_tx_de-skew = <8>;
|
|
+ cs1_dq20_rx_de-skew = <7>;
|
|
+ cs1_dq20_tx_de-skew = <8>;
|
|
+ cs1_dq21_rx_de-skew = <7>;
|
|
+ cs1_dq21_tx_de-skew = <8>;
|
|
+ cs1_dq22_rx_de-skew = <7>;
|
|
+ cs1_dq22_tx_de-skew = <8>;
|
|
+ cs1_dq23_rx_de-skew = <7>;
|
|
+ cs1_dq23_tx_de-skew = <8>;
|
|
+ cs1_dqs2_rx_de-skew = <6>;
|
|
+ cs1_dqs2p_tx_de-skew = <9>;
|
|
+ cs1_dqs2n_tx_de-skew = <9>;
|
|
+
|
|
+ cs1_dm3_rx_de-skew = <7>;
|
|
+ cs1_dm3_tx_de-skew = <7>;
|
|
+ cs1_dq24_rx_de-skew = <7>;
|
|
+ cs1_dq24_tx_de-skew = <8>;
|
|
+ cs1_dq25_rx_de-skew = <7>;
|
|
+ cs1_dq25_tx_de-skew = <7>;
|
|
+ cs1_dq26_rx_de-skew = <7>;
|
|
+ cs1_dq26_tx_de-skew = <7>;
|
|
+ cs1_dq27_rx_de-skew = <7>;
|
|
+ cs1_dq27_tx_de-skew = <7>;
|
|
+ cs1_dq28_rx_de-skew = <7>;
|
|
+ cs1_dq28_tx_de-skew = <7>;
|
|
+ cs1_dq29_rx_de-skew = <7>;
|
|
+ cs1_dq29_tx_de-skew = <7>;
|
|
+ cs1_dq30_rx_de-skew = <7>;
|
|
+ cs1_dq30_tx_de-skew = <7>;
|
|
+ cs1_dq31_rx_de-skew = <7>;
|
|
+ cs1_dq31_tx_de-skew = <7>;
|
|
+ cs1_dqs3_rx_de-skew = <7>;
|
|
+ cs1_dqs3p_tx_de-skew = <9>;
|
|
+ cs1_dqs3n_tx_de-skew = <9>;
|
|
+ };
|
|
+};
|
|
diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
|
|
index 7a7bf3aafd31..2425ed0e94c4 100644
|
|
--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi
|
|
+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
|
|
@@ -565,6 +565,67 @@ tsadc: tsadc@ff250000 {
|
|
status = "disabled";
|
|
};
|
|
|
|
+ dfi: dfi@ff790000 {
|
|
+ reg = <0x00 0xff790000 0x00 0x400>;
|
|
+ compatible = "rockchip,rk3328-dfi";
|
|
+ rockchip,grf = <&grf>;
|
|
+ status = "okay";
|
|
+ };
|
|
+
|
|
+ dmc: dmc@ff780000 {
|
|
+ reg = <0x00 0xff780000 0x00 0x400>;
|
|
+ compatible = "rockchip,rk3328-dmc";
|
|
+ devfreq-events = <&dfi>;
|
|
+ clocks = <&cru SCLK_DDRCLK>;
|
|
+ clock-names = "dmc_clk";
|
|
+ operating-points-v2 = <&dmc_opp_table>;
|
|
+ #cooling-cells = <2>;
|
|
+ status = "disabled";
|
|
+ };
|
|
+
|
|
+ dmc_opp_table: dmc-opp-table {
|
|
+ compatible = "operating-points-v2";
|
|
+
|
|
+ opp-600000000 {
|
|
+ opp-hz = /bits/ 64 <600000000>;
|
|
+ opp-microvolt = <1000000 1000000 1200000>;
|
|
+ };
|
|
+
|
|
+ opp-666000000 {
|
|
+ opp-hz = /bits/ 64 <666000000>;
|
|
+ opp-microvolt = <1025000 1025000 1200000>;
|
|
+ };
|
|
+
|
|
+ opp-786000000 {
|
|
+ opp-hz = /bits/ 64 <786000000>;
|
|
+ opp-microvolt = <1050000 1050000 1200000>;
|
|
+ };
|
|
+
|
|
+ opp-800000000 {
|
|
+ opp-hz = /bits/ 64 <800000000>;
|
|
+ opp-microvolt = <1050000 1050000 1200000>;
|
|
+ status = "disabled";
|
|
+ };
|
|
+
|
|
+ opp-850000000 {
|
|
+ opp-hz = /bits/ 64 <850000000>;
|
|
+ opp-microvolt = <1050000 1050000 1200000>; // Untested
|
|
+ status = "disabled";
|
|
+ };
|
|
+
|
|
+ opp-933000000 {
|
|
+ opp-hz = /bits/ 64 <933000000>;
|
|
+ opp-microvolt = <1100000 1100000 1200000>; // Untested
|
|
+ status = "disabled";
|
|
+ };
|
|
+
|
|
+ opp-1066000000 {
|
|
+ opp-hz = /bits/ 64 <1066000000>;
|
|
+ opp-microvolt = <1150000 1150000 1200000>; // Untested
|
|
+ status = "disabled";
|
|
+ };
|
|
+ };
|
|
+
|
|
efuse: efuse@ff260000 {
|
|
compatible = "rockchip,rk3328-efuse";
|
|
reg = <0x0 0xff260000 0x0 0x50>;
|
|
diff --git a/drivers/clk/rockchip/clk-ddr.c b/drivers/clk/rockchip/clk-ddr.c
|
|
index 86718c54e56b..08b313495e8c 100644
|
|
--- a/drivers/clk/rockchip/clk-ddr.c
|
|
+++ b/drivers/clk/rockchip/clk-ddr.c
|
|
@@ -87,6 +87,134 @@ static const struct clk_ops rockchip_ddrclk_sip_ops = {
|
|
.get_parent = rockchip_ddrclk_get_parent,
|
|
};
|
|
|
|
+/* See v4.4/include/dt-bindings/display/rk_fb.h */
|
|
+#define SCREEN_NULL 0
|
|
+#define SCREEN_HDMI 6
|
|
+
|
|
+static inline int rk_drm_get_lcdc_type(void)
|
|
+{
|
|
+ return SCREEN_NULL;
|
|
+}
|
|
+
|
|
+struct share_params {
|
|
+ u32 hz;
|
|
+ u32 lcdc_type;
|
|
+ u32 vop;
|
|
+ u32 vop_dclk_mode;
|
|
+ u32 sr_idle_en;
|
|
+ u32 addr_mcu_el3;
|
|
+ /*
|
|
+ * 1: need to wait flag1
|
|
+ * 0: never wait flag1
|
|
+ */
|
|
+ u32 wait_flag1;
|
|
+ /*
|
|
+ * 1: need to wait flag1
|
|
+ * 0: never wait flag1
|
|
+ */
|
|
+ u32 wait_flag0;
|
|
+ u32 complt_hwirq;
|
|
+ /* if need, add parameter after */
|
|
+};
|
|
+
|
|
+struct rockchip_ddrclk_data {
|
|
+ u32 inited_flag;
|
|
+ void __iomem *share_memory;
|
|
+};
|
|
+
|
|
+static struct rockchip_ddrclk_data ddr_data;
|
|
+
|
|
+static void rockchip_ddrclk_data_init(void)
|
|
+{
|
|
+ struct arm_smccc_res res;
|
|
+
|
|
+ arm_smccc_smc(ROCKCHIP_SIP_SHARE_MEM,
|
|
+ 1, SHARE_PAGE_TYPE_DDR, 0,
|
|
+ 0, 0, 0, 0, &res);
|
|
+
|
|
+ if (!res.a0) {
|
|
+ ddr_data.share_memory = (void __iomem *)ioremap(res.a1, 1<<12);
|
|
+ ddr_data.inited_flag = 1;
|
|
+ }
|
|
+}
|
|
+
|
|
+static int rockchip_ddrclk_sip_set_rate_v2(struct clk_hw *hw,
|
|
+ unsigned long drate,
|
|
+ unsigned long prate)
|
|
+{
|
|
+ struct share_params *p;
|
|
+ struct arm_smccc_res res;
|
|
+
|
|
+ if (!ddr_data.inited_flag)
|
|
+ rockchip_ddrclk_data_init();
|
|
+
|
|
+ p = (struct share_params *)ddr_data.share_memory;
|
|
+
|
|
+ p->hz = drate;
|
|
+ p->lcdc_type = rk_drm_get_lcdc_type();
|
|
+ p->wait_flag1 = 1;
|
|
+ p->wait_flag0 = 1;
|
|
+
|
|
+ arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ,
|
|
+ SHARE_PAGE_TYPE_DDR, 0,
|
|
+ ROCKCHIP_SIP_CONFIG_DRAM_SET_RATE,
|
|
+ 0, 0, 0, 0, &res);
|
|
+
|
|
+ if ((int)res.a1 == -6) {
|
|
+ pr_err("%s: timeout, drate = %lumhz\n", __func__, drate/1000000);
|
|
+ /* TODO: rockchip_dmcfreq_wait_complete(); */
|
|
+ }
|
|
+
|
|
+ return res.a0;
|
|
+}
|
|
+
|
|
+static unsigned long rockchip_ddrclk_sip_recalc_rate_v2
|
|
+ (struct clk_hw *hw, unsigned long parent_rate)
|
|
+{
|
|
+ struct arm_smccc_res res;
|
|
+
|
|
+ arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ,
|
|
+ SHARE_PAGE_TYPE_DDR, 0,
|
|
+ ROCKCHIP_SIP_CONFIG_DRAM_GET_RATE,
|
|
+ 0, 0, 0, 0, &res);
|
|
+ if (!res.a0)
|
|
+ return res.a1;
|
|
+ else
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static long rockchip_ddrclk_sip_round_rate_v2(struct clk_hw *hw,
|
|
+ unsigned long rate,
|
|
+ unsigned long *prate)
|
|
+{
|
|
+ struct share_params *p;
|
|
+ struct arm_smccc_res res;
|
|
+
|
|
+ if (!ddr_data.inited_flag)
|
|
+ rockchip_ddrclk_data_init();
|
|
+
|
|
+ p = (struct share_params *)ddr_data.share_memory;
|
|
+
|
|
+ p->hz = rate;
|
|
+
|
|
+ arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ,
|
|
+ SHARE_PAGE_TYPE_DDR, 0,
|
|
+ ROCKCHIP_SIP_CONFIG_DRAM_ROUND_RATE,
|
|
+ 0, 0, 0, 0, &res);
|
|
+
|
|
+ if (!res.a0)
|
|
+ return res.a1;
|
|
+ else
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static const struct clk_ops rockchip_ddrclk_sip_ops_v2 = {
|
|
+ .recalc_rate = rockchip_ddrclk_sip_recalc_rate_v2,
|
|
+ .set_rate = rockchip_ddrclk_sip_set_rate_v2,
|
|
+ .round_rate = rockchip_ddrclk_sip_round_rate_v2,
|
|
+ .get_parent = rockchip_ddrclk_get_parent,
|
|
+};
|
|
+
|
|
struct clk *rockchip_clk_register_ddrclk(const char *name, int flags,
|
|
const char *const *parent_names,
|
|
u8 num_parents, int mux_offset,
|
|
@@ -114,6 +242,9 @@ struct clk *rockchip_clk_register_ddrclk(const char *name, int flags,
|
|
case ROCKCHIP_DDRCLK_SIP:
|
|
init.ops = &rockchip_ddrclk_sip_ops;
|
|
break;
|
|
+ case ROCKCHIP_DDRCLK_SIP_V2:
|
|
+ init.ops = &rockchip_ddrclk_sip_ops_v2;
|
|
+ break;
|
|
default:
|
|
pr_err("%s: unsupported ddrclk type %d\n", __func__, ddr_flag);
|
|
kfree(ddrclk);
|
|
diff --git a/drivers/clk/rockchip/clk-rk3328.c b/drivers/clk/rockchip/clk-rk3328.c
|
|
index 267ab54937d3..aa4afc8a17aa 100644
|
|
--- a/drivers/clk/rockchip/clk-rk3328.c
|
|
+++ b/drivers/clk/rockchip/clk-rk3328.c
|
|
@@ -315,14 +315,15 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = {
|
|
RK3328_CLKGATE_CON(14), 1, GFLAGS),
|
|
|
|
/* PD_DDR */
|
|
- COMPOSITE(0, "clk_ddr", mux_ddrphy_p, CLK_IGNORE_UNUSED,
|
|
- RK3328_CLKSEL_CON(3), 8, 2, MFLAGS, 0, 3, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
|
|
- RK3328_CLKGATE_CON(0), 4, GFLAGS),
|
|
- GATE(0, "clk_ddrmsch", "clk_ddr", CLK_IGNORE_UNUSED,
|
|
+ COMPOSITE_DDRCLK(SCLK_DDRCLK, "sclk_ddrc", mux_ddrphy_p, 0,
|
|
+ RK3328_CLKSEL_CON(3), 8, 2, 0, 3,
|
|
+ ROCKCHIP_DDRCLK_SIP_V2),
|
|
+
|
|
+ GATE(0, "clk_ddrmsch", "sclk_ddrc", CLK_IGNORE_UNUSED,
|
|
RK3328_CLKGATE_CON(18), 6, GFLAGS),
|
|
- GATE(0, "clk_ddrupctl", "clk_ddr", CLK_IGNORE_UNUSED,
|
|
+ GATE(0, "clk_ddrupctl", "sclk_ddrc", CLK_IGNORE_UNUSED,
|
|
RK3328_CLKGATE_CON(18), 5, GFLAGS),
|
|
- GATE(0, "aclk_ddrupctl", "clk_ddr", CLK_IGNORE_UNUSED,
|
|
+ GATE(0, "aclk_ddrupctl", "sclk_ddrc", CLK_IGNORE_UNUSED,
|
|
RK3328_CLKGATE_CON(18), 4, GFLAGS),
|
|
GATE(0, "clk_ddrmon", "xin24m", CLK_IGNORE_UNUSED,
|
|
RK3328_CLKGATE_CON(0), 6, GFLAGS),
|
|
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
|
|
index 758ebaf2236b..fe033ebcb62d 100644
|
|
--- a/drivers/clk/rockchip/clk.h
|
|
+++ b/drivers/clk/rockchip/clk.h
|
|
@@ -486,7 +486,8 @@ struct clk *rockchip_clk_register_mmc(const char *name,
|
|
* DDRCLK flags, including method of setting the rate
|
|
* ROCKCHIP_DDRCLK_SIP: use SIP call to bl31 to change ddrclk rate.
|
|
*/
|
|
-#define ROCKCHIP_DDRCLK_SIP BIT(0)
|
|
+#define ROCKCHIP_DDRCLK_SIP 0x01
|
|
+#define ROCKCHIP_DDRCLK_SIP_V2 0x03
|
|
|
|
struct clk *rockchip_clk_register_ddrclk(const char *name, int flags,
|
|
const char *const *parent_names,
|
|
diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig
|
|
index 9754d8b31621..c3380b360c68 100644
|
|
--- a/drivers/devfreq/Kconfig
|
|
+++ b/drivers/devfreq/Kconfig
|
|
@@ -130,6 +130,18 @@ config ARM_MEDIATEK_CCI_DEVFREQ
|
|
buck voltages and update a proper CCI frequency. Use the notification
|
|
to get the regulator status.
|
|
|
|
+config ARM_RK3328_DMC_DEVFREQ
|
|
+ tristate "ARM RK3328 DMC DEVFREQ Driver"
|
|
+ depends on ARCH_ROCKCHIP
|
|
+ select DEVFREQ_EVENT_ROCKCHIP_DFI
|
|
+ select DEVFREQ_GOV_SIMPLE_ONDEMAND
|
|
+ select PM_DEVFREQ_EVENT
|
|
+ select PM_OPP
|
|
+ help
|
|
+ This adds the DEVFREQ driver for the RK3328 DMC(Dynamic Memory Controller).
|
|
+ It sets the frequency for the memory controller and reads the usage counts
|
|
+ from hardware.
|
|
+
|
|
config ARM_RK3399_DMC_DEVFREQ
|
|
tristate "ARM RK3399 DMC DEVFREQ Driver"
|
|
depends on (ARCH_ROCKCHIP && HAVE_ARM_SMCCC) || \
|
|
diff --git a/drivers/devfreq/Makefile b/drivers/devfreq/Makefile
|
|
index bf40d04928d0..08c0738ae439 100644
|
|
--- a/drivers/devfreq/Makefile
|
|
+++ b/drivers/devfreq/Makefile
|
|
@@ -13,6 +13,7 @@ obj-$(CONFIG_ARM_IMX_BUS_DEVFREQ) += imx-bus.o
|
|
obj-$(CONFIG_ARM_IMX8M_DDRC_DEVFREQ) += imx8m-ddrc.o
|
|
obj-$(CONFIG_ARM_MEDIATEK_CCI_DEVFREQ) += mtk-cci-devfreq.o
|
|
obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ) += rk3399_dmc.o
|
|
+obj-$(CONFIG_ARM_RK3328_DMC_DEVFREQ) += rk3328_dmc.o
|
|
obj-$(CONFIG_ARM_SUN8I_A33_MBUS_DEVFREQ) += sun8i-a33-mbus.o
|
|
obj-$(CONFIG_ARM_TEGRA_DEVFREQ) += tegra30-devfreq.o
|
|
|
|
diff --git a/drivers/devfreq/event/rockchip-dfi.c b/drivers/devfreq/event/rockchip-dfi.c
|
|
index 39ac069cabc7..7d53fc10c63b 100644
|
|
--- a/drivers/devfreq/event/rockchip-dfi.c
|
|
+++ b/drivers/devfreq/event/rockchip-dfi.c
|
|
@@ -18,25 +18,66 @@
|
|
#include <linux/list.h>
|
|
#include <linux/of.h>
|
|
|
|
-#include <soc/rockchip/rk3399_grf.h>
|
|
-
|
|
-#define RK3399_DMC_NUM_CH 2
|
|
-
|
|
+#define PX30_PMUGRF_OS_REG2 0x208
|
|
+
|
|
+#define RK3128_GRF_SOC_CON0 0x140
|
|
+#define RK3128_GRF_OS_REG1 0x1cc
|
|
+#define RK3128_GRF_DFI_WRNUM 0x220
|
|
+#define RK3128_GRF_DFI_RDNUM 0x224
|
|
+#define RK3128_GRF_DFI_TIMERVAL 0x22c
|
|
+#define RK3128_DDR_MONITOR_EN ((1 << (16 + 6)) + (1 << 6))
|
|
+#define RK3128_DDR_MONITOR_DISB ((1 << (16 + 6)) + (0 << 6))
|
|
+
|
|
+#define RK3288_PMU_SYS_REG2 0x9c
|
|
+#define RK3288_GRF_SOC_CON4 0x254
|
|
+#define RK3288_GRF_SOC_STATUS(n) (0x280 + (n) * 4)
|
|
+#define RK3288_DFI_EN (0x30003 << 14)
|
|
+#define RK3288_DFI_DIS (0x30000 << 14)
|
|
+#define RK3288_LPDDR_SEL (0x10001 << 13)
|
|
+#define RK3288_DDR3_SEL (0x10000 << 13)
|
|
+
|
|
+#define RK3328_GRF_OS_REG2 0x5d0
|
|
+
|
|
+#define RK3368_GRF_DDRC0_CON0 0x600
|
|
+#define RK3368_GRF_SOC_STATUS5 0x494
|
|
+#define RK3368_GRF_SOC_STATUS6 0x498
|
|
+#define RK3368_GRF_SOC_STATUS8 0x4a0
|
|
+#define RK3368_GRF_SOC_STATUS9 0x4a4
|
|
+#define RK3368_GRF_SOC_STATUS10 0x4a8
|
|
+#define RK3368_DFI_EN (0x30003 << 5)
|
|
+#define RK3368_DFI_DIS (0x30000 << 5)
|
|
+
|
|
+#define MAX_DMC_NUM_CH 2
|
|
+#define READ_DRAMTYPE_INFO(n) (((n) >> 13) & 0x7)
|
|
+#define READ_CH_INFO(n) (((n) >> 28) & 0x3)
|
|
/* DDRMON_CTRL */
|
|
-#define DDRMON_CTRL 0x04
|
|
-#define CLR_DDRMON_CTRL (0x1f0000 << 0)
|
|
-#define LPDDR4_EN (0x10001 << 4)
|
|
-#define HARDWARE_EN (0x10001 << 3)
|
|
-#define LPDDR3_EN (0x10001 << 2)
|
|
-#define SOFTWARE_EN (0x10001 << 1)
|
|
-#define SOFTWARE_DIS (0x10000 << 1)
|
|
-#define TIME_CNT_EN (0x10001 << 0)
|
|
+#define DDRMON_CTRL 0x04
|
|
+#define CLR_DDRMON_CTRL (0x3f0000 << 0)
|
|
+#define DDR4_EN (0x10001 << 5)
|
|
+#define LPDDR4_EN (0x10001 << 4)
|
|
+#define HARDWARE_EN (0x10001 << 3)
|
|
+#define LPDDR2_3_EN (0x10001 << 2)
|
|
+#define SOFTWARE_EN (0x10001 << 1)
|
|
+#define SOFTWARE_DIS (0x10000 << 1)
|
|
+#define TIME_CNT_EN (0x10001 << 0)
|
|
|
|
#define DDRMON_CH0_COUNT_NUM 0x28
|
|
#define DDRMON_CH0_DFI_ACCESS_NUM 0x2c
|
|
#define DDRMON_CH1_COUNT_NUM 0x3c
|
|
#define DDRMON_CH1_DFI_ACCESS_NUM 0x40
|
|
|
|
+/* pmu grf */
|
|
+#define PMUGRF_OS_REG2 0x308
|
|
+
|
|
+enum {
|
|
+ DDR4 = 0,
|
|
+ DDR3 = 3,
|
|
+ LPDDR2 = 5,
|
|
+ LPDDR3 = 6,
|
|
+ LPDDR4 = 7,
|
|
+ UNUSED = 0xFF
|
|
+};
|
|
+
|
|
struct dmc_usage {
|
|
u32 access;
|
|
u32 total;
|
|
@@ -50,33 +91,261 @@ struct dmc_usage {
|
|
struct rockchip_dfi {
|
|
struct devfreq_event_dev *edev;
|
|
struct devfreq_event_desc *desc;
|
|
- struct dmc_usage ch_usage[RK3399_DMC_NUM_CH];
|
|
+ struct dmc_usage ch_usage[MAX_DMC_NUM_CH];
|
|
struct device *dev;
|
|
void __iomem *regs;
|
|
struct regmap *regmap_pmu;
|
|
+ struct regmap *regmap_grf;
|
|
+ struct regmap *regmap_pmugrf;
|
|
struct clk *clk;
|
|
+ u32 dram_type;
|
|
+ /*
|
|
+ * available mask, 1: available, 0: not available
|
|
+ * each bit represent a channel
|
|
+ */
|
|
+ u32 ch_msk;
|
|
+};
|
|
+
|
|
+static void rk3128_dfi_start_hardware_counter(struct devfreq_event_dev *edev)
|
|
+{
|
|
+ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
|
|
+
|
|
+ regmap_write(info->regmap_grf,
|
|
+ RK3128_GRF_SOC_CON0,
|
|
+ RK3128_DDR_MONITOR_EN);
|
|
+}
|
|
+
|
|
+static void rk3128_dfi_stop_hardware_counter(struct devfreq_event_dev *edev)
|
|
+{
|
|
+ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
|
|
+
|
|
+ regmap_write(info->regmap_grf,
|
|
+ RK3128_GRF_SOC_CON0,
|
|
+ RK3128_DDR_MONITOR_DISB);
|
|
+}
|
|
+
|
|
+static int rk3128_dfi_disable(struct devfreq_event_dev *edev)
|
|
+{
|
|
+ rk3128_dfi_stop_hardware_counter(edev);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rk3128_dfi_enable(struct devfreq_event_dev *edev)
|
|
+{
|
|
+ rk3128_dfi_start_hardware_counter(edev);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rk3128_dfi_set_event(struct devfreq_event_dev *edev)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rk3128_dfi_get_event(struct devfreq_event_dev *edev,
|
|
+ struct devfreq_event_data *edata)
|
|
+{
|
|
+ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
|
|
+ unsigned long flags;
|
|
+ u32 dfi_wr, dfi_rd, dfi_timer;
|
|
+
|
|
+ local_irq_save(flags);
|
|
+
|
|
+ rk3128_dfi_stop_hardware_counter(edev);
|
|
+
|
|
+ regmap_read(info->regmap_grf, RK3128_GRF_DFI_WRNUM, &dfi_wr);
|
|
+ regmap_read(info->regmap_grf, RK3128_GRF_DFI_RDNUM, &dfi_rd);
|
|
+ regmap_read(info->regmap_grf, RK3128_GRF_DFI_TIMERVAL, &dfi_timer);
|
|
+
|
|
+ edata->load_count = (dfi_wr + dfi_rd) * 4;
|
|
+ edata->total_count = dfi_timer;
|
|
+
|
|
+ rk3128_dfi_start_hardware_counter(edev);
|
|
+
|
|
+ local_irq_restore(flags);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static const struct devfreq_event_ops rk3128_dfi_ops = {
|
|
+ .disable = rk3128_dfi_disable,
|
|
+ .enable = rk3128_dfi_enable,
|
|
+ .get_event = rk3128_dfi_get_event,
|
|
+ .set_event = rk3128_dfi_set_event,
|
|
+};
|
|
+
|
|
+static void rk3288_dfi_start_hardware_counter(struct devfreq_event_dev *edev)
|
|
+{
|
|
+ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
|
|
+
|
|
+ regmap_write(info->regmap_grf, RK3288_GRF_SOC_CON4, RK3288_DFI_EN);
|
|
+}
|
|
+
|
|
+static void rk3288_dfi_stop_hardware_counter(struct devfreq_event_dev *edev)
|
|
+{
|
|
+ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
|
|
+
|
|
+ regmap_write(info->regmap_grf, RK3288_GRF_SOC_CON4, RK3288_DFI_DIS);
|
|
+}
|
|
+
|
|
+static int rk3288_dfi_disable(struct devfreq_event_dev *edev)
|
|
+{
|
|
+ rk3288_dfi_stop_hardware_counter(edev);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rk3288_dfi_enable(struct devfreq_event_dev *edev)
|
|
+{
|
|
+ rk3288_dfi_start_hardware_counter(edev);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rk3288_dfi_set_event(struct devfreq_event_dev *edev)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rk3288_dfi_get_busier_ch(struct devfreq_event_dev *edev)
|
|
+{
|
|
+ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
|
|
+ u32 tmp, max = 0;
|
|
+ u32 i, busier_ch = 0;
|
|
+ u32 rd_count, wr_count, total_count;
|
|
+
|
|
+ rk3288_dfi_stop_hardware_counter(edev);
|
|
+
|
|
+ /* Find out which channel is busier */
|
|
+ for (i = 0; i < MAX_DMC_NUM_CH; i++) {
|
|
+ if (!(info->ch_msk & BIT(i)))
|
|
+ continue;
|
|
+ regmap_read(info->regmap_grf,
|
|
+ RK3288_GRF_SOC_STATUS(11 + i * 4), &wr_count);
|
|
+ regmap_read(info->regmap_grf,
|
|
+ RK3288_GRF_SOC_STATUS(12 + i * 4), &rd_count);
|
|
+ regmap_read(info->regmap_grf,
|
|
+ RK3288_GRF_SOC_STATUS(14 + i * 4), &total_count);
|
|
+ info->ch_usage[i].access = (wr_count + rd_count) * 4;
|
|
+ info->ch_usage[i].total = total_count;
|
|
+ tmp = info->ch_usage[i].access;
|
|
+ if (tmp > max) {
|
|
+ busier_ch = i;
|
|
+ max = tmp;
|
|
+ }
|
|
+ }
|
|
+ rk3288_dfi_start_hardware_counter(edev);
|
|
+
|
|
+ return busier_ch;
|
|
+}
|
|
+
|
|
+static int rk3288_dfi_get_event(struct devfreq_event_dev *edev,
|
|
+ struct devfreq_event_data *edata)
|
|
+{
|
|
+ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
|
|
+ int busier_ch;
|
|
+ unsigned long flags;
|
|
+
|
|
+ local_irq_save(flags);
|
|
+ busier_ch = rk3288_dfi_get_busier_ch(edev);
|
|
+ local_irq_restore(flags);
|
|
+
|
|
+ edata->load_count = info->ch_usage[busier_ch].access;
|
|
+ edata->total_count = info->ch_usage[busier_ch].total;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static const struct devfreq_event_ops rk3288_dfi_ops = {
|
|
+ .disable = rk3288_dfi_disable,
|
|
+ .enable = rk3288_dfi_enable,
|
|
+ .get_event = rk3288_dfi_get_event,
|
|
+ .set_event = rk3288_dfi_set_event,
|
|
+};
|
|
+
|
|
+static void rk3368_dfi_start_hardware_counter(struct devfreq_event_dev *edev)
|
|
+{
|
|
+ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
|
|
+
|
|
+ regmap_write(info->regmap_grf, RK3368_GRF_DDRC0_CON0, RK3368_DFI_EN);
|
|
+}
|
|
+
|
|
+static void rk3368_dfi_stop_hardware_counter(struct devfreq_event_dev *edev)
|
|
+{
|
|
+ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
|
|
+
|
|
+ regmap_write(info->regmap_grf, RK3368_GRF_DDRC0_CON0, RK3368_DFI_DIS);
|
|
+}
|
|
+
|
|
+static int rk3368_dfi_disable(struct devfreq_event_dev *edev)
|
|
+{
|
|
+ rk3368_dfi_stop_hardware_counter(edev);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rk3368_dfi_enable(struct devfreq_event_dev *edev)
|
|
+{
|
|
+ rk3368_dfi_start_hardware_counter(edev);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rk3368_dfi_set_event(struct devfreq_event_dev *edev)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rk3368_dfi_get_event(struct devfreq_event_dev *edev,
|
|
+ struct devfreq_event_data *edata)
|
|
+{
|
|
+ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
|
|
+ unsigned long flags;
|
|
+ u32 dfi0_wr, dfi0_rd, dfi1_wr, dfi1_rd, dfi_timer;
|
|
+
|
|
+ local_irq_save(flags);
|
|
+
|
|
+ rk3368_dfi_stop_hardware_counter(edev);
|
|
+
|
|
+ regmap_read(info->regmap_grf, RK3368_GRF_SOC_STATUS5, &dfi0_wr);
|
|
+ regmap_read(info->regmap_grf, RK3368_GRF_SOC_STATUS6, &dfi0_rd);
|
|
+ regmap_read(info->regmap_grf, RK3368_GRF_SOC_STATUS9, &dfi1_wr);
|
|
+ regmap_read(info->regmap_grf, RK3368_GRF_SOC_STATUS10, &dfi1_rd);
|
|
+ regmap_read(info->regmap_grf, RK3368_GRF_SOC_STATUS8, &dfi_timer);
|
|
+
|
|
+ edata->load_count = (dfi0_wr + dfi0_rd + dfi1_wr + dfi1_rd) * 2;
|
|
+ edata->total_count = dfi_timer;
|
|
+
|
|
+ rk3368_dfi_start_hardware_counter(edev);
|
|
+
|
|
+ local_irq_restore(flags);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static const struct devfreq_event_ops rk3368_dfi_ops = {
|
|
+ .disable = rk3368_dfi_disable,
|
|
+ .enable = rk3368_dfi_enable,
|
|
+ .get_event = rk3368_dfi_get_event,
|
|
+ .set_event = rk3368_dfi_set_event,
|
|
};
|
|
|
|
static void rockchip_dfi_start_hardware_counter(struct devfreq_event_dev *edev)
|
|
{
|
|
struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
|
|
void __iomem *dfi_regs = info->regs;
|
|
- u32 val;
|
|
- u32 ddr_type;
|
|
-
|
|
- /* get ddr type */
|
|
- regmap_read(info->regmap_pmu, RK3399_PMUGRF_OS_REG2, &val);
|
|
- ddr_type = (val >> RK3399_PMUGRF_DDRTYPE_SHIFT) &
|
|
- RK3399_PMUGRF_DDRTYPE_MASK;
|
|
|
|
/* clear DDRMON_CTRL setting */
|
|
writel_relaxed(CLR_DDRMON_CTRL, dfi_regs + DDRMON_CTRL);
|
|
|
|
/* set ddr type to dfi */
|
|
- if (ddr_type == RK3399_PMUGRF_DDRTYPE_LPDDR3)
|
|
- writel_relaxed(LPDDR3_EN, dfi_regs + DDRMON_CTRL);
|
|
- else if (ddr_type == RK3399_PMUGRF_DDRTYPE_LPDDR4)
|
|
+ if (info->dram_type == LPDDR3 || info->dram_type == LPDDR2)
|
|
+ writel_relaxed(LPDDR2_3_EN, dfi_regs + DDRMON_CTRL);
|
|
+ else if (info->dram_type == LPDDR4)
|
|
writel_relaxed(LPDDR4_EN, dfi_regs + DDRMON_CTRL);
|
|
+ else if (info->dram_type == DDR4)
|
|
+ writel_relaxed(DDR4_EN, dfi_regs + DDRMON_CTRL);
|
|
|
|
/* enable count, use software mode */
|
|
writel_relaxed(SOFTWARE_EN, dfi_regs + DDRMON_CTRL);
|
|
@@ -100,12 +369,22 @@ static int rockchip_dfi_get_busier_ch(struct devfreq_event_dev *edev)
|
|
rockchip_dfi_stop_hardware_counter(edev);
|
|
|
|
/* Find out which channel is busier */
|
|
- for (i = 0; i < RK3399_DMC_NUM_CH; i++) {
|
|
- info->ch_usage[i].access = readl_relaxed(dfi_regs +
|
|
- DDRMON_CH0_DFI_ACCESS_NUM + i * 20) * 4;
|
|
+ for (i = 0; i < MAX_DMC_NUM_CH; i++) {
|
|
+ if (!(info->ch_msk & BIT(i)))
|
|
+ continue;
|
|
+
|
|
info->ch_usage[i].total = readl_relaxed(dfi_regs +
|
|
DDRMON_CH0_COUNT_NUM + i * 20);
|
|
- tmp = info->ch_usage[i].access;
|
|
+
|
|
+ /* LPDDR4 BL = 16,other DDR type BL = 8 */
|
|
+ tmp = readl_relaxed(dfi_regs +
|
|
+ DDRMON_CH0_DFI_ACCESS_NUM + i * 20);
|
|
+ if (info->dram_type == LPDDR4)
|
|
+ tmp *= 8;
|
|
+ else
|
|
+ tmp *= 4;
|
|
+ info->ch_usage[i].access = tmp;
|
|
+
|
|
if (tmp > max) {
|
|
busier_ch = i;
|
|
max = tmp;
|
|
@@ -121,7 +400,8 @@ static int rockchip_dfi_disable(struct devfreq_event_dev *edev)
|
|
struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
|
|
|
|
rockchip_dfi_stop_hardware_counter(edev);
|
|
- clk_disable_unprepare(info->clk);
|
|
+ if (info->clk)
|
|
+ clk_disable_unprepare(info->clk);
|
|
|
|
return 0;
|
|
}
|
|
@@ -131,10 +411,13 @@ static int rockchip_dfi_enable(struct devfreq_event_dev *edev)
|
|
struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
|
|
int ret;
|
|
|
|
- ret = clk_prepare_enable(info->clk);
|
|
- if (ret) {
|
|
- dev_err(&edev->dev, "failed to enable dfi clk: %d\n", ret);
|
|
- return ret;
|
|
+ if (info->clk) {
|
|
+ ret = clk_prepare_enable(info->clk);
|
|
+ if (ret) {
|
|
+ dev_err(&edev->dev, "failed to enable dfi clk: %d\n",
|
|
+ ret);
|
|
+ return ret;
|
|
+ }
|
|
}
|
|
|
|
rockchip_dfi_start_hardware_counter(edev);
|
|
@@ -151,8 +434,11 @@ static int rockchip_dfi_get_event(struct devfreq_event_dev *edev,
|
|
{
|
|
struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
|
|
int busier_ch;
|
|
+ unsigned long flags;
|
|
|
|
+ local_irq_save(flags);
|
|
busier_ch = rockchip_dfi_get_busier_ch(edev);
|
|
+ local_irq_restore(flags);
|
|
|
|
edata->load_count = info->ch_usage[busier_ch].access;
|
|
edata->total_count = info->ch_usage[busier_ch].total;
|
|
@@ -167,22 +453,116 @@ static const struct devfreq_event_ops rockchip_dfi_ops = {
|
|
.set_event = rockchip_dfi_set_event,
|
|
};
|
|
|
|
-static const struct of_device_id rockchip_dfi_id_match[] = {
|
|
- { .compatible = "rockchip,rk3399-dfi" },
|
|
- { },
|
|
-};
|
|
-MODULE_DEVICE_TABLE(of, rockchip_dfi_id_match);
|
|
+static __init int px30_dfi_init(struct platform_device *pdev,
|
|
+ struct rockchip_dfi *data,
|
|
+ struct devfreq_event_desc *desc)
|
|
+{
|
|
+ struct device_node *np = pdev->dev.of_node, *node;
|
|
+ struct resource *res;
|
|
+ u32 val;
|
|
|
|
-static int rockchip_dfi_probe(struct platform_device *pdev)
|
|
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
+ data->regs = devm_ioremap_resource(&pdev->dev, res);
|
|
+ if (IS_ERR(data->regs))
|
|
+ return PTR_ERR(data->regs);
|
|
+
|
|
+ node = of_parse_phandle(np, "rockchip,pmugrf", 0);
|
|
+ if (node) {
|
|
+ data->regmap_pmugrf = syscon_node_to_regmap(node);
|
|
+ if (IS_ERR(data->regmap_pmugrf))
|
|
+ return PTR_ERR(data->regmap_pmugrf);
|
|
+ }
|
|
+
|
|
+ regmap_read(data->regmap_pmugrf, PX30_PMUGRF_OS_REG2, &val);
|
|
+ data->dram_type = READ_DRAMTYPE_INFO(val);
|
|
+ data->ch_msk = 1;
|
|
+ data->clk = NULL;
|
|
+
|
|
+ desc->ops = &rockchip_dfi_ops;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static __init int rk3128_dfi_init(struct platform_device *pdev,
|
|
+ struct rockchip_dfi *data,
|
|
+ struct devfreq_event_desc *desc)
|
|
{
|
|
- struct device *dev = &pdev->dev;
|
|
- struct rockchip_dfi *data;
|
|
- struct devfreq_event_desc *desc;
|
|
struct device_node *np = pdev->dev.of_node, *node;
|
|
|
|
- data = devm_kzalloc(dev, sizeof(struct rockchip_dfi), GFP_KERNEL);
|
|
- if (!data)
|
|
- return -ENOMEM;
|
|
+ node = of_parse_phandle(np, "rockchip,grf", 0);
|
|
+ if (node) {
|
|
+ data->regmap_grf = syscon_node_to_regmap(node);
|
|
+ if (IS_ERR(data->regmap_grf))
|
|
+ return PTR_ERR(data->regmap_grf);
|
|
+ }
|
|
+
|
|
+ desc->ops = &rk3128_dfi_ops;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static __init int rk3288_dfi_init(struct platform_device *pdev,
|
|
+ struct rockchip_dfi *data,
|
|
+ struct devfreq_event_desc *desc)
|
|
+{
|
|
+ struct device_node *np = pdev->dev.of_node, *node;
|
|
+ u32 val;
|
|
+
|
|
+ node = of_parse_phandle(np, "rockchip,pmu", 0);
|
|
+ if (node) {
|
|
+ data->regmap_pmu = syscon_node_to_regmap(node);
|
|
+ if (IS_ERR(data->regmap_pmu))
|
|
+ return PTR_ERR(data->regmap_pmu);
|
|
+ }
|
|
+
|
|
+ node = of_parse_phandle(np, "rockchip,grf", 0);
|
|
+ if (node) {
|
|
+ data->regmap_grf = syscon_node_to_regmap(node);
|
|
+ if (IS_ERR(data->regmap_grf))
|
|
+ return PTR_ERR(data->regmap_grf);
|
|
+ }
|
|
+
|
|
+ regmap_read(data->regmap_pmu, RK3288_PMU_SYS_REG2, &val);
|
|
+ data->dram_type = READ_DRAMTYPE_INFO(val);
|
|
+ data->ch_msk = READ_CH_INFO(val);
|
|
+
|
|
+ if (data->dram_type == DDR3)
|
|
+ regmap_write(data->regmap_grf, RK3288_GRF_SOC_CON4,
|
|
+ RK3288_DDR3_SEL);
|
|
+ else
|
|
+ regmap_write(data->regmap_grf, RK3288_GRF_SOC_CON4,
|
|
+ RK3288_LPDDR_SEL);
|
|
+
|
|
+ desc->ops = &rk3288_dfi_ops;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static __init int rk3368_dfi_init(struct platform_device *pdev,
|
|
+ struct rockchip_dfi *data,
|
|
+ struct devfreq_event_desc *desc)
|
|
+{
|
|
+ struct device *dev = &pdev->dev;
|
|
+
|
|
+ if (!dev->parent || !dev->parent->of_node)
|
|
+ return -EINVAL;
|
|
+
|
|
+ data->regmap_grf = syscon_node_to_regmap(dev->parent->of_node);
|
|
+ if (IS_ERR(data->regmap_grf))
|
|
+ return PTR_ERR(data->regmap_grf);
|
|
+
|
|
+ desc->ops = &rk3368_dfi_ops;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static __init int rockchip_dfi_init(struct platform_device *pdev,
|
|
+ struct rockchip_dfi *data,
|
|
+ struct devfreq_event_desc *desc)
|
|
+{
|
|
+ struct device *dev = &pdev->dev;
|
|
+ struct device_node *np = pdev->dev.of_node, *node;
|
|
+ u32 val;
|
|
|
|
data->regs = devm_platform_ioremap_resource(pdev, 0);
|
|
if (IS_ERR(data->regs))
|
|
@@ -201,21 +581,97 @@ static int rockchip_dfi_probe(struct platform_device *pdev)
|
|
if (IS_ERR(data->regmap_pmu))
|
|
return PTR_ERR(data->regmap_pmu);
|
|
}
|
|
- data->dev = dev;
|
|
+
|
|
+ regmap_read(data->regmap_pmu, PMUGRF_OS_REG2, &val);
|
|
+ data->dram_type = READ_DRAMTYPE_INFO(val);
|
|
+ data->ch_msk = READ_CH_INFO(val);
|
|
+
|
|
+ desc->ops = &rockchip_dfi_ops;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static __init int rk3328_dfi_init(struct platform_device *pdev,
|
|
+ struct rockchip_dfi *data,
|
|
+ struct devfreq_event_desc *desc)
|
|
+{
|
|
+ struct device_node *np = pdev->dev.of_node, *node;
|
|
+ struct resource *res;
|
|
+ u32 val;
|
|
+
|
|
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
+ data->regs = devm_ioremap_resource(&pdev->dev, res);
|
|
+ if (IS_ERR(data->regs))
|
|
+ return PTR_ERR(data->regs);
|
|
+
|
|
+ node = of_parse_phandle(np, "rockchip,grf", 0);
|
|
+ if (node) {
|
|
+ data->regmap_grf = syscon_node_to_regmap(node);
|
|
+ if (IS_ERR(data->regmap_grf))
|
|
+ return PTR_ERR(data->regmap_grf);
|
|
+ }
|
|
+
|
|
+ regmap_read(data->regmap_grf, RK3328_GRF_OS_REG2, &val);
|
|
+ data->dram_type = READ_DRAMTYPE_INFO(val);
|
|
+ data->ch_msk = 1;
|
|
+ data->clk = NULL;
|
|
+
|
|
+ desc->ops = &rockchip_dfi_ops;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static const struct of_device_id rockchip_dfi_id_match[] = {
|
|
+ { .compatible = "rockchip,px30-dfi", .data = px30_dfi_init },
|
|
+ { .compatible = "rockchip,rk1808-dfi", .data = px30_dfi_init },
|
|
+ { .compatible = "rockchip,rk3128-dfi", .data = rk3128_dfi_init },
|
|
+ { .compatible = "rockchip,rk3288-dfi", .data = rk3288_dfi_init },
|
|
+ { .compatible = "rockchip,rk3328-dfi", .data = rk3328_dfi_init },
|
|
+ { .compatible = "rockchip,rk3368-dfi", .data = rk3368_dfi_init },
|
|
+ { .compatible = "rockchip,rk3399-dfi", .data = rockchip_dfi_init },
|
|
+ { },
|
|
+};
|
|
+MODULE_DEVICE_TABLE(of, rockchip_dfi_id_match);
|
|
+
|
|
+static int rockchip_dfi_probe(struct platform_device *pdev)
|
|
+{
|
|
+ struct device *dev = &pdev->dev;
|
|
+ struct rockchip_dfi *data;
|
|
+ struct devfreq_event_desc *desc;
|
|
+ struct device_node *np = pdev->dev.of_node;
|
|
+ const struct of_device_id *match;
|
|
+ int (*init)(struct platform_device *pdev, struct rockchip_dfi *data,
|
|
+ struct devfreq_event_desc *desc);
|
|
+
|
|
+ data = devm_kzalloc(dev, sizeof(struct rockchip_dfi), GFP_KERNEL);
|
|
+ if (!data)
|
|
+ return -ENOMEM;
|
|
|
|
desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
|
|
if (!desc)
|
|
return -ENOMEM;
|
|
|
|
- desc->ops = &rockchip_dfi_ops;
|
|
+ match = of_match_node(rockchip_dfi_id_match, pdev->dev.of_node);
|
|
+ if (match) {
|
|
+ init = match->data;
|
|
+ if (init) {
|
|
+ if (init(pdev, data, desc))
|
|
+ return -EINVAL;
|
|
+ } else {
|
|
+ return 0;
|
|
+ }
|
|
+ } else {
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
desc->driver_data = data;
|
|
desc->name = np->name;
|
|
data->desc = desc;
|
|
+ data->dev = dev;
|
|
|
|
- data->edev = devm_devfreq_event_add_edev(&pdev->dev, desc);
|
|
+ data->edev = devm_devfreq_event_add_edev(dev, desc);
|
|
if (IS_ERR(data->edev)) {
|
|
- dev_err(&pdev->dev,
|
|
- "failed to add devfreq-event device\n");
|
|
+ dev_err(dev, "failed to add devfreq-event device\n");
|
|
return PTR_ERR(data->edev);
|
|
}
|
|
|
|
diff --git a/drivers/devfreq/rk3328_dmc.c b/drivers/devfreq/rk3328_dmc.c
|
|
new file mode 100644
|
|
index 000000000000..7665526f0863
|
|
--- /dev/null
|
|
+++ b/drivers/devfreq/rk3328_dmc.c
|
|
@@ -0,0 +1,836 @@
|
|
+// SPDX-License-Identifier: GPL-2.0-only
|
|
+/*
|
|
+ * Copyright (c) 2016, Fuzhou Rockchip Electronics Co., Ltd.
|
|
+ * Author: Lin Huang <hl@rock-chips.com>
|
|
+ */
|
|
+
|
|
+#include <linux/arm-smccc.h>
|
|
+#include <linux/clk.h>
|
|
+#include <linux/delay.h>
|
|
+#include <linux/devfreq.h>
|
|
+#include <linux/devfreq-event.h>
|
|
+#include <linux/devfreq_cooling.h>
|
|
+#include <linux/interrupt.h>
|
|
+#include <linux/mfd/syscon.h>
|
|
+#include <linux/module.h>
|
|
+#include <linux/of.h>
|
|
+#include <linux/platform_device.h>
|
|
+#include <linux/pm_opp.h>
|
|
+#include <linux/regmap.h>
|
|
+#include <linux/regulator/consumer.h>
|
|
+#include <linux/rwsem.h>
|
|
+#include <linux/suspend.h>
|
|
+
|
|
+#include <soc/rockchip/rockchip_sip.h>
|
|
+
|
|
+#define DTS_PAR_OFFSET (4096)
|
|
+
|
|
+struct share_params {
|
|
+ u32 hz;
|
|
+ u32 lcdc_type;
|
|
+ u32 vop;
|
|
+ u32 vop_dclk_mode;
|
|
+ u32 sr_idle_en;
|
|
+ u32 addr_mcu_el3;
|
|
+ /*
|
|
+ * 1: need to wait flag1
|
|
+ * 0: never wait flag1
|
|
+ */
|
|
+ u32 wait_flag1;
|
|
+ /*
|
|
+ * 1: need to wait flag1
|
|
+ * 0: never wait flag1
|
|
+ */
|
|
+ u32 wait_flag0;
|
|
+ u32 complt_hwirq;
|
|
+ /* if need, add parameter after */
|
|
+};
|
|
+
|
|
+static struct share_params *ddr_psci_param;
|
|
+
|
|
+/* hope this define can adapt all future platform */
|
|
+static const char * const rk3328_dts_timing[] = {
|
|
+ "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",
|
|
+ "ddr3_dll_dis_freq",
|
|
+ "ddr4_dll_dis_freq",
|
|
+ "phy_dll_dis_freq",
|
|
+
|
|
+ "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",
|
|
+
|
|
+ "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",
|
|
+};
|
|
+
|
|
+static const char * const rk3328_dts_ca_timing[] = {
|
|
+ "ddr3a1_ddr4a9_de-skew",
|
|
+ "ddr3a0_ddr4a10_de-skew",
|
|
+ "ddr3a3_ddr4a6_de-skew",
|
|
+ "ddr3a2_ddr4a4_de-skew",
|
|
+ "ddr3a5_ddr4a8_de-skew",
|
|
+ "ddr3a4_ddr4a5_de-skew",
|
|
+ "ddr3a7_ddr4a11_de-skew",
|
|
+ "ddr3a6_ddr4a7_de-skew",
|
|
+ "ddr3a9_ddr4a0_de-skew",
|
|
+ "ddr3a8_ddr4a13_de-skew",
|
|
+ "ddr3a11_ddr4a3_de-skew",
|
|
+ "ddr3a10_ddr4cs0_de-skew",
|
|
+ "ddr3a13_ddr4a2_de-skew",
|
|
+ "ddr3a12_ddr4ba1_de-skew",
|
|
+ "ddr3a15_ddr4odt0_de-skew",
|
|
+ "ddr3a14_ddr4a1_de-skew",
|
|
+ "ddr3ba1_ddr4a15_de-skew",
|
|
+ "ddr3ba0_ddr4bg0_de-skew",
|
|
+ "ddr3ras_ddr4cke_de-skew",
|
|
+ "ddr3ba2_ddr4ba0_de-skew",
|
|
+ "ddr3we_ddr4bg1_de-skew",
|
|
+ "ddr3cas_ddr4a12_de-skew",
|
|
+ "ddr3ckn_ddr4ckn_de-skew",
|
|
+ "ddr3ckp_ddr4ckp_de-skew",
|
|
+ "ddr3cke_ddr4a16_de-skew",
|
|
+ "ddr3odt0_ddr4a14_de-skew",
|
|
+ "ddr3cs0_ddr4act_de-skew",
|
|
+ "ddr3reset_ddr4reset_de-skew",
|
|
+ "ddr3cs1_ddr4cs1_de-skew",
|
|
+ "ddr3odt1_ddr4odt1_de-skew",
|
|
+};
|
|
+
|
|
+static const char * const rk3328_dts_cs0_timing[] = {
|
|
+ "cs0_dm0_rx_de-skew",
|
|
+ "cs0_dm0_tx_de-skew",
|
|
+ "cs0_dq0_rx_de-skew",
|
|
+ "cs0_dq0_tx_de-skew",
|
|
+ "cs0_dq1_rx_de-skew",
|
|
+ "cs0_dq1_tx_de-skew",
|
|
+ "cs0_dq2_rx_de-skew",
|
|
+ "cs0_dq2_tx_de-skew",
|
|
+ "cs0_dq3_rx_de-skew",
|
|
+ "cs0_dq3_tx_de-skew",
|
|
+ "cs0_dq4_rx_de-skew",
|
|
+ "cs0_dq4_tx_de-skew",
|
|
+ "cs0_dq5_rx_de-skew",
|
|
+ "cs0_dq5_tx_de-skew",
|
|
+ "cs0_dq6_rx_de-skew",
|
|
+ "cs0_dq6_tx_de-skew",
|
|
+ "cs0_dq7_rx_de-skew",
|
|
+ "cs0_dq7_tx_de-skew",
|
|
+ "cs0_dqs0_rx_de-skew",
|
|
+ "cs0_dqs0p_tx_de-skew",
|
|
+ "cs0_dqs0n_tx_de-skew",
|
|
+
|
|
+ "cs0_dm1_rx_de-skew",
|
|
+ "cs0_dm1_tx_de-skew",
|
|
+ "cs0_dq8_rx_de-skew",
|
|
+ "cs0_dq8_tx_de-skew",
|
|
+ "cs0_dq9_rx_de-skew",
|
|
+ "cs0_dq9_tx_de-skew",
|
|
+ "cs0_dq10_rx_de-skew",
|
|
+ "cs0_dq10_tx_de-skew",
|
|
+ "cs0_dq11_rx_de-skew",
|
|
+ "cs0_dq11_tx_de-skew",
|
|
+ "cs0_dq12_rx_de-skew",
|
|
+ "cs0_dq12_tx_de-skew",
|
|
+ "cs0_dq13_rx_de-skew",
|
|
+ "cs0_dq13_tx_de-skew",
|
|
+ "cs0_dq14_rx_de-skew",
|
|
+ "cs0_dq14_tx_de-skew",
|
|
+ "cs0_dq15_rx_de-skew",
|
|
+ "cs0_dq15_tx_de-skew",
|
|
+ "cs0_dqs1_rx_de-skew",
|
|
+ "cs0_dqs1p_tx_de-skew",
|
|
+ "cs0_dqs1n_tx_de-skew",
|
|
+
|
|
+ "cs0_dm2_rx_de-skew",
|
|
+ "cs0_dm2_tx_de-skew",
|
|
+ "cs0_dq16_rx_de-skew",
|
|
+ "cs0_dq16_tx_de-skew",
|
|
+ "cs0_dq17_rx_de-skew",
|
|
+ "cs0_dq17_tx_de-skew",
|
|
+ "cs0_dq18_rx_de-skew",
|
|
+ "cs0_dq18_tx_de-skew",
|
|
+ "cs0_dq19_rx_de-skew",
|
|
+ "cs0_dq19_tx_de-skew",
|
|
+ "cs0_dq20_rx_de-skew",
|
|
+ "cs0_dq20_tx_de-skew",
|
|
+ "cs0_dq21_rx_de-skew",
|
|
+ "cs0_dq21_tx_de-skew",
|
|
+ "cs0_dq22_rx_de-skew",
|
|
+ "cs0_dq22_tx_de-skew",
|
|
+ "cs0_dq23_rx_de-skew",
|
|
+ "cs0_dq23_tx_de-skew",
|
|
+ "cs0_dqs2_rx_de-skew",
|
|
+ "cs0_dqs2p_tx_de-skew",
|
|
+ "cs0_dqs2n_tx_de-skew",
|
|
+
|
|
+ "cs0_dm3_rx_de-skew",
|
|
+ "cs0_dm3_tx_de-skew",
|
|
+ "cs0_dq24_rx_de-skew",
|
|
+ "cs0_dq24_tx_de-skew",
|
|
+ "cs0_dq25_rx_de-skew",
|
|
+ "cs0_dq25_tx_de-skew",
|
|
+ "cs0_dq26_rx_de-skew",
|
|
+ "cs0_dq26_tx_de-skew",
|
|
+ "cs0_dq27_rx_de-skew",
|
|
+ "cs0_dq27_tx_de-skew",
|
|
+ "cs0_dq28_rx_de-skew",
|
|
+ "cs0_dq28_tx_de-skew",
|
|
+ "cs0_dq29_rx_de-skew",
|
|
+ "cs0_dq29_tx_de-skew",
|
|
+ "cs0_dq30_rx_de-skew",
|
|
+ "cs0_dq30_tx_de-skew",
|
|
+ "cs0_dq31_rx_de-skew",
|
|
+ "cs0_dq31_tx_de-skew",
|
|
+ "cs0_dqs3_rx_de-skew",
|
|
+ "cs0_dqs3p_tx_de-skew",
|
|
+ "cs0_dqs3n_tx_de-skew",
|
|
+};
|
|
+
|
|
+static const char * const rk3328_dts_cs1_timing[] = {
|
|
+ "cs1_dm0_rx_de-skew",
|
|
+ "cs1_dm0_tx_de-skew",
|
|
+ "cs1_dq0_rx_de-skew",
|
|
+ "cs1_dq0_tx_de-skew",
|
|
+ "cs1_dq1_rx_de-skew",
|
|
+ "cs1_dq1_tx_de-skew",
|
|
+ "cs1_dq2_rx_de-skew",
|
|
+ "cs1_dq2_tx_de-skew",
|
|
+ "cs1_dq3_rx_de-skew",
|
|
+ "cs1_dq3_tx_de-skew",
|
|
+ "cs1_dq4_rx_de-skew",
|
|
+ "cs1_dq4_tx_de-skew",
|
|
+ "cs1_dq5_rx_de-skew",
|
|
+ "cs1_dq5_tx_de-skew",
|
|
+ "cs1_dq6_rx_de-skew",
|
|
+ "cs1_dq6_tx_de-skew",
|
|
+ "cs1_dq7_rx_de-skew",
|
|
+ "cs1_dq7_tx_de-skew",
|
|
+ "cs1_dqs0_rx_de-skew",
|
|
+ "cs1_dqs0p_tx_de-skew",
|
|
+ "cs1_dqs0n_tx_de-skew",
|
|
+
|
|
+ "cs1_dm1_rx_de-skew",
|
|
+ "cs1_dm1_tx_de-skew",
|
|
+ "cs1_dq8_rx_de-skew",
|
|
+ "cs1_dq8_tx_de-skew",
|
|
+ "cs1_dq9_rx_de-skew",
|
|
+ "cs1_dq9_tx_de-skew",
|
|
+ "cs1_dq10_rx_de-skew",
|
|
+ "cs1_dq10_tx_de-skew",
|
|
+ "cs1_dq11_rx_de-skew",
|
|
+ "cs1_dq11_tx_de-skew",
|
|
+ "cs1_dq12_rx_de-skew",
|
|
+ "cs1_dq12_tx_de-skew",
|
|
+ "cs1_dq13_rx_de-skew",
|
|
+ "cs1_dq13_tx_de-skew",
|
|
+ "cs1_dq14_rx_de-skew",
|
|
+ "cs1_dq14_tx_de-skew",
|
|
+ "cs1_dq15_rx_de-skew",
|
|
+ "cs1_dq15_tx_de-skew",
|
|
+ "cs1_dqs1_rx_de-skew",
|
|
+ "cs1_dqs1p_tx_de-skew",
|
|
+ "cs1_dqs1n_tx_de-skew",
|
|
+
|
|
+ "cs1_dm2_rx_de-skew",
|
|
+ "cs1_dm2_tx_de-skew",
|
|
+ "cs1_dq16_rx_de-skew",
|
|
+ "cs1_dq16_tx_de-skew",
|
|
+ "cs1_dq17_rx_de-skew",
|
|
+ "cs1_dq17_tx_de-skew",
|
|
+ "cs1_dq18_rx_de-skew",
|
|
+ "cs1_dq18_tx_de-skew",
|
|
+ "cs1_dq19_rx_de-skew",
|
|
+ "cs1_dq19_tx_de-skew",
|
|
+ "cs1_dq20_rx_de-skew",
|
|
+ "cs1_dq20_tx_de-skew",
|
|
+ "cs1_dq21_rx_de-skew",
|
|
+ "cs1_dq21_tx_de-skew",
|
|
+ "cs1_dq22_rx_de-skew",
|
|
+ "cs1_dq22_tx_de-skew",
|
|
+ "cs1_dq23_rx_de-skew",
|
|
+ "cs1_dq23_tx_de-skew",
|
|
+ "cs1_dqs2_rx_de-skew",
|
|
+ "cs1_dqs2p_tx_de-skew",
|
|
+ "cs1_dqs2n_tx_de-skew",
|
|
+
|
|
+ "cs1_dm3_rx_de-skew",
|
|
+ "cs1_dm3_tx_de-skew",
|
|
+ "cs1_dq24_rx_de-skew",
|
|
+ "cs1_dq24_tx_de-skew",
|
|
+ "cs1_dq25_rx_de-skew",
|
|
+ "cs1_dq25_tx_de-skew",
|
|
+ "cs1_dq26_rx_de-skew",
|
|
+ "cs1_dq26_tx_de-skew",
|
|
+ "cs1_dq27_rx_de-skew",
|
|
+ "cs1_dq27_tx_de-skew",
|
|
+ "cs1_dq28_rx_de-skew",
|
|
+ "cs1_dq28_tx_de-skew",
|
|
+ "cs1_dq29_rx_de-skew",
|
|
+ "cs1_dq29_tx_de-skew",
|
|
+ "cs1_dq30_rx_de-skew",
|
|
+ "cs1_dq30_tx_de-skew",
|
|
+ "cs1_dq31_rx_de-skew",
|
|
+ "cs1_dq31_tx_de-skew",
|
|
+ "cs1_dqs3_rx_de-skew",
|
|
+ "cs1_dqs3p_tx_de-skew",
|
|
+ "cs1_dqs3n_tx_de-skew",
|
|
+};
|
|
+
|
|
+struct rk3328_ddr_dts_config_timing {
|
|
+ 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 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 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 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;
|
|
+};
|
|
+
|
|
+struct rk3328_ddr_de_skew_setting {
|
|
+ unsigned int ca_de_skew[30];
|
|
+ unsigned int cs0_de_skew[84];
|
|
+ unsigned int cs1_de_skew[84];
|
|
+};
|
|
+
|
|
+struct rk3328_devfreq {
|
|
+ struct devfreq *devfreq;
|
|
+ struct thermal_cooling_device *cooling;
|
|
+};
|
|
+
|
|
+struct rk3328_dmcfreq {
|
|
+ struct device *dev;
|
|
+ //struct devfreq *devfreq;
|
|
+ struct devfreq_simple_ondemand_data ondemand_data;
|
|
+ struct clk *dmc_clk;
|
|
+ struct devfreq_event_dev *edev;
|
|
+ struct mutex lock;
|
|
+ struct regulator *vdd_center;
|
|
+ struct rk3328_devfreq devfreq;
|
|
+ unsigned long rate, target_rate;
|
|
+ unsigned long volt, target_volt;
|
|
+
|
|
+ int (*set_auto_self_refresh)(u32 en);
|
|
+};
|
|
+
|
|
+static void
|
|
+rk3328_de_skew_setting_2_register(struct rk3328_ddr_de_skew_setting *de_skew,
|
|
+ struct rk3328_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);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void of_get_rk3328_timings(struct device *dev,
|
|
+ struct device_node *np, uint32_t *timing)
|
|
+{
|
|
+ struct device_node *np_tim;
|
|
+ u32 *p;
|
|
+ struct rk3328_ddr_dts_config_timing *dts_timing;
|
|
+ struct rk3328_ddr_de_skew_setting *de_skew;
|
|
+ int ret = 0;
|
|
+ u32 i;
|
|
+
|
|
+ dts_timing =
|
|
+ (struct rk3328_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(rk3328_dts_timing); i++) {
|
|
+ ret |= of_property_read_u32(np_tim, rk3328_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)
|
|
+ rk3328_de_skew_setting_2_register(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 int rockchip_ddr_set_auto_self_refresh(uint32_t en)
|
|
+{
|
|
+ struct arm_smccc_res res;
|
|
+
|
|
+ ddr_psci_param->sr_idle_en = en;
|
|
+
|
|
+ arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ,
|
|
+ SHARE_PAGE_TYPE_DDR, 0, ROCKCHIP_SIP_CONFIG_DRAM_SET_AT_SR,
|
|
+ 0, 0, 0, 0, &res);
|
|
+
|
|
+ return res.a0;
|
|
+}
|
|
+
|
|
+static int rk3328_dmc_init(struct platform_device *pdev,
|
|
+ struct rk3328_dmcfreq *dmcfreq)
|
|
+{
|
|
+ struct arm_smccc_res res;
|
|
+ u32 size, page_num;
|
|
+
|
|
+ arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ,
|
|
+ 0, 0, ROCKCHIP_SIP_CONFIG_DRAM_GET_VERSION,
|
|
+ 0, 0, 0, 0, &res);
|
|
+ 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, "current ATF version 0x%lx\n", res.a1);
|
|
+
|
|
+ /*
|
|
+ * first 4KB is used for interface parameters
|
|
+ * after 4KB * N is dts parameters
|
|
+ */
|
|
+ size = sizeof(struct rk3328_ddr_dts_config_timing);
|
|
+ page_num = DIV_ROUND_UP(size, 4096) + 1;
|
|
+
|
|
+ arm_smccc_smc(ROCKCHIP_SIP_SHARE_MEM,
|
|
+ page_num, SHARE_PAGE_TYPE_DDR, 0,
|
|
+ 0, 0, 0, 0, &res);
|
|
+ if (res.a0 != 0) {
|
|
+ dev_err(&pdev->dev, "no ATF memory for init\n");
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+
|
|
+ ddr_psci_param = ioremap(res.a1, page_num << 12);
|
|
+ of_get_rk3328_timings(&pdev->dev, pdev->dev.of_node,
|
|
+ (uint32_t *)ddr_psci_param);
|
|
+
|
|
+ arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ,
|
|
+ SHARE_PAGE_TYPE_DDR, 0, ROCKCHIP_SIP_CONFIG_DRAM_INIT,
|
|
+ 0, 0, 0, 0, &res);
|
|
+ if (res.a0) {
|
|
+ dev_err(&pdev->dev, "Rockchip dram init error %lx\n", res.a0);
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+
|
|
+ dmcfreq->set_auto_self_refresh = rockchip_ddr_set_auto_self_refresh;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rk3328_dmcfreq_target(struct device *dev, unsigned long *freq,
|
|
+ u32 flags)
|
|
+{
|
|
+ struct rk3328_dmcfreq *rdev = dev_get_drvdata(dev);
|
|
+ struct dev_pm_opp *opp;
|
|
+ int err;
|
|
+
|
|
+ opp = devfreq_recommended_opp(dev, freq, flags);
|
|
+ if (IS_ERR(opp))
|
|
+ return PTR_ERR(opp);
|
|
+ dev_pm_opp_put(opp);
|
|
+
|
|
+ err = dev_pm_opp_set_rate(dev, *freq);
|
|
+ if (err)
|
|
+ return err;
|
|
+
|
|
+ rdev->rate = *freq;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rk3328_dmcfreq_get_dev_status(struct device *dev,
|
|
+ struct devfreq_dev_status *stat)
|
|
+{
|
|
+ struct rk3328_dmcfreq *dmcfreq = dev_get_drvdata(dev);
|
|
+ struct devfreq_event_data edata;
|
|
+ int ret = 0;
|
|
+
|
|
+ ret = devfreq_event_get_event(dmcfreq->edev, &edata);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
+ stat->current_frequency = dmcfreq->rate;
|
|
+ stat->busy_time = edata.load_count;
|
|
+ stat->total_time = edata.total_count;
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int rk3328_dmcfreq_get_cur_freq(struct device *dev, unsigned long *freq)
|
|
+{
|
|
+ struct rk3328_dmcfreq *dmcfreq = dev_get_drvdata(dev);
|
|
+
|
|
+ *freq = dmcfreq->rate;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static struct devfreq_dev_profile rk3328_devfreq_dmc_profile = {
|
|
+ .polling_ms = 50,
|
|
+ .target = rk3328_dmcfreq_target,
|
|
+ .get_dev_status = rk3328_dmcfreq_get_dev_status,
|
|
+ .get_cur_freq = rk3328_dmcfreq_get_cur_freq,
|
|
+};
|
|
+
|
|
+static __maybe_unused int rk3328_dmcfreq_suspend(struct device *dev)
|
|
+{
|
|
+ struct rk3328_dmcfreq *dmcfreq = dev_get_drvdata(dev);
|
|
+ int ret = 0;
|
|
+
|
|
+ ret = devfreq_event_disable_edev(dmcfreq->edev);
|
|
+ if (ret < 0) {
|
|
+ dev_err(dev, "failed to disable the devfreq-event devices\n");
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ ret = devfreq_suspend_device(dmcfreq->devfreq.devfreq);
|
|
+ if (ret < 0) {
|
|
+ dev_err(dev, "failed to suspend the devfreq devices\n");
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static __maybe_unused int rk3328_dmcfreq_resume(struct device *dev)
|
|
+{
|
|
+ struct rk3328_dmcfreq *dmcfreq = dev_get_drvdata(dev);
|
|
+ int ret = 0;
|
|
+
|
|
+ ret = devfreq_event_enable_edev(dmcfreq->edev);
|
|
+ if (ret < 0) {
|
|
+ dev_err(dev, "failed to enable the devfreq-event devices\n");
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ ret = devfreq_resume_device(dmcfreq->devfreq.devfreq);
|
|
+ if (ret < 0) {
|
|
+ dev_err(dev, "failed to resume the devfreq devices\n");
|
|
+ return ret;
|
|
+ }
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static SIMPLE_DEV_PM_OPS(rk3328_dmcfreq_pm, rk3328_dmcfreq_suspend,
|
|
+ rk3328_dmcfreq_resume);
|
|
+
|
|
+void rk3328_devfreq_fini(struct rk3328_dmcfreq *rdev)
|
|
+{
|
|
+ struct rk3328_devfreq *devfreq = &rdev->devfreq;
|
|
+
|
|
+ if (devfreq->cooling) {
|
|
+ devfreq_cooling_unregister(devfreq->cooling);
|
|
+ devfreq->cooling = NULL;
|
|
+ }
|
|
+
|
|
+ if (devfreq->devfreq) {
|
|
+ devm_devfreq_remove_device(rdev->dev, devfreq->devfreq);
|
|
+ devfreq->devfreq = NULL;
|
|
+ }
|
|
+
|
|
+}
|
|
+
|
|
+int rk3328_devfreq_init(struct rk3328_dmcfreq *rdev)
|
|
+{
|
|
+ struct thermal_cooling_device *cooling;
|
|
+ struct device *dev = rdev->dev;
|
|
+ struct devfreq *devfreq;
|
|
+ struct rk3328_devfreq *rdevfreq = &rdev->devfreq;
|
|
+ const char *regulator_names[] = { "center", NULL };
|
|
+
|
|
+ struct dev_pm_opp *opp;
|
|
+ unsigned long cur_freq;
|
|
+ int ret;
|
|
+
|
|
+ if (!device_property_present(dev, "operating-points-v2"))
|
|
+ /* Optional, continue without devfreq */
|
|
+ return 0;
|
|
+
|
|
+ ret= devm_pm_opp_set_clkname(dev, "dmc_clk");
|
|
+ if (ret)
|
|
+ goto err_fini;
|
|
+
|
|
+ ret = devm_pm_opp_set_regulators(dev, regulator_names);
|
|
+
|
|
+ if (ret) {
|
|
+ /* Continue if the optional regulator is missing */
|
|
+ if (ret != -ENODEV)
|
|
+ goto err_fini;
|
|
+ }
|
|
+
|
|
+ ret = devm_pm_opp_of_add_table(dev);
|
|
+ if (ret)
|
|
+ goto err_fini;
|
|
+
|
|
+ cur_freq = 0;
|
|
+
|
|
+ opp = devfreq_recommended_opp(dev, &cur_freq, 0);
|
|
+ if (IS_ERR(opp)) {
|
|
+ ret = PTR_ERR(opp);
|
|
+ goto err_fini;
|
|
+ }
|
|
+
|
|
+ rk3328_devfreq_dmc_profile.initial_freq = cur_freq;
|
|
+ dev_pm_opp_put(opp);
|
|
+
|
|
+ rdev->ondemand_data.upthreshold = 15;
|
|
+ rdev->ondemand_data.downdifferential = 5;
|
|
+
|
|
+ devfreq = devm_devfreq_add_device(dev, &rk3328_devfreq_dmc_profile,
|
|
+ DEVFREQ_GOV_SIMPLE_ONDEMAND, &rdev->ondemand_data);
|
|
+ if (IS_ERR(devfreq)) {
|
|
+ dev_err(dev, "Couldn't initialize rk3328-dmc devfreq\n");
|
|
+ ret = PTR_ERR(devfreq);
|
|
+ goto err_fini;
|
|
+ }
|
|
+
|
|
+ rdevfreq->devfreq = devfreq;
|
|
+
|
|
+ cooling = of_devfreq_cooling_register(dev->of_node, devfreq);
|
|
+ if (IS_ERR(cooling))
|
|
+ dev_warn(dev, "Failed to register cooling device\n");
|
|
+ else
|
|
+ rdevfreq->cooling = cooling;
|
|
+
|
|
+ return 0;
|
|
+
|
|
+err_fini:
|
|
+ rk3328_devfreq_fini(rdev);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int rk3328_dmcfreq_probe(struct platform_device *pdev)
|
|
+{
|
|
+ struct device *dev = &pdev->dev;
|
|
+ struct rk3328_dmcfreq *data;
|
|
+ int ret;
|
|
+
|
|
+ data = devm_kzalloc(dev, sizeof(struct rk3328_dmcfreq), GFP_KERNEL);
|
|
+ if (!data)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ mutex_init(&data->lock);
|
|
+
|
|
+ data->dev = dev;
|
|
+
|
|
+ data->dmc_clk = devm_clk_get(dev, "dmc_clk");
|
|
+ if (IS_ERR(data->dmc_clk)) {
|
|
+ if (PTR_ERR(data->dmc_clk) == -EPROBE_DEFER)
|
|
+ return -EPROBE_DEFER;
|
|
+
|
|
+ dev_err(dev, "Cannot get the clk dmc_clk\n");
|
|
+ return PTR_ERR(data->dmc_clk);
|
|
+ }
|
|
+
|
|
+ data->edev = devfreq_event_get_edev_by_phandle(dev, "devfreq-events", 0);
|
|
+ if (IS_ERR(data->edev))
|
|
+ return -EPROBE_DEFER;
|
|
+
|
|
+ ret = devfreq_event_enable_edev(data->edev);
|
|
+ if (ret < 0) {
|
|
+ dev_err(dev, "failed to enable devfreq-event devices\n");
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ ret = rk3328_dmc_init(pdev, data);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ ret = rk3328_devfreq_init(data);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ platform_set_drvdata(pdev, data);
|
|
+
|
|
+ return 0;
|
|
+
|
|
+}
|
|
+
|
|
+static int rk3328_dmcfreq_remove(struct platform_device *pdev)
|
|
+{
|
|
+ struct rk3328_dmcfreq *dmcfreq = dev_get_drvdata(&pdev->dev);
|
|
+
|
|
+ /*
|
|
+ * Before remove the opp table we need to unregister the opp notifier.
|
|
+ */
|
|
+ rk3328_devfreq_fini(dmcfreq);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static const struct of_device_id rk3328dmc_devfreq_of_match[] = {
|
|
+ { .compatible = "rockchip,rk3328-dmc" },
|
|
+ { },
|
|
+};
|
|
+MODULE_DEVICE_TABLE(of, rk3328dmc_devfreq_of_match);
|
|
+
|
|
+static struct platform_driver rk3328_dmcfreq_driver = {
|
|
+ .probe = rk3328_dmcfreq_probe,
|
|
+ .remove = rk3328_dmcfreq_remove,
|
|
+ .driver = {
|
|
+ .name = "rk3328-dmc",
|
|
+ .pm = &rk3328_dmcfreq_pm,
|
|
+ .of_match_table = rk3328dmc_devfreq_of_match,
|
|
+ },
|
|
+};
|
|
+module_platform_driver(rk3328_dmcfreq_driver);
|
|
+
|
|
+MODULE_LICENSE("GPL v2");
|
|
+MODULE_AUTHOR("Lin Huang <hl@rock-chips.com>");
|
|
+MODULE_DESCRIPTION("RK3328 dmcfreq driver with devfreq framework");
|
|
diff --git a/include/dt-bindings/clock/rockchip-ddr.h b/include/dt-bindings/clock/rockchip-ddr.h
|
|
new file mode 100644
|
|
index 000000000000..b065432e7793
|
|
--- /dev/null
|
|
+++ b/include/dt-bindings/clock/rockchip-ddr.h
|
|
@@ -0,0 +1,63 @@
|
|
+/*
|
|
+ *
|
|
+ * Copyright (C) 2017 ROCKCHIP, Inc.
|
|
+ *
|
|
+ * This software is licensed under the terms of the GNU General Public
|
|
+ * License version 2, as published by the Free Software Foundation, and
|
|
+ * may be copied, distributed, and modified under those terms.
|
|
+ *
|
|
+ * This program is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ * GNU General Public License for more details.
|
|
+ *
|
|
+ */
|
|
+
|
|
+#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 */
|
|
+#define DDR3_1066F (3) /* 7-7-7 */
|
|
+#define DDR3_1066G (4) /* 8-8-8 */
|
|
+#define DDR3_1333F (5) /* 7-7-7 */
|
|
+#define DDR3_1333G (6) /* 8-8-8 */
|
|
+#define DDR3_1333H (7) /* 9-9-9 */
|
|
+#define DDR3_1333J (8) /* 10-10-10 */
|
|
+#define DDR3_1600G (9) /* 8-8-8 */
|
|
+#define DDR3_1600H (10) /* 9-9-9 */
|
|
+#define DDR3_1600J (11) /* 10-10-10 */
|
|
+#define DDR3_1600K (12) /* 11-11-11 */
|
|
+#define DDR3_1866J (13) /* 10-10-10 */
|
|
+#define DDR3_1866K (14) /* 11-11-11 */
|
|
+#define DDR3_1866L (15) /* 12-12-12 */
|
|
+#define DDR3_1866M (16) /* 13-13-13 */
|
|
+#define DDR3_2133K (17) /* 11-11-11 */
|
|
+#define DDR3_2133L (18) /* 12-12-12 */
|
|
+#define DDR3_2133M (19) /* 13-13-13 */
|
|
+#define DDR3_2133N (20) /* 14-14-14 */
|
|
+#define DDR3_DEFAULT (21)
|
|
+#define DDR_DDR2 (22)
|
|
+#define DDR_LPDDR (23)
|
|
+#define DDR_LPDDR2 (24)
|
|
+
|
|
+#define DDR4_1600J (0) /* 10-10-10 */
|
|
+#define DDR4_1600K (1) /* 11-11-11 */
|
|
+#define DDR4_1600L (2) /* 12-12-12 */
|
|
+#define DDR4_1866L (3) /* 12-12-12 */
|
|
+#define DDR4_1866M (4) /* 13-13-13 */
|
|
+#define DDR4_1866N (5) /* 14-14-14 */
|
|
+#define DDR4_2133N (6) /* 14-14-14 */
|
|
+#define DDR4_2133P (7) /* 15-15-15 */
|
|
+#define DDR4_2133R (8) /* 16-16-16 */
|
|
+#define DDR4_2400P (9) /* 15-15-15 */
|
|
+#define DDR4_2400R (10) /* 16-16-16 */
|
|
+#define DDR4_2400U (11) /* 18-18-18 */
|
|
+#define DDR4_DEFAULT (12)
|
|
+
|
|
+#define PAUSE_CPU_STACK_SIZE 16
|
|
+
|
|
+#endif
|
|
diff --git a/include/dt-bindings/memory/rk3328-dram.h b/include/dt-bindings/memory/rk3328-dram.h
|
|
new file mode 100644
|
|
index 000000000000..171f41c256d3
|
|
--- /dev/null
|
|
+++ b/include/dt-bindings/memory/rk3328-dram.h
|
|
@@ -0,0 +1,159 @@
|
|
+/*
|
|
+ * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd
|
|
+ *
|
|
+ * This file is dual-licensed: you can use it either under the terms
|
|
+ * of the GPL or the X11 license, at your option. Note that this dual
|
|
+ * licensing only applies to this file, and not this project as a
|
|
+ * whole.
|
|
+ *
|
|
+ * a) This library is free software; you can redistribute it and/or
|
|
+ * modify it under the terms of the GNU General Public License as
|
|
+ * published by the Free Software Foundation; either version 2 of the
|
|
+ * License, or (at your option) any later version.
|
|
+ *
|
|
+ * This library is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ * GNU General Public License for more details.
|
|
+ *
|
|
+ * Or, alternatively,
|
|
+ *
|
|
+ * b) Permission is hereby granted, free of charge, to any person
|
|
+ * obtaining a copy of this software and associated documentation
|
|
+ * files (the "Software"), to deal in the Software without
|
|
+ * restriction, including without limitation the rights to use,
|
|
+ * copy, modify, merge, publish, distribute, sublicense, and/or
|
|
+ * sell copies of the Software, and to permit persons to whom the
|
|
+ * Software is furnished to do so, subject to the following
|
|
+ * conditions:
|
|
+ *
|
|
+ * The above copyright notice and this permission notice shall be
|
|
+ * included in all copies or substantial portions of the Software.
|
|
+ *
|
|
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
+ * OTHER DEALINGS IN THE SOFTWARE.
|
|
+ */
|
|
+#ifndef _DT_BINDINGS_DRAM_ROCKCHIP_RK3328_H
|
|
+#define _DT_BINDINGS_DRAM_ROCKCHIP_RK3328_H
|
|
+
|
|
+#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_RON_RTT_DISABLE (0)
|
|
+#define PHY_DDR4_LPDDR3_RON_RTT_480ohm (1)
|
|
+#define PHY_DDR4_LPDDR3_RON_RTT_240ohm (2)
|
|
+#define PHY_DDR4_LPDDR3_RON_RTT_160ohm (3)
|
|
+#define PHY_DDR4_LPDDR3_RON_RTT_120ohm (4)
|
|
+#define PHY_DDR4_LPDDR3_RON_RTT_96ohm (5)
|
|
+#define PHY_DDR4_LPDDR3_RON_RTT_80ohm (6)
|
|
+#define PHY_DDR4_LPDDR3_RON_RTT_68ohm (7)
|
|
+#define PHY_DDR4_LPDDR3_RON_RTT_60ohm (16)
|
|
+#define PHY_DDR4_LPDDR3_RON_RTT_53ohm (17)
|
|
+#define PHY_DDR4_LPDDR3_RON_RTT_48ohm (18)
|
|
+#define PHY_DDR4_LPDDR3_RON_RTT_43ohm (19)
|
|
+#define PHY_DDR4_LPDDR3_RON_RTT_40ohm (20)
|
|
+#define PHY_DDR4_LPDDR3_RON_RTT_37ohm (21)
|
|
+#define PHY_DDR4_LPDDR3_RON_RTT_34ohm (22)
|
|
+#define PHY_DDR4_LPDDR3_RON_RTT_32ohm (23)
|
|
+#define PHY_DDR4_LPDDR3_RON_RTT_30ohm (24)
|
|
+#define PHY_DDR4_LPDDR3_RON_RTT_28ohm (25)
|
|
+#define PHY_DDR4_LPDDR3_RON_RTT_26ohm (26)
|
|
+#define PHY_DDR4_LPDDR3_RON_RTT_25ohm (27)
|
|
+#define PHY_DDR4_LPDDR3_RON_RTT_24ohm (28)
|
|
+#define PHY_DDR4_LPDDR3_RON_RTT_22ohm (29)
|
|
+#define PHY_DDR4_LPDDR3_RON_RTT_21ohm (30)
|
|
+#define PHY_DDR4_LPDDR3_RON_RTT_20ohm (31)
|
|
+
|
|
+#endif /*_DT_BINDINGS_DRAM_ROCKCHIP_RK3328_H*/
|
|
diff --git a/include/soc/rockchip/rockchip_sip.h b/include/soc/rockchip/rockchip_sip.h
|
|
index c46a9ae2a2ab..fa7e0a2d72cc 100644
|
|
--- a/include/soc/rockchip/rockchip_sip.h
|
|
+++ b/include/soc/rockchip/rockchip_sip.h
|
|
@@ -16,5 +16,16 @@
|
|
#define ROCKCHIP_SIP_CONFIG_DRAM_CLR_IRQ 0x06
|
|
#define ROCKCHIP_SIP_CONFIG_DRAM_SET_PARAM 0x07
|
|
#define ROCKCHIP_SIP_CONFIG_DRAM_SET_ODT_PD 0x08
|
|
+#define ROCKCHIP_SIP_CONFIG_DRAM_GET_VERSION 0x08
|
|
+
|
|
+#define ROCKCHIP_SIP_SHARE_MEM 0x82000009
|
|
+
|
|
+/* Share mem page types */
|
|
+typedef enum {
|
|
+ SHARE_PAGE_TYPE_INVALID = 0,
|
|
+ SHARE_PAGE_TYPE_UARTDBG,
|
|
+ SHARE_PAGE_TYPE_DDR,
|
|
+ SHARE_PAGE_TYPE_MAX,
|
|
+} share_page_type_t;
|
|
|
|
#endif
|
|
--
|
|
Armbian
|
|
|