[PATCH v7 5/5] drm/rockchip: support dp training outside dp firmware

2018-05-24 Thread Lin Huang
DP firmware uses fixed phy config values to do training, but some
boards need to adjust these values to fit for their unique hardware
design. So get phy config values from dts and use software link training
instead of relying on firmware, if software training fail, keep firmware
training as a fallback if sw training fails.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
Signed-off-by: Lin Huang <h...@rock-chips.com>
Reviewed-by: Sean Paul <seanp...@chromium.org>
---
Changes in v2:
- update patch following Enric suggest
Changes in v3:
- use variable fw_training instead sw_training_success
- base on DP SPCE, if training fail use lower link rate to retry training
Changes in v4:
- improve cdn_dp_get_lower_link_rate() and cdn_dp_software_train_link() follow 
Sean suggest
Changes in v5:
- fix some whitespcae issue
Changes in v6:
- None
Changes in v7:
- None

 drivers/gpu/drm/rockchip/Makefile   |   3 +-
 drivers/gpu/drm/rockchip/cdn-dp-core.c  |  24 +-
 drivers/gpu/drm/rockchip/cdn-dp-core.h  |   2 +
 drivers/gpu/drm/rockchip/cdn-dp-link-training.c | 420 
 drivers/gpu/drm/rockchip/cdn-dp-reg.c   |  31 +-
 drivers/gpu/drm/rockchip/cdn-dp-reg.h   |  38 ++-
 6 files changed, 505 insertions(+), 13 deletions(-)
 create mode 100644 drivers/gpu/drm/rockchip/cdn-dp-link-training.c

diff --git a/drivers/gpu/drm/rockchip/Makefile 
b/drivers/gpu/drm/rockchip/Makefile
index a314e21..b932f62 100644
--- a/drivers/gpu/drm/rockchip/Makefile
+++ b/drivers/gpu/drm/rockchip/Makefile
@@ -9,7 +9,8 @@ rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \
 rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o
 
 rockchipdrm-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o
-rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o
+rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o \
+   cdn-dp-link-training.o
 rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o
 rockchipdrm-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi.o
 rockchipdrm-$(CONFIG_ROCKCHIP_INNO_HDMI) += inno_hdmi.o
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c 
b/drivers/gpu/drm/rockchip/cdn-dp-core.c
index cce64c1..783d57a 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -629,11 +629,13 @@ static void cdn_dp_encoder_enable(struct drm_encoder 
*encoder)
goto out;
}
}
-
-   ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_IDLE);
-   if (ret) {
-   DRM_DEV_ERROR(dp->dev, "Failed to idle video %d\n", ret);
-   goto out;
+   if (dp->use_fw_training) {
+   ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_IDLE);
+   if (ret) {
+   DRM_DEV_ERROR(dp->dev,
+ "Failed to idle video %d\n", ret);
+   goto out;
+   }
}
 
ret = cdn_dp_config_video(dp);
@@ -642,11 +644,15 @@ static void cdn_dp_encoder_enable(struct drm_encoder 
*encoder)
goto out;
}
 
-   ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_VALID);
-   if (ret) {
-   DRM_DEV_ERROR(dp->dev, "Failed to valid video %d\n", ret);
-   goto out;
+   if (dp->use_fw_training) {
+   ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_VALID);
+   if (ret) {
+   DRM_DEV_ERROR(dp->dev,
+   "Failed to valid video %d\n", ret);
+   goto out;
+   }
}
+
 out:
mutex_unlock(>lock);
 }
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.h 
b/drivers/gpu/drm/rockchip/cdn-dp-core.h
index 46159b2..77a9793 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.h
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.h
@@ -84,6 +84,7 @@ struct cdn_dp_device {
bool connected;
bool active;
bool suspended;
+   bool use_fw_training;
 
const struct firmware *fw;  /* cdn dp firmware */
unsigned int fw_version;/* cdn fw version */
@@ -106,6 +107,7 @@ struct cdn_dp_device {
u8 ports;
u8 lanes;
int active_port;
+   u8 train_set[4];
 
u8 dpcd[DP_RECEIVER_CAP_SIZE];
bool sink_has_audio;
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-link-training.c 
b/drivers/gpu/drm/rockchip/cdn-dp-link-training.c
new file mode 100644
index 000..73c3290
--- /dev/null
+++ b/drivers/gpu/drm/rockchip/cdn-dp-link-training.c
@@ -0,0 +1,420 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
+ * Author: Chris Zhong <z...@rock-chips.com>
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "cdn-dp-core.h"
+#include "cdn-dp-reg.h"
+
+static 

[PATCH v7 4/5] phy: rockchip-typec: support variable phy config value

2018-05-24 Thread Lin Huang
the phy config values used to fix in dp firmware, but some boards
need change these values to do training and get the better eye diagram
result. So support that in phy driver.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
Signed-off-by: Lin Huang <h...@rock-chips.com>
---
Changes in v2:
- update patch following Enric suggest
Changes in v3:
- delete need_software_training variable
- add default phy config value, if dts do not define phy config value, use 
these value
Changes in v4:
- rename variable config to tcphy_default_config
Changes in v5:
- None
Changes in v6:
- split the header file to new patch
Changes in v7:
- add default case when check link rate
- move struct rockchip_typec_phy new element to this patch

 drivers/phy/rockchip/phy-rockchip-typec.c | 263 --
 include/soc/rockchip/rockchip_phy_typec.h |   8 +
 2 files changed, 218 insertions(+), 53 deletions(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-typec.c 
b/drivers/phy/rockchip/phy-rockchip-typec.c
index 795055f..69af90e 100644
--- a/drivers/phy/rockchip/phy-rockchip-typec.c
+++ b/drivers/phy/rockchip/phy-rockchip-typec.c
@@ -324,21 +324,29 @@
  * clock 0: PLL 0 div 1
  * clock 1: PLL 1 div 2
  */
-#define CLK_PLL_CONFIG 0X30
+#define CLK_PLL1_DIV1  0x20
+#define CLK_PLL1_DIV2  0x30
 #define CLK_PLL_MASK   0x33
 
 #define CMN_READY  BIT(0)
 
+#define DP_PLL_CLOCK_ENABLE_ACKBIT(3)
 #define DP_PLL_CLOCK_ENABLEBIT(2)
+#define DP_PLL_ENABLE_ACK  BIT(1)
 #define DP_PLL_ENABLE  BIT(0)
 #define DP_PLL_DATA_RATE_RBR   ((2 << 12) | (4 << 8))
 #define DP_PLL_DATA_RATE_HBR   ((2 << 12) | (4 << 8))
 #define DP_PLL_DATA_RATE_HBR2  ((1 << 12) | (2 << 8))
+#define DP_PLL_DATA_RATE_MASK  0xff00
 
-#define DP_MODE_A0 BIT(4)
-#define DP_MODE_A2 BIT(6)
-#define DP_MODE_ENTER_A0   0xc101
-#define DP_MODE_ENTER_A2   0xc104
+#define DP_MODE_MASK   0xf
+#define DP_MODE_ENTER_A0   BIT(0)
+#define DP_MODE_ENTER_A2   BIT(2)
+#define DP_MODE_ENTER_A3   BIT(3)
+#define DP_MODE_A0_ACK BIT(4)
+#define DP_MODE_A2_ACK BIT(6)
+#define DP_MODE_A3_ACK BIT(7)
+#define DP_LINK_RESET_DEASSERTED   BIT(8)
 
 #define PHY_MODE_SET_TIMEOUT   10
 
@@ -350,6 +358,8 @@
 #define MODE_DFP_USB   BIT(1)
 #define MODE_DFP_DPBIT(2)
 
+#define DP_DEFAULT_RATE162000
+
 struct phy_reg {
u16 value;
u32 addr;
@@ -372,15 +382,15 @@ struct phy_reg usb3_pll_cfg[] = {
{ 0x8,  CMN_DIAG_PLL0_LF_PROG },
 };
 
-struct phy_reg dp_pll_cfg[] = {
+struct phy_reg dp_pll_rbr_cfg[] = {
{ 0xf0, CMN_PLL1_VCOCAL_INIT },
{ 0x18, CMN_PLL1_VCOCAL_ITER },
{ 0x30b9,   CMN_PLL1_VCOCAL_START },
-   { 0x21c,CMN_PLL1_INTDIV },
+   { 0x87, CMN_PLL1_INTDIV },
{ 0,CMN_PLL1_FRACDIV },
-   { 0x5,  CMN_PLL1_HIGH_THR },
-   { 0x35, CMN_PLL1_SS_CTRL1 },
-   { 0x7f1e,   CMN_PLL1_SS_CTRL2 },
+   { 0x22, CMN_PLL1_HIGH_THR },
+   { 0x8000,   CMN_PLL1_SS_CTRL1 },
+   { 0,CMN_PLL1_SS_CTRL2 },
{ 0x20, CMN_PLL1_DSM_DIAG },
{ 0,CMN_PLLSM1_USER_DEF_CTRL },
{ 0,CMN_DIAG_PLL1_OVRD },
@@ -391,9 +401,52 @@ struct phy_reg dp_pll_cfg[] = {
{ 0x8,  CMN_DIAG_PLL1_LF_PROG },
{ 0x100,CMN_DIAG_PLL1_PTATIS_TUNE1 },
{ 0x7,  CMN_DIAG_PLL1_PTATIS_TUNE2 },
-   { 0x4,  CMN_DIAG_PLL1_INCLK_CTRL },
+   { 0x1,  CMN_DIAG_PLL1_INCLK_CTRL },
 };
 
+struct phy_reg dp_pll_hbr_cfg[] = {
+   { 0xf0, CMN_PLL1_VCOCAL_INIT },
+   { 0x18, CMN_PLL1_VCOCAL_ITER },
+   { 0x30b4,   CMN_PLL1_VCOCAL_START },
+   { 0xe1, CMN_PLL1_INTDIV },
+   { 0,CMN_PLL1_FRACDIV },
+   { 0x5,  CMN_PLL1_HIGH_THR },
+   { 0x8000,   CMN_PLL1_SS_CTRL1 },
+   { 0,CMN_PLL1_SS_CTRL2 },
+   { 0x20, CMN_PLL1_DSM_DIAG },
+   { 0x1000,   CMN_PLLSM1_USER_DEF_CTRL },
+   { 0,CMN_DIAG_PLL1_OVRD },
+   { 0,CMN_DIAG_PLL1_FBH_OVRD },
+   { 0,CMN_DIAG_PLL1_FBL_OVRD },
+   { 0x7,  CMN_DIAG_PLL1_V2I_TUNE },
+   { 0x45, CMN_DIAG_PLL1_CP_TUNE },
+   { 0x8,  CMN_DIAG_PLL1_LF_PROG },
+   { 0x1,  CMN_DIAG_PLL1_PTATIS_TUNE1 },
+   { 0x1,  CMN_DIAG_PLL1_PTATIS_TUNE2 },
+   { 0x1,  CMN_DIAG_PLL1_INCLK_CTRL },
+};
+
+struct phy_reg dp_pll_hbr2_cfg[] = {
+   { 0xf0, CMN_PLL1_VCOCAL_INIT

[PATCH v7 2/5] Documentation: dt-bindings: phy: add phy_config for Rockchip USB Type-C PHY

2018-05-24 Thread Lin Huang
If want to do training outside DP Firmware, need phy voltage swing
and pre_emphasis value.

Signed-off-by: Lin Huang <h...@rock-chips.com>
Reviewed-by: Rob Herring <r...@kernel.org>
---
Changes in v2:
- None 
Changes in v3:
- modify property description and add this property to Example
Changes in v4:
- None
Changes in v5:
- None
Changes in v6:
- change rockchip,phy_config to rockchip,phy-config and descript it in detail.
Changes in v7:
- None

 .../devicetree/bindings/phy/phy-rockchip-typec.txt | 36 +-
 1 file changed, 35 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt 
b/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
index 960da7f..40d5e7a 100644
--- a/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
+++ b/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
@@ -17,7 +17,11 @@ Required properties:
 
 Optional properties:
  - extcon : extcon specifier for the Power Delivery
-
+ - rockchip,phy-config : A list of voltage swing(mV) and pre-emphasis
+   (dB) pairs. They are 3 blocks of 4 entries and
+   correspond to s0p0 ~ s0p3, s1p0 ~ s1p3,
+   s2p0 ~ s2p3, s3p0 ~ s2p3 swing and pre-emphasis
+   values.
 Required nodes : a sub-node is required for each port the phy provides.
 The sub-node name is used to identify dp or usb3 port,
 and shall be the following entries:
@@ -50,6 +54,21 @@ Example:
 < SRST_P_UPHY0_TCPHY>;
reset-names = "uphy", "uphy-pipe", "uphy-tcphy";
 
+   rockchip,phy-config = <0x2a 0x00>,
+   <0x1f 0x15>,
+   <0x14 0x22>,
+   <0x02 0x2b>,
+
+   <0x21 0x00>,
+   <0x12 0x15>,
+   <0x02 0x22>,
+   <0 0>,
+
+   <0x15 0x00>,
+   <0x00 0x15>,
+   <0 0>,
+   <0 0>;
+
tcphy0_dp: dp-port {
#phy-cells = <0>;
};
@@ -74,6 +93,21 @@ Example:
 < SRST_P_UPHY1_TCPHY>;
reset-names = "uphy", "uphy-pipe", "uphy-tcphy";
 
+   rockchip,phy-config = <0x2a 0x00>,
+   <0x1f 0x15>,
+   <0x14 0x22>,
+   <0x02 0x2b>,
+
+   <0x21 0x00>,
+   <0x12 0x15>,
+   <0x02 0x22>,
+   <0 0>,
+
+   <0x15 0x00>,
+   <0x00 0x15>,
+   <0 0>,
+   <0 0>;
+
tcphy1_dp: dp-port {
#phy-cells = <0>;
};
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v7 1/5] drm/rockchip: add transfer function for cdn-dp

2018-05-24 Thread Lin Huang
From: Chris Zhong <z...@rock-chips.com>

We may support training outside firmware, so we need support
dpcd read/write to get the message or do some setting with
display.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
Signed-off-by: Lin Huang <h...@rock-chips.com>
Reviewed-by: Sean Paul <seanp...@chromium.org>
Reviewed-by: Enric Balletbo <enric.balle...@collabora.com>
---
Changes in v2:
- update patch following Enric suggest
Changes in v3:
- None
Changes in v4:
- None
Changes in v5:
- None
Changes in v6:
- None
Changes in v7:
- None

 drivers/gpu/drm/rockchip/cdn-dp-core.c | 55 +++
 drivers/gpu/drm/rockchip/cdn-dp-core.h |  1 +
 drivers/gpu/drm/rockchip/cdn-dp-reg.c  | 69 ++
 drivers/gpu/drm/rockchip/cdn-dp-reg.h  | 14 ++-
 4 files changed, 122 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c 
b/drivers/gpu/drm/rockchip/cdn-dp-core.c
index c6fbdcd..cce64c1 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -176,8 +176,8 @@ static int cdn_dp_get_sink_count(struct cdn_dp_device *dp, 
u8 *sink_count)
u8 value;
 
*sink_count = 0;
-   ret = cdn_dp_dpcd_read(dp, DP_SINK_COUNT, , 1);
-   if (ret)
+   ret = drm_dp_dpcd_read(>aux, DP_SINK_COUNT, , 1);
+   if (ret < 0)
return ret;
 
*sink_count = DP_GET_SINK_COUNT(value);
@@ -374,9 +374,9 @@ static int cdn_dp_get_sink_capability(struct cdn_dp_device 
*dp)
if (!cdn_dp_check_sink_connection(dp))
return -ENODEV;
 
-   ret = cdn_dp_dpcd_read(dp, DP_DPCD_REV, dp->dpcd,
-  DP_RECEIVER_CAP_SIZE);
-   if (ret) {
+   ret = drm_dp_dpcd_read(>aux, DP_DPCD_REV, dp->dpcd,
+  sizeof(dp->dpcd));
+   if (ret < 0) {
DRM_DEV_ERROR(dp->dev, "Failed to get caps %d\n", ret);
return ret;
}
@@ -582,8 +582,8 @@ static bool cdn_dp_check_link_status(struct cdn_dp_device 
*dp)
if (!port || !dp->link.rate || !dp->link.num_lanes)
return false;
 
-   if (cdn_dp_dpcd_read(dp, DP_LANE0_1_STATUS, link_status,
-DP_LINK_STATUS_SIZE)) {
+   if (drm_dp_dpcd_read_link_status(>aux, link_status) !=
+   DP_LINK_STATUS_SIZE) {
DRM_ERROR("Failed to get link status\n");
return false;
}
@@ -1012,6 +1012,40 @@ static int cdn_dp_pd_event(struct notifier_block *nb,
return NOTIFY_DONE;
 }
 
+static ssize_t cdn_dp_aux_transfer(struct drm_dp_aux *aux,
+  struct drm_dp_aux_msg *msg)
+{
+   struct cdn_dp_device *dp = container_of(aux, struct cdn_dp_device, aux);
+   int ret;
+   u8 status;
+
+   switch (msg->request & ~DP_AUX_I2C_MOT) {
+   case DP_AUX_NATIVE_WRITE:
+   case DP_AUX_I2C_WRITE:
+   case DP_AUX_I2C_WRITE_STATUS_UPDATE:
+   ret = cdn_dp_dpcd_write(dp, msg->address, msg->buffer,
+   msg->size);
+   break;
+   case DP_AUX_NATIVE_READ:
+   case DP_AUX_I2C_READ:
+   ret = cdn_dp_dpcd_read(dp, msg->address, msg->buffer,
+  msg->size);
+   break;
+   default:
+   return -EINVAL;
+   }
+
+   status = cdn_dp_get_aux_status(dp);
+   if (status == AUX_STATUS_ACK)
+   msg->reply = DP_AUX_NATIVE_REPLY_ACK;
+   else if (status == AUX_STATUS_NACK)
+   msg->reply = DP_AUX_NATIVE_REPLY_NACK;
+   else if (status == AUX_STATUS_DEFER)
+   msg->reply = DP_AUX_NATIVE_REPLY_DEFER;
+
+   return ret;
+}
+
 static int cdn_dp_bind(struct device *dev, struct device *master, void *data)
 {
struct cdn_dp_device *dp = dev_get_drvdata(dev);
@@ -1030,6 +1064,13 @@ static int cdn_dp_bind(struct device *dev, struct device 
*master, void *data)
dp->active = false;
dp->active_port = -1;
dp->fw_loaded = false;
+   dp->aux.name = "DP-AUX";
+   dp->aux.transfer = cdn_dp_aux_transfer;
+   dp->aux.dev = dev;
+
+   ret = drm_dp_aux_register(>aux);
+   if (ret)
+   return ret;
 
INIT_WORK(>event_work, cdn_dp_pd_event_work);
 
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.h 
b/drivers/gpu/drm/rockchip/cdn-dp-core.h
index f57e296..46159b2 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.h
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.h
@@ -78,6 +78,7 @@ struct cdn_dp_device {
struct platform_device *audio_pdev;
struct work_struct event_work;
struct edid *edid;
+   struct drm_dp_aux aux;
 
struct mutex lock;
bool connected;
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.c 
b/driv

[PATCH v7 3/5] soc: rockchip: split rockchip_typec_phy struct to separate header

2018-05-24 Thread Lin Huang
we may use rockchip_phy_typec struct in other driver, so split
it to separate header.

Signed-off-by: Lin Huang <h...@rock-chips.com>
---
Changes in v2:
- None
Changes in v3:
- None
Changes in v4:
- None
Changes in v5:
- None
Changes in v6:
- new patch here
Changes in v7:
- move new element to next patch

 drivers/phy/rockchip/phy-rockchip-typec.c | 47 +-
 include/soc/rockchip/rockchip_phy_typec.h | 55 +++
 2 files changed, 56 insertions(+), 46 deletions(-)
 create mode 100644 include/soc/rockchip/rockchip_phy_typec.h

diff --git a/drivers/phy/rockchip/phy-rockchip-typec.c 
b/drivers/phy/rockchip/phy-rockchip-typec.c
index 76a4b58..795055f 100644
--- a/drivers/phy/rockchip/phy-rockchip-typec.c
+++ b/drivers/phy/rockchip/phy-rockchip-typec.c
@@ -63,6 +63,7 @@
 
 #include 
 #include 
+#include 
 
 #define CMN_SSM_BANDGAP(0x21 << 2)
 #define CMN_SSM_BIAS   (0x22 << 2)
@@ -349,52 +350,6 @@
 #define MODE_DFP_USB   BIT(1)
 #define MODE_DFP_DPBIT(2)
 
-struct usb3phy_reg {
-   u32 offset;
-   u32 enable_bit;
-   u32 write_enable;
-};
-
-/**
- * struct rockchip_usb3phy_port_cfg: usb3-phy port configuration.
- * @reg: the base address for usb3-phy config.
- * @typec_conn_dir: the register of type-c connector direction.
- * @usb3tousb2_en: the register of type-c force usb2 to usb2 enable.
- * @external_psm: the register of type-c phy external psm clock.
- * @pipe_status: the register of type-c phy pipe status.
- * @usb3_host_disable: the register of type-c usb3 host disable.
- * @usb3_host_port: the register of type-c usb3 host port.
- * @uphy_dp_sel: the register of type-c phy DP select control.
- */
-struct rockchip_usb3phy_port_cfg {
-   unsigned int reg;
-   struct usb3phy_reg typec_conn_dir;
-   struct usb3phy_reg usb3tousb2_en;
-   struct usb3phy_reg external_psm;
-   struct usb3phy_reg pipe_status;
-   struct usb3phy_reg usb3_host_disable;
-   struct usb3phy_reg usb3_host_port;
-   struct usb3phy_reg uphy_dp_sel;
-};
-
-struct rockchip_typec_phy {
-   struct device *dev;
-   void __iomem *base;
-   struct extcon_dev *extcon;
-   struct regmap *grf_regs;
-   struct clk *clk_core;
-   struct clk *clk_ref;
-   struct reset_control *uphy_rst;
-   struct reset_control *pipe_rst;
-   struct reset_control *tcphy_rst;
-   const struct rockchip_usb3phy_port_cfg *port_cfgs;
-   /* mutex to protect access to individual PHYs */
-   struct mutex lock;
-
-   bool flip;
-   u8 mode;
-};
-
 struct phy_reg {
u16 value;
u32 addr;
diff --git a/include/soc/rockchip/rockchip_phy_typec.h 
b/include/soc/rockchip/rockchip_phy_typec.h
new file mode 100644
index 000..4afe039
--- /dev/null
+++ b/include/soc/rockchip/rockchip_phy_typec.h
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
+ * Author: Lin Huang <h...@rock-chips.com>
+ */
+
+#ifndef __SOC_ROCKCHIP_PHY_TYPEC_H
+#define __SOC_ROCKCHIP_PHY_TYPEC_H
+
+struct usb3phy_reg {
+   u32 offset;
+   u32 enable_bit;
+   u32 write_enable;
+};
+
+/**
+ * struct rockchip_usb3phy_port_cfg: usb3-phy port configuration.
+ * @reg: the base address for usb3-phy config.
+ * @typec_conn_dir: the register of type-c connector direction.
+ * @usb3tousb2_en: the register of type-c force usb2 to usb2 enable.
+ * @external_psm: the register of type-c phy external psm clock.
+ * @pipe_status: the register of type-c phy pipe status.
+ * @usb3_host_disable: the register of type-c usb3 host disable.
+ * @usb3_host_port: the register of type-c usb3 host port.
+ * @uphy_dp_sel: the register of type-c phy DP select control.
+ */
+struct rockchip_usb3phy_port_cfg {
+   unsigned int reg;
+   struct usb3phy_reg typec_conn_dir;
+   struct usb3phy_reg usb3tousb2_en;
+   struct usb3phy_reg external_psm;
+   struct usb3phy_reg pipe_status;
+   struct usb3phy_reg usb3_host_disable;
+   struct usb3phy_reg usb3_host_port;
+   struct usb3phy_reg uphy_dp_sel;
+};
+
+struct rockchip_typec_phy {
+   struct device *dev;
+   void __iomem *base;
+   struct extcon_dev *extcon;
+   struct regmap *grf_regs;
+   struct clk *clk_core;
+   struct clk *clk_ref;
+   struct reset_control *uphy_rst;
+   struct reset_control *pipe_rst;
+   struct reset_control *tcphy_rst;
+   const struct rockchip_usb3phy_port_cfg *port_cfgs;
+   /* mutex to protect access to individual PHYs */
+   struct mutex lock;
+   bool flip;
+   u8 mode;
+};
+
+#endif
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH 2/2] ASoC: rockchip: cdn-dp sound output use spdif

2018-05-23 Thread Lin Huang
some monitors care about the parity bit in the sub-frame of I2S,
but the cdn-dp always set this bit to "1", so these monitors
do not have sound output if use i2s, use spdif can fix this issue.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
Signed-off-by: Lin Huang <h...@rock-chips.com>
---
 sound/soc/rockchip/rk3399_gru_sound.c | 46 +--
 1 file changed, 1 insertion(+), 45 deletions(-)

diff --git a/sound/soc/rockchip/rk3399_gru_sound.c 
b/sound/soc/rockchip/rk3399_gru_sound.c
index 9a10181..f184168 100644
--- a/sound/soc/rockchip/rk3399_gru_sound.c
+++ b/sound/soc/rockchip/rk3399_gru_sound.c
@@ -220,45 +220,6 @@ static int rockchip_sound_da7219_init(struct 
snd_soc_pcm_runtime *rtd)
return 0;
 }
 
-static int rockchip_sound_cdndp_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
-   struct snd_soc_pcm_runtime *rtd = substream->private_data;
-   struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-   struct snd_soc_dai *codec_dai = rtd->codec_dai;
-   int mclk, ret;
-
-   /* in bypass mode, the mclk has to be one of the frequencies below */
-   switch (params_rate(params)) {
-   case 8000:
-   case 16000:
-   case 24000:
-   case 32000:
-   case 48000:
-   case 64000:
-   case 96000:
-   mclk = 12288000;
-   break;
-   case 11025:
-   case 22050:
-   case 44100:
-   case 88200:
-   mclk = 11289600;
-   break;
-   default:
-   return -EINVAL;
-   }
-
-   ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk,
-SND_SOC_CLOCK_OUT);
-   if (ret < 0) {
-   dev_err(codec_dai->dev, "Can't set cpu clock out %d\n", ret);
-   return ret;
-   }
-
-   return 0;
-}
-
 static int rockchip_sound_dmic_hw_params(struct snd_pcm_substream *substream,
 struct snd_pcm_hw_params *params)
 {
@@ -293,10 +254,6 @@ static const struct snd_soc_ops rockchip_sound_da7219_ops 
= {
.hw_params = rockchip_sound_da7219_hw_params,
 };
 
-static const struct snd_soc_ops rockchip_sound_cdndp_ops = {
-   .hw_params = rockchip_sound_cdndp_hw_params,
-};
-
 static const struct snd_soc_ops rockchip_sound_dmic_ops = {
.hw_params = rockchip_sound_dmic_hw_params,
 };
@@ -323,8 +280,7 @@ static const struct snd_soc_dai_link rockchip_dais[] = {
[DAILINK_CDNDP] = {
.name = "DP",
.stream_name = "DP PCM",
-   .codec_dai_name = "i2s-hifi",
-   .ops = _sound_cdndp_ops,
+   .codec_dai_name = "spdif-hifi",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS,
},
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH 1/2] drm/rockchip: cnd-dp: adjust spdif register setting

2018-05-23 Thread Lin Huang
We use jitter bypass mode for spdif, so do not need to set jitter mode
related bit in SPDIF_CTRL_ADDR register. Also, we need to enable
SPDIF_ENABLE bit.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
Signed-off-by: Lin Huang <h...@rock-chips.com>
---
 drivers/gpu/drm/rockchip/cdn-dp-reg.c | 16 +---
 1 file changed, 1 insertion(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.c 
b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
index eb3042c..3105965 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-reg.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
@@ -792,7 +792,6 @@ int cdn_dp_config_video(struct cdn_dp_device *dp)
 
 int cdn_dp_audio_stop(struct cdn_dp_device *dp, struct audio_info *audio)
 {
-   u32 val;
int ret;
 
ret = cdn_dp_reg_write(dp, AUDIO_PACK_CONTROL, 0);
@@ -801,11 +800,7 @@ int cdn_dp_audio_stop(struct cdn_dp_device *dp, struct 
audio_info *audio)
return ret;
}
 
-   val = SPDIF_AVG_SEL | SPDIF_JITTER_BYPASS;
-   val |= SPDIF_FIFO_MID_RANGE(0xe0);
-   val |= SPDIF_JITTER_THRSH(0xe0);
-   val |= SPDIF_JITTER_AVG_WIN(7);
-   writel(val, dp->regs + SPDIF_CTRL_ADDR);
+   writel(0, dp->regs + SPDIF_CTRL_ADDR);
 
/* clearn the audio config and reset */
writel(0, dp->regs + AUDIO_SRC_CNTL);
@@ -929,12 +924,6 @@ static void cdn_dp_audio_config_spdif(struct cdn_dp_device 
*dp)
 {
u32 val;
 
-   val = SPDIF_AVG_SEL | SPDIF_JITTER_BYPASS;
-   val |= SPDIF_FIFO_MID_RANGE(0xe0);
-   val |= SPDIF_JITTER_THRSH(0xe0);
-   val |= SPDIF_JITTER_AVG_WIN(7);
-   writel(val, dp->regs + SPDIF_CTRL_ADDR);
-
writel(SYNC_WR_TO_CH_ZERO, dp->regs + FIFO_CNTL);
 
val = MAX_NUM_CH(2) | AUDIO_TYPE_LPCM | CFG_SUB_PCKT_NUM(4);
@@ -942,9 +931,6 @@ static void cdn_dp_audio_config_spdif(struct cdn_dp_device 
*dp)
writel(SMPL2PKT_EN, dp->regs + SMPL2PKT_CNTL);
 
val = SPDIF_ENABLE | SPDIF_AVG_SEL | SPDIF_JITTER_BYPASS;
-   val |= SPDIF_FIFO_MID_RANGE(0xe0);
-   val |= SPDIF_JITTER_THRSH(0xe0);
-   val |= SPDIF_JITTER_AVG_WIN(7);
writel(val, dp->regs + SPDIF_CTRL_ADDR);
 
clk_prepare_enable(dp->spdif_clk);
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v6 5/5] drm/rockchip: support dp training outside dp firmware

2018-05-21 Thread Lin Huang
DP firmware uses fixed phy config values to do training, but some
boards need to adjust these values to fit for their unique hardware
design. So get phy config values from dts and use software link training
instead of relying on firmware, if software training fail, keep firmware
training as a fallback if sw training fails.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
Signed-off-by: Lin Huang <h...@rock-chips.com>
Reviewed-by: Sean Paul <seanp...@chromium.org>
---
Changes in v2:
- update patch following Enric suggest
Changes in v3:
- use variable fw_training instead sw_training_success
- base on DP SPCE, if training fail use lower link rate to retry training
Changes in v4:
- improve cdn_dp_get_lower_link_rate() and cdn_dp_software_train_link() follow 
Sean suggest
Changes in v5:
- fix some whitespcae issue
Changes in v6:
- None

 drivers/gpu/drm/rockchip/Makefile   |   3 +-
 drivers/gpu/drm/rockchip/cdn-dp-core.c  |  24 +-
 drivers/gpu/drm/rockchip/cdn-dp-core.h  |   2 +
 drivers/gpu/drm/rockchip/cdn-dp-link-training.c | 420 
 drivers/gpu/drm/rockchip/cdn-dp-reg.c   |  31 +-
 drivers/gpu/drm/rockchip/cdn-dp-reg.h   |  38 ++-
 6 files changed, 505 insertions(+), 13 deletions(-)
 create mode 100644 drivers/gpu/drm/rockchip/cdn-dp-link-training.c

diff --git a/drivers/gpu/drm/rockchip/Makefile 
b/drivers/gpu/drm/rockchip/Makefile
index a314e21..b932f62 100644
--- a/drivers/gpu/drm/rockchip/Makefile
+++ b/drivers/gpu/drm/rockchip/Makefile
@@ -9,7 +9,8 @@ rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \
 rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o
 
 rockchipdrm-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o
-rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o
+rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o \
+   cdn-dp-link-training.o
 rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o
 rockchipdrm-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi.o
 rockchipdrm-$(CONFIG_ROCKCHIP_INNO_HDMI) += inno_hdmi.o
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c 
b/drivers/gpu/drm/rockchip/cdn-dp-core.c
index cce64c1..d9d0d4d 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -629,11 +629,13 @@ static void cdn_dp_encoder_enable(struct drm_encoder 
*encoder)
goto out;
}
}
-
-   ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_IDLE);
-   if (ret) {
-   DRM_DEV_ERROR(dp->dev, "Failed to idle video %d\n", ret);
-   goto out;
+   if (dp->use_fw_training == true) {
+   ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_IDLE);
+   if (ret) {
+   DRM_DEV_ERROR(dp->dev,
+ "Failed to idle video %d\n", ret);
+   goto out;
+   }
}
 
ret = cdn_dp_config_video(dp);
@@ -642,11 +644,15 @@ static void cdn_dp_encoder_enable(struct drm_encoder 
*encoder)
goto out;
}
 
-   ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_VALID);
-   if (ret) {
-   DRM_DEV_ERROR(dp->dev, "Failed to valid video %d\n", ret);
-   goto out;
+   if (dp->use_fw_training == true) {
+   ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_VALID);
+   if (ret) {
+   DRM_DEV_ERROR(dp->dev,
+   "Failed to valid video %d\n", ret);
+   goto out;
+   }
}
+
 out:
mutex_unlock(>lock);
 }
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.h 
b/drivers/gpu/drm/rockchip/cdn-dp-core.h
index 46159b2..77a9793 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.h
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.h
@@ -84,6 +84,7 @@ struct cdn_dp_device {
bool connected;
bool active;
bool suspended;
+   bool use_fw_training;
 
const struct firmware *fw;  /* cdn dp firmware */
unsigned int fw_version;/* cdn fw version */
@@ -106,6 +107,7 @@ struct cdn_dp_device {
u8 ports;
u8 lanes;
int active_port;
+   u8 train_set[4];
 
u8 dpcd[DP_RECEIVER_CAP_SIZE];
bool sink_has_audio;
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-link-training.c 
b/drivers/gpu/drm/rockchip/cdn-dp-link-training.c
new file mode 100644
index 000..73c3290
--- /dev/null
+++ b/drivers/gpu/drm/rockchip/cdn-dp-link-training.c
@@ -0,0 +1,420 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
+ * Author: Chris Zhong <z...@rock-chips.com>
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "cdn-dp-core.h"
+#include "cdn-dp-reg.h"
+
+static void cdn_dp_s

[PATCH v6 3/5] soc: rockchip: split rockchip_typec_phy struct to separate header

2018-05-21 Thread Lin Huang
we may use rockchip_phy_typec struct in other driver, so split
it to separate header.

Signed-off-by: Lin Huang <h...@rock-chips.com>
---
Changes in v2:
- None
Changes in v3:
- None
Changes in v4:
- None
Changes in v5:
- None
Changes in v6:
- new patch here

 drivers/phy/rockchip/phy-rockchip-typec.c | 47 +--
 include/soc/rockchip/rockchip_phy_typec.h | 63 +++
 2 files changed, 64 insertions(+), 46 deletions(-)
 create mode 100644 include/soc/rockchip/rockchip_phy_typec.h

diff --git a/drivers/phy/rockchip/phy-rockchip-typec.c 
b/drivers/phy/rockchip/phy-rockchip-typec.c
index 76a4b58..795055f 100644
--- a/drivers/phy/rockchip/phy-rockchip-typec.c
+++ b/drivers/phy/rockchip/phy-rockchip-typec.c
@@ -63,6 +63,7 @@
 
 #include 
 #include 
+#include 
 
 #define CMN_SSM_BANDGAP(0x21 << 2)
 #define CMN_SSM_BIAS   (0x22 << 2)
@@ -349,52 +350,6 @@
 #define MODE_DFP_USB   BIT(1)
 #define MODE_DFP_DPBIT(2)
 
-struct usb3phy_reg {
-   u32 offset;
-   u32 enable_bit;
-   u32 write_enable;
-};
-
-/**
- * struct rockchip_usb3phy_port_cfg: usb3-phy port configuration.
- * @reg: the base address for usb3-phy config.
- * @typec_conn_dir: the register of type-c connector direction.
- * @usb3tousb2_en: the register of type-c force usb2 to usb2 enable.
- * @external_psm: the register of type-c phy external psm clock.
- * @pipe_status: the register of type-c phy pipe status.
- * @usb3_host_disable: the register of type-c usb3 host disable.
- * @usb3_host_port: the register of type-c usb3 host port.
- * @uphy_dp_sel: the register of type-c phy DP select control.
- */
-struct rockchip_usb3phy_port_cfg {
-   unsigned int reg;
-   struct usb3phy_reg typec_conn_dir;
-   struct usb3phy_reg usb3tousb2_en;
-   struct usb3phy_reg external_psm;
-   struct usb3phy_reg pipe_status;
-   struct usb3phy_reg usb3_host_disable;
-   struct usb3phy_reg usb3_host_port;
-   struct usb3phy_reg uphy_dp_sel;
-};
-
-struct rockchip_typec_phy {
-   struct device *dev;
-   void __iomem *base;
-   struct extcon_dev *extcon;
-   struct regmap *grf_regs;
-   struct clk *clk_core;
-   struct clk *clk_ref;
-   struct reset_control *uphy_rst;
-   struct reset_control *pipe_rst;
-   struct reset_control *tcphy_rst;
-   const struct rockchip_usb3phy_port_cfg *port_cfgs;
-   /* mutex to protect access to individual PHYs */
-   struct mutex lock;
-
-   bool flip;
-   u8 mode;
-};
-
 struct phy_reg {
u16 value;
u32 addr;
diff --git a/include/soc/rockchip/rockchip_phy_typec.h 
b/include/soc/rockchip/rockchip_phy_typec.h
new file mode 100644
index 000..be6af0e
--- /dev/null
+++ b/include/soc/rockchip/rockchip_phy_typec.h
@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
+ * Author: Lin Huang <h...@rock-chips.com>
+ */
+
+#ifndef __SOC_ROCKCHIP_PHY_TYPEC_H
+#define __SOC_ROCKCHIP_PHY_TYPEC_H
+
+struct usb3phy_reg {
+   u32 offset;
+   u32 enable_bit;
+   u32 write_enable;
+};
+
+/**
+ * struct rockchip_usb3phy_port_cfg: usb3-phy port configuration.
+ * @reg: the base address for usb3-phy config.
+ * @typec_conn_dir: the register of type-c connector direction.
+ * @usb3tousb2_en: the register of type-c force usb2 to usb2 enable.
+ * @external_psm: the register of type-c phy external psm clock.
+ * @pipe_status: the register of type-c phy pipe status.
+ * @usb3_host_disable: the register of type-c usb3 host disable.
+ * @usb3_host_port: the register of type-c usb3 host port.
+ * @uphy_dp_sel: the register of type-c phy DP select control.
+ */
+struct rockchip_usb3phy_port_cfg {
+   unsigned int reg;
+   struct usb3phy_reg typec_conn_dir;
+   struct usb3phy_reg usb3tousb2_en;
+   struct usb3phy_reg external_psm;
+   struct usb3phy_reg pipe_status;
+   struct usb3phy_reg usb3_host_disable;
+   struct usb3phy_reg usb3_host_port;
+   struct usb3phy_reg uphy_dp_sel;
+};
+
+struct phy_config {
+   int swing;
+   int pe;
+};
+
+struct rockchip_typec_phy {
+   struct device *dev;
+   void __iomem *base;
+   struct extcon_dev *extcon;
+   struct regmap *grf_regs;
+   struct clk *clk_core;
+   struct clk *clk_ref;
+   struct reset_control *uphy_rst;
+   struct reset_control *pipe_rst;
+   struct reset_control *tcphy_rst;
+   const struct rockchip_usb3phy_port_cfg *port_cfgs;
+   /* mutex to protect access to individual PHYs */
+   struct mutex lock;
+   struct phy_config config[3][4];
+   bool flip;
+   u8 mode;
+   int (*typec_phy_config)(struct phy *phy, int link_rate,
+   int lanes, u8 swing, u8 pre_emp);
+};
+
+#endif
-- 
2.7.4

___
dri-devel mailing list
dri-dev

[PATCH v6 1/5] drm/rockchip: add transfer function for cdn-dp

2018-05-21 Thread Lin Huang
From: Chris Zhong <z...@rock-chips.com>

We may support training outside firmware, so we need support
dpcd read/write to get the message or do some setting with
display.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
Signed-off-by: Lin Huang <h...@rock-chips.com>
Reviewed-by: Sean Paul <seanp...@chromium.org>
Reviewed-by: Enric Balletbo <enric.balle...@collabora.com>
---
Changes in v2:
- update patch following Enric suggest
Changes in v3:
- None
Changes in v4:
- None
Changes in v5:
- None
Changes in v6:
- None

 drivers/gpu/drm/rockchip/cdn-dp-core.c | 55 +++
 drivers/gpu/drm/rockchip/cdn-dp-core.h |  1 +
 drivers/gpu/drm/rockchip/cdn-dp-reg.c  | 69 ++
 drivers/gpu/drm/rockchip/cdn-dp-reg.h  | 14 ++-
 4 files changed, 122 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c 
b/drivers/gpu/drm/rockchip/cdn-dp-core.c
index c6fbdcd..cce64c1 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -176,8 +176,8 @@ static int cdn_dp_get_sink_count(struct cdn_dp_device *dp, 
u8 *sink_count)
u8 value;
 
*sink_count = 0;
-   ret = cdn_dp_dpcd_read(dp, DP_SINK_COUNT, , 1);
-   if (ret)
+   ret = drm_dp_dpcd_read(>aux, DP_SINK_COUNT, , 1);
+   if (ret < 0)
return ret;
 
*sink_count = DP_GET_SINK_COUNT(value);
@@ -374,9 +374,9 @@ static int cdn_dp_get_sink_capability(struct cdn_dp_device 
*dp)
if (!cdn_dp_check_sink_connection(dp))
return -ENODEV;
 
-   ret = cdn_dp_dpcd_read(dp, DP_DPCD_REV, dp->dpcd,
-  DP_RECEIVER_CAP_SIZE);
-   if (ret) {
+   ret = drm_dp_dpcd_read(>aux, DP_DPCD_REV, dp->dpcd,
+  sizeof(dp->dpcd));
+   if (ret < 0) {
DRM_DEV_ERROR(dp->dev, "Failed to get caps %d\n", ret);
return ret;
}
@@ -582,8 +582,8 @@ static bool cdn_dp_check_link_status(struct cdn_dp_device 
*dp)
if (!port || !dp->link.rate || !dp->link.num_lanes)
return false;
 
-   if (cdn_dp_dpcd_read(dp, DP_LANE0_1_STATUS, link_status,
-DP_LINK_STATUS_SIZE)) {
+   if (drm_dp_dpcd_read_link_status(>aux, link_status) !=
+   DP_LINK_STATUS_SIZE) {
DRM_ERROR("Failed to get link status\n");
return false;
}
@@ -1012,6 +1012,40 @@ static int cdn_dp_pd_event(struct notifier_block *nb,
return NOTIFY_DONE;
 }
 
+static ssize_t cdn_dp_aux_transfer(struct drm_dp_aux *aux,
+  struct drm_dp_aux_msg *msg)
+{
+   struct cdn_dp_device *dp = container_of(aux, struct cdn_dp_device, aux);
+   int ret;
+   u8 status;
+
+   switch (msg->request & ~DP_AUX_I2C_MOT) {
+   case DP_AUX_NATIVE_WRITE:
+   case DP_AUX_I2C_WRITE:
+   case DP_AUX_I2C_WRITE_STATUS_UPDATE:
+   ret = cdn_dp_dpcd_write(dp, msg->address, msg->buffer,
+   msg->size);
+   break;
+   case DP_AUX_NATIVE_READ:
+   case DP_AUX_I2C_READ:
+   ret = cdn_dp_dpcd_read(dp, msg->address, msg->buffer,
+  msg->size);
+   break;
+   default:
+   return -EINVAL;
+   }
+
+   status = cdn_dp_get_aux_status(dp);
+   if (status == AUX_STATUS_ACK)
+   msg->reply = DP_AUX_NATIVE_REPLY_ACK;
+   else if (status == AUX_STATUS_NACK)
+   msg->reply = DP_AUX_NATIVE_REPLY_NACK;
+   else if (status == AUX_STATUS_DEFER)
+   msg->reply = DP_AUX_NATIVE_REPLY_DEFER;
+
+   return ret;
+}
+
 static int cdn_dp_bind(struct device *dev, struct device *master, void *data)
 {
struct cdn_dp_device *dp = dev_get_drvdata(dev);
@@ -1030,6 +1064,13 @@ static int cdn_dp_bind(struct device *dev, struct device 
*master, void *data)
dp->active = false;
dp->active_port = -1;
dp->fw_loaded = false;
+   dp->aux.name = "DP-AUX";
+   dp->aux.transfer = cdn_dp_aux_transfer;
+   dp->aux.dev = dev;
+
+   ret = drm_dp_aux_register(>aux);
+   if (ret)
+   return ret;
 
INIT_WORK(>event_work, cdn_dp_pd_event_work);
 
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.h 
b/drivers/gpu/drm/rockchip/cdn-dp-core.h
index f57e296..46159b2 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.h
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.h
@@ -78,6 +78,7 @@ struct cdn_dp_device {
struct platform_device *audio_pdev;
struct work_struct event_work;
struct edid *edid;
+   struct drm_dp_aux aux;
 
struct mutex lock;
bool connected;
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.c 
b/drivers/gpu/drm/rockch

[PATCH v6 2/5] Documentation: dt-bindings: phy: add phy_config for Rockchip USB Type-C PHY

2018-05-21 Thread Lin Huang
If want to do training outside DP Firmware, need phy voltage swing
and pre_emphasis value.

Signed-off-by: Lin Huang <h...@rock-chips.com>
---
Changes in v2:
- None 
Changes in v3:
- modify property description and add this property to Example
Changes in v4:
- None
Changes in v5:
- None
Changes in v6:
- change rockchip,phy_config to rockchip,phy-config and descript it in detail.
 
 .../devicetree/bindings/phy/phy-rockchip-typec.txt | 36 +-
 1 file changed, 35 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt 
b/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
index 960da7f..40d5e7a 100644
--- a/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
+++ b/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
@@ -17,7 +17,11 @@ Required properties:
 
 Optional properties:
  - extcon : extcon specifier for the Power Delivery
-
+ - rockchip,phy-config : A list of voltage swing(mV) and pre-emphasis
+   (dB) pairs. They are 3 blocks of 4 entries and
+   correspond to s0p0 ~ s0p3, s1p0 ~ s1p3,
+   s2p0 ~ s2p3, s3p0 ~ s2p3 swing and pre-emphasis
+   values.
 Required nodes : a sub-node is required for each port the phy provides.
 The sub-node name is used to identify dp or usb3 port,
 and shall be the following entries:
@@ -50,6 +54,21 @@ Example:
 < SRST_P_UPHY0_TCPHY>;
reset-names = "uphy", "uphy-pipe", "uphy-tcphy";
 
+   rockchip,phy-config = <0x2a 0x00>,
+   <0x1f 0x15>,
+   <0x14 0x22>,
+   <0x02 0x2b>,
+
+   <0x21 0x00>,
+   <0x12 0x15>,
+   <0x02 0x22>,
+   <0 0>,
+
+   <0x15 0x00>,
+   <0x00 0x15>,
+   <0 0>,
+   <0 0>;
+
tcphy0_dp: dp-port {
#phy-cells = <0>;
};
@@ -74,6 +93,21 @@ Example:
 < SRST_P_UPHY1_TCPHY>;
reset-names = "uphy", "uphy-pipe", "uphy-tcphy";
 
+   rockchip,phy-config = <0x2a 0x00>,
+   <0x1f 0x15>,
+   <0x14 0x22>,
+   <0x02 0x2b>,
+
+   <0x21 0x00>,
+   <0x12 0x15>,
+   <0x02 0x22>,
+   <0 0>,
+
+   <0x15 0x00>,
+   <0x00 0x15>,
+   <0 0>,
+   <0 0>;
+
tcphy1_dp: dp-port {
#phy-cells = <0>;
};
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v6 4/5] phy: rockchip-typec: support variable phy config value

2018-05-21 Thread Lin Huang
the phy config values used to fix in dp firmware, but some boards
need change these values to do training and get the better eye diagram
result. So support that in phy driver.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
Signed-off-by: Lin Huang <h...@rock-chips.com>
---
Changes in v2:
- update patch following Enric suggest
Changes in v3:
- delete need_software_training variable
- add default phy config value, if dts do not define phy config value, use 
these value
Changes in v4:
- rename variable config to tcphy_default_config
Changes in v5:
- None
Changes in v6:
- split the header file to new patch

 drivers/phy/rockchip/phy-rockchip-typec.c | 261 --
 1 file changed, 208 insertions(+), 53 deletions(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-typec.c 
b/drivers/phy/rockchip/phy-rockchip-typec.c
index 795055f..4c4b925 100644
--- a/drivers/phy/rockchip/phy-rockchip-typec.c
+++ b/drivers/phy/rockchip/phy-rockchip-typec.c
@@ -324,21 +324,29 @@
  * clock 0: PLL 0 div 1
  * clock 1: PLL 1 div 2
  */
-#define CLK_PLL_CONFIG 0X30
+#define CLK_PLL1_DIV1  0x20
+#define CLK_PLL1_DIV2  0x30
 #define CLK_PLL_MASK   0x33
 
 #define CMN_READY  BIT(0)
 
+#define DP_PLL_CLOCK_ENABLE_ACKBIT(3)
 #define DP_PLL_CLOCK_ENABLEBIT(2)
+#define DP_PLL_ENABLE_ACK  BIT(1)
 #define DP_PLL_ENABLE  BIT(0)
 #define DP_PLL_DATA_RATE_RBR   ((2 << 12) | (4 << 8))
 #define DP_PLL_DATA_RATE_HBR   ((2 << 12) | (4 << 8))
 #define DP_PLL_DATA_RATE_HBR2  ((1 << 12) | (2 << 8))
+#define DP_PLL_DATA_RATE_MASK  0xff00
 
-#define DP_MODE_A0 BIT(4)
-#define DP_MODE_A2 BIT(6)
-#define DP_MODE_ENTER_A0   0xc101
-#define DP_MODE_ENTER_A2   0xc104
+#define DP_MODE_MASK   0xf
+#define DP_MODE_ENTER_A0   BIT(0)
+#define DP_MODE_ENTER_A2   BIT(2)
+#define DP_MODE_ENTER_A3   BIT(3)
+#define DP_MODE_A0_ACK BIT(4)
+#define DP_MODE_A2_ACK BIT(6)
+#define DP_MODE_A3_ACK BIT(7)
+#define DP_LINK_RESET_DEASSERTED   BIT(8)
 
 #define PHY_MODE_SET_TIMEOUT   10
 
@@ -350,6 +358,8 @@
 #define MODE_DFP_USB   BIT(1)
 #define MODE_DFP_DPBIT(2)
 
+#define DP_DEFAULT_RATE162000
+
 struct phy_reg {
u16 value;
u32 addr;
@@ -372,15 +382,15 @@ struct phy_reg usb3_pll_cfg[] = {
{ 0x8,  CMN_DIAG_PLL0_LF_PROG },
 };
 
-struct phy_reg dp_pll_cfg[] = {
+struct phy_reg dp_pll_rbr_cfg[] = {
{ 0xf0, CMN_PLL1_VCOCAL_INIT },
{ 0x18, CMN_PLL1_VCOCAL_ITER },
{ 0x30b9,   CMN_PLL1_VCOCAL_START },
-   { 0x21c,CMN_PLL1_INTDIV },
+   { 0x87, CMN_PLL1_INTDIV },
{ 0,CMN_PLL1_FRACDIV },
-   { 0x5,  CMN_PLL1_HIGH_THR },
-   { 0x35, CMN_PLL1_SS_CTRL1 },
-   { 0x7f1e,   CMN_PLL1_SS_CTRL2 },
+   { 0x22, CMN_PLL1_HIGH_THR },
+   { 0x8000,   CMN_PLL1_SS_CTRL1 },
+   { 0,CMN_PLL1_SS_CTRL2 },
{ 0x20, CMN_PLL1_DSM_DIAG },
{ 0,CMN_PLLSM1_USER_DEF_CTRL },
{ 0,CMN_DIAG_PLL1_OVRD },
@@ -391,9 +401,52 @@ struct phy_reg dp_pll_cfg[] = {
{ 0x8,  CMN_DIAG_PLL1_LF_PROG },
{ 0x100,CMN_DIAG_PLL1_PTATIS_TUNE1 },
{ 0x7,  CMN_DIAG_PLL1_PTATIS_TUNE2 },
-   { 0x4,  CMN_DIAG_PLL1_INCLK_CTRL },
+   { 0x1,  CMN_DIAG_PLL1_INCLK_CTRL },
 };
 
+struct phy_reg dp_pll_hbr_cfg[] = {
+   { 0xf0, CMN_PLL1_VCOCAL_INIT },
+   { 0x18, CMN_PLL1_VCOCAL_ITER },
+   { 0x30b4,   CMN_PLL1_VCOCAL_START },
+   { 0xe1, CMN_PLL1_INTDIV },
+   { 0,CMN_PLL1_FRACDIV },
+   { 0x5,  CMN_PLL1_HIGH_THR },
+   { 0x8000,   CMN_PLL1_SS_CTRL1 },
+   { 0,CMN_PLL1_SS_CTRL2 },
+   { 0x20, CMN_PLL1_DSM_DIAG },
+   { 0x1000,   CMN_PLLSM1_USER_DEF_CTRL },
+   { 0,CMN_DIAG_PLL1_OVRD },
+   { 0,CMN_DIAG_PLL1_FBH_OVRD },
+   { 0,CMN_DIAG_PLL1_FBL_OVRD },
+   { 0x7,  CMN_DIAG_PLL1_V2I_TUNE },
+   { 0x45, CMN_DIAG_PLL1_CP_TUNE },
+   { 0x8,  CMN_DIAG_PLL1_LF_PROG },
+   { 0x1,  CMN_DIAG_PLL1_PTATIS_TUNE1 },
+   { 0x1,  CMN_DIAG_PLL1_PTATIS_TUNE2 },
+   { 0x1,  CMN_DIAG_PLL1_INCLK_CTRL },
+};
+
+struct phy_reg dp_pll_hbr2_cfg[] = {
+   { 0xf0, CMN_PLL1_VCOCAL_INIT },
+   { 0x18, CMN_PLL1_VCOCAL_ITER },
+   { 0x30b4,   CMN_PLL1_VCOCAL_START },
+   { 0xe1, CMN_PLL1_INTDIV },
+   {

[PATCH v5 4/4] drm/rockchip: support dp training outside dp firmware

2018-05-18 Thread Lin Huang
DP firmware uses fixed phy config values to do training, but some
boards need to adjust these values to fit for their unique hardware
design. So get phy config values from dts and use software link training
instead of relying on firmware, if software training fail, keep firmware
training as a fallback if sw training fails.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
Signed-off-by: Lin Huang <h...@rock-chips.com>
---
Changes in v2:
- update patch following Enric suggest
Changes in v3:
- use variable fw_training instead sw_training_success
- base on DP SPCE, if training fail use lower link rate to retry training
Changes in v4:
- improve cdn_dp_get_lower_link_rate() and cdn_dp_software_train_link() follow 
Sean suggest
Changes in v5:
- fix some whitespcae issue

 drivers/gpu/drm/rockchip/Makefile   |   3 +-
 drivers/gpu/drm/rockchip/cdn-dp-core.c  |  24 +-
 drivers/gpu/drm/rockchip/cdn-dp-core.h  |   2 +
 drivers/gpu/drm/rockchip/cdn-dp-link-training.c | 420 
 drivers/gpu/drm/rockchip/cdn-dp-reg.c   |  31 +-
 drivers/gpu/drm/rockchip/cdn-dp-reg.h   |  38 ++-
 6 files changed, 505 insertions(+), 13 deletions(-)
 create mode 100644 drivers/gpu/drm/rockchip/cdn-dp-link-training.c

diff --git a/drivers/gpu/drm/rockchip/Makefile 
b/drivers/gpu/drm/rockchip/Makefile
index a314e21..b932f62 100644
--- a/drivers/gpu/drm/rockchip/Makefile
+++ b/drivers/gpu/drm/rockchip/Makefile
@@ -9,7 +9,8 @@ rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \
 rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o
 
 rockchipdrm-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o
-rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o
+rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o \
+   cdn-dp-link-training.o
 rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o
 rockchipdrm-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi.o
 rockchipdrm-$(CONFIG_ROCKCHIP_INNO_HDMI) += inno_hdmi.o
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c 
b/drivers/gpu/drm/rockchip/cdn-dp-core.c
index cce64c1..d9d0d4d 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -629,11 +629,13 @@ static void cdn_dp_encoder_enable(struct drm_encoder 
*encoder)
goto out;
}
}
-
-   ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_IDLE);
-   if (ret) {
-   DRM_DEV_ERROR(dp->dev, "Failed to idle video %d\n", ret);
-   goto out;
+   if (dp->use_fw_training == true) {
+   ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_IDLE);
+   if (ret) {
+   DRM_DEV_ERROR(dp->dev,
+ "Failed to idle video %d\n", ret);
+   goto out;
+   }
}
 
ret = cdn_dp_config_video(dp);
@@ -642,11 +644,15 @@ static void cdn_dp_encoder_enable(struct drm_encoder 
*encoder)
goto out;
}
 
-   ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_VALID);
-   if (ret) {
-   DRM_DEV_ERROR(dp->dev, "Failed to valid video %d\n", ret);
-   goto out;
+   if (dp->use_fw_training == true) {
+   ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_VALID);
+   if (ret) {
+   DRM_DEV_ERROR(dp->dev,
+   "Failed to valid video %d\n", ret);
+   goto out;
+   }
}
+
 out:
mutex_unlock(>lock);
 }
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.h 
b/drivers/gpu/drm/rockchip/cdn-dp-core.h
index 46159b2..77a9793 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.h
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.h
@@ -84,6 +84,7 @@ struct cdn_dp_device {
bool connected;
bool active;
bool suspended;
+   bool use_fw_training;
 
const struct firmware *fw;  /* cdn dp firmware */
unsigned int fw_version;/* cdn fw version */
@@ -106,6 +107,7 @@ struct cdn_dp_device {
u8 ports;
u8 lanes;
int active_port;
+   u8 train_set[4];
 
u8 dpcd[DP_RECEIVER_CAP_SIZE];
bool sink_has_audio;
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-link-training.c 
b/drivers/gpu/drm/rockchip/cdn-dp-link-training.c
new file mode 100644
index 000..73c3290
--- /dev/null
+++ b/drivers/gpu/drm/rockchip/cdn-dp-link-training.c
@@ -0,0 +1,420 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
+ * Author: Chris Zhong <z...@rock-chips.com>
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "cdn-dp-core.h"
+#include "cdn-dp-reg.h"
+
+static void cdn_dp_set_signal_levels(struct cdn_dp_device *dp)
+{
+   struct cdn_dp_port *por

[PATCH v5 3/4] phy: rockchip-typec: support variable phy config value

2018-05-18 Thread Lin Huang
the phy config values used to fix in dp firmware, but some boards
need change these values to do training and get the better eye diagram
result. So support that in phy driver.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
Signed-off-by: Lin Huang <h...@rock-chips.com>
---
Changes in v2:
- update patch following Enric suggest
Changes in v3:
- delete need_software_training variable
- add default phy config value, if dts do not define phy config value, use 
these value
Changes in v4:
- rename variable config to tcphy_default_config
Changes in v5:
- None

 drivers/phy/rockchip/phy-rockchip-typec.c | 306 --
 include/soc/rockchip/rockchip_phy_typec.h |  63 ++
 2 files changed, 271 insertions(+), 98 deletions(-)
 create mode 100644 include/soc/rockchip/rockchip_phy_typec.h

diff --git a/drivers/phy/rockchip/phy-rockchip-typec.c 
b/drivers/phy/rockchip/phy-rockchip-typec.c
index 76a4b58..5d8692d 100644
--- a/drivers/phy/rockchip/phy-rockchip-typec.c
+++ b/drivers/phy/rockchip/phy-rockchip-typec.c
@@ -63,6 +63,7 @@
 
 #include 
 #include 
+#include 
 
 #define CMN_SSM_BANDGAP(0x21 << 2)
 #define CMN_SSM_BIAS   (0x22 << 2)
@@ -323,21 +324,29 @@
  * clock 0: PLL 0 div 1
  * clock 1: PLL 1 div 2
  */
-#define CLK_PLL_CONFIG 0X30
+#define CLK_PLL1_DIV1  0x20
+#define CLK_PLL1_DIV2  0x30
 #define CLK_PLL_MASK   0x33
 
 #define CMN_READY  BIT(0)
 
+#define DP_PLL_CLOCK_ENABLE_ACKBIT(3)
 #define DP_PLL_CLOCK_ENABLEBIT(2)
+#define DP_PLL_ENABLE_ACK  BIT(1)
 #define DP_PLL_ENABLE  BIT(0)
 #define DP_PLL_DATA_RATE_RBR   ((2 << 12) | (4 << 8))
 #define DP_PLL_DATA_RATE_HBR   ((2 << 12) | (4 << 8))
 #define DP_PLL_DATA_RATE_HBR2  ((1 << 12) | (2 << 8))
+#define DP_PLL_DATA_RATE_MASK  0xff00
 
-#define DP_MODE_A0 BIT(4)
-#define DP_MODE_A2 BIT(6)
-#define DP_MODE_ENTER_A0   0xc101
-#define DP_MODE_ENTER_A2   0xc104
+#define DP_MODE_MASK   0xf
+#define DP_MODE_ENTER_A0   BIT(0)
+#define DP_MODE_ENTER_A2   BIT(2)
+#define DP_MODE_ENTER_A3   BIT(3)
+#define DP_MODE_A0_ACK BIT(4)
+#define DP_MODE_A2_ACK BIT(6)
+#define DP_MODE_A3_ACK BIT(7)
+#define DP_LINK_RESET_DEASSERTED   BIT(8)
 
 #define PHY_MODE_SET_TIMEOUT   10
 
@@ -349,51 +358,7 @@
 #define MODE_DFP_USB   BIT(1)
 #define MODE_DFP_DPBIT(2)
 
-struct usb3phy_reg {
-   u32 offset;
-   u32 enable_bit;
-   u32 write_enable;
-};
-
-/**
- * struct rockchip_usb3phy_port_cfg: usb3-phy port configuration.
- * @reg: the base address for usb3-phy config.
- * @typec_conn_dir: the register of type-c connector direction.
- * @usb3tousb2_en: the register of type-c force usb2 to usb2 enable.
- * @external_psm: the register of type-c phy external psm clock.
- * @pipe_status: the register of type-c phy pipe status.
- * @usb3_host_disable: the register of type-c usb3 host disable.
- * @usb3_host_port: the register of type-c usb3 host port.
- * @uphy_dp_sel: the register of type-c phy DP select control.
- */
-struct rockchip_usb3phy_port_cfg {
-   unsigned int reg;
-   struct usb3phy_reg typec_conn_dir;
-   struct usb3phy_reg usb3tousb2_en;
-   struct usb3phy_reg external_psm;
-   struct usb3phy_reg pipe_status;
-   struct usb3phy_reg usb3_host_disable;
-   struct usb3phy_reg usb3_host_port;
-   struct usb3phy_reg uphy_dp_sel;
-};
-
-struct rockchip_typec_phy {
-   struct device *dev;
-   void __iomem *base;
-   struct extcon_dev *extcon;
-   struct regmap *grf_regs;
-   struct clk *clk_core;
-   struct clk *clk_ref;
-   struct reset_control *uphy_rst;
-   struct reset_control *pipe_rst;
-   struct reset_control *tcphy_rst;
-   const struct rockchip_usb3phy_port_cfg *port_cfgs;
-   /* mutex to protect access to individual PHYs */
-   struct mutex lock;
-
-   bool flip;
-   u8 mode;
-};
+#define DP_DEFAULT_RATE162000
 
 struct phy_reg {
u16 value;
@@ -417,15 +382,15 @@ struct phy_reg usb3_pll_cfg[] = {
{ 0x8,  CMN_DIAG_PLL0_LF_PROG },
 };
 
-struct phy_reg dp_pll_cfg[] = {
+struct phy_reg dp_pll_rbr_cfg[] = {
{ 0xf0, CMN_PLL1_VCOCAL_INIT },
{ 0x18, CMN_PLL1_VCOCAL_ITER },
{ 0x30b9,   CMN_PLL1_VCOCAL_START },
-   { 0x21c,CMN_PLL1_INTDIV },
+   { 0x87, CMN_PLL1_INTDIV },
{ 0,CMN_PLL1_FRACDIV },
-   { 0x5,  CMN_PLL1_HIGH_THR },
-   { 0x35, CMN_PLL1_SS_CTRL1 },
-   { 0x7f1e,   CMN_PLL1_SS_CTRL2 },
+   { 0x22, CM

[PATCH v5 1/4] drm/rockchip: add transfer function for cdn-dp

2018-05-18 Thread Lin Huang
From: Chris Zhong <z...@rock-chips.com>

We may support training outside firmware, so we need support
dpcd read/write to get the message or do some setting with
display.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
Signed-off-by: Lin Huang <h...@rock-chips.com>
Reviewed-by: Sean Paul <seanp...@chromium.org>
Reviewed-by: Enric Balletbo <enric.balle...@collabora.com>
---
Changes in v2:
- update patch following Enric suggest
Changes in v3:
- None
Changes in v4:
- None
Changes in v5:
- None

 drivers/gpu/drm/rockchip/cdn-dp-core.c | 55 +++
 drivers/gpu/drm/rockchip/cdn-dp-core.h |  1 +
 drivers/gpu/drm/rockchip/cdn-dp-reg.c  | 69 ++
 drivers/gpu/drm/rockchip/cdn-dp-reg.h  | 14 ++-
 4 files changed, 122 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c 
b/drivers/gpu/drm/rockchip/cdn-dp-core.c
index c6fbdcd..cce64c1 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -176,8 +176,8 @@ static int cdn_dp_get_sink_count(struct cdn_dp_device *dp, 
u8 *sink_count)
u8 value;
 
*sink_count = 0;
-   ret = cdn_dp_dpcd_read(dp, DP_SINK_COUNT, , 1);
-   if (ret)
+   ret = drm_dp_dpcd_read(>aux, DP_SINK_COUNT, , 1);
+   if (ret < 0)
return ret;
 
*sink_count = DP_GET_SINK_COUNT(value);
@@ -374,9 +374,9 @@ static int cdn_dp_get_sink_capability(struct cdn_dp_device 
*dp)
if (!cdn_dp_check_sink_connection(dp))
return -ENODEV;
 
-   ret = cdn_dp_dpcd_read(dp, DP_DPCD_REV, dp->dpcd,
-  DP_RECEIVER_CAP_SIZE);
-   if (ret) {
+   ret = drm_dp_dpcd_read(>aux, DP_DPCD_REV, dp->dpcd,
+  sizeof(dp->dpcd));
+   if (ret < 0) {
DRM_DEV_ERROR(dp->dev, "Failed to get caps %d\n", ret);
return ret;
}
@@ -582,8 +582,8 @@ static bool cdn_dp_check_link_status(struct cdn_dp_device 
*dp)
if (!port || !dp->link.rate || !dp->link.num_lanes)
return false;
 
-   if (cdn_dp_dpcd_read(dp, DP_LANE0_1_STATUS, link_status,
-DP_LINK_STATUS_SIZE)) {
+   if (drm_dp_dpcd_read_link_status(>aux, link_status) !=
+   DP_LINK_STATUS_SIZE) {
DRM_ERROR("Failed to get link status\n");
return false;
}
@@ -1012,6 +1012,40 @@ static int cdn_dp_pd_event(struct notifier_block *nb,
return NOTIFY_DONE;
 }
 
+static ssize_t cdn_dp_aux_transfer(struct drm_dp_aux *aux,
+  struct drm_dp_aux_msg *msg)
+{
+   struct cdn_dp_device *dp = container_of(aux, struct cdn_dp_device, aux);
+   int ret;
+   u8 status;
+
+   switch (msg->request & ~DP_AUX_I2C_MOT) {
+   case DP_AUX_NATIVE_WRITE:
+   case DP_AUX_I2C_WRITE:
+   case DP_AUX_I2C_WRITE_STATUS_UPDATE:
+   ret = cdn_dp_dpcd_write(dp, msg->address, msg->buffer,
+   msg->size);
+   break;
+   case DP_AUX_NATIVE_READ:
+   case DP_AUX_I2C_READ:
+   ret = cdn_dp_dpcd_read(dp, msg->address, msg->buffer,
+  msg->size);
+   break;
+   default:
+   return -EINVAL;
+   }
+
+   status = cdn_dp_get_aux_status(dp);
+   if (status == AUX_STATUS_ACK)
+   msg->reply = DP_AUX_NATIVE_REPLY_ACK;
+   else if (status == AUX_STATUS_NACK)
+   msg->reply = DP_AUX_NATIVE_REPLY_NACK;
+   else if (status == AUX_STATUS_DEFER)
+   msg->reply = DP_AUX_NATIVE_REPLY_DEFER;
+
+   return ret;
+}
+
 static int cdn_dp_bind(struct device *dev, struct device *master, void *data)
 {
struct cdn_dp_device *dp = dev_get_drvdata(dev);
@@ -1030,6 +1064,13 @@ static int cdn_dp_bind(struct device *dev, struct device 
*master, void *data)
dp->active = false;
dp->active_port = -1;
dp->fw_loaded = false;
+   dp->aux.name = "DP-AUX";
+   dp->aux.transfer = cdn_dp_aux_transfer;
+   dp->aux.dev = dev;
+
+   ret = drm_dp_aux_register(>aux);
+   if (ret)
+   return ret;
 
INIT_WORK(>event_work, cdn_dp_pd_event_work);
 
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.h 
b/drivers/gpu/drm/rockchip/cdn-dp-core.h
index f57e296..46159b2 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.h
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.h
@@ -78,6 +78,7 @@ struct cdn_dp_device {
struct platform_device *audio_pdev;
struct work_struct event_work;
struct edid *edid;
+   struct drm_dp_aux aux;
 
struct mutex lock;
bool connected;
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.c 
b/drivers/gpu/drm/rockchip/cdn-dp-reg.

[PATCH v5 2/4] Documentation: bindings: add phy_config for Rockchip USB Type-C PHY

2018-05-18 Thread Lin Huang
If want to do training outside DP Firmware, need phy voltage swing
and pre_emphasis value.

Signed-off-by: Lin Huang <h...@rock-chips.com>
---
Changes in v2:
- None 
Changes in v3:
- modify property description and add this property to Example
Change in v4:
- None
Change in v5:
- None

 .../devicetree/bindings/phy/phy-rockchip-typec.txt | 29 +-
 1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt 
b/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
index 960da7f..af298f2 100644
--- a/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
+++ b/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
@@ -17,7 +17,8 @@ Required properties:
 
 Optional properties:
  - extcon : extcon specifier for the Power Delivery
-
+ - rockchip,phy_config : A list of voltage swing(mv) and pre-emphasis
+   (dB) pairs.
 Required nodes : a sub-node is required for each port the phy provides.
 The sub-node name is used to identify dp or usb3 port,
 and shall be the following entries:
@@ -50,6 +51,19 @@ Example:
 < SRST_P_UPHY0_TCPHY>;
reset-names = "uphy", "uphy-pipe", "uphy-tcphy";
 
+   rockchip,phy_config =<0x2a 0x00
+   0x1f 0x15
+   0x14 0x22
+   0x02 0x2b
+   0x21 0x00
+   0x12 0x15
+   0x02 0x22
+   0 0
+   0x15 0x00
+   0x00 0x15
+   0 0
+   0 0>;
+
tcphy0_dp: dp-port {
#phy-cells = <0>;
};
@@ -74,6 +88,19 @@ Example:
 < SRST_P_UPHY1_TCPHY>;
reset-names = "uphy", "uphy-pipe", "uphy-tcphy";
 
+   rockchip,phy_config =<0x2a 0x00
+   0x1f 0x15
+   0x14 0x22
+   0x02 0x2b
+   0x21 0x00
+   0x12 0x15
+   0x02 0x22
+   0 0
+   0x15 0x00
+   0x00 0x15
+   0 0
+   0 0>;
+
tcphy1_dp: dp-port {
#phy-cells = <0>;
};
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v4 3/4] phy: rockchip-typec: support variable phy config value

2018-05-15 Thread Lin Huang
the phy config values used to fix in dp firmware, but some boards
need change these values to do training and get the better eye diagram
result. So support that in phy driver.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
Signed-off-by: Lin Huang <h...@rock-chips.com>
---
Changes in v2:
- update patch following Enric suggest
Changes in v3:
- delete need_software_training variable
- add default phy config value, if dts do not define phy config value, use 
these value
Changes in v4:
- rename variable config to tcphy_default_config

 drivers/phy/rockchip/phy-rockchip-typec.c | 306 --
 include/soc/rockchip/rockchip_phy_typec.h |  63 ++
 2 files changed, 271 insertions(+), 98 deletions(-)
 create mode 100644 include/soc/rockchip/rockchip_phy_typec.h

diff --git a/drivers/phy/rockchip/phy-rockchip-typec.c 
b/drivers/phy/rockchip/phy-rockchip-typec.c
index 76a4b58..5d8692d 100644
--- a/drivers/phy/rockchip/phy-rockchip-typec.c
+++ b/drivers/phy/rockchip/phy-rockchip-typec.c
@@ -63,6 +63,7 @@
 
 #include 
 #include 
+#include 
 
 #define CMN_SSM_BANDGAP(0x21 << 2)
 #define CMN_SSM_BIAS   (0x22 << 2)
@@ -323,21 +324,29 @@
  * clock 0: PLL 0 div 1
  * clock 1: PLL 1 div 2
  */
-#define CLK_PLL_CONFIG 0X30
+#define CLK_PLL1_DIV1  0x20
+#define CLK_PLL1_DIV2  0x30
 #define CLK_PLL_MASK   0x33
 
 #define CMN_READY  BIT(0)
 
+#define DP_PLL_CLOCK_ENABLE_ACKBIT(3)
 #define DP_PLL_CLOCK_ENABLEBIT(2)
+#define DP_PLL_ENABLE_ACK  BIT(1)
 #define DP_PLL_ENABLE  BIT(0)
 #define DP_PLL_DATA_RATE_RBR   ((2 << 12) | (4 << 8))
 #define DP_PLL_DATA_RATE_HBR   ((2 << 12) | (4 << 8))
 #define DP_PLL_DATA_RATE_HBR2  ((1 << 12) | (2 << 8))
+#define DP_PLL_DATA_RATE_MASK  0xff00
 
-#define DP_MODE_A0 BIT(4)
-#define DP_MODE_A2 BIT(6)
-#define DP_MODE_ENTER_A0   0xc101
-#define DP_MODE_ENTER_A2   0xc104
+#define DP_MODE_MASK   0xf
+#define DP_MODE_ENTER_A0   BIT(0)
+#define DP_MODE_ENTER_A2   BIT(2)
+#define DP_MODE_ENTER_A3   BIT(3)
+#define DP_MODE_A0_ACK BIT(4)
+#define DP_MODE_A2_ACK BIT(6)
+#define DP_MODE_A3_ACK BIT(7)
+#define DP_LINK_RESET_DEASSERTED   BIT(8)
 
 #define PHY_MODE_SET_TIMEOUT   10
 
@@ -349,51 +358,7 @@
 #define MODE_DFP_USB   BIT(1)
 #define MODE_DFP_DPBIT(2)
 
-struct usb3phy_reg {
-   u32 offset;
-   u32 enable_bit;
-   u32 write_enable;
-};
-
-/**
- * struct rockchip_usb3phy_port_cfg: usb3-phy port configuration.
- * @reg: the base address for usb3-phy config.
- * @typec_conn_dir: the register of type-c connector direction.
- * @usb3tousb2_en: the register of type-c force usb2 to usb2 enable.
- * @external_psm: the register of type-c phy external psm clock.
- * @pipe_status: the register of type-c phy pipe status.
- * @usb3_host_disable: the register of type-c usb3 host disable.
- * @usb3_host_port: the register of type-c usb3 host port.
- * @uphy_dp_sel: the register of type-c phy DP select control.
- */
-struct rockchip_usb3phy_port_cfg {
-   unsigned int reg;
-   struct usb3phy_reg typec_conn_dir;
-   struct usb3phy_reg usb3tousb2_en;
-   struct usb3phy_reg external_psm;
-   struct usb3phy_reg pipe_status;
-   struct usb3phy_reg usb3_host_disable;
-   struct usb3phy_reg usb3_host_port;
-   struct usb3phy_reg uphy_dp_sel;
-};
-
-struct rockchip_typec_phy {
-   struct device *dev;
-   void __iomem *base;
-   struct extcon_dev *extcon;
-   struct regmap *grf_regs;
-   struct clk *clk_core;
-   struct clk *clk_ref;
-   struct reset_control *uphy_rst;
-   struct reset_control *pipe_rst;
-   struct reset_control *tcphy_rst;
-   const struct rockchip_usb3phy_port_cfg *port_cfgs;
-   /* mutex to protect access to individual PHYs */
-   struct mutex lock;
-
-   bool flip;
-   u8 mode;
-};
+#define DP_DEFAULT_RATE162000
 
 struct phy_reg {
u16 value;
@@ -417,15 +382,15 @@ struct phy_reg usb3_pll_cfg[] = {
{ 0x8,  CMN_DIAG_PLL0_LF_PROG },
 };
 
-struct phy_reg dp_pll_cfg[] = {
+struct phy_reg dp_pll_rbr_cfg[] = {
{ 0xf0, CMN_PLL1_VCOCAL_INIT },
{ 0x18, CMN_PLL1_VCOCAL_ITER },
{ 0x30b9,   CMN_PLL1_VCOCAL_START },
-   { 0x21c,CMN_PLL1_INTDIV },
+   { 0x87, CMN_PLL1_INTDIV },
{ 0,CMN_PLL1_FRACDIV },
-   { 0x5,  CMN_PLL1_HIGH_THR },
-   { 0x35, CMN_PLL1_SS_CTRL1 },
-   { 0x7f1e,   CMN_PLL1_SS_CTRL2 },
+   { 0x22, CMN_PLL1_HIGH_THR

[PATCH v3 1/4] drm/rockchip: add transfer function for cdn-dp

2018-05-15 Thread Lin Huang
From: Chris Zhong <z...@rock-chips.com>

We may support training outside firmware, so we need support
dpcd read/write to get the message or do some setting with
display.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
Signed-off-by: Lin Huang <h...@rock-chips.com>
Reviewed-by: Sean Paul <seanp...@chromium.org>
Reviewed-by: Enric Balletbo <eballe...@gmail.com>
---
Changes in v2:
- update patch following Enric suggest
- None
 drivers/gpu/drm/rockchip/cdn-dp-core.c | 55 +++
 drivers/gpu/drm/rockchip/cdn-dp-core.h |  1 +
 drivers/gpu/drm/rockchip/cdn-dp-reg.c  | 69 ++
 drivers/gpu/drm/rockchip/cdn-dp-reg.h  | 14 ++-
 4 files changed, 122 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c 
b/drivers/gpu/drm/rockchip/cdn-dp-core.c
index c6fbdcd..cce64c1 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -176,8 +176,8 @@ static int cdn_dp_get_sink_count(struct cdn_dp_device *dp, 
u8 *sink_count)
u8 value;
 
*sink_count = 0;
-   ret = cdn_dp_dpcd_read(dp, DP_SINK_COUNT, , 1);
-   if (ret)
+   ret = drm_dp_dpcd_read(>aux, DP_SINK_COUNT, , 1);
+   if (ret < 0)
return ret;
 
*sink_count = DP_GET_SINK_COUNT(value);
@@ -374,9 +374,9 @@ static int cdn_dp_get_sink_capability(struct cdn_dp_device 
*dp)
if (!cdn_dp_check_sink_connection(dp))
return -ENODEV;
 
-   ret = cdn_dp_dpcd_read(dp, DP_DPCD_REV, dp->dpcd,
-  DP_RECEIVER_CAP_SIZE);
-   if (ret) {
+   ret = drm_dp_dpcd_read(>aux, DP_DPCD_REV, dp->dpcd,
+  sizeof(dp->dpcd));
+   if (ret < 0) {
DRM_DEV_ERROR(dp->dev, "Failed to get caps %d\n", ret);
return ret;
}
@@ -582,8 +582,8 @@ static bool cdn_dp_check_link_status(struct cdn_dp_device 
*dp)
if (!port || !dp->link.rate || !dp->link.num_lanes)
return false;
 
-   if (cdn_dp_dpcd_read(dp, DP_LANE0_1_STATUS, link_status,
-DP_LINK_STATUS_SIZE)) {
+   if (drm_dp_dpcd_read_link_status(>aux, link_status) !=
+   DP_LINK_STATUS_SIZE) {
DRM_ERROR("Failed to get link status\n");
return false;
}
@@ -1012,6 +1012,40 @@ static int cdn_dp_pd_event(struct notifier_block *nb,
return NOTIFY_DONE;
 }
 
+static ssize_t cdn_dp_aux_transfer(struct drm_dp_aux *aux,
+  struct drm_dp_aux_msg *msg)
+{
+   struct cdn_dp_device *dp = container_of(aux, struct cdn_dp_device, aux);
+   int ret;
+   u8 status;
+
+   switch (msg->request & ~DP_AUX_I2C_MOT) {
+   case DP_AUX_NATIVE_WRITE:
+   case DP_AUX_I2C_WRITE:
+   case DP_AUX_I2C_WRITE_STATUS_UPDATE:
+   ret = cdn_dp_dpcd_write(dp, msg->address, msg->buffer,
+   msg->size);
+   break;
+   case DP_AUX_NATIVE_READ:
+   case DP_AUX_I2C_READ:
+   ret = cdn_dp_dpcd_read(dp, msg->address, msg->buffer,
+  msg->size);
+   break;
+   default:
+   return -EINVAL;
+   }
+
+   status = cdn_dp_get_aux_status(dp);
+   if (status == AUX_STATUS_ACK)
+   msg->reply = DP_AUX_NATIVE_REPLY_ACK;
+   else if (status == AUX_STATUS_NACK)
+   msg->reply = DP_AUX_NATIVE_REPLY_NACK;
+   else if (status == AUX_STATUS_DEFER)
+   msg->reply = DP_AUX_NATIVE_REPLY_DEFER;
+
+   return ret;
+}
+
 static int cdn_dp_bind(struct device *dev, struct device *master, void *data)
 {
struct cdn_dp_device *dp = dev_get_drvdata(dev);
@@ -1030,6 +1064,13 @@ static int cdn_dp_bind(struct device *dev, struct device 
*master, void *data)
dp->active = false;
dp->active_port = -1;
dp->fw_loaded = false;
+   dp->aux.name = "DP-AUX";
+   dp->aux.transfer = cdn_dp_aux_transfer;
+   dp->aux.dev = dev;
+
+   ret = drm_dp_aux_register(>aux);
+   if (ret)
+   return ret;
 
INIT_WORK(>event_work, cdn_dp_pd_event_work);
 
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.h 
b/drivers/gpu/drm/rockchip/cdn-dp-core.h
index f57e296..46159b2 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.h
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.h
@@ -78,6 +78,7 @@ struct cdn_dp_device {
struct platform_device *audio_pdev;
struct work_struct event_work;
struct edid *edid;
+   struct drm_dp_aux aux;
 
struct mutex lock;
bool connected;
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.c 
b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
index eb3042c..979355d 100644
--- a/drivers/gpu/drm/roc

[PATCH v3 2/4] Documentation: bindings: add phy_config for Rockchip USB Type-C PHY

2018-05-15 Thread Lin Huang
If want to do training outside DP Firmware, need phy voltage swing
and pre_emphasis value.

Signed-off-by: Lin Huang <h...@rock-chips.com>
---
Changes in v2:
- rebase
Changes in v3:
- modify property description and add this property to example

 .../devicetree/bindings/phy/phy-rockchip-typec.txt | 29 +-
 1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt 
b/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
index 960da7f..af298f2 100644
--- a/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
+++ b/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
@@ -17,7 +17,8 @@ Required properties:
 
 Optional properties:
  - extcon : extcon specifier for the Power Delivery
-
+ - rockchip,phy_config : A list of voltage swing(mv) and pre-emphasis
+   (dB) pairs.
 Required nodes : a sub-node is required for each port the phy provides.
 The sub-node name is used to identify dp or usb3 port,
 and shall be the following entries:
@@ -50,6 +51,19 @@ Example:
 < SRST_P_UPHY0_TCPHY>;
reset-names = "uphy", "uphy-pipe", "uphy-tcphy";
 
+   rockchip,phy_config =<0x2a 0x00
+   0x1f 0x15
+   0x14 0x22
+   0x02 0x2b
+   0x21 0x00
+   0x12 0x15
+   0x02 0x22
+   0 0
+   0x15 0x00
+   0x00 0x15
+   0 0
+   0 0>;
+
tcphy0_dp: dp-port {
#phy-cells = <0>;
};
@@ -74,6 +88,19 @@ Example:
 < SRST_P_UPHY1_TCPHY>;
reset-names = "uphy", "uphy-pipe", "uphy-tcphy";
 
+   rockchip,phy_config =<0x2a 0x00
+   0x1f 0x15
+   0x14 0x22
+   0x02 0x2b
+   0x21 0x00
+   0x12 0x15
+   0x02 0x22
+   0 0
+   0x15 0x00
+   0x00 0x15
+   0 0
+   0 0>;
+
tcphy1_dp: dp-port {
#phy-cells = <0>;
};
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v4 4/4] drm/rockchip: support dp training outside dp firmware

2018-05-15 Thread Lin Huang
DP firmware uses fixed phy config values to do training, but some
boards need to adjust these values to fit for their unique hardware
design. So get phy config values from dts and use software link training
instead of relying on firmware, if software training fail, keep firmware
training as a fallback if sw training fails.


Signed-off-by: Chris Zhong <z...@rock-chips.com>
Signed-off-by: Lin Huang <h...@rock-chips.com>
---
Changes in v2:
- update patch following Enric suggest
Changes in v3:
- use variable fw_training instead sw_training_success
- base on DP SPCE, if training fail use lower link rate to retry training
Changes in v4:
- improve cdn_dp_get_lower_link_rate() and cdn_dp_software_train_link() follow 
Sean suggest

 drivers/gpu/drm/rockchip/Makefile   |   3 +-
 drivers/gpu/drm/rockchip/cdn-dp-core.c  |  24 +-
 drivers/gpu/drm/rockchip/cdn-dp-core.h  |   2 +
 drivers/gpu/drm/rockchip/cdn-dp-link-training.c | 420 
 drivers/gpu/drm/rockchip/cdn-dp-reg.c   |  31 +-
 drivers/gpu/drm/rockchip/cdn-dp-reg.h   |  38 ++-
 6 files changed, 505 insertions(+), 13 deletions(-)
 create mode 100644 drivers/gpu/drm/rockchip/cdn-dp-link-training.c

diff --git a/drivers/gpu/drm/rockchip/Makefile 
b/drivers/gpu/drm/rockchip/Makefile
index a314e21..b932f62 100644
--- a/drivers/gpu/drm/rockchip/Makefile
+++ b/drivers/gpu/drm/rockchip/Makefile
@@ -9,7 +9,8 @@ rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \
 rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o
 
 rockchipdrm-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o
-rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o
+rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o \
+   cdn-dp-link-training.o
 rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o
 rockchipdrm-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi.o
 rockchipdrm-$(CONFIG_ROCKCHIP_INNO_HDMI) += inno_hdmi.o
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c 
b/drivers/gpu/drm/rockchip/cdn-dp-core.c
index cce64c1..d9d0d4d 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -629,11 +629,13 @@ static void cdn_dp_encoder_enable(struct drm_encoder 
*encoder)
goto out;
}
}
-
-   ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_IDLE);
-   if (ret) {
-   DRM_DEV_ERROR(dp->dev, "Failed to idle video %d\n", ret);
-   goto out;
+   if (dp->use_fw_training == true) {
+   ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_IDLE);
+   if (ret) {
+   DRM_DEV_ERROR(dp->dev,
+ "Failed to idle video %d\n", ret);
+   goto out;
+   }
}
 
ret = cdn_dp_config_video(dp);
@@ -642,11 +644,15 @@ static void cdn_dp_encoder_enable(struct drm_encoder 
*encoder)
goto out;
}
 
-   ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_VALID);
-   if (ret) {
-   DRM_DEV_ERROR(dp->dev, "Failed to valid video %d\n", ret);
-   goto out;
+   if (dp->use_fw_training == true) {
+   ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_VALID);
+   if (ret) {
+   DRM_DEV_ERROR(dp->dev,
+   "Failed to valid video %d\n", ret);
+   goto out;
+   }
}
+
 out:
mutex_unlock(>lock);
 }
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.h 
b/drivers/gpu/drm/rockchip/cdn-dp-core.h
index 46159b2..77a9793 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.h
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.h
@@ -84,6 +84,7 @@ struct cdn_dp_device {
bool connected;
bool active;
bool suspended;
+   bool use_fw_training;
 
const struct firmware *fw;  /* cdn dp firmware */
unsigned int fw_version;/* cdn fw version */
@@ -106,6 +107,7 @@ struct cdn_dp_device {
u8 ports;
u8 lanes;
int active_port;
+   u8 train_set[4];
 
u8 dpcd[DP_RECEIVER_CAP_SIZE];
bool sink_has_audio;
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-link-training.c 
b/drivers/gpu/drm/rockchip/cdn-dp-link-training.c
new file mode 100644
index 000..7efd070
--- /dev/null
+++ b/drivers/gpu/drm/rockchip/cdn-dp-link-training.c
@@ -0,0 +1,420 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
+ * Author: Chris Zhong <z...@rock-chips.com>
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "cdn-dp-core.h"
+#include "cdn-dp-reg.h"
+
+static void cdn_dp_set_signal_levels(struct cdn_dp_device *dp)
+{
+   struct cdn_dp_port *port = dp->port[dp-&g

[PATCH v3 4/4] drm/rockchip: support dp training outside dp firmware

2018-05-15 Thread Lin Huang
DP firmware uses fixed phy config values to do training, but some
boards need to adjust these values to fit for their unique hardware
design. So if the phy is using custom config values, do software
link training instead of relying on firmware, if software training
fail, keep firmware training as a fallback if sw training fails.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
Signed-off-by: Lin Huang <h...@rock-chips.com>
---
Changes in v2:
- update patch following Enric suggest
Changes in v3:
- use variable fw_training instead sw_training_success
- base on DP SPCE, if training fail use lower link rate to retry training

 drivers/gpu/drm/rockchip/Makefile   |   3 +-
 drivers/gpu/drm/rockchip/cdn-dp-core.c  |  24 +-
 drivers/gpu/drm/rockchip/cdn-dp-core.h  |   2 +
 drivers/gpu/drm/rockchip/cdn-dp-link-training.c | 416 
 drivers/gpu/drm/rockchip/cdn-dp-reg.c   |  31 +-
 drivers/gpu/drm/rockchip/cdn-dp-reg.h   |  38 ++-
 6 files changed, 501 insertions(+), 13 deletions(-)
 create mode 100644 drivers/gpu/drm/rockchip/cdn-dp-link-training.c

diff --git a/drivers/gpu/drm/rockchip/Makefile 
b/drivers/gpu/drm/rockchip/Makefile
index a314e21..b932f62 100644
--- a/drivers/gpu/drm/rockchip/Makefile
+++ b/drivers/gpu/drm/rockchip/Makefile
@@ -9,7 +9,8 @@ rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \
 rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o
 
 rockchipdrm-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o
-rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o
+rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o \
+   cdn-dp-link-training.o
 rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o
 rockchipdrm-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi.o
 rockchipdrm-$(CONFIG_ROCKCHIP_INNO_HDMI) += inno_hdmi.o
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c 
b/drivers/gpu/drm/rockchip/cdn-dp-core.c
index cce64c1..d9d0d4d 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -629,11 +629,13 @@ static void cdn_dp_encoder_enable(struct drm_encoder 
*encoder)
goto out;
}
}
-
-   ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_IDLE);
-   if (ret) {
-   DRM_DEV_ERROR(dp->dev, "Failed to idle video %d\n", ret);
-   goto out;
+   if (dp->use_fw_training == true) {
+   ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_IDLE);
+   if (ret) {
+   DRM_DEV_ERROR(dp->dev,
+ "Failed to idle video %d\n", ret);
+   goto out;
+   }
}
 
ret = cdn_dp_config_video(dp);
@@ -642,11 +644,15 @@ static void cdn_dp_encoder_enable(struct drm_encoder 
*encoder)
goto out;
}
 
-   ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_VALID);
-   if (ret) {
-   DRM_DEV_ERROR(dp->dev, "Failed to valid video %d\n", ret);
-   goto out;
+   if (dp->use_fw_training == true) {
+   ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_VALID);
+   if (ret) {
+   DRM_DEV_ERROR(dp->dev,
+   "Failed to valid video %d\n", ret);
+   goto out;
+   }
}
+
 out:
mutex_unlock(>lock);
 }
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.h 
b/drivers/gpu/drm/rockchip/cdn-dp-core.h
index 46159b2..77a9793 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.h
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.h
@@ -84,6 +84,7 @@ struct cdn_dp_device {
bool connected;
bool active;
bool suspended;
+   bool use_fw_training;
 
const struct firmware *fw;  /* cdn dp firmware */
unsigned int fw_version;/* cdn fw version */
@@ -106,6 +107,7 @@ struct cdn_dp_device {
u8 ports;
u8 lanes;
int active_port;
+   u8 train_set[4];
 
u8 dpcd[DP_RECEIVER_CAP_SIZE];
bool sink_has_audio;
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-link-training.c 
b/drivers/gpu/drm/rockchip/cdn-dp-link-training.c
new file mode 100644
index 000..b8fd5bc
--- /dev/null
+++ b/drivers/gpu/drm/rockchip/cdn-dp-link-training.c
@@ -0,0 +1,416 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
+ * Author: Chris Zhong <z...@rock-chips.com>
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "cdn-dp-core.h"
+#include "cdn-dp-reg.h"
+
+static void cdn_dp_set_signal_levels(struct cdn_dp_device *dp)
+{
+   struct cdn_dp_port *port = dp->port[dp->active_port];
+   struct rockchip_typec_phy *tcphy = phy_get_drvdata(port->phy);
+
+   int rate = dr

[PATCH v4 1/4] drm/rockchip: add transfer function for cdn-dp

2018-05-15 Thread Lin Huang
From: Chris Zhong <z...@rock-chips.com>

We may support training outside firmware, so we need support
dpcd read/write to get the message or do some setting with
display.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
Signed-off-by: Lin Huang <h...@rock-chips.com>
Reviewed-by: Sean Paul <seanp...@chromium.org>
Reviewed-by: Enric Balletbo <enric.balle...@collabora.com>
---
Changes in v2:
- update patch following Enric suggest
Changes in v3:
- None
Changes in v4:
- None

 drivers/gpu/drm/rockchip/cdn-dp-core.c | 55 +++
 drivers/gpu/drm/rockchip/cdn-dp-core.h |  1 +
 drivers/gpu/drm/rockchip/cdn-dp-reg.c  | 69 ++
 drivers/gpu/drm/rockchip/cdn-dp-reg.h  | 14 ++-
 4 files changed, 122 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c 
b/drivers/gpu/drm/rockchip/cdn-dp-core.c
index c6fbdcd..cce64c1 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -176,8 +176,8 @@ static int cdn_dp_get_sink_count(struct cdn_dp_device *dp, 
u8 *sink_count)
u8 value;
 
*sink_count = 0;
-   ret = cdn_dp_dpcd_read(dp, DP_SINK_COUNT, , 1);
-   if (ret)
+   ret = drm_dp_dpcd_read(>aux, DP_SINK_COUNT, , 1);
+   if (ret < 0)
return ret;
 
*sink_count = DP_GET_SINK_COUNT(value);
@@ -374,9 +374,9 @@ static int cdn_dp_get_sink_capability(struct cdn_dp_device 
*dp)
if (!cdn_dp_check_sink_connection(dp))
return -ENODEV;
 
-   ret = cdn_dp_dpcd_read(dp, DP_DPCD_REV, dp->dpcd,
-  DP_RECEIVER_CAP_SIZE);
-   if (ret) {
+   ret = drm_dp_dpcd_read(>aux, DP_DPCD_REV, dp->dpcd,
+  sizeof(dp->dpcd));
+   if (ret < 0) {
DRM_DEV_ERROR(dp->dev, "Failed to get caps %d\n", ret);
return ret;
}
@@ -582,8 +582,8 @@ static bool cdn_dp_check_link_status(struct cdn_dp_device 
*dp)
if (!port || !dp->link.rate || !dp->link.num_lanes)
return false;
 
-   if (cdn_dp_dpcd_read(dp, DP_LANE0_1_STATUS, link_status,
-DP_LINK_STATUS_SIZE)) {
+   if (drm_dp_dpcd_read_link_status(>aux, link_status) !=
+   DP_LINK_STATUS_SIZE) {
DRM_ERROR("Failed to get link status\n");
return false;
}
@@ -1012,6 +1012,40 @@ static int cdn_dp_pd_event(struct notifier_block *nb,
return NOTIFY_DONE;
 }
 
+static ssize_t cdn_dp_aux_transfer(struct drm_dp_aux *aux,
+  struct drm_dp_aux_msg *msg)
+{
+   struct cdn_dp_device *dp = container_of(aux, struct cdn_dp_device, aux);
+   int ret;
+   u8 status;
+
+   switch (msg->request & ~DP_AUX_I2C_MOT) {
+   case DP_AUX_NATIVE_WRITE:
+   case DP_AUX_I2C_WRITE:
+   case DP_AUX_I2C_WRITE_STATUS_UPDATE:
+   ret = cdn_dp_dpcd_write(dp, msg->address, msg->buffer,
+   msg->size);
+   break;
+   case DP_AUX_NATIVE_READ:
+   case DP_AUX_I2C_READ:
+   ret = cdn_dp_dpcd_read(dp, msg->address, msg->buffer,
+  msg->size);
+   break;
+   default:
+   return -EINVAL;
+   }
+
+   status = cdn_dp_get_aux_status(dp);
+   if (status == AUX_STATUS_ACK)
+   msg->reply = DP_AUX_NATIVE_REPLY_ACK;
+   else if (status == AUX_STATUS_NACK)
+   msg->reply = DP_AUX_NATIVE_REPLY_NACK;
+   else if (status == AUX_STATUS_DEFER)
+   msg->reply = DP_AUX_NATIVE_REPLY_DEFER;
+
+   return ret;
+}
+
 static int cdn_dp_bind(struct device *dev, struct device *master, void *data)
 {
struct cdn_dp_device *dp = dev_get_drvdata(dev);
@@ -1030,6 +1064,13 @@ static int cdn_dp_bind(struct device *dev, struct device 
*master, void *data)
dp->active = false;
dp->active_port = -1;
dp->fw_loaded = false;
+   dp->aux.name = "DP-AUX";
+   dp->aux.transfer = cdn_dp_aux_transfer;
+   dp->aux.dev = dev;
+
+   ret = drm_dp_aux_register(>aux);
+   if (ret)
+   return ret;
 
INIT_WORK(>event_work, cdn_dp_pd_event_work);
 
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.h 
b/drivers/gpu/drm/rockchip/cdn-dp-core.h
index f57e296..46159b2 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.h
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.h
@@ -78,6 +78,7 @@ struct cdn_dp_device {
struct platform_device *audio_pdev;
struct work_struct event_work;
struct edid *edid;
+   struct drm_dp_aux aux;
 
struct mutex lock;
bool connected;
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.c 
b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
index eb3042c..979355d 100

[PATCH v4 2/4] Documentation: bindings: add phy_config for Rockchip USB Type-C PHY

2018-05-15 Thread Lin Huang
If want to do training outside DP Firmware, need phy voltage swing
and pre_emphasis value.

Signed-off-by: Lin Huang <h...@rock-chips.com>
---
Changes in v2:
- None 
Changes in v3:
- modify property description and add this property to Example
Change in v4:
- None

 .../devicetree/bindings/phy/phy-rockchip-typec.txt | 29 +-
 1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt 
b/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
index 960da7f..af298f2 100644
--- a/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
+++ b/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
@@ -17,7 +17,8 @@ Required properties:
 
 Optional properties:
  - extcon : extcon specifier for the Power Delivery
-
+ - rockchip,phy_config : A list of voltage swing(mv) and pre-emphasis
+   (dB) pairs.
 Required nodes : a sub-node is required for each port the phy provides.
 The sub-node name is used to identify dp or usb3 port,
 and shall be the following entries:
@@ -50,6 +51,19 @@ Example:
 < SRST_P_UPHY0_TCPHY>;
reset-names = "uphy", "uphy-pipe", "uphy-tcphy";
 
+   rockchip,phy_config =<0x2a 0x00
+   0x1f 0x15
+   0x14 0x22
+   0x02 0x2b
+   0x21 0x00
+   0x12 0x15
+   0x02 0x22
+   0 0
+   0x15 0x00
+   0x00 0x15
+   0 0
+   0 0>;
+
tcphy0_dp: dp-port {
#phy-cells = <0>;
};
@@ -74,6 +88,19 @@ Example:
 < SRST_P_UPHY1_TCPHY>;
reset-names = "uphy", "uphy-pipe", "uphy-tcphy";
 
+   rockchip,phy_config =<0x2a 0x00
+   0x1f 0x15
+   0x14 0x22
+   0x02 0x2b
+   0x21 0x00
+   0x12 0x15
+   0x02 0x22
+   0 0
+   0x15 0x00
+   0x00 0x15
+   0 0
+   0 0>;
+
tcphy1_dp: dp-port {
#phy-cells = <0>;
};
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v3 3/4] phy: rockchip-typec: support variable phy config value

2018-05-15 Thread Lin Huang
the phy config values used to fix in dp firmware, but some boards
need change these values to do training and get the better eye diagram
result. So support that in phy driver.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
Signed-off-by: Lin Huang <h...@rock-chips.com>
---
Changes in v2:
- update patch following Enric suggest
Changes in v3:
- delete need_software_training variable
- add default phy config value, if dts do not define phy config value, use 
these value

 drivers/phy/rockchip/phy-rockchip-typec.c | 305 --
 include/soc/rockchip/rockchip_phy_typec.h |  63 ++
 2 files changed, 270 insertions(+), 98 deletions(-)
 create mode 100644 include/soc/rockchip/rockchip_phy_typec.h

diff --git a/drivers/phy/rockchip/phy-rockchip-typec.c 
b/drivers/phy/rockchip/phy-rockchip-typec.c
index 76a4b58..10253ad 100644
--- a/drivers/phy/rockchip/phy-rockchip-typec.c
+++ b/drivers/phy/rockchip/phy-rockchip-typec.c
@@ -63,6 +63,7 @@
 
 #include 
 #include 
+#include 
 
 #define CMN_SSM_BANDGAP(0x21 << 2)
 #define CMN_SSM_BIAS   (0x22 << 2)
@@ -323,21 +324,29 @@
  * clock 0: PLL 0 div 1
  * clock 1: PLL 1 div 2
  */
-#define CLK_PLL_CONFIG 0X30
+#define CLK_PLL1_DIV1  0x20
+#define CLK_PLL1_DIV2  0x30
 #define CLK_PLL_MASK   0x33
 
 #define CMN_READY  BIT(0)
 
+#define DP_PLL_CLOCK_ENABLE_ACKBIT(3)
 #define DP_PLL_CLOCK_ENABLEBIT(2)
+#define DP_PLL_ENABLE_ACK  BIT(1)
 #define DP_PLL_ENABLE  BIT(0)
 #define DP_PLL_DATA_RATE_RBR   ((2 << 12) | (4 << 8))
 #define DP_PLL_DATA_RATE_HBR   ((2 << 12) | (4 << 8))
 #define DP_PLL_DATA_RATE_HBR2  ((1 << 12) | (2 << 8))
+#define DP_PLL_DATA_RATE_MASK  0xff00
 
-#define DP_MODE_A0 BIT(4)
-#define DP_MODE_A2 BIT(6)
-#define DP_MODE_ENTER_A0   0xc101
-#define DP_MODE_ENTER_A2   0xc104
+#define DP_MODE_MASK   0xf
+#define DP_MODE_ENTER_A0   BIT(0)
+#define DP_MODE_ENTER_A2   BIT(2)
+#define DP_MODE_ENTER_A3   BIT(3)
+#define DP_MODE_A0_ACK BIT(4)
+#define DP_MODE_A2_ACK BIT(6)
+#define DP_MODE_A3_ACK BIT(7)
+#define DP_LINK_RESET_DEASSERTED   BIT(8)
 
 #define PHY_MODE_SET_TIMEOUT   10
 
@@ -349,51 +358,7 @@
 #define MODE_DFP_USB   BIT(1)
 #define MODE_DFP_DPBIT(2)
 
-struct usb3phy_reg {
-   u32 offset;
-   u32 enable_bit;
-   u32 write_enable;
-};
-
-/**
- * struct rockchip_usb3phy_port_cfg: usb3-phy port configuration.
- * @reg: the base address for usb3-phy config.
- * @typec_conn_dir: the register of type-c connector direction.
- * @usb3tousb2_en: the register of type-c force usb2 to usb2 enable.
- * @external_psm: the register of type-c phy external psm clock.
- * @pipe_status: the register of type-c phy pipe status.
- * @usb3_host_disable: the register of type-c usb3 host disable.
- * @usb3_host_port: the register of type-c usb3 host port.
- * @uphy_dp_sel: the register of type-c phy DP select control.
- */
-struct rockchip_usb3phy_port_cfg {
-   unsigned int reg;
-   struct usb3phy_reg typec_conn_dir;
-   struct usb3phy_reg usb3tousb2_en;
-   struct usb3phy_reg external_psm;
-   struct usb3phy_reg pipe_status;
-   struct usb3phy_reg usb3_host_disable;
-   struct usb3phy_reg usb3_host_port;
-   struct usb3phy_reg uphy_dp_sel;
-};
-
-struct rockchip_typec_phy {
-   struct device *dev;
-   void __iomem *base;
-   struct extcon_dev *extcon;
-   struct regmap *grf_regs;
-   struct clk *clk_core;
-   struct clk *clk_ref;
-   struct reset_control *uphy_rst;
-   struct reset_control *pipe_rst;
-   struct reset_control *tcphy_rst;
-   const struct rockchip_usb3phy_port_cfg *port_cfgs;
-   /* mutex to protect access to individual PHYs */
-   struct mutex lock;
-
-   bool flip;
-   u8 mode;
-};
+#define DP_DEFAULT_RATE162000
 
 struct phy_reg {
u16 value;
@@ -417,15 +382,15 @@ struct phy_reg usb3_pll_cfg[] = {
{ 0x8,  CMN_DIAG_PLL0_LF_PROG },
 };
 
-struct phy_reg dp_pll_cfg[] = {
+struct phy_reg dp_pll_rbr_cfg[] = {
{ 0xf0, CMN_PLL1_VCOCAL_INIT },
{ 0x18, CMN_PLL1_VCOCAL_ITER },
{ 0x30b9,   CMN_PLL1_VCOCAL_START },
-   { 0x21c,CMN_PLL1_INTDIV },
+   { 0x87, CMN_PLL1_INTDIV },
{ 0,CMN_PLL1_FRACDIV },
-   { 0x5,  CMN_PLL1_HIGH_THR },
-   { 0x35, CMN_PLL1_SS_CTRL1 },
-   { 0x7f1e,   CMN_PLL1_SS_CTRL2 },
+   { 0x22, CMN_PLL1_HIGH_THR },
+   { 0x8000,   CMN_PLL1_SS_CTRL1 },
+   { 0,CM

[PATCH v2 4/4] drm/rockchip: support dp training outside dp firmware

2018-05-10 Thread Lin Huang
DP firmware uses fixed phy config values to do training, but some
boards need to adjust these values to fit for their unique hardware
design. So if the phy is using custom config values, do software
link training instead of relying on firmware, if software training
fail, keep firmware training as a fallback if sw training fails.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
Signed-off-by: Lin Huang <h...@rock-chips.com>
---
Changes in v2:
- update patch following Enric suggest

 drivers/gpu/drm/rockchip/Makefile   |   3 +-
 drivers/gpu/drm/rockchip/cdn-dp-core.c  |  24 +-
 drivers/gpu/drm/rockchip/cdn-dp-core.h  |   2 +
 drivers/gpu/drm/rockchip/cdn-dp-link-training.c | 391 
 drivers/gpu/drm/rockchip/cdn-dp-reg.c   |  34 ++-
 drivers/gpu/drm/rockchip/cdn-dp-reg.h   |  38 ++-
 6 files changed, 479 insertions(+), 13 deletions(-)
 create mode 100644 drivers/gpu/drm/rockchip/cdn-dp-link-training.c

diff --git a/drivers/gpu/drm/rockchip/Makefile 
b/drivers/gpu/drm/rockchip/Makefile
index a314e21..b932f62 100644
--- a/drivers/gpu/drm/rockchip/Makefile
+++ b/drivers/gpu/drm/rockchip/Makefile
@@ -9,7 +9,8 @@ rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \
 rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o
 
 rockchipdrm-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o
-rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o
+rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o \
+   cdn-dp-link-training.o
 rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o
 rockchipdrm-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi.o
 rockchipdrm-$(CONFIG_ROCKCHIP_INNO_HDMI) += inno_hdmi.o
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c 
b/drivers/gpu/drm/rockchip/cdn-dp-core.c
index cce64c1..2359d82 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -629,11 +629,13 @@ static void cdn_dp_encoder_enable(struct drm_encoder 
*encoder)
goto out;
}
}
-
-   ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_IDLE);
-   if (ret) {
-   DRM_DEV_ERROR(dp->dev, "Failed to idle video %d\n", ret);
-   goto out;
+   if (dp->sw_training_success == false) {
+   ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_IDLE);
+   if (ret) {
+   DRM_DEV_ERROR(dp->dev,
+ "Failed to idle video %d\n", ret);
+   goto out;
+   }
}
 
ret = cdn_dp_config_video(dp);
@@ -642,11 +644,15 @@ static void cdn_dp_encoder_enable(struct drm_encoder 
*encoder)
goto out;
}
 
-   ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_VALID);
-   if (ret) {
-   DRM_DEV_ERROR(dp->dev, "Failed to valid video %d\n", ret);
-   goto out;
+   if (dp->sw_training_success == false) {
+   ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_VALID);
+   if (ret) {
+   DRM_DEV_ERROR(dp->dev,
+   "Failed to valid video %d\n", ret);
+   goto out;
+   }
}
+
 out:
mutex_unlock(>lock);
 }
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.h 
b/drivers/gpu/drm/rockchip/cdn-dp-core.h
index 46159b2..c6050ab 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.h
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.h
@@ -84,6 +84,7 @@ struct cdn_dp_device {
bool connected;
bool active;
bool suspended;
+   bool sw_training_success;
 
const struct firmware *fw;  /* cdn dp firmware */
unsigned int fw_version;/* cdn fw version */
@@ -106,6 +107,7 @@ struct cdn_dp_device {
u8 ports;
u8 lanes;
int active_port;
+   u8 train_set[4];
 
u8 dpcd[DP_RECEIVER_CAP_SIZE];
bool sink_has_audio;
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-link-training.c 
b/drivers/gpu/drm/rockchip/cdn-dp-link-training.c
new file mode 100644
index 000..25282de
--- /dev/null
+++ b/drivers/gpu/drm/rockchip/cdn-dp-link-training.c
@@ -0,0 +1,391 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
+ * Author: Chris Zhong <z...@rock-chips.com>
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "cdn-dp-core.h"
+#include "cdn-dp-reg.h"
+
+static void cdn_dp_set_signal_levels(struct cdn_dp_device *dp)
+{
+   struct cdn_dp_port *port = dp->port[dp->active_port];
+   struct rockchip_typec_phy *tcphy = phy_get_drvdata(port->phy);
+
+   int rate = drm_dp_bw_code_to_link_rate(dp->link.rate);
+   u8 swing = (dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) >&g

[PATCH v2 1/4] drm/rockchip: add transfer function for cdn-dp

2018-05-10 Thread Lin Huang
From: Chris Zhong <z...@rock-chips.com>

We may support training outside firmware, so we need support
dpcd read/write to get the message or do some setting with
display.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
Signed-off-by: Lin Huang <h...@rock-chips.com>
---

Changes in v2: 
- update patch following Enric suggest

 drivers/gpu/drm/rockchip/cdn-dp-core.c | 55 
 drivers/gpu/drm/rockchip/cdn-dp-core.h |  1 +
 drivers/gpu/drm/rockchip/cdn-dp-reg.c  | 67 ++
 drivers/gpu/drm/rockchip/cdn-dp-reg.h  | 14 ++-
 4 files changed, 120 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c 
b/drivers/gpu/drm/rockchip/cdn-dp-core.c
index c6fbdcd..cce64c1 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -176,8 +176,8 @@ static int cdn_dp_get_sink_count(struct cdn_dp_device *dp, 
u8 *sink_count)
u8 value;
 
*sink_count = 0;
-   ret = cdn_dp_dpcd_read(dp, DP_SINK_COUNT, , 1);
-   if (ret)
+   ret = drm_dp_dpcd_read(>aux, DP_SINK_COUNT, , 1);
+   if (ret < 0)
return ret;
 
*sink_count = DP_GET_SINK_COUNT(value);
@@ -374,9 +374,9 @@ static int cdn_dp_get_sink_capability(struct cdn_dp_device 
*dp)
if (!cdn_dp_check_sink_connection(dp))
return -ENODEV;
 
-   ret = cdn_dp_dpcd_read(dp, DP_DPCD_REV, dp->dpcd,
-  DP_RECEIVER_CAP_SIZE);
-   if (ret) {
+   ret = drm_dp_dpcd_read(>aux, DP_DPCD_REV, dp->dpcd,
+  sizeof(dp->dpcd));
+   if (ret < 0) {
DRM_DEV_ERROR(dp->dev, "Failed to get caps %d\n", ret);
return ret;
}
@@ -582,8 +582,8 @@ static bool cdn_dp_check_link_status(struct cdn_dp_device 
*dp)
if (!port || !dp->link.rate || !dp->link.num_lanes)
return false;
 
-   if (cdn_dp_dpcd_read(dp, DP_LANE0_1_STATUS, link_status,
-DP_LINK_STATUS_SIZE)) {
+   if (drm_dp_dpcd_read_link_status(>aux, link_status) !=
+   DP_LINK_STATUS_SIZE) {
DRM_ERROR("Failed to get link status\n");
return false;
}
@@ -1012,6 +1012,40 @@ static int cdn_dp_pd_event(struct notifier_block *nb,
return NOTIFY_DONE;
 }
 
+static ssize_t cdn_dp_aux_transfer(struct drm_dp_aux *aux,
+  struct drm_dp_aux_msg *msg)
+{
+   struct cdn_dp_device *dp = container_of(aux, struct cdn_dp_device, aux);
+   int ret;
+   u8 status;
+
+   switch (msg->request & ~DP_AUX_I2C_MOT) {
+   case DP_AUX_NATIVE_WRITE:
+   case DP_AUX_I2C_WRITE:
+   case DP_AUX_I2C_WRITE_STATUS_UPDATE:
+   ret = cdn_dp_dpcd_write(dp, msg->address, msg->buffer,
+   msg->size);
+   break;
+   case DP_AUX_NATIVE_READ:
+   case DP_AUX_I2C_READ:
+   ret = cdn_dp_dpcd_read(dp, msg->address, msg->buffer,
+  msg->size);
+   break;
+   default:
+   return -EINVAL;
+   }
+
+   status = cdn_dp_get_aux_status(dp);
+   if (status == AUX_STATUS_ACK)
+   msg->reply = DP_AUX_NATIVE_REPLY_ACK;
+   else if (status == AUX_STATUS_NACK)
+   msg->reply = DP_AUX_NATIVE_REPLY_NACK;
+   else if (status == AUX_STATUS_DEFER)
+   msg->reply = DP_AUX_NATIVE_REPLY_DEFER;
+
+   return ret;
+}
+
 static int cdn_dp_bind(struct device *dev, struct device *master, void *data)
 {
struct cdn_dp_device *dp = dev_get_drvdata(dev);
@@ -1030,6 +1064,13 @@ static int cdn_dp_bind(struct device *dev, struct device 
*master, void *data)
dp->active = false;
dp->active_port = -1;
dp->fw_loaded = false;
+   dp->aux.name = "DP-AUX";
+   dp->aux.transfer = cdn_dp_aux_transfer;
+   dp->aux.dev = dev;
+
+   ret = drm_dp_aux_register(>aux);
+   if (ret)
+   return ret;
 
INIT_WORK(>event_work, cdn_dp_pd_event_work);
 
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.h 
b/drivers/gpu/drm/rockchip/cdn-dp-core.h
index f57e296..46159b2 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.h
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.h
@@ -78,6 +78,7 @@ struct cdn_dp_device {
struct platform_device *audio_pdev;
struct work_struct event_work;
struct edid *edid;
+   struct drm_dp_aux aux;
 
struct mutex lock;
bool connected;
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.c 
b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
index eb3042c..afdfda0 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-reg.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
@@ -221,7 +221,11 @@ static int cdn_dp_reg_write_bit(struct cdn_dp_dev

[PATCH v2 2/4] phy: rockchip-typec: support variable phy config value

2018-05-10 Thread Lin Huang
the phy config values used to fix in dp firmware, but some boards
need change these values to do training and get the better eye diagram
result. So support that in phy driver.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
Signed-off-by: Lin Huang <h...@rock-chips.com>
---
Changes in v2:
- update patch following Enric suggest

 drivers/phy/rockchip/phy-rockchip-typec.c | 284 +++---
 include/soc/rockchip/rockchip_phy_typec.h |  64 +++
 2 files changed, 250 insertions(+), 98 deletions(-)
 create mode 100644 include/soc/rockchip/rockchip_phy_typec.h

diff --git a/drivers/phy/rockchip/phy-rockchip-typec.c 
b/drivers/phy/rockchip/phy-rockchip-typec.c
index 76a4b58..86cbd6c 100644
--- a/drivers/phy/rockchip/phy-rockchip-typec.c
+++ b/drivers/phy/rockchip/phy-rockchip-typec.c
@@ -63,6 +63,7 @@
 
 #include 
 #include 
+#include 
 
 #define CMN_SSM_BANDGAP(0x21 << 2)
 #define CMN_SSM_BIAS   (0x22 << 2)
@@ -323,21 +324,29 @@
  * clock 0: PLL 0 div 1
  * clock 1: PLL 1 div 2
  */
-#define CLK_PLL_CONFIG 0X30
+#define CLK_PLL1_DIV1  0x20
+#define CLK_PLL1_DIV2  0x30
 #define CLK_PLL_MASK   0x33
 
 #define CMN_READY  BIT(0)
 
+#define DP_PLL_CLOCK_ENABLE_ACKBIT(3)
 #define DP_PLL_CLOCK_ENABLEBIT(2)
+#define DP_PLL_ENABLE_ACK  BIT(1)
 #define DP_PLL_ENABLE  BIT(0)
 #define DP_PLL_DATA_RATE_RBR   ((2 << 12) | (4 << 8))
 #define DP_PLL_DATA_RATE_HBR   ((2 << 12) | (4 << 8))
 #define DP_PLL_DATA_RATE_HBR2  ((1 << 12) | (2 << 8))
+#define DP_PLL_DATA_RATE_MASK  0xff00
 
-#define DP_MODE_A0 BIT(4)
-#define DP_MODE_A2 BIT(6)
-#define DP_MODE_ENTER_A0   0xc101
-#define DP_MODE_ENTER_A2   0xc104
+#define DP_MODE_MASK   0xf
+#define DP_MODE_ENTER_A0   BIT(0)
+#define DP_MODE_ENTER_A2   BIT(2)
+#define DP_MODE_ENTER_A3   BIT(3)
+#define DP_MODE_A0_ACK BIT(4)
+#define DP_MODE_A2_ACK BIT(6)
+#define DP_MODE_A3_ACK BIT(7)
+#define DP_LINK_RESET_DEASSERTED   BIT(8)
 
 #define PHY_MODE_SET_TIMEOUT   10
 
@@ -349,51 +358,7 @@
 #define MODE_DFP_USB   BIT(1)
 #define MODE_DFP_DPBIT(2)
 
-struct usb3phy_reg {
-   u32 offset;
-   u32 enable_bit;
-   u32 write_enable;
-};
-
-/**
- * struct rockchip_usb3phy_port_cfg: usb3-phy port configuration.
- * @reg: the base address for usb3-phy config.
- * @typec_conn_dir: the register of type-c connector direction.
- * @usb3tousb2_en: the register of type-c force usb2 to usb2 enable.
- * @external_psm: the register of type-c phy external psm clock.
- * @pipe_status: the register of type-c phy pipe status.
- * @usb3_host_disable: the register of type-c usb3 host disable.
- * @usb3_host_port: the register of type-c usb3 host port.
- * @uphy_dp_sel: the register of type-c phy DP select control.
- */
-struct rockchip_usb3phy_port_cfg {
-   unsigned int reg;
-   struct usb3phy_reg typec_conn_dir;
-   struct usb3phy_reg usb3tousb2_en;
-   struct usb3phy_reg external_psm;
-   struct usb3phy_reg pipe_status;
-   struct usb3phy_reg usb3_host_disable;
-   struct usb3phy_reg usb3_host_port;
-   struct usb3phy_reg uphy_dp_sel;
-};
-
-struct rockchip_typec_phy {
-   struct device *dev;
-   void __iomem *base;
-   struct extcon_dev *extcon;
-   struct regmap *grf_regs;
-   struct clk *clk_core;
-   struct clk *clk_ref;
-   struct reset_control *uphy_rst;
-   struct reset_control *pipe_rst;
-   struct reset_control *tcphy_rst;
-   const struct rockchip_usb3phy_port_cfg *port_cfgs;
-   /* mutex to protect access to individual PHYs */
-   struct mutex lock;
-
-   bool flip;
-   u8 mode;
-};
+#define DP_DEFAULT_RATE162000
 
 struct phy_reg {
u16 value;
@@ -417,15 +382,15 @@ struct phy_reg usb3_pll_cfg[] = {
{ 0x8,  CMN_DIAG_PLL0_LF_PROG },
 };
 
-struct phy_reg dp_pll_cfg[] = {
+struct phy_reg dp_pll_rbr_cfg[] = {
{ 0xf0, CMN_PLL1_VCOCAL_INIT },
{ 0x18, CMN_PLL1_VCOCAL_ITER },
{ 0x30b9,   CMN_PLL1_VCOCAL_START },
-   { 0x21c,CMN_PLL1_INTDIV },
+   { 0x87, CMN_PLL1_INTDIV },
{ 0,CMN_PLL1_FRACDIV },
-   { 0x5,  CMN_PLL1_HIGH_THR },
-   { 0x35, CMN_PLL1_SS_CTRL1 },
-   { 0x7f1e,   CMN_PLL1_SS_CTRL2 },
+   { 0x22, CMN_PLL1_HIGH_THR },
+   { 0x8000,   CMN_PLL1_SS_CTRL1 },
+   { 0,CMN_PLL1_SS_CTRL2 },
{ 0x20, CMN_PLL1_DSM_DIAG },
{ 0,CMN_PLLSM1_USER_DEF_CTRL },
{ 0, 

[PATCH v2 3/4] Documentation: bindings: add phy_config for Rockchip USB Type-C PHY

2018-05-10 Thread Lin Huang
If want to do training outside DP Firmware, need phy voltage swing
and pre_emphasis value.

Signed-off-by: Lin Huang <h...@rock-chips.com>
---
Changes in v2:
- rebase

 Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt 
b/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
index 960da7f..eda26dd 100644
--- a/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
+++ b/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
@@ -17,7 +17,9 @@ Required properties:
 
 Optional properties:
  - extcon : extcon specifier for the Power Delivery
-
+ - rockchip,phy_config : That's phy voltage swing and pre_emphasis
+setting, if want to do dp training outside
+dp firmware, need to add these value.
 Required nodes : a sub-node is required for each port the phy provides.
 The sub-node name is used to identify dp or usb3 port,
 and shall be the following entries:
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH 1/4] drm/rockchip: add transfer function for cdn-dp

2018-05-05 Thread Lin Huang
From: Chris Zhong <z...@rock-chips.com>

We may support training outside firmware, so we need support
dpcd read/write to get the message or do some setting with
display.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
Signed-off-by: Lin Huang <h...@rock-chips.com>
---
 drivers/gpu/drm/rockchip/cdn-dp-core.c | 55 
 drivers/gpu/drm/rockchip/cdn-dp-core.h |  1 +
 drivers/gpu/drm/rockchip/cdn-dp-reg.c  | 66 +-
 drivers/gpu/drm/rockchip/cdn-dp-reg.h  | 14 ++--
 4 files changed, 119 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c 
b/drivers/gpu/drm/rockchip/cdn-dp-core.c
index c6fbdcd..268c190 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -176,8 +176,8 @@ static int cdn_dp_get_sink_count(struct cdn_dp_device *dp, 
u8 *sink_count)
u8 value;
 
*sink_count = 0;
-   ret = cdn_dp_dpcd_read(dp, DP_SINK_COUNT, , 1);
-   if (ret)
+   ret = drm_dp_dpcd_read(>aux, DP_SINK_COUNT, , 1);
+   if (ret < 0)
return ret;
 
*sink_count = DP_GET_SINK_COUNT(value);
@@ -374,9 +374,9 @@ static int cdn_dp_get_sink_capability(struct cdn_dp_device 
*dp)
if (!cdn_dp_check_sink_connection(dp))
return -ENODEV;
 
-   ret = cdn_dp_dpcd_read(dp, DP_DPCD_REV, dp->dpcd,
-  DP_RECEIVER_CAP_SIZE);
-   if (ret) {
+   ret = drm_dp_dpcd_read(>aux, DP_DPCD_REV, dp->dpcd,
+  sizeof(dp->dpcd));
+   if (ret < 0) {
DRM_DEV_ERROR(dp->dev, "Failed to get caps %d\n", ret);
return ret;
}
@@ -582,8 +582,8 @@ static bool cdn_dp_check_link_status(struct cdn_dp_device 
*dp)
if (!port || !dp->link.rate || !dp->link.num_lanes)
return false;
 
-   if (cdn_dp_dpcd_read(dp, DP_LANE0_1_STATUS, link_status,
-DP_LINK_STATUS_SIZE)) {
+   if (drm_dp_dpcd_read_link_status(>aux, link_status) !=
+   DP_LINK_STATUS_SIZE) {
DRM_ERROR("Failed to get link status\n");
return false;
}
@@ -1012,6 +1012,40 @@ static int cdn_dp_pd_event(struct notifier_block *nb,
return NOTIFY_DONE;
 }
 
+static ssize_t cdn_dp_aux_transfer(struct drm_dp_aux *aux,
+  struct drm_dp_aux_msg *msg)
+{
+   struct cdn_dp_device *dp = container_of(aux, struct cdn_dp_device, aux);
+   int ret;
+   u8 status;
+
+   switch (msg->request & ~DP_AUX_I2C_MOT) {
+   case DP_AUX_NATIVE_WRITE:
+   case DP_AUX_I2C_WRITE:
+   case DP_AUX_I2C_WRITE_STATUS_UPDATE:
+   ret = cdn_dp_dpcd_write(dp, msg->address, msg->buffer,
+   msg->size);
+   break;
+   case DP_AUX_NATIVE_READ:
+   case DP_AUX_I2C_READ:
+   ret = cdn_dp_dpcd_read(dp, msg->address, msg->buffer,
+  msg->size);
+   break;
+   default:
+   return -EINVAL;
+   }
+
+   status = cdn_dp_get_aux_status(dp);
+   if (status == AUX_STAUS_ACK)
+   msg->reply = DP_AUX_NATIVE_REPLY_ACK;
+   else if (status == AUX_STAUS_NACK)
+   msg->reply = DP_AUX_NATIVE_REPLY_NACK;
+   else if (status == AUX_STAUS_DEFER)
+   msg->reply = DP_AUX_NATIVE_REPLY_DEFER;
+
+   return ret;
+}
+
 static int cdn_dp_bind(struct device *dev, struct device *master, void *data)
 {
struct cdn_dp_device *dp = dev_get_drvdata(dev);
@@ -1030,6 +1064,13 @@ static int cdn_dp_bind(struct device *dev, struct device 
*master, void *data)
dp->active = false;
dp->active_port = -1;
dp->fw_loaded = false;
+   dp->aux.name = "DP-AUX";
+   dp->aux.transfer = cdn_dp_aux_transfer;
+   dp->aux.dev = dev;
+
+   ret = drm_dp_aux_register(>aux);
+   if (ret)
+   return ret;
 
INIT_WORK(>event_work, cdn_dp_pd_event_work);
 
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.h 
b/drivers/gpu/drm/rockchip/cdn-dp-core.h
index f57e296..46159b2 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.h
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.h
@@ -78,6 +78,7 @@ struct cdn_dp_device {
struct platform_device *audio_pdev;
struct work_struct event_work;
struct edid *edid;
+   struct drm_dp_aux aux;
 
struct mutex lock;
bool connected;
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.c 
b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
index eb3042c..b2f532a 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-reg.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
@@ -221,7 +221,11 @@ static int cdn_dp_reg_write_bit(struct cdn_dp_device *dp, 
u16 addr,
   s

[PATCH 4/4] drm/rockchip: support dp training outside dp firmware

2018-05-05 Thread Lin Huang
DP firware use fix phy config value to do training, but some
board need to adjust these value to fit for their hardware design,
so we use new phy config to do training outside firmware to meet
this situation, if there have new phy config pass from dts, it will
use training outside firmware.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
Signed-off-by: Lin Huang <h...@rock-chips.com>
---
 drivers/gpu/drm/rockchip/Makefile   |   3 +-
 drivers/gpu/drm/rockchip/cdn-dp-core.c  |  23 +-
 drivers/gpu/drm/rockchip/cdn-dp-core.h  |   2 +
 drivers/gpu/drm/rockchip/cdn-dp-link-training.c | 398 
 drivers/gpu/drm/rockchip/cdn-dp-reg.c   |  33 +-
 drivers/gpu/drm/rockchip/cdn-dp-reg.h   |  38 ++-
 6 files changed, 480 insertions(+), 17 deletions(-)
 create mode 100644 drivers/gpu/drm/rockchip/cdn-dp-link-training.c

diff --git a/drivers/gpu/drm/rockchip/Makefile 
b/drivers/gpu/drm/rockchip/Makefile
index a314e21..b932f62 100644
--- a/drivers/gpu/drm/rockchip/Makefile
+++ b/drivers/gpu/drm/rockchip/Makefile
@@ -9,7 +9,8 @@ rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \
 rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o
 
 rockchipdrm-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o
-rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o
+rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o \
+   cdn-dp-link-training.o
 rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o
 rockchipdrm-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi.o
 rockchipdrm-$(CONFIG_ROCKCHIP_INNO_HDMI) += inno_hdmi.o
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c 
b/drivers/gpu/drm/rockchip/cdn-dp-core.c
index 268c190..a2a4208 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -629,11 +629,13 @@ static void cdn_dp_encoder_enable(struct drm_encoder 
*encoder)
goto out;
}
}
-
-   ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_IDLE);
-   if (ret) {
-   DRM_DEV_ERROR(dp->dev, "Failed to idle video %d\n", ret);
-   goto out;
+   if (dp->sw_training_success == false) {
+   ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_IDLE);
+   if (ret) {
+   DRM_DEV_ERROR(dp->dev,
+ "Failed to idle video %d\n", ret);
+   goto out;
+   }
}
 
ret = cdn_dp_config_video(dp);
@@ -642,11 +644,14 @@ static void cdn_dp_encoder_enable(struct drm_encoder 
*encoder)
goto out;
}
 
-   ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_VALID);
-   if (ret) {
-   DRM_DEV_ERROR(dp->dev, "Failed to valid video %d\n", ret);
-   goto out;
+   if (dp->sw_training_success == false) {
+   ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_VALID);
+   if (ret) {
+   DRM_DEV_ERROR(dp->dev, "Failed to valid video %d\n", 
ret);
+   goto out;
+   }
}
+
 out:
mutex_unlock(>lock);
 }
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.h 
b/drivers/gpu/drm/rockchip/cdn-dp-core.h
index 46159b2..c6050ab 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.h
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.h
@@ -84,6 +84,7 @@ struct cdn_dp_device {
bool connected;
bool active;
bool suspended;
+   bool sw_training_success;
 
const struct firmware *fw;  /* cdn dp firmware */
unsigned int fw_version;/* cdn fw version */
@@ -106,6 +107,7 @@ struct cdn_dp_device {
u8 ports;
u8 lanes;
int active_port;
+   u8 train_set[4];
 
u8 dpcd[DP_RECEIVER_CAP_SIZE];
bool sink_has_audio;
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-link-training.c 
b/drivers/gpu/drm/rockchip/cdn-dp-link-training.c
new file mode 100644
index 000..558c945
--- /dev/null
+++ b/drivers/gpu/drm/rockchip/cdn-dp-link-training.c
@@ -0,0 +1,398 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
+ * Author: Chris Zhong <z...@rock-chips.com>
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "cdn-dp-core.h"
+#include "cdn-dp-reg.h"
+
+static void cdn_dp_set_signal_levels(struct cdn_dp_device *dp)
+{
+   struct cdn_dp_port *port = dp->port[dp->active_port];
+   struct rockchip_typec_phy *tcphy = phy_get_drvdata(port->phy);
+
+   int rate = drm_dp_bw_code_to_link_rate(dp->link.rate);
+   u8 swing = (dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) >>
+  DP_TRAIN_VOLTAGE_SWING_SHIFT;
+   u8 pre_emphasis

[PATCH 2/4] phy: rockchip-typec: support variable phy config value

2018-05-05 Thread Lin Huang
the phy config values used to fix in dp firmware, but some boards
need change these values to do training and get the better eye diagram
result. So support that in phy driver.

Signed-off-by: Chris Zhong <z...@rock-chips.com>
Signed-off-by: Lin Huang <h...@rock-chips.com>
---
 drivers/phy/rockchip/phy-rockchip-typec.c | 286 +++---
 include/soc/rockchip/rockchip_phy_typec.h |  72 
 2 files changed, 259 insertions(+), 99 deletions(-)
 create mode 100644 include/soc/rockchip/rockchip_phy_typec.h

diff --git a/drivers/phy/rockchip/phy-rockchip-typec.c 
b/drivers/phy/rockchip/phy-rockchip-typec.c
index 76a4b58..831a93b 100644
--- a/drivers/phy/rockchip/phy-rockchip-typec.c
+++ b/drivers/phy/rockchip/phy-rockchip-typec.c
@@ -63,6 +63,7 @@
 
 #include 
 #include 
+#include 
 
 #define CMN_SSM_BANDGAP(0x21 << 2)
 #define CMN_SSM_BIAS   (0x22 << 2)
@@ -323,23 +324,31 @@
  * clock 0: PLL 0 div 1
  * clock 1: PLL 1 div 2
  */
-#define CLK_PLL_CONFIG 0X30
+#define CLK_PLL1_DIV1  0x20
+#define CLK_PLL1_DIV2  0x30
 #define CLK_PLL_MASK   0x33
 
 #define CMN_READY  BIT(0)
 
+#define DP_PLL_CLOCK_ENABLE_ACKBIT(3)
 #define DP_PLL_CLOCK_ENABLEBIT(2)
+#define DP_PLL_ENABLE_ACK  BIT(1)
 #define DP_PLL_ENABLE  BIT(0)
 #define DP_PLL_DATA_RATE_RBR   ((2 << 12) | (4 << 8))
 #define DP_PLL_DATA_RATE_HBR   ((2 << 12) | (4 << 8))
 #define DP_PLL_DATA_RATE_HBR2  ((1 << 12) | (2 << 8))
+#define DP_PLL_DATA_RATE_MASK  0xff00
 
-#define DP_MODE_A0 BIT(4)
-#define DP_MODE_A2 BIT(6)
-#define DP_MODE_ENTER_A0   0xc101
-#define DP_MODE_ENTER_A2   0xc104
+#define DP_MODE_MASK   0xf
+#define DP_MODE_ENTER_A0   BIT(0)
+#define DP_MODE_ENTER_A2   BIT(2)
+#define DP_MODE_ENTER_A3   BIT(3)
+#define DP_MODE_A0_ACK BIT(4)
+#define DP_MODE_A2_ACK BIT(6)
+#define DP_MODE_A3_ACK BIT(7)
+#define DP_LINK_RESET_DEASSERTED   BIT(8)
 
-#define PHY_MODE_SET_TIMEOUT   10
+#define PHY_MODE_SET_TIMEOUT   100
 
 #define PIN_ASSIGN_C_E 0x51d9
 #define PIN_ASSIGN_D_F 0x5100
@@ -349,51 +358,7 @@
 #define MODE_DFP_USB   BIT(1)
 #define MODE_DFP_DPBIT(2)
 
-struct usb3phy_reg {
-   u32 offset;
-   u32 enable_bit;
-   u32 write_enable;
-};
-
-/**
- * struct rockchip_usb3phy_port_cfg: usb3-phy port configuration.
- * @reg: the base address for usb3-phy config.
- * @typec_conn_dir: the register of type-c connector direction.
- * @usb3tousb2_en: the register of type-c force usb2 to usb2 enable.
- * @external_psm: the register of type-c phy external psm clock.
- * @pipe_status: the register of type-c phy pipe status.
- * @usb3_host_disable: the register of type-c usb3 host disable.
- * @usb3_host_port: the register of type-c usb3 host port.
- * @uphy_dp_sel: the register of type-c phy DP select control.
- */
-struct rockchip_usb3phy_port_cfg {
-   unsigned int reg;
-   struct usb3phy_reg typec_conn_dir;
-   struct usb3phy_reg usb3tousb2_en;
-   struct usb3phy_reg external_psm;
-   struct usb3phy_reg pipe_status;
-   struct usb3phy_reg usb3_host_disable;
-   struct usb3phy_reg usb3_host_port;
-   struct usb3phy_reg uphy_dp_sel;
-};
-
-struct rockchip_typec_phy {
-   struct device *dev;
-   void __iomem *base;
-   struct extcon_dev *extcon;
-   struct regmap *grf_regs;
-   struct clk *clk_core;
-   struct clk *clk_ref;
-   struct reset_control *uphy_rst;
-   struct reset_control *pipe_rst;
-   struct reset_control *tcphy_rst;
-   const struct rockchip_usb3phy_port_cfg *port_cfgs;
-   /* mutex to protect access to individual PHYs */
-   struct mutex lock;
-
-   bool flip;
-   u8 mode;
-};
+#define DEFAULT_RATE   162000
 
 struct phy_reg {
u16 value;
@@ -417,15 +382,15 @@ struct phy_reg usb3_pll_cfg[] = {
{ 0x8,  CMN_DIAG_PLL0_LF_PROG },
 };
 
-struct phy_reg dp_pll_cfg[] = {
+struct phy_reg dp_pll_rbr_cfg[] = {
{ 0xf0, CMN_PLL1_VCOCAL_INIT },
{ 0x18, CMN_PLL1_VCOCAL_ITER },
{ 0x30b9,   CMN_PLL1_VCOCAL_START },
-   { 0x21c,CMN_PLL1_INTDIV },
+   { 0x87, CMN_PLL1_INTDIV },
{ 0,CMN_PLL1_FRACDIV },
-   { 0x5,  CMN_PLL1_HIGH_THR },
-   { 0x35, CMN_PLL1_SS_CTRL1 },
-   { 0x7f1e,   CMN_PLL1_SS_CTRL2 },
+   { 0x22, CMN_PLL1_HIGH_THR },
+   { 0x8000,   CMN_PLL1_SS_CTRL1 },
+   { 0,CMN_PLL1_SS_CTRL2 },
{ 0x20, CMN_PLL1_

[PATCH 3/4] Documentation: bindings: add phy_config for Rockchip USB Type-C PHY

2018-05-05 Thread Lin Huang
If want to do training outside DP Firmware, need phy voltage swing
and pre_emphasis value.

Signed-off-by: Lin Huang <h...@rock-chips.com>
---
 Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt 
b/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
index 960da7f..eda26dd 100644
--- a/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
+++ b/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
@@ -17,7 +17,9 @@ Required properties:
 
 Optional properties:
  - extcon : extcon specifier for the Power Delivery
-
+ - rockchip,phy_config : That's phy voltage swing and pre_emphasis
+setting, if want to do dp training outside
+dp firmware, need to add these value.
 Required nodes : a sub-node is required for each port the phy provides.
 The sub-node name is used to identify dp or usb3 port,
 and shall be the following entries:
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v4 1/3] drm/panel: refactor INNOLUX P079ZCA panel driver

2018-03-15 Thread Lin Huang
From: huang lin <h...@rock-chips.com>

Refactor Innolux P079ZCA panel driver, let it support
multi panel.

Change-Id: If89be5e56dba8cb498e2d50c1bbeb0e8016123a2
Signed-off-by: Lin Huang <h...@rock-chips.com>
---
Changes in v2:
- Change regulator property name to meet the panel datasheet 
Changes in v3:
- this patch only refactor P079ZCA panel to support multi panel, support 
P097PFG panel in another patch 
Changes in v4:
- Modify the patch which suggest by Thierry
 
 drivers/gpu/drm/panel/panel-innolux-p079zca.c | 142 ++
 1 file changed, 101 insertions(+), 41 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-innolux-p079zca.c 
b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
index 57df39b..2075a9d 100644
--- a/drivers/gpu/drm/panel/panel-innolux-p079zca.c
+++ b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
@@ -20,12 +20,28 @@
 
 #include 
 
+struct panel_desc {
+   const struct drm_display_mode *modes;
+   unsigned int bpc;
+   struct {
+   unsigned int width;
+   unsigned int height;
+   } size;
+
+   unsigned long flags;
+   enum mipi_dsi_pixel_format format;
+   unsigned int lanes;
+};
+
 struct innolux_panel {
struct drm_panel base;
struct mipi_dsi_device *link;
+   const struct panel_desc *desc;
 
struct backlight_device *backlight;
-   struct regulator *supply;
+   struct regulator *vddi;
+   struct regulator *avdd;
+   struct regulator *avee;
struct gpio_desc *enable_gpio;
 
bool prepared;
@@ -77,9 +93,9 @@ static int innolux_panel_unprepare(struct drm_panel *panel)
/* T8: 80ms - 1000ms */
msleep(80);
 
-   err = regulator_disable(innolux->supply);
-   if (err < 0)
-   return err;
+   regulator_disable(innolux->avee);
+   regulator_disable(innolux->avdd);
+   regulator_disable(innolux->vddi);
 
innolux->prepared = false;
 
@@ -89,17 +105,25 @@ static int innolux_panel_unprepare(struct drm_panel *panel)
 static int innolux_panel_prepare(struct drm_panel *panel)
 {
struct innolux_panel *innolux = to_innolux_panel(panel);
-   int err, regulator_err;
+   int err;
 
if (innolux->prepared)
return 0;
 
gpiod_set_value_cansleep(innolux->enable_gpio, 0);
 
-   err = regulator_enable(innolux->supply);
+   err = regulator_enable(innolux->vddi);
if (err < 0)
return err;
 
+   err = regulator_enable(innolux->avdd);
+   if (err < 0)
+   goto disable_vddi;
+
+   err = regulator_enable(innolux->avee);
+   if (err < 0)
+   goto disable_avdd;
+
/* T2: 15ms - 1000ms */
usleep_range(15000, 16000);
 
@@ -133,12 +157,13 @@ static int innolux_panel_prepare(struct drm_panel *panel)
return 0;
 
 poweroff:
-   regulator_err = regulator_disable(innolux->supply);
-   if (regulator_err)
-   DRM_DEV_ERROR(panel->dev, "failed to disable regulator: %d\n",
- regulator_err);
-
gpiod_set_value_cansleep(innolux->enable_gpio, 0);
+   regulator_disable(innolux->avee);
+disable_avdd:
+   regulator_disable(innolux->avdd);
+disable_vddi:
+   regulator_disable(innolux->vddi);
+
return err;
 }
 
@@ -162,7 +187,7 @@ static int innolux_panel_enable(struct drm_panel *panel)
return 0;
 }
 
-static const struct drm_display_mode default_mode = {
+static const struct drm_display_mode innolux_p079zca_mode = {
.clock = 56900,
.hdisplay = 768,
.hsync_start = 768 + 40,
@@ -175,15 +200,29 @@ static const struct drm_display_mode default_mode = {
.vrefresh = 60,
 };
 
+static const struct panel_desc innolux_p079zca_panel_desc = {
+   .modes = _p079zca_mode,
+   .bpc = 8,
+   .size = {
+   .width = 120,
+   .height = 160,
+   },
+   .flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
+MIPI_DSI_MODE_LPM,
+   .format = MIPI_DSI_FMT_RGB888,
+   .lanes = 4,
+};
+
 static int innolux_panel_get_modes(struct drm_panel *panel)
 {
struct drm_display_mode *mode;
+   struct innolux_panel *innolux = to_innolux_panel(panel);
+   const struct drm_display_mode *m = innolux->desc->modes;
 
-   mode = drm_mode_duplicate(panel->drm, _mode);
+   mode = drm_mode_duplicate(panel->drm, m);
if (!mode) {
DRM_DEV_ERROR(panel->drm->dev, "failed to add mode %ux%ux@%u\n",
- default_mode.hdisplay, default_mode.vdisplay,
- default_mode.vrefresh);
+ m->hdisplay, m->vdisplay, m->vrefresh);
return -ENOMEM;
}
 
@@ -191,9 +230,11 @@ static int innolux_panel_get_modes(struct drm_pa

[PATCH v4 2/3] drm/panel: support Innolux P097PFG panel

2018-03-15 Thread Lin Huang
Support Innolux P097PFG 9.7" 1536x2048 TFT LCD panel, it reuse
the Innolux P079ZCA panel driver.

Change-Id: I97923aa3735f707332681691b0231c9421b427d0
Signed-off-by: Lin Huang <h...@rock-chips.com>
---
Changes in v2:
- None
Changes in v3:
- None
Changes in v4:
- download panel initial code 

 drivers/gpu/drm/panel/panel-innolux-p079zca.c | 192 +-
 1 file changed, 187 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-innolux-p079zca.c 
b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
index 2075a9d..883b279 100644
--- a/drivers/gpu/drm/panel/panel-innolux-p079zca.c
+++ b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
@@ -20,6 +20,15 @@
 
 #include 
 
+struct panel_init_cmd {
+   int len;
+   const char *data;
+};
+
+#define _INIT_CMD(...) { \
+   .len = sizeof((char[]){__VA_ARGS__}), \
+   .data = (char[]){__VA_ARGS__} }
+
 struct panel_desc {
const struct drm_display_mode *modes;
unsigned int bpc;
@@ -30,6 +39,7 @@ struct panel_desc {
 
unsigned long flags;
enum mipi_dsi_pixel_format format;
+   const struct panel_init_cmd *init_cmds;
unsigned int lanes;
 };
 
@@ -88,9 +98,12 @@ static int innolux_panel_unprepare(struct drm_panel *panel)
return err;
}
 
+   /* p097pfg: t15 */
+   msleep(100);
+
gpiod_set_value_cansleep(innolux->enable_gpio, 0);
 
-   /* T8: 80ms - 1000ms */
+   /* p079zca: t8*/
msleep(80);
 
regulator_disable(innolux->avee);
@@ -124,13 +137,43 @@ static int innolux_panel_prepare(struct drm_panel *panel)
if (err < 0)
goto disable_avdd;
 
-   /* T2: 15ms - 1000ms */
-   usleep_range(15000, 16000);
+   /* p079zca: t2 (20ms), p097pfg: t4 (15ms) */
+   usleep_range(2, 21000);
 
gpiod_set_value_cansleep(innolux->enable_gpio, 1);
 
-   /* T4: 15ms - 1000ms */
-   usleep_range(15000, 16000);
+   /* p079zca: t4, p097pfg: t5 */
+   usleep_range(2, 21000);
+
+   if (innolux->desc->init_cmds) {
+   const struct panel_init_cmd *cmds =
+   innolux->desc->init_cmds;
+   int i;
+
+   for (i = 0; cmds[i].len != 0; i++) {
+   const struct panel_init_cmd *cmd = [i];
+
+   err = mipi_dsi_generic_write(innolux->link, cmd->data,
+cmd->len);
+   if (err < 0) {
+   dev_err(panel->dev,
+   "failed to write command %d\n", i);
+   goto poweroff;
+   }
+
+   /*
+* Included by random guessing, because without this
+* (or at least, some delay), the panel sometimes
+* didn't appear to pick up the command sequence.
+*/
+   err = mipi_dsi_dcs_nop(innolux->link);
+   if (err < 0) {
+   dev_err(panel->dev,
+   "failed to send DCS nop: %d\n", err);
+   goto poweroff;
+   }
+   }
+   }
 
err = mipi_dsi_dcs_exit_sleep_mode(innolux->link);
if (err < 0) {
@@ -213,6 +256,142 @@ static const struct panel_desc innolux_p079zca_panel_desc 
= {
.lanes = 4,
 };
 
+static const struct drm_display_mode innolux_p097pfg_mode = {
+   .clock = 229000,
+   .hdisplay = 1536,
+   .hsync_start = 1536 + 100,
+   .hsync_end = 1536 + 100 + 24,
+   .htotal = 1536 + 100 + 24 + 100,
+   .vdisplay = 2048,
+   .vsync_start = 2048 + 100,
+   .vsync_end = 2048 + 100 + 2,
+   .vtotal = 2048 + 100 + 2 + 18,
+   .vrefresh = 60,
+};
+
+static const struct panel_init_cmd innolux_p097pfg_init_cmds[] = {
+   /* page 0 */
+   _INIT_CMD(0xF0, 0x55, 0xAA, 0x52, 0x08, 0x00),
+   _INIT_CMD(0xB1, 0xE8, 0x11),
+   _INIT_CMD(0xB2, 0x25, 0x02),
+   _INIT_CMD(0xB5, 0x08, 0x00),
+   _INIT_CMD(0xBC, 0x0F, 0x00),
+   _INIT_CMD(0xB8, 0x03, 0x06, 0x00, 0x00),
+   _INIT_CMD(0xBD, 0x01, 0x90, 0x14, 0x14),
+   _INIT_CMD(0x6F, 0x01),
+   _INIT_CMD(0xC0, 0x03),
+   _INIT_CMD(0x6F, 0x02),
+   _INIT_CMD(0xC1, 0x0D),
+   _INIT_CMD(0xD9, 0x01, 0x09, 0x70),
+   _INIT_CMD(0xC5, 0x12, 0x21, 0x00),
+   _INIT_CMD(0xBB, 0x93, 0x93),
+
+   /* page 1 */
+   _INIT_CMD(0xF0, 0x55, 0xAA, 0x52, 0x08, 0x01),
+   _INIT_CMD(0xB3, 0x3C, 0x3C),
+   _INIT_CMD(0xB4, 0x0F, 0x0F),
+   _INIT_CMD(0xB9, 0x45, 0x45),
+   _INIT_CMD(0xBA, 0x14, 0x14),
+   _INIT_CMD(0xCA, 0x02),
+   _INIT_CMD(0xCE, 0x04),
+   _INIT_CMD(0xC3, 0x9B, 0x9B),
+   _INIT_CMD(0xD8,

[PATCH v4 3/3] dt-bindings: Add INNOLUX P097PFG panel bindings

2018-03-15 Thread Lin Huang
From: huang lin <h...@rock-chips.com>

The Innolux P097PFG panel is 9.7" panel with 1536X2048
resolution, it reuse P079ZCA panel driver, so improve
p079ZCA dt-binding to support P097PFG.

Change-Id: I8704914898fe53b734d31fbe646df8aa5fd8b30d
Signed-off-by: Lin Huang <h...@rock-chips.com>
---
Changes in v2:
- None
Changes in v3:
- None
Changes in v4:
- None

 .../devicetree/bindings/display/panel/innolux,p079zca.txt | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git 
a/Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt 
b/Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt
index d0f5516..8cadd8c 100644
--- a/Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt
+++ b/Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt
@@ -1,13 +1,18 @@
 Innolux P079ZCA 7.85" 768x1024 TFT LCD panel
+Innolux P097PFG 9.7" 1536x2048 TFT LCD panel
 
 Required properties:
-- compatible: should be "innolux,p079zca"
+- compatible: should be should be one of the following.
+-"innolux,p079zca" for Innolux 7.9" P079ZCA 768*1024 panel
+-"innolux,p097pfg" for Innolux 9.7" P097PFG 1536*2048 panel
 - reg: DSI virtual channel of the peripheral
-- power-supply: phandle of the regulator that provides the supply voltage
 - enable-gpios: panel enable gpio
 
 Optional properties:
 - backlight: phandle of the backlight device attached to the panel
+- power-supply: phandle of the regulator that provides the supply voltage
+- avdd-supply: phandle of the regulator that provides positive voltage
+- avee-supply: phandle of the regulator that provides negative voltage
 
 Example:
 
@@ -16,6 +21,8 @@ Example:
compatible = "innolux,p079zca";
reg = <0>;
power-supply = <...>;
+   avdd-supply = <...>;
+   avee-supply = <...>;
backlight = <>;
enable-gpios = < 13 GPIO_ACTIVE_HIGH>;
};
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v3 2/3] drm/panel: support Innolux P097PFG panel

2017-12-04 Thread Lin Huang
Support Innolux P097PFG 9.7" 1536x2048 TFT LCD panel, it reuse
the Innolux P079ZCA panel driver.

Signed-off-by: Lin Huang <h...@rock-chips.com>
---
 drivers/gpu/drm/panel/Kconfig |  9 
 drivers/gpu/drm/panel/panel-innolux-p079zca.c | 31 +++
 2 files changed, 35 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index 726f3fb..429cf59 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -29,15 +29,14 @@ config DRM_PANEL_SIMPLE
  low power state.
 
 config DRM_PANEL_INNOLUX_P079ZCA
-   tristate "Innolux P079ZCA panel"
+   tristate "Innolux P079ZCA or P097PFG panel"
depends on OF
depends on DRM_MIPI_DSI
depends on BACKLIGHT_CLASS_DEVICE
help
- Say Y here if you want to enable support for Innolux P079ZCA
- TFT-LCD modules. The panel has a 1024x768 resolution and uses
- 24 bit RGB per pixel. It provides a MIPI DSI interface to
- the host and has a built-in LED backlight.
+ Say Y here if you want to enable support for Innolux P079ZCA or
+ Innolux P097PFG panel. They provide a MIPI DSI interface to
+ the host and have a built-in LED backlight.
 
 config DRM_PANEL_JDI_LT070ME05000
tristate "JDI LT070ME05000 WUXGA DSI panel"
diff --git a/drivers/gpu/drm/panel/panel-innolux-p079zca.c 
b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
index 1597744..5d690b7 100644
--- a/drivers/gpu/drm/panel/panel-innolux-p079zca.c
+++ b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
@@ -221,6 +221,34 @@ static const struct panel_desc_dsi 
innolux_p079zca_panel_desc = {
.lanes = 4,
 };
 
+static const struct drm_display_mode innolux_p097pfg_mode = {
+   .clock = 22,
+   .hdisplay = 1536,
+   .hsync_start = 1536 + 100,
+   .hsync_end = 1536 + 100 + 24,
+   .htotal = 1536 + 100 + 24 + 100,
+   .vdisplay = 2048,
+   .vsync_start = 2048 + 18,
+   .vsync_end = 2048 + 18 + 2,
+   .vtotal = 2048 + 18 + 2 + 18,
+   .vrefresh = 60,
+};
+
+static const struct panel_desc_dsi innolux_p097pfg_panel_desc = {
+   .desc = {
+   .modes = _p097pfg_mode,
+   .bpc = 8,
+   .size = {
+   .width = 147,
+   .height = 196,
+   },
+   },
+   .flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
+MIPI_DSI_MODE_LPM,
+   .format = MIPI_DSI_FMT_RGB888,
+   .lanes = 8,
+};
+
 static int innolux_panel_get_modes(struct drm_panel *panel)
 {
struct drm_display_mode *mode;
@@ -259,6 +287,9 @@ static const struct of_device_id innolux_of_match[] = {
{ .compatible = "innolux,p079zca",
  .data = _p079zca_panel_desc
},
+   { .compatible = "innolux,p097pfg",
+ .data = _p097pfg_panel_desc
+   }
 };
 MODULE_DEVICE_TABLE(of, innolux_of_match);
 
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[RESEND PATCH v3 2/3] drm/panel: support Innolux P097PFG panel

2017-12-04 Thread Lin Huang
Support Innolux P097PFG 9.7" 1536x2048 TFT LCD panel, it reuse
the Innolux P079ZCA panel driver.

Signed-off-by: Lin Huang <h...@rock-chips.com>
---
 drivers/gpu/drm/panel/Kconfig |  9 
 drivers/gpu/drm/panel/panel-innolux-p079zca.c | 31 +++
 2 files changed, 35 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index 726f3fb..429cf59 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -29,15 +29,14 @@ config DRM_PANEL_SIMPLE
  low power state.
 
 config DRM_PANEL_INNOLUX_P079ZCA
-   tristate "Innolux P079ZCA panel"
+   tristate "Innolux P079ZCA or P097PFG panel"
depends on OF
depends on DRM_MIPI_DSI
depends on BACKLIGHT_CLASS_DEVICE
help
- Say Y here if you want to enable support for Innolux P079ZCA
- TFT-LCD modules. The panel has a 1024x768 resolution and uses
- 24 bit RGB per pixel. It provides a MIPI DSI interface to
- the host and has a built-in LED backlight.
+ Say Y here if you want to enable support for Innolux P079ZCA or
+ Innolux P097PFG panel. They provide a MIPI DSI interface to
+ the host and have a built-in LED backlight.
 
 config DRM_PANEL_JDI_LT070ME05000
tristate "JDI LT070ME05000 WUXGA DSI panel"
diff --git a/drivers/gpu/drm/panel/panel-innolux-p079zca.c 
b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
index 1597744..5d690b7 100644
--- a/drivers/gpu/drm/panel/panel-innolux-p079zca.c
+++ b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
@@ -221,6 +221,34 @@ static const struct panel_desc_dsi 
innolux_p079zca_panel_desc = {
.lanes = 4,
 };
 
+static const struct drm_display_mode innolux_p097pfg_mode = {
+   .clock = 22,
+   .hdisplay = 1536,
+   .hsync_start = 1536 + 100,
+   .hsync_end = 1536 + 100 + 24,
+   .htotal = 1536 + 100 + 24 + 100,
+   .vdisplay = 2048,
+   .vsync_start = 2048 + 18,
+   .vsync_end = 2048 + 18 + 2,
+   .vtotal = 2048 + 18 + 2 + 18,
+   .vrefresh = 60,
+};
+
+static const struct panel_desc_dsi innolux_p097pfg_panel_desc = {
+   .desc = {
+   .modes = _p097pfg_mode,
+   .bpc = 8,
+   .size = {
+   .width = 147,
+   .height = 196,
+   },
+   },
+   .flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
+MIPI_DSI_MODE_LPM,
+   .format = MIPI_DSI_FMT_RGB888,
+   .lanes = 8,
+};
+
 static int innolux_panel_get_modes(struct drm_panel *panel)
 {
struct drm_display_mode *mode;
@@ -259,6 +287,9 @@ static const struct of_device_id innolux_of_match[] = {
{ .compatible = "innolux,p079zca",
  .data = _p079zca_panel_desc
},
+   { .compatible = "innolux,p097pfg",
+ .data = _p097pfg_panel_desc
+   }
 };
 MODULE_DEVICE_TABLE(of, innolux_of_match);
 
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[RESEND PATCH v3 1/3] drm/panel: refactor INNOLUX P079ZCA panel driver

2017-12-04 Thread Lin Huang
Refactor Innolux P079ZCA panel driver, let it support
multi panel.

Signed-off-by: Lin Huang <h...@rock-chips.com>
---
Changes in v2:
- Change regulator property name to meet the panel datasheet 
Changes in v3:
- this patch only refactor P079ZCA panel to support multi panel, support 
P097PFG panel in another patch 

 drivers/gpu/drm/panel/panel-innolux-p079zca.c | 147 ++
 1 file changed, 105 insertions(+), 42 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-innolux-p079zca.c 
b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
index 6ba9344..1597744 100644
--- a/drivers/gpu/drm/panel/panel-innolux-p079zca.c
+++ b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
@@ -20,12 +20,32 @@
 
 #include 
 
+struct panel_desc {
+   const struct drm_display_mode *modes;
+   unsigned int bpc;
+   struct {
+   unsigned int width;
+   unsigned int height;
+   } size;
+};
+
+struct panel_desc_dsi {
+   struct panel_desc desc;
+
+   unsigned long flags;
+   enum mipi_dsi_pixel_format format;
+   unsigned int lanes;
+};
+
 struct innolux_panel {
struct drm_panel base;
struct mipi_dsi_device *link;
+   const struct panel_desc_dsi *dsi_desc;
 
struct backlight_device *backlight;
-   struct regulator *supply;
+   struct regulator *vddi;
+   struct regulator *avdd;
+   struct regulator *avee;
struct gpio_desc *enable_gpio;
 
bool prepared;
@@ -78,9 +98,9 @@ static int innolux_panel_unprepare(struct drm_panel *panel)
/* T8: 80ms - 1000ms */
msleep(80);
 
-   err = regulator_disable(innolux->supply);
-   if (err < 0)
-   return err;
+   regulator_disable(innolux->avee);
+   regulator_disable(innolux->avdd);
+   regulator_disable(innolux->vddi);
 
innolux->prepared = false;
 
@@ -97,10 +117,18 @@ static int innolux_panel_prepare(struct drm_panel *panel)
 
gpiod_set_value_cansleep(innolux->enable_gpio, 0);
 
-   err = regulator_enable(innolux->supply);
+   err = regulator_enable(innolux->vddi);
if (err < 0)
return err;
 
+   err = regulator_enable(innolux->avdd);
+   if (err < 0)
+   goto disable_vddi;
+
+   err = regulator_enable(innolux->avee);
+   if (err < 0)
+   goto disable_avdd;
+
/* T2: 15ms - 1000ms */
usleep_range(15000, 16000);
 
@@ -134,12 +162,13 @@ static int innolux_panel_prepare(struct drm_panel *panel)
return 0;
 
 poweroff:
-   regulator_err = regulator_disable(innolux->supply);
-   if (regulator_err)
-   DRM_DEV_ERROR(panel->dev, "failed to disable regulator: %d\n",
- regulator_err);
-
gpiod_set_value_cansleep(innolux->enable_gpio, 0);
+   regulator_disable(innolux->avee);
+disable_avdd:
+   regulator_disable(innolux->avdd);
+disable_vddi:
+   regulator_disable(innolux->vddi);
+
return err;
 }
 
@@ -164,7 +193,7 @@ static int innolux_panel_enable(struct drm_panel *panel)
return 0;
 }
 
-static const struct drm_display_mode default_mode = {
+static const struct drm_display_mode innolux_p079zca_mode = {
.clock = 56900,
.hdisplay = 768,
.hsync_start = 768 + 40,
@@ -177,15 +206,31 @@ static const struct drm_display_mode default_mode = {
.vrefresh = 60,
 };
 
+static const struct panel_desc_dsi innolux_p079zca_panel_desc = {
+   .desc = {
+   .modes = _p079zca_mode,
+   .bpc = 8,
+   .size = {
+   .width = 120,
+   .height = 160,
+   },
+   },
+   .flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
+MIPI_DSI_MODE_LPM,
+   .format = MIPI_DSI_FMT_RGB888,
+   .lanes = 4,
+};
+
 static int innolux_panel_get_modes(struct drm_panel *panel)
 {
struct drm_display_mode *mode;
+   struct innolux_panel *innolux = to_innolux_panel(panel);
+   const struct drm_display_mode *m = innolux->dsi_desc->desc.modes;
 
-   mode = drm_mode_duplicate(panel->drm, _mode);
+   mode = drm_mode_duplicate(panel->drm, m);
if (!mode) {
DRM_DEV_ERROR(panel->drm->dev, "failed to add mode %ux%ux@%u\n",
- default_mode.hdisplay, default_mode.vdisplay,
- default_mode.vrefresh);
+ m->hdisplay, m->vdisplay, m->vrefresh);
return -ENOMEM;
}
 
@@ -193,9 +238,11 @@ static int innolux_panel_get_modes(struct drm_panel *panel)
 
drm_mode_probed_add(panel->connector, mode);
 
-   panel->connector->display_info.width_mm = 120;
-   panel->connector->display_info.height_mm = 160;
-   panel->connector->display_info.bpc = 8;

[RESEND PATCH v3 3/3] dt-bindings: Add INNOLUX P097PFG panel bindings

2017-12-04 Thread Lin Huang
The Innolux P097PFG panel is 9.7" panel with 1536X2048
resolution, it reuse P079ZCA panel driver, so improve
p079ZCA dt-binding to support P097PFG.

Signed-off-by: Lin Huang <h...@rock-chips.com>
---
 .../devicetree/bindings/display/panel/innolux,p079zca.txt | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git 
a/Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt 
b/Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt
index d0f5516..8cadd8c 100644
--- a/Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt
+++ b/Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt
@@ -1,13 +1,18 @@
 Innolux P079ZCA 7.85" 768x1024 TFT LCD panel
+Innolux P097PFG 9.7" 1536x2048 TFT LCD panel
 
 Required properties:
-- compatible: should be "innolux,p079zca"
+- compatible: should be should be one of the following.
+-"innolux,p079zca" for Innolux 7.9" P079ZCA 768*1024 panel
+-"innolux,p097pfg" for Innolux 9.7" P097PFG 1536*2048 panel
 - reg: DSI virtual channel of the peripheral
-- power-supply: phandle of the regulator that provides the supply voltage
 - enable-gpios: panel enable gpio
 
 Optional properties:
 - backlight: phandle of the backlight device attached to the panel
+- power-supply: phandle of the regulator that provides the supply voltage
+- avdd-supply: phandle of the regulator that provides positive voltage
+- avee-supply: phandle of the regulator that provides negative voltage
 
 Example:
 
@@ -16,6 +21,8 @@ Example:
compatible = "innolux,p079zca";
reg = <0>;
power-supply = <...>;
+   avdd-supply = <...>;
+   avee-supply = <...>;
backlight = <>;
enable-gpios = < 13 GPIO_ACTIVE_HIGH>;
};
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v3 3/3] dt-bindings: Add INNOLUX P097PFG panel bindings

2017-12-04 Thread Lin Huang
The Innolux P097PFG panel is 9.7" panel with 1536X2048
resolution, it reuse P079ZCA panel driver, so improve
p079ZCA dt-binding to support P097PFG.

Change-Id: I8704914898fe53b734d31fbe646df8aa5fd8b30d
Signed-off-by: Lin Huang <h...@rock-chips.com>
---
 .../devicetree/bindings/display/panel/innolux,p079zca.txt | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git 
a/Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt 
b/Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt
index d0f5516..8cadd8c 100644
--- a/Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt
+++ b/Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt
@@ -1,13 +1,18 @@
 Innolux P079ZCA 7.85" 768x1024 TFT LCD panel
+Innolux P097PFG 9.7" 1536x2048 TFT LCD panel
 
 Required properties:
-- compatible: should be "innolux,p079zca"
+- compatible: should be should be one of the following.
+-"innolux,p079zca" for Innolux 7.9" P079ZCA 768*1024 panel
+-"innolux,p097pfg" for Innolux 9.7" P097PFG 1536*2048 panel
 - reg: DSI virtual channel of the peripheral
-- power-supply: phandle of the regulator that provides the supply voltage
 - enable-gpios: panel enable gpio
 
 Optional properties:
 - backlight: phandle of the backlight device attached to the panel
+- power-supply: phandle of the regulator that provides the supply voltage
+- avdd-supply: phandle of the regulator that provides positive voltage
+- avee-supply: phandle of the regulator that provides negative voltage
 
 Example:
 
@@ -16,6 +21,8 @@ Example:
compatible = "innolux,p079zca";
reg = <0>;
power-supply = <...>;
+   avdd-supply = <...>;
+   avee-supply = <...>;
backlight = <>;
enable-gpios = < 13 GPIO_ACTIVE_HIGH>;
};
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v3 1/3] drm/panel: refactor INNOLUX P079ZCA panel driver

2017-12-04 Thread Lin Huang
Refactor Innolux P079ZCA panel driver, let it support
multi panel.

Signed-off-by: Lin Huang <h...@rock-chips.com>
---
Changes in v2:
- Change regulator property name to meet the panel datasheet 
Changes in v3:
- this patch only refactor P079ZCA panel to support multi panel, support 
P097PFG panel in another patch 

 drivers/gpu/drm/panel/panel-innolux-p079zca.c | 147 ++
 1 file changed, 105 insertions(+), 42 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-innolux-p079zca.c 
b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
index 6ba9344..1597744 100644
--- a/drivers/gpu/drm/panel/panel-innolux-p079zca.c
+++ b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
@@ -20,12 +20,32 @@
 
 #include 
 
+struct panel_desc {
+   const struct drm_display_mode *modes;
+   unsigned int bpc;
+   struct {
+   unsigned int width;
+   unsigned int height;
+   } size;
+};
+
+struct panel_desc_dsi {
+   struct panel_desc desc;
+
+   unsigned long flags;
+   enum mipi_dsi_pixel_format format;
+   unsigned int lanes;
+};
+
 struct innolux_panel {
struct drm_panel base;
struct mipi_dsi_device *link;
+   const struct panel_desc_dsi *dsi_desc;
 
struct backlight_device *backlight;
-   struct regulator *supply;
+   struct regulator *vddi;
+   struct regulator *avdd;
+   struct regulator *avee;
struct gpio_desc *enable_gpio;
 
bool prepared;
@@ -78,9 +98,9 @@ static int innolux_panel_unprepare(struct drm_panel *panel)
/* T8: 80ms - 1000ms */
msleep(80);
 
-   err = regulator_disable(innolux->supply);
-   if (err < 0)
-   return err;
+   regulator_disable(innolux->avee);
+   regulator_disable(innolux->avdd);
+   regulator_disable(innolux->vddi);
 
innolux->prepared = false;
 
@@ -97,10 +117,18 @@ static int innolux_panel_prepare(struct drm_panel *panel)
 
gpiod_set_value_cansleep(innolux->enable_gpio, 0);
 
-   err = regulator_enable(innolux->supply);
+   err = regulator_enable(innolux->vddi);
if (err < 0)
return err;
 
+   err = regulator_enable(innolux->avdd);
+   if (err < 0)
+   goto disable_vddi;
+
+   err = regulator_enable(innolux->avee);
+   if (err < 0)
+   goto disable_avdd;
+
/* T2: 15ms - 1000ms */
usleep_range(15000, 16000);
 
@@ -134,12 +162,13 @@ static int innolux_panel_prepare(struct drm_panel *panel)
return 0;
 
 poweroff:
-   regulator_err = regulator_disable(innolux->supply);
-   if (regulator_err)
-   DRM_DEV_ERROR(panel->dev, "failed to disable regulator: %d\n",
- regulator_err);
-
gpiod_set_value_cansleep(innolux->enable_gpio, 0);
+   regulator_disable(innolux->avee);
+disable_avdd:
+   regulator_disable(innolux->avdd);
+disable_vddi:
+   regulator_disable(innolux->vddi);
+
return err;
 }
 
@@ -164,7 +193,7 @@ static int innolux_panel_enable(struct drm_panel *panel)
return 0;
 }
 
-static const struct drm_display_mode default_mode = {
+static const struct drm_display_mode innolux_p079zca_mode = {
.clock = 56900,
.hdisplay = 768,
.hsync_start = 768 + 40,
@@ -177,15 +206,31 @@ static const struct drm_display_mode default_mode = {
.vrefresh = 60,
 };
 
+static const struct panel_desc_dsi innolux_p079zca_panel_desc = {
+   .desc = {
+   .modes = _p079zca_mode,
+   .bpc = 8,
+   .size = {
+   .width = 120,
+   .height = 160,
+   },
+   },
+   .flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
+MIPI_DSI_MODE_LPM,
+   .format = MIPI_DSI_FMT_RGB888,
+   .lanes = 4,
+};
+
 static int innolux_panel_get_modes(struct drm_panel *panel)
 {
struct drm_display_mode *mode;
+   struct innolux_panel *innolux = to_innolux_panel(panel);
+   const struct drm_display_mode *m = innolux->dsi_desc->desc.modes;
 
-   mode = drm_mode_duplicate(panel->drm, _mode);
+   mode = drm_mode_duplicate(panel->drm, m);
if (!mode) {
DRM_DEV_ERROR(panel->drm->dev, "failed to add mode %ux%ux@%u\n",
- default_mode.hdisplay, default_mode.vdisplay,
- default_mode.vrefresh);
+ m->hdisplay, m->vdisplay, m->vrefresh);
return -ENOMEM;
}
 
@@ -193,9 +238,11 @@ static int innolux_panel_get_modes(struct drm_panel *panel)
 
drm_mode_probed_add(panel->connector, mode);
 
-   panel->connector->display_info.width_mm = 120;
-   panel->connector->display_info.height_mm = 160;
-   panel->connector->display_info.bpc = 8;

[PATCH v2 2/2] dt-bindings: Add INNOLUX P097PFG panel bindings

2017-12-01 Thread Lin Huang
The Innolux P097PFG panel is 9.7" panel with 1536X2048
resolution, it reuse P079ZCA panel driver, so improve
p079ZCA dt-binding to support P097PFG.

Signed-off-by: Lin Huang <h...@rock-chips.com>
---
 .../devicetree/bindings/display/panel/innolux,p079zca.txt | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git 
a/Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt 
b/Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt
index d0f5516..8cadd8c 100644
--- a/Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt
+++ b/Documentation/devicetree/bindings/display/panel/innolux,p079zca.txt
@@ -1,13 +1,18 @@
 Innolux P079ZCA 7.85" 768x1024 TFT LCD panel
+Innolux P097PFG 9.7" 1536x2048 TFT LCD panel
 
 Required properties:
-- compatible: should be "innolux,p079zca"
+- compatible: should be should be one of the following.
+-"innolux,p079zca" for Innolux 7.9" P079ZCA 768*1024 panel
+-"innolux,p097pfg" for Innolux 9.7" P097PFG 1536*2048 panel
 - reg: DSI virtual channel of the peripheral
-- power-supply: phandle of the regulator that provides the supply voltage
 - enable-gpios: panel enable gpio
 
 Optional properties:
 - backlight: phandle of the backlight device attached to the panel
+- power-supply: phandle of the regulator that provides the supply voltage
+- avdd-supply: phandle of the regulator that provides positive voltage
+- avee-supply: phandle of the regulator that provides negative voltage
 
 Example:
 
@@ -16,6 +21,8 @@ Example:
compatible = "innolux,p079zca";
reg = <0>;
power-supply = <...>;
+   avdd-supply = <...>;
+   avee-supply = <...>;
backlight = <>;
enable-gpios = < 13 GPIO_ACTIVE_HIGH>;
};
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 1/2] drm/panel: support Innolux P097PFG panel

2017-12-01 Thread Lin Huang
Support Innolux P097PFG 9.7" 1536x2048 TFT LCD panel,
it refactor Innolux P079ZCA panel driver, let it support
multi panel, and add support P097PFG panel in this driver.

Signed-off-by: Lin Huang <h...@rock-chips.com>
---
Changes in v2:
- change regulator property name to meet the panel datasheet 

 drivers/gpu/drm/panel/panel-innolux-p079zca.c | 178 --
 1 file changed, 136 insertions(+), 42 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-innolux-p079zca.c 
b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
index 6ba9344..5d690b7 100644
--- a/drivers/gpu/drm/panel/panel-innolux-p079zca.c
+++ b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
@@ -20,12 +20,32 @@
 
 #include 
 
+struct panel_desc {
+   const struct drm_display_mode *modes;
+   unsigned int bpc;
+   struct {
+   unsigned int width;
+   unsigned int height;
+   } size;
+};
+
+struct panel_desc_dsi {
+   struct panel_desc desc;
+
+   unsigned long flags;
+   enum mipi_dsi_pixel_format format;
+   unsigned int lanes;
+};
+
 struct innolux_panel {
struct drm_panel base;
struct mipi_dsi_device *link;
+   const struct panel_desc_dsi *dsi_desc;
 
struct backlight_device *backlight;
-   struct regulator *supply;
+   struct regulator *vddi;
+   struct regulator *avdd;
+   struct regulator *avee;
struct gpio_desc *enable_gpio;
 
bool prepared;
@@ -78,9 +98,9 @@ static int innolux_panel_unprepare(struct drm_panel *panel)
/* T8: 80ms - 1000ms */
msleep(80);
 
-   err = regulator_disable(innolux->supply);
-   if (err < 0)
-   return err;
+   regulator_disable(innolux->avee);
+   regulator_disable(innolux->avdd);
+   regulator_disable(innolux->vddi);
 
innolux->prepared = false;
 
@@ -97,10 +117,18 @@ static int innolux_panel_prepare(struct drm_panel *panel)
 
gpiod_set_value_cansleep(innolux->enable_gpio, 0);
 
-   err = regulator_enable(innolux->supply);
+   err = regulator_enable(innolux->vddi);
if (err < 0)
return err;
 
+   err = regulator_enable(innolux->avdd);
+   if (err < 0)
+   goto disable_vddi;
+
+   err = regulator_enable(innolux->avee);
+   if (err < 0)
+   goto disable_avdd;
+
/* T2: 15ms - 1000ms */
usleep_range(15000, 16000);
 
@@ -134,12 +162,13 @@ static int innolux_panel_prepare(struct drm_panel *panel)
return 0;
 
 poweroff:
-   regulator_err = regulator_disable(innolux->supply);
-   if (regulator_err)
-   DRM_DEV_ERROR(panel->dev, "failed to disable regulator: %d\n",
- regulator_err);
-
gpiod_set_value_cansleep(innolux->enable_gpio, 0);
+   regulator_disable(innolux->avee);
+disable_avdd:
+   regulator_disable(innolux->avdd);
+disable_vddi:
+   regulator_disable(innolux->vddi);
+
return err;
 }
 
@@ -164,7 +193,7 @@ static int innolux_panel_enable(struct drm_panel *panel)
return 0;
 }
 
-static const struct drm_display_mode default_mode = {
+static const struct drm_display_mode innolux_p079zca_mode = {
.clock = 56900,
.hdisplay = 768,
.hsync_start = 768 + 40,
@@ -177,15 +206,59 @@ static const struct drm_display_mode default_mode = {
.vrefresh = 60,
 };
 
+static const struct panel_desc_dsi innolux_p079zca_panel_desc = {
+   .desc = {
+   .modes = _p079zca_mode,
+   .bpc = 8,
+   .size = {
+   .width = 120,
+   .height = 160,
+   },
+   },
+   .flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
+MIPI_DSI_MODE_LPM,
+   .format = MIPI_DSI_FMT_RGB888,
+   .lanes = 4,
+};
+
+static const struct drm_display_mode innolux_p097pfg_mode = {
+   .clock = 22,
+   .hdisplay = 1536,
+   .hsync_start = 1536 + 100,
+   .hsync_end = 1536 + 100 + 24,
+   .htotal = 1536 + 100 + 24 + 100,
+   .vdisplay = 2048,
+   .vsync_start = 2048 + 18,
+   .vsync_end = 2048 + 18 + 2,
+   .vtotal = 2048 + 18 + 2 + 18,
+   .vrefresh = 60,
+};
+
+static const struct panel_desc_dsi innolux_p097pfg_panel_desc = {
+   .desc = {
+   .modes = _p097pfg_mode,
+   .bpc = 8,
+   .size = {
+   .width = 147,
+   .height = 196,
+   },
+   },
+   .flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
+MIPI_DSI_MODE_LPM,
+   .format = MIPI_DSI_FMT_RGB888,
+   .lanes = 8,
+};
+
 static int innolux_panel_get_modes(struct drm_panel *panel)
 {
struct drm_display_mode *mode;
+   struct innolux_panel *innolux = to_innolux_panel(panel);
+   const struct drm_display_mode *

[RESENT PATCH] drm/panel: support Innolux P097PFG panel

2017-11-30 Thread Lin Huang
Support Innolux P097PFG 9.7" 1536x2048 TFT LCD panel,
it refactor Innolux P079ZCA panel driver, let it support
multi panel, and add support P097PFG panel in this driver.

Signed-off-by: Lin Huang <h...@rock-chips.com>

---
 drivers/gpu/drm/panel/panel-innolux-p079zca.c | 178 --
 1 file changed, 136 insertions(+), 42 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-innolux-p079zca.c 
b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
index 6ba9344..a40798f 100644
--- a/drivers/gpu/drm/panel/panel-innolux-p079zca.c
+++ b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
@@ -20,12 +20,32 @@
 
 #include 
 
+struct panel_desc {
+   const struct drm_display_mode *modes;
+   unsigned int bpc;
+   struct {
+   unsigned int width;
+   unsigned int height;
+   } size;
+};
+
+struct panel_desc_dsi {
+   struct panel_desc desc;
+
+   unsigned long flags;
+   enum mipi_dsi_pixel_format format;
+   unsigned int lanes;
+};
+
 struct innolux_panel {
struct drm_panel base;
struct mipi_dsi_device *link;
+   const struct panel_desc_dsi *dsi_desc;
 
struct backlight_device *backlight;
-   struct regulator *supply;
+   struct regulator *vddi;
+   struct regulator *avdd;
+   struct regulator *avee;
struct gpio_desc *enable_gpio;
 
bool prepared;
@@ -78,9 +98,9 @@ static int innolux_panel_unprepare(struct drm_panel *panel)
/* T8: 80ms - 1000ms */
msleep(80);
 
-   err = regulator_disable(innolux->supply);
-   if (err < 0)
-   return err;
+   regulator_disable(innolux->avee);
+   regulator_disable(innolux->avdd);
+   regulator_disable(innolux->vddi);
 
innolux->prepared = false;
 
@@ -97,10 +117,18 @@ static int innolux_panel_prepare(struct drm_panel *panel)
 
gpiod_set_value_cansleep(innolux->enable_gpio, 0);
 
-   err = regulator_enable(innolux->supply);
+   err = regulator_enable(innolux->vddi);
if (err < 0)
return err;
 
+   err = regulator_enable(innolux->avdd);
+   if (err < 0)
+   goto disable_vddi;
+
+   err = regulator_enable(innolux->avee);
+   if (err < 0)
+   goto disable_avdd;
+
/* T2: 15ms - 1000ms */
usleep_range(15000, 16000);
 
@@ -134,12 +162,13 @@ static int innolux_panel_prepare(struct drm_panel *panel)
return 0;
 
 poweroff:
-   regulator_err = regulator_disable(innolux->supply);
-   if (regulator_err)
-   DRM_DEV_ERROR(panel->dev, "failed to disable regulator: %d\n",
- regulator_err);
-
gpiod_set_value_cansleep(innolux->enable_gpio, 0);
+   regulator_disable(innolux->avee);
+disable_avdd:
+   regulator_disable(innolux->avdd);
+disable_vddi:
+   regulator_disable(innolux->vddi);
+
return err;
 }
 
@@ -164,7 +193,7 @@ static int innolux_panel_enable(struct drm_panel *panel)
return 0;
 }
 
-static const struct drm_display_mode default_mode = {
+static const struct drm_display_mode innolux_p079zca_mode = {
.clock = 56900,
.hdisplay = 768,
.hsync_start = 768 + 40,
@@ -177,15 +206,59 @@ static const struct drm_display_mode default_mode = {
.vrefresh = 60,
 };
 
+static const struct panel_desc_dsi innolux_p079zca_panel_desc = {
+   .desc = {
+   .modes = _p079zca_mode,
+   .bpc = 8,
+   .size = {
+   .width = 120,
+   .height = 160,
+   },
+   },
+   .flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
+MIPI_DSI_MODE_LPM,
+   .format = MIPI_DSI_FMT_RGB888,
+   .lanes = 4,
+};
+
+static const struct drm_display_mode innolux_p097pfg_mode = {
+   .clock = 22,
+   .hdisplay = 1536,
+   .hsync_start = 1536 + 100,
+   .hsync_end = 1536 + 100 + 24,
+   .htotal = 1536 + 100 + 24 + 100,
+   .vdisplay = 2048,
+   .vsync_start = 2048 + 18,
+   .vsync_end = 2048 + 18 + 2,
+   .vtotal = 2048 + 18 + 2 + 18,
+   .vrefresh = 60,
+};
+
+static const struct panel_desc_dsi innolux_p097pfg_panel_desc = {
+   .desc = {
+   .modes = _p097pfg_mode,
+   .bpc = 8,
+   .size = {
+   .width = 147,
+   .height = 196,
+   },
+   },
+   .flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
+MIPI_DSI_MODE_LPM,
+   .format = MIPI_DSI_FMT_RGB888,
+   .lanes = 8,
+};
+
 static int innolux_panel_get_modes(struct drm_panel *panel)
 {
struct drm_display_mode *mode;
+   struct innolux_panel *innolux = to_innolux_panel(panel);
+   const struct drm_display_mode *m = innolux->dsi_desc->desc.modes;
 
-   mode = drm_mode_duplicate(

[PATCH] drm/panel: support Innolux P097PFG panel

2017-11-30 Thread Lin Huang
Support Innolux P097PFG 9.7" 1536x2048 TFT LCD panel,
it refactor Innolux P079ZCA panel driver, let it support
multi panel, and add support P097PFG panel in this driver.

Change-Id: If342e58a3de2861219b0b1313f402b6cb41ffa29
Signed-off-by: Lin Huang <h...@rock-chips.com>
---
 drivers/gpu/drm/panel/panel-innolux-p079zca.c | 178 --
 1 file changed, 136 insertions(+), 42 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-innolux-p079zca.c 
b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
index 6ba9344..a40798f 100644
--- a/drivers/gpu/drm/panel/panel-innolux-p079zca.c
+++ b/drivers/gpu/drm/panel/panel-innolux-p079zca.c
@@ -20,12 +20,32 @@
 
 #include 
 
+struct panel_desc {
+   const struct drm_display_mode *modes;
+   unsigned int bpc;
+   struct {
+   unsigned int width;
+   unsigned int height;
+   } size;
+};
+
+struct panel_desc_dsi {
+   struct panel_desc desc;
+
+   unsigned long flags;
+   enum mipi_dsi_pixel_format format;
+   unsigned int lanes;
+};
+
 struct innolux_panel {
struct drm_panel base;
struct mipi_dsi_device *link;
+   const struct panel_desc_dsi *dsi_desc;
 
struct backlight_device *backlight;
-   struct regulator *supply;
+   struct regulator *vddi;
+   struct regulator *avdd;
+   struct regulator *avee;
struct gpio_desc *enable_gpio;
 
bool prepared;
@@ -78,9 +98,9 @@ static int innolux_panel_unprepare(struct drm_panel *panel)
/* T8: 80ms - 1000ms */
msleep(80);
 
-   err = regulator_disable(innolux->supply);
-   if (err < 0)
-   return err;
+   regulator_disable(innolux->avee);
+   regulator_disable(innolux->avdd);
+   regulator_disable(innolux->vddi);
 
innolux->prepared = false;
 
@@ -97,10 +117,18 @@ static int innolux_panel_prepare(struct drm_panel *panel)
 
gpiod_set_value_cansleep(innolux->enable_gpio, 0);
 
-   err = regulator_enable(innolux->supply);
+   err = regulator_enable(innolux->vddi);
if (err < 0)
return err;
 
+   err = regulator_enable(innolux->avdd);
+   if (err < 0)
+   goto disable_vddi;
+
+   err = regulator_enable(innolux->avee);
+   if (err < 0)
+   goto disable_avdd;
+
/* T2: 15ms - 1000ms */
usleep_range(15000, 16000);
 
@@ -134,12 +162,13 @@ static int innolux_panel_prepare(struct drm_panel *panel)
return 0;
 
 poweroff:
-   regulator_err = regulator_disable(innolux->supply);
-   if (regulator_err)
-   DRM_DEV_ERROR(panel->dev, "failed to disable regulator: %d\n",
- regulator_err);
-
gpiod_set_value_cansleep(innolux->enable_gpio, 0);
+   regulator_disable(innolux->avee);
+disable_avdd:
+   regulator_disable(innolux->avdd);
+disable_vddi:
+   regulator_disable(innolux->vddi);
+
return err;
 }
 
@@ -164,7 +193,7 @@ static int innolux_panel_enable(struct drm_panel *panel)
return 0;
 }
 
-static const struct drm_display_mode default_mode = {
+static const struct drm_display_mode innolux_p079zca_mode = {
.clock = 56900,
.hdisplay = 768,
.hsync_start = 768 + 40,
@@ -177,15 +206,59 @@ static const struct drm_display_mode default_mode = {
.vrefresh = 60,
 };
 
+static const struct panel_desc_dsi innolux_p079zca_panel_desc = {
+   .desc = {
+   .modes = _p079zca_mode,
+   .bpc = 8,
+   .size = {
+   .width = 120,
+   .height = 160,
+   },
+   },
+   .flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
+MIPI_DSI_MODE_LPM,
+   .format = MIPI_DSI_FMT_RGB888,
+   .lanes = 4,
+};
+
+static const struct drm_display_mode innolux_p097pfg_mode = {
+   .clock = 22,
+   .hdisplay = 1536,
+   .hsync_start = 1536 + 100,
+   .hsync_end = 1536 + 100 + 24,
+   .htotal = 1536 + 100 + 24 + 100,
+   .vdisplay = 2048,
+   .vsync_start = 2048 + 18,
+   .vsync_end = 2048 + 18 + 2,
+   .vtotal = 2048 + 18 + 2 + 18,
+   .vrefresh = 60,
+};
+
+static const struct panel_desc_dsi innolux_p097pfg_panel_desc = {
+   .desc = {
+   .modes = _p097pfg_mode,
+   .bpc = 8,
+   .size = {
+   .width = 147,
+   .height = 196,
+   },
+   },
+   .flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
+MIPI_DSI_MODE_LPM,
+   .format = MIPI_DSI_FMT_RGB888,
+   .lanes = 8,
+};
+
 static int innolux_panel_get_modes(struct drm_panel *panel)
 {
struct drm_display_mode *mode;
+   struct innolux_panel *innolux = to_innolux_panel(panel);
+   const struct drm_display_mode *m = innolux->dsi_de

[PATCH v10 5/5] drm/rockchip: Add dmc notifier in vop driver

2016-09-05 Thread Lin Huang
when in ddr frequency scaling process, vop can not do enable or
disable operation, since in dcf we check vop clock to see whether
vop work. If vop work, dcf do ddr frequency scaling when vop
in vblank status, and we need to read vop register to check whether
vop go into vblank status. If vop not work, dcf can do ddr frequency
any time. So when do ddr frequency scaling, you disabled or enable
vop, there may two bad thing happen: 1, the panel flicker(when vop from
disable status change to enable). 2, kernel hang (when vop from enable
status change to disable, dcf need to read vblank status, but if you disable
vop clock, it can not get the status, it will lead soc dead) So we need
register to devfreq notifier, and we can get the dmc status. Also, when
there have two vop enabled, we need to disable dmc, since dcf only base
on one vop vblank time, so the other panel will flicker when do ddr
frequency scaling.

Signed-off-by: Lin Huang 
Reviewed-by: Chanwoo Choi 
---
Changes in v10:
- None

Changes in v9:
- None

Changes in v8:
- None

Changes in v7:
- None

Changes in v6:
- fix a build error

Changes in v5:
- improve some nits

Changes in v4:
- register notifier to devfreq_register_notifier
- use DEVFREQ_PRECHANGE and DEVFREQ_POSTCHANGE to get dmc status
- when two vop enable, disable dmc
- when two vop back to one vop, enable dmc

Changes in v3:
- when do vop eanble/disable, dmc will wait until it finish

Changes in v2:
- None

Changes in v1:
- use wait_event instead usleep

 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 116 
 1 file changed, 116 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index efbc41a..a73f3aa 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -19,6 +19,8 @@
 #include 
 #include 

+#include 
+#include 
 #include 
 #include 
 #include 
@@ -118,6 +120,13 @@ struct vop {

const struct vop_data *data;

+   struct devfreq *devfreq;
+   struct devfreq_event_dev *devfreq_event_dev;
+   struct notifier_block dmc_nb;
+   int dmc_in_process;
+   int vop_switch_status;
+   wait_queue_head_t wait_dmc_queue;
+   wait_queue_head_t wait_vop_switch_queue;
uint32_t *regsbak;
void __iomem *regs;

@@ -428,11 +437,47 @@ static void vop_dsp_hold_valid_irq_disable(struct vop 
*vop)
spin_unlock_irqrestore(>irq_lock, flags);
 }

+static int dmc_notify(struct notifier_block *nb, unsigned long event,
+ void *data)
+{
+   struct vop *vop = container_of(nb, struct vop, dmc_nb);
+
+   if (event == DEVFREQ_PRECHANGE) {
+   /*
+* check if vop in enable or disable process,
+* if yes, wait until it finishes, use 200ms as
+* timeout.
+*/
+   if (!wait_event_timeout(vop->wait_vop_switch_queue,
+   !vop->vop_switch_status, HZ / 5))
+   dev_warn(vop->dev,
+"Timeout waiting for vop swtich status\n");
+   vop->dmc_in_process = 1;
+   } else if (event == DEVFREQ_POSTCHANGE) {
+   vop->dmc_in_process = 0;
+   wake_up(>wait_dmc_queue);
+   }
+
+   return NOTIFY_OK;
+}
+
 static int vop_enable(struct drm_crtc *crtc)
 {
struct vop *vop = to_vop(crtc);
+   int num_enabled_crtc = 0;
int ret;

+   /*
+* if in dmc scaling frequency process, wait until it finishes
+* use 200ms as timeout time.
+*/
+   if (!wait_event_timeout(vop->wait_dmc_queue,
+   !vop->dmc_in_process, HZ / 5))
+   dev_warn(vop->dev,
+"Timeout waiting for dmc when vop enable\n");
+
+   vop->vop_switch_status = 1;
+
ret = pm_runtime_get_sync(vop->dev);
if (ret < 0) {
dev_err(vop->dev, "failed to get pm runtime: %d\n", ret);
@@ -479,6 +524,21 @@ static int vop_enable(struct drm_crtc *crtc)

drm_crtc_vblank_on(crtc);

+   vop->vop_switch_status = 0;
+   wake_up(>wait_vop_switch_queue);
+
+   /* check how many VOPs in use now */
+   drm_for_each_crtc(crtc, vop->drm_dev) {
+   if (crtc->state->enable)
+   num_enabled_crtc++;
+   }
+
+   /* if enable two vop, need to disable dmc */
+   if ((num_enabled_crtc > 1) && vop->devfreq) {
+   if (vop->devfreq_event_dev)
+   devfreq_event_disable_edev(vop->devfreq_event_dev);
+   devfreq_suspend_device(vop->devfreq);
+   }
return 0;

 err_disable_aclk:
@@ -489,17 +549,31 @@ err_disable_hclk:
clk_disable(vop->hclk);
 err_put_pm_runtime:
pm_runtime_put_sync(vop->dev

[PATCH v10 4/5] PM / devfreq: rockchip: add devfreq driver for rk3399 dmc

2016-09-05 Thread Lin Huang
base on dfi result, we do ddr frequency scaling, register
dmc driver to devfreq framework, and use simple-ondemand
policy.

Signed-off-by: Lin Huang 
Signed-off-by: MyngJoo Ham 
Reviewed-by: Chanwoo Choi 
---
Changes in v10:
- None

Changes in v9:
- None

Changes in v8:
- None

Changes in v8:
- do not use ddr_timing node, get ddr timing directly

Changes in v7:
- remove a blank line

Changes in v6:
- fix some nit suggest by Chanwoo Choi

Changes in v5:
- improve dmc driver suggest by Chanwoo Choi

Changes in v4:
- use arm_smccc_smc() function talk to bl31
- delete rockchip_dmc.c file and config
- delete dmc_notify
- adjust probe order

Changes in v3:
- operate dram setting through sip call
- imporve set rate flow

Changes in v2:
- None

Changes in v1:
- move dfi controller to event
- fix set voltage sequence when set rate fail
- change Kconfig type from tristate to bool
- move unuse EXPORT_SYMBOL_GPL()

 drivers/devfreq/Kconfig  |  11 +
 drivers/devfreq/Makefile |   1 +
 drivers/devfreq/rk3399_dmc.c | 480 +++
 3 files changed, 492 insertions(+)
 create mode 100644 drivers/devfreq/rk3399_dmc.c

diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig
index a5be56e..e848121 100644
--- a/drivers/devfreq/Kconfig
+++ b/drivers/devfreq/Kconfig
@@ -100,6 +100,17 @@ config ARM_TEGRA_DEVFREQ
  It reads ACTMON counters of memory controllers and adjusts the
  operating frequencies and voltages with OPP support.

+config ARM_RK3399_DMC_DEVFREQ
+   tristate "ARM RK3399 DMC DEVFREQ Driver"
+   depends on ARCH_ROCKCHIP
+   select DEVFREQ_EVENT_ROCKCHIP_DFI
+   select DEVFREQ_GOV_SIMPLE_ONDEMAND
+   select PM_OPP
+   help
+  This adds the DEVFREQ driver for the RK3399 DMC(Dynamic Memory 
Controller).
+  It sets the frequency for the memory controller and reads the usage 
counts
+  from hardware.
+
 source "drivers/devfreq/event/Kconfig"

 endif # PM_DEVFREQ
diff --git a/drivers/devfreq/Makefile b/drivers/devfreq/Makefile
index 09f11d9..fbff40a 100644
--- a/drivers/devfreq/Makefile
+++ b/drivers/devfreq/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_DEVFREQ_GOV_PASSIVE)   += governor_passive.o

 # DEVFREQ Drivers
 obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ)   += exynos-bus.o
+obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ)   += rk3399_dmc.o
 obj-$(CONFIG_ARM_TEGRA_DEVFREQ)+= tegra-devfreq.o

 # DEVFREQ Event Drivers
diff --git a/drivers/devfreq/rk3399_dmc.c b/drivers/devfreq/rk3399_dmc.c
new file mode 100644
index 000..54d65f2
--- /dev/null
+++ b/drivers/devfreq/rk3399_dmc.c
@@ -0,0 +1,480 @@
+/*
+ * Copyright (c) 2016, Fuzhou Rockchip Electronics Co., Ltd.
+ * Author: Lin Huang 
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+struct dram_timing {
+   unsigned int ddr3_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 dram_dll_dis_freq;
+   unsigned int phy_dll_dis_freq;
+   unsigned int ddr3_odt_dis_freq;
+   unsigned int ddr3_drv;
+   unsigned int ddr3_odt;
+   unsigned int phy_ddr3_ca_drv;
+   unsigned int phy_ddr3_dq_drv;
+   unsigned int phy_ddr3_odt;
+   unsigned int lpddr3_odt_dis_freq;
+   unsigned int lpddr3_drv;
+   unsigned int lpddr3_odt;
+   unsigned int phy_lpddr3_ca_drv;
+   unsigned int phy_lpddr3_dq_drv;
+   unsigned int phy_lpddr3_odt;
+   unsigned int 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;
+};
+
+struct rk3399_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 dram_timing timing;
+
+   /*
+* DDR Converser of Frequency (DCF) is used to implement DDR frequency
+* conversion without the participation of CPU, we will implement and
+* control it in arm trust firmware.
+*/
+   wait_queue_head_t 

[PATCH v10 3/5] Documentation: bindings: add dt documentation for rk3399 dmc

2016-09-05 Thread Lin Huang
This patch adds the documentation for rockchip rk3399 dmc driver.

Signed-off-by: Lin Huang 
Reviewed-by: Chanwoo Choi 
---
Changes in v10:
- add rockchip prefix in property describe

Changes in v9:
- add ddr timing property to node

Changes in v8:
- add ddr timing properties

Changes in v7:
- None

Changes in v6:
-Add more detail in Documentation

Changes in v5:
-None

Changes in v4:
-None

Changes in v3:
-None

Changes in v2:
-None 

Changes in v1:
-None
 .../devicetree/bindings/devfreq/rk3399_dmc.txt | 202 +
 1 file changed, 202 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt

diff --git a/Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt 
b/Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt
new file mode 100644
index 000..84660a3
--- /dev/null
+++ b/Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt
@@ -0,0 +1,210 @@
+* Rockchip rk3399 DMC(Dynamic Memory Controller) device
+
+Required properties:
+- compatible:   Must be "rockchip,rk3399-dmc".
+- devfreq-events:   Node to get DDR loading, Refer to
+Documentation/devicetree/bindings/devfreq/
+rockchip-dfi.txt
+- interrupts:   The interrupt number to the CPU. The interrupt
+specifier format depends on the interrupt controller.
+It should be DCF interrupts, when DDR dvfs finish,
+it will happen.
+- clocks:   Phandles for clock specified in "clock-names" property
+- clock-names : The name of clock used by the DFI, must be
+"pclk_ddr_mon";
+- operating-points-v2:  Refer to 
Documentation/devicetree/bindings/power/opp.txt
+for details.
+- center-supply:DMC supply node.
+- status:   Marks the node enabled/disabled.
+
+Following properties are ddr timing:
+
+- rockchip,dram_speed_bin :  Value reference 
include/dt-bindings/clock/ddr.h,
+ it select ddr3 cl-trp-trcd type, default value
+ "DDR3_DEFAULT".it must selected according to
+ "Speed Bin" in ddr3 datasheet, DO NOT use
+ smaller "Speed Bin" than ddr3 exactly is.
+
+- rockchip,pd_idle : Config the PD_IDLE value, defined the 
power-down
+ idle period, memories are places into 
power-down
+ mode if bus is idle for PD_IDLE DFI clocks.
+
+- rockchip,sr_idle : Configure the SR_IDLE value, defined the
+ selfrefresh idle period, memories are places
+ into self-refresh mode if bus is idle for
+ SR_IDLE*1024 DFI clocks (DFI clocks freq is
+ half of dram's clocks), defaule value is "0".
+
+- rockchip,sr_mc_gate_idle : Defined the self-refresh with memory and
+ controller clock gating idle period, memories
+ are places into self-refresh mode and memory
+ controller clock arg gating if bus is idle for
+ sr_mc_gate_idle*1024 DFI clocks.
+
+- rockchip,srpd_lite_idle :  Defined the self-refresh power down idle
+ period, memories are places into self-refresh
+ power down mode if bus is idle for
+ srpd_lite_idle*1024 DFI clocks. This parameter
+ is for LPDDR4 only.
+
+- rockchip,standby_idle :Defined the standby idle period, memories are
+ places into self-refresh than controller, pi,
+ phy and dram clock will gating if bus is idle
+ for standby_idle * DFI clocks.
+
+- rockchip,dram_dll_disb_freq :  It's defined the DDR3 dll bypass frequency in
+ MHz, when ddr freq less than 
DRAM_DLL_DISB_FREQ,
+ ddr3 dll will bypssed note: if dll was 
bypassed,
+ the odt also stop working.
+
+- rockchip,phy_dll_disb_freq :   Defined the PHY dll bypass frequency in
+ MHz (Mega Hz), when ddr freq less than
+ DRAM_DLL_DISB_FREQ, phy dll will bypssed.
+ note: phy dll and phy odt are independent.
+
+- rockchip,ddr3_odt_disb_freq :  When dram type is DDR3, this parameter defined
+ the odt disable frequency in MHz (Mega Hz),
+ when ddr frequency less then 
ddr3_odt_disb_freq,
+   

[PATCH v10 2/5] PM / devfreq: event: support rockchip dfi controller

2016-09-05 Thread Lin Huang
on rk3399 platform, there is dfi conroller can monitor
ddr load, base on this result, we can do ddr freqency
scaling.

Signed-off-by: Lin Huang 
Signed-off-by: MyungJoo Ham 
Acked-by: Chanwoo Choi 
---
Changes in v10:
-None

Changes in v9:
-None

Changes in v8:
-None

Changes in v7:
-access need to *4 to get right DDR loading

Changes in v6:
-None

Changes in v5:
-None

Changes in v4:
-None

Changes in v3:
-None

Changes in v2:
-None 

Changes in v1:
-None

 drivers/devfreq/event/Kconfig|   7 +
 drivers/devfreq/event/Makefile   |   1 +
 drivers/devfreq/event/rockchip-dfi.c | 256 +++
 3 files changed, 264 insertions(+)
 create mode 100644 drivers/devfreq/event/rockchip-dfi.c

diff --git a/drivers/devfreq/event/Kconfig b/drivers/devfreq/event/Kconfig
index eb6f74a..20d82c2 100644
--- a/drivers/devfreq/event/Kconfig
+++ b/drivers/devfreq/event/Kconfig
@@ -30,4 +30,11 @@ config DEVFREQ_EVENT_EXYNOS_PPMU
  (Platform Performance Monitoring Unit) counters to estimate the
  utilization of each module.

+config DEVFREQ_EVENT_ROCKCHIP_DFI
+   tristate "ROCKCHIP DFI DEVFREQ event Driver"
+   depends on ARCH_ROCKCHIP
+   help
+ This add the devfreq-event driver for Rockchip SoC. It provides DFI
+ (DDR Monitor Module) driver to count ddr load.
+
 endif # PM_DEVFREQ_EVENT
diff --git a/drivers/devfreq/event/Makefile b/drivers/devfreq/event/Makefile
index 3d6afd3..dda7090 100644
--- a/drivers/devfreq/event/Makefile
+++ b/drivers/devfreq/event/Makefile
@@ -2,3 +2,4 @@

 obj-$(CONFIG_DEVFREQ_EVENT_EXYNOS_NOCP) += exynos-nocp.o
 obj-$(CONFIG_DEVFREQ_EVENT_EXYNOS_PPMU) += exynos-ppmu.o
+obj-$(CONFIG_DEVFREQ_EVENT_ROCKCHIP_DFI) += rockchip-dfi.o
diff --git a/drivers/devfreq/event/rockchip-dfi.c 
b/drivers/devfreq/event/rockchip-dfi.c
new file mode 100644
index 000..43fcc5a
--- /dev/null
+++ b/drivers/devfreq/event/rockchip-dfi.c
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2016, Fuzhou Rockchip Electronics Co., Ltd
+ * Author: Lin Huang 
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define RK3399_DMC_NUM_CH  2
+
+/* DDRMON_CTRL */
+#define DDRMON_CTRL0x04
+#define CLR_DDRMON_CTRL(0x1f << 0)
+#define LPDDR4_EN  (0x10001 << 4)
+#define HARDWARE_EN(0x10001 << 3)
+#define LPDDR3_EN  (0x10001 << 2)
+#define SOFTWARE_EN(0x10001 << 1)
+#define SOFTWARE_DIS   (0x1 << 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
+#define DDRTYPE_SHIFT  13
+#define DDRTYPE_MASK   7
+
+enum {
+   DDR3 = 3,
+   LPDDR3 = 6,
+   LPDDR4 = 7,
+   UNUSED = 0xFF
+};
+
+struct dmc_usage {
+   u32 access;
+   u32 total;
+};
+
+/*
+ * The dfi controller can monitor DDR load. It has an upper and lower threshold
+ * for the operating points. Whenever the usage leaves these bounds an event is
+ * generated to indicate the DDR frequency should be changed.
+ */
+struct rockchip_dfi {
+   struct devfreq_event_dev *edev;
+   struct devfreq_event_desc *desc;
+   struct dmc_usage ch_usage[RK3399_DMC_NUM_CH];
+   struct device *dev;
+   void __iomem *regs;
+   struct regmap *regmap_pmu;
+   struct clk *clk;
+};
+
+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, PMUGRF_OS_REG2, );
+   ddr_type = (val >> DDRTYPE_SHIFT) & DDRTYPE_MASK;
+
+   /* clear DDRMON_CTRL setting */
+   writel_relaxed(CLR_DDRMON_CTRL, dfi_regs + DDRMON_CTRL);
+
+   /* set ddr type to dfi */
+   if (ddr_type == LPDDR3)
+   writel_relaxed(LPDDR3_EN, dfi_regs + DDRMON_CTRL);
+   else if (ddr_type == LPDDR4)
+   writel_relaxed(LPDDR4_EN, dfi_regs + DDRMON_CTRL);
+
+   /* enable count, use software mode */
+   writel_relaxed(SOFTWARE_EN, dfi_regs + DDRMON_CTRL);
+}
+
+static void rockchip_dfi_stop_hardware_counter(struct devfreq_event_dev *edev)
+{
+   struct rockchip_dfi *in

[PATCH v10 1/5] Documentation: bindings: add dt documentation for dfi controller

2016-09-05 Thread Lin Huang
This patch adds the documentation for rockchip dfi devfreq-event driver.

Signed-off-by: Lin Huang 
Acked-by: Chanwoo Choi 
---
Changes in v10:
- None

Changes in v9:
- reorder compatible and reg

Changes in v8:
- delete a unuse blank line

Changes in v7:
- None

Changes in v6:
- None

Changes in v5:
- None

Changes in v4:
- None

Changes in v3:
- None

Changes in v2:
- None 

Changes in v1:
- None

 .../bindings/devfreq/event/rockchip-dfi.txt   | 19 +++
 1 file changed, 19 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt

diff --git a/Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt 
b/Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt
new file mode 100644
index 000..f223313
--- /dev/null
+++ b/Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt
@@ -0,0 +1,19 @@
+
+* Rockchip rk3399 DFI device
+
+Required properties:
+- compatible: Must be "rockchip,rk3399-dfi".
+- reg: physical base address of each DFI and length of memory mapped region
+- rockchip,pmu: phandle to the syscon managing the "pmu general register files"
+- clocks: phandles for clock specified in "clock-names" property
+- clock-names : the name of clock used by the DFI, must be "pclk_ddr_mon";
+
+Example:
+   dfi: dfi at 0xff63 {
+   compatible = "rockchip,rk3399-dfi";
+   reg = <0x00 0xff63 0x00 0x4000>;
+   rockchip,pmu = <>;
+   clocks = < PCLK_DDR_MON>;
+   clock-names = "pclk_ddr_mon";
+   status = "disabled";
+   };
-- 
2.6.6



[PATCH v10 0/5] rk3399 support ddr frequency scaling

2016-09-05 Thread Lin Huang
rk3399 platform have dfi controller can monitor ddr load,
and dcf controller to handle ddr register so we can get the
right ddr frequency and make ddr controller happy work(which
will implement in bl31). So we do ddr frequency scaling with
following flow:

 kernelbl31

monitor ddr load
|
|
get_target_rate
|
|   pass rate to bl31
clk_set_rate(ddr) ->run dcf flow
|   |
|   |
wait dcf interrupt<---trigger dcf interrupt
|
|
  return


Lin Huang (5):
  Documentation: bindings: add dt documentation for dfi controller
  PM / devfreq: event: support rockchip dfi controller
  Documentation: bindings: add dt documentation for rk3399 dmc
  PM / devfreq: rockchip: add devfreq driver for rk3399 dmc
  drm/rockchip: Add dmc notifier in vop driver

Following patch:
clk: rockchip: add new clock-type for the ddrclk
clk: rockchip: rk3399: add SCLK_DDRCLK ID for ddrc
clk: rockchip: rk3399: add ddrc clock support
have applied to:
http://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git/v4.9-clk/next


 .../bindings/devfreq/event/rockchip-dfi.txt|  19 +
 .../devicetree/bindings/devfreq/rk3399_dmc.txt | 210 +
 drivers/devfreq/Kconfig|  11 +
 drivers/devfreq/Makefile   |   1 +
 drivers/devfreq/event/Kconfig  |   7 +
 drivers/devfreq/event/Makefile |   1 +
 drivers/devfreq/event/rockchip-dfi.c   | 256 +++
 drivers/devfreq/rk3399_dmc.c   | 480 +
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c| 116 +
 9 files changed, 1101 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt
 create mode 100644 Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt
 create mode 100644 drivers/devfreq/event/rockchip-dfi.c
 create mode 100644 drivers/devfreq/rk3399_dmc.c

-- 
2.6.6



[PATCH v9 5/5] drm/rockchip: Add dmc notifier in vop driver

2016-09-03 Thread Lin Huang
when in ddr frequency scaling process, vop can not do enable or
disable operation, since in dcf we check vop clock to see whether
vop work. If vop work, dcf do ddr frequency scaling when vop
in vblank status, and we need to read vop register to check whether
vop go into vblank status. If vop not work, dcf can do ddr frequency
any time. So when do ddr frequency scaling, you disabled or enable
vop, there may two bad thing happen: 1, the panel flicker(when vop from
disable status change to enable). 2, kernel hang (when vop from enable
status change to disable, dcf need to read vblank status, but if you disable
vop clock, it can not get the status, it will lead soc dead) So we need
register to devfreq notifier, and we can get the dmc status. Also, when
there have two vop enabled, we need to disable dmc, since dcf only base
on one vop vblank time, so the other panel will flicker when do ddr
frequency scaling.

Signed-off-by: Lin Huang 
Reviewed-by: Chanwoo Choi 
---
Changes in v9:
- None

Changes in v8:
- None

Changes in v7:
- None

Changes in v6:
- fix a build error

Changes in v5:
- improve some nits

Changes in v4:
- register notifier to devfreq_register_notifier
- use DEVFREQ_PRECHANGE and DEVFREQ_POSTCHANGE to get dmc status
- when two vop enable, disable dmc
- when two vop back to one vop, enable dmc

Changes in v3:
- when do vop eanble/disable, dmc will wait until it finish

Changes in v2:
- None

Changes in v1:
- use wait_event instead usleep

 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 116 
 1 file changed, 116 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index efbc41a..a73f3aa 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -19,6 +19,8 @@
 #include 
 #include 

+#include 
+#include 
 #include 
 #include 
 #include 
@@ -118,6 +120,13 @@ struct vop {

const struct vop_data *data;

+   struct devfreq *devfreq;
+   struct devfreq_event_dev *devfreq_event_dev;
+   struct notifier_block dmc_nb;
+   int dmc_in_process;
+   int vop_switch_status;
+   wait_queue_head_t wait_dmc_queue;
+   wait_queue_head_t wait_vop_switch_queue;
uint32_t *regsbak;
void __iomem *regs;

@@ -428,11 +437,47 @@ static void vop_dsp_hold_valid_irq_disable(struct vop 
*vop)
spin_unlock_irqrestore(>irq_lock, flags);
 }

+static int dmc_notify(struct notifier_block *nb, unsigned long event,
+ void *data)
+{
+   struct vop *vop = container_of(nb, struct vop, dmc_nb);
+
+   if (event == DEVFREQ_PRECHANGE) {
+   /*
+* check if vop in enable or disable process,
+* if yes, wait until it finishes, use 200ms as
+* timeout.
+*/
+   if (!wait_event_timeout(vop->wait_vop_switch_queue,
+   !vop->vop_switch_status, HZ / 5))
+   dev_warn(vop->dev,
+"Timeout waiting for vop swtich status\n");
+   vop->dmc_in_process = 1;
+   } else if (event == DEVFREQ_POSTCHANGE) {
+   vop->dmc_in_process = 0;
+   wake_up(>wait_dmc_queue);
+   }
+
+   return NOTIFY_OK;
+}
+
 static int vop_enable(struct drm_crtc *crtc)
 {
struct vop *vop = to_vop(crtc);
+   int num_enabled_crtc = 0;
int ret;

+   /*
+* if in dmc scaling frequency process, wait until it finishes
+* use 200ms as timeout time.
+*/
+   if (!wait_event_timeout(vop->wait_dmc_queue,
+   !vop->dmc_in_process, HZ / 5))
+   dev_warn(vop->dev,
+"Timeout waiting for dmc when vop enable\n");
+
+   vop->vop_switch_status = 1;
+
ret = pm_runtime_get_sync(vop->dev);
if (ret < 0) {
dev_err(vop->dev, "failed to get pm runtime: %d\n", ret);
@@ -479,6 +524,21 @@ static int vop_enable(struct drm_crtc *crtc)

drm_crtc_vblank_on(crtc);

+   vop->vop_switch_status = 0;
+   wake_up(>wait_vop_switch_queue);
+
+   /* check how many VOPs in use now */
+   drm_for_each_crtc(crtc, vop->drm_dev) {
+   if (crtc->state->enable)
+   num_enabled_crtc++;
+   }
+
+   /* if enable two vop, need to disable dmc */
+   if ((num_enabled_crtc > 1) && vop->devfreq) {
+   if (vop->devfreq_event_dev)
+   devfreq_event_disable_edev(vop->devfreq_event_dev);
+   devfreq_suspend_device(vop->devfreq);
+   }
return 0;

 err_disable_aclk:
@@ -489,17 +549,31 @@ err_disable_hclk:
clk_disable(vop->hclk);
 err_put_pm_runtime:
pm_runtime_put_sync(vop->dev);
+   vop->vop_s

[PATCH v9 4/5] PM / devfreq: rockchip: add devfreq driver for rk3399 dmc

2016-09-03 Thread Lin Huang
base on dfi result, we do ddr frequency scaling, register
dmc driver to devfreq framework, and use simple-ondemand
policy.

Signed-off-by: Lin Huang 
Signed-off-by: MyngJoo Ham 
Reviewed-by: Chanwoo Choi 
---
Changes in v8:
- None

Changes in v8:
- do not use ddr_timing node, get ddr timing directly

Changes in v7:
- remove a blank line

Changes in v6:
- fix some nit suggest by Chanwoo Choi

Changes in v5:
- improve dmc driver suggest by Chanwoo Choi

Changes in v4:
- use arm_smccc_smc() function talk to bl31
- delete rockchip_dmc.c file and config
- delete dmc_notify
- adjust probe order

Changes in v3:
- operate dram setting through sip call
- imporve set rate flow

Changes in v2:
- None

Changes in v1:
- move dfi controller to event
- fix set voltage sequence when set rate fail
- change Kconfig type from tristate to bool
- move unuse EXPORT_SYMBOL_GPL()

 drivers/devfreq/Kconfig  |  11 +
 drivers/devfreq/Makefile |   1 +
 drivers/devfreq/rk3399_dmc.c | 480 +++
 3 files changed, 492 insertions(+)
 create mode 100644 drivers/devfreq/rk3399_dmc.c

diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig
index a5be56e..e848121 100644
--- a/drivers/devfreq/Kconfig
+++ b/drivers/devfreq/Kconfig
@@ -100,6 +100,17 @@ config ARM_TEGRA_DEVFREQ
  It reads ACTMON counters of memory controllers and adjusts the
  operating frequencies and voltages with OPP support.

+config ARM_RK3399_DMC_DEVFREQ
+   tristate "ARM RK3399 DMC DEVFREQ Driver"
+   depends on ARCH_ROCKCHIP
+   select DEVFREQ_EVENT_ROCKCHIP_DFI
+   select DEVFREQ_GOV_SIMPLE_ONDEMAND
+   select PM_OPP
+   help
+  This adds the DEVFREQ driver for the RK3399 DMC(Dynamic Memory 
Controller).
+  It sets the frequency for the memory controller and reads the usage 
counts
+  from hardware.
+
 source "drivers/devfreq/event/Kconfig"

 endif # PM_DEVFREQ
diff --git a/drivers/devfreq/Makefile b/drivers/devfreq/Makefile
index 09f11d9..fbff40a 100644
--- a/drivers/devfreq/Makefile
+++ b/drivers/devfreq/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_DEVFREQ_GOV_PASSIVE)   += governor_passive.o

 # DEVFREQ Drivers
 obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ)   += exynos-bus.o
+obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ)   += rk3399_dmc.o
 obj-$(CONFIG_ARM_TEGRA_DEVFREQ)+= tegra-devfreq.o

 # DEVFREQ Event Drivers
diff --git a/drivers/devfreq/rk3399_dmc.c b/drivers/devfreq/rk3399_dmc.c
new file mode 100644
index 000..54d65f2
--- /dev/null
+++ b/drivers/devfreq/rk3399_dmc.c
@@ -0,0 +1,480 @@
+/*
+ * Copyright (c) 2016, Fuzhou Rockchip Electronics Co., Ltd.
+ * Author: Lin Huang 
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+struct dram_timing {
+   unsigned int ddr3_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 dram_dll_dis_freq;
+   unsigned int phy_dll_dis_freq;
+   unsigned int ddr3_odt_dis_freq;
+   unsigned int ddr3_drv;
+   unsigned int ddr3_odt;
+   unsigned int phy_ddr3_ca_drv;
+   unsigned int phy_ddr3_dq_drv;
+   unsigned int phy_ddr3_odt;
+   unsigned int lpddr3_odt_dis_freq;
+   unsigned int lpddr3_drv;
+   unsigned int lpddr3_odt;
+   unsigned int phy_lpddr3_ca_drv;
+   unsigned int phy_lpddr3_dq_drv;
+   unsigned int phy_lpddr3_odt;
+   unsigned int 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;
+};
+
+struct rk3399_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 dram_timing timing;
+
+   /*
+* DDR Converser of Frequency (DCF) is used to implement DDR frequency
+* conversion without the participation of CPU, we will implement and
+* control it in arm trust firmware.
+*/
+   wait_queue_head_t   wait_dcf_queue;
+   int irq;
+

[PATCH v9 3/5] Documentation: bindings: add dt documentation for rk3399 dmc

2016-09-03 Thread Lin Huang
This patch adds the documentation for rockchip rk3399 dmc driver.

Signed-off-by: Lin Huang 
---
Changes in v9:
- add ddr timing property to node

Changes in v8:
- add ddr timing properties

Changes in v7:
- None

Changes in v6:
-Add more detail in Documentation

Changes in v5:
-None

Changes in v4:
-None

Changes in v3:
-None

Changes in v2:
-None 

Changes in v1:
-None
 .../devicetree/bindings/devfreq/rk3399_dmc.txt | 202 +
 1 file changed, 202 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt

diff --git a/Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt 
b/Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt
new file mode 100644
index 000..f187c8fa
--- /dev/null
+++ b/Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt
@@ -0,0 +1,202 @@
+* Rockchip rk3399 DMC(Dynamic Memory Controller) device
+
+Required properties:
+- compatible:   Must be "rockchip,rk3399-dmc".
+- devfreq-events:   Node to get DDR loading, Refer to
+Documentation/devicetree/bindings/devfreq/
+rockchip-dfi.txt
+- interrupts:   The interrupt number to the CPU. The interrupt
+specifier format depends on the interrupt controller.
+It should be DCF interrupts, when DDR dvfs finish,
+it will happen.
+- clocks:   Phandles for clock specified in "clock-names" property
+- clock-names : The name of clock used by the DFI, must be
+"pclk_ddr_mon";
+- operating-points-v2:  Refer to 
Documentation/devicetree/bindings/power/opp.txt
+for details.
+- center-supply:DMC supply node.
+- status:   Marks the node enabled/disabled.
+
+Following properties are ddr timing:
+
+- dram_speed_bin :  Value is defined at include/dt-bindings/clock/ddr.h,
+it select ddr3 cl-trp-trcd type, default value
+"DDR3_DEFAULT".it must selected according to
+"Speed Bin" in ddr3 datasheet, DO NOT use smaller
+"Speed Bin" than ddr3 exactly is.
+
+- pd_idle : Config the PD_IDLE value, defined the power-down idle
+period, memories are places into power-down mode if
+bus is idle for PD_IDLE DFI clocks.
+
+- sr_idle : Configure the SR_IDLE value, defined the selfrefresh
+idle period, memories are places into self-refresh
+mode if bus is idle for SR_IDLE*1024 DFI clocks
+(DFI clocks freq is half of dram's clocks), defaule
+value is "0".
+
+- sr_mc_gate_idle : Defined the self-refresh with memory and controller
+clock gating idle period, memories are places into
+self-refresh mode and memory controller clock arg
+gating if bus is idle for sr_mc_gate_idle*1024 DFI
+clocks.
+
+- srpd_lite_idle :  Defined the self-refresh power down idle period,
+memories are places into self-refresh power down
+mode if bus is idle for srpd_lite_idle*1024 DFI
+clocks. This parameter is for LPDDR4 only.
+
+- standby_idle :Defined the standby idle period, memories are places
+into self-refresh than controller, pi, phy and dram
+clock will gating if bus is idle for
+standby_idle * DFI clocks.
+
+- dram_dll_disb_freq :  It's defined the DDR3 dll bypass frequency in MHz
+when ddr freq less than DRAM_DLL_DISB_FREQ, ddr3
+dll will bypssed note: if dll was bypassed, the
+odt also stop working.
+
+- phy_dll_disb_freq :   Defined the PHY dll bypass frequency in MHz (Mega Hz),
+when ddr freq less than DRAM_DLL_DISB_FREQ, phy dll
+will bypssed. note: phy dll and phy odt are
+independent
+
+- ddr3_odt_disb_freq :  When dram type is DDR3, this parameter defined the
+odt disable frequency in MHz (Mega Hz), when ddr
+frequency less then ddr3_odt_disb_freq, the odt
+on dram side and controller side are both disabled.
+
+- ddr3_drv :When dram type is DDR3, this parameter define the
+dram side driver stength in ohm, default value is
+DDR3_DS_40ohm.
+
+- ddr3_odt :When dram type is DDR3, this parameter define the
+dram side ODT stength in ohm, default value is
+DDR3_ODT_120ohm.
+
+- phy_d

[PATCH v9 2/5] PM / devfreq: event: support rockchip dfi controller

2016-09-03 Thread Lin Huang
on rk3399 platform, there is dfi conroller can monitor
ddr load, base on this result, we can do ddr freqency
scaling.

Signed-off-by: Lin Huang 
Signed-off-by: MyungJoo Ham 
Acked-by: Chanwoo Choi 
---
Changes in v9:
-None

Changes in v8:
-None

Changes in v7:
-access need to *4 to get right DDR loading

Changes in v6:
-None

Changes in v5:
-None

Changes in v4:
-None

Changes in v3:
-None

Changes in v2:
-None 

Changes in v1:
-None

 drivers/devfreq/event/Kconfig|   7 +
 drivers/devfreq/event/Makefile   |   1 +
 drivers/devfreq/event/rockchip-dfi.c | 256 +++
 3 files changed, 264 insertions(+)
 create mode 100644 drivers/devfreq/event/rockchip-dfi.c

diff --git a/drivers/devfreq/event/Kconfig b/drivers/devfreq/event/Kconfig
index eb6f74a..20d82c2 100644
--- a/drivers/devfreq/event/Kconfig
+++ b/drivers/devfreq/event/Kconfig
@@ -30,4 +30,11 @@ config DEVFREQ_EVENT_EXYNOS_PPMU
  (Platform Performance Monitoring Unit) counters to estimate the
  utilization of each module.

+config DEVFREQ_EVENT_ROCKCHIP_DFI
+   tristate "ROCKCHIP DFI DEVFREQ event Driver"
+   depends on ARCH_ROCKCHIP
+   help
+ This add the devfreq-event driver for Rockchip SoC. It provides DFI
+ (DDR Monitor Module) driver to count ddr load.
+
 endif # PM_DEVFREQ_EVENT
diff --git a/drivers/devfreq/event/Makefile b/drivers/devfreq/event/Makefile
index 3d6afd3..dda7090 100644
--- a/drivers/devfreq/event/Makefile
+++ b/drivers/devfreq/event/Makefile
@@ -2,3 +2,4 @@

 obj-$(CONFIG_DEVFREQ_EVENT_EXYNOS_NOCP) += exynos-nocp.o
 obj-$(CONFIG_DEVFREQ_EVENT_EXYNOS_PPMU) += exynos-ppmu.o
+obj-$(CONFIG_DEVFREQ_EVENT_ROCKCHIP_DFI) += rockchip-dfi.o
diff --git a/drivers/devfreq/event/rockchip-dfi.c 
b/drivers/devfreq/event/rockchip-dfi.c
new file mode 100644
index 000..43fcc5a
--- /dev/null
+++ b/drivers/devfreq/event/rockchip-dfi.c
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2016, Fuzhou Rockchip Electronics Co., Ltd
+ * Author: Lin Huang 
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define RK3399_DMC_NUM_CH  2
+
+/* DDRMON_CTRL */
+#define DDRMON_CTRL0x04
+#define CLR_DDRMON_CTRL(0x1f << 0)
+#define LPDDR4_EN  (0x10001 << 4)
+#define HARDWARE_EN(0x10001 << 3)
+#define LPDDR3_EN  (0x10001 << 2)
+#define SOFTWARE_EN(0x10001 << 1)
+#define SOFTWARE_DIS   (0x1 << 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
+#define DDRTYPE_SHIFT  13
+#define DDRTYPE_MASK   7
+
+enum {
+   DDR3 = 3,
+   LPDDR3 = 6,
+   LPDDR4 = 7,
+   UNUSED = 0xFF
+};
+
+struct dmc_usage {
+   u32 access;
+   u32 total;
+};
+
+/*
+ * The dfi controller can monitor DDR load. It has an upper and lower threshold
+ * for the operating points. Whenever the usage leaves these bounds an event is
+ * generated to indicate the DDR frequency should be changed.
+ */
+struct rockchip_dfi {
+   struct devfreq_event_dev *edev;
+   struct devfreq_event_desc *desc;
+   struct dmc_usage ch_usage[RK3399_DMC_NUM_CH];
+   struct device *dev;
+   void __iomem *regs;
+   struct regmap *regmap_pmu;
+   struct clk *clk;
+};
+
+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, PMUGRF_OS_REG2, );
+   ddr_type = (val >> DDRTYPE_SHIFT) & DDRTYPE_MASK;
+
+   /* clear DDRMON_CTRL setting */
+   writel_relaxed(CLR_DDRMON_CTRL, dfi_regs + DDRMON_CTRL);
+
+   /* set ddr type to dfi */
+   if (ddr_type == LPDDR3)
+   writel_relaxed(LPDDR3_EN, dfi_regs + DDRMON_CTRL);
+   else if (ddr_type == LPDDR4)
+   writel_relaxed(LPDDR4_EN, dfi_regs + DDRMON_CTRL);
+
+   /* enable count, use software mode */
+   writel_relaxed(SOFTWARE_EN, dfi_regs + DDRMON_CTRL);
+}
+
+static void rockchip_dfi_stop_hardware_counter(struct devfreq_event_dev *edev)
+{
+   struct rockchip_dfi *info = devfreq_

[PATCH v9 1/5] Documentation: bindings: add dt documentation for dfi controller

2016-09-03 Thread Lin Huang
This patch adds the documentation for rockchip dfi devfreq-event driver.

Signed-off-by: Lin Huang 
---
Changes in v9:
- reorder compatible and reg

Changes in v8:
- delete a unuse blank line

Changes in v7:
- None

Changes in v6:
- None

Changes in v5:
- None

Changes in v4:
- None

Changes in v3:
- None

Changes in v2:
- None 

Changes in v1:
- None

 .../bindings/devfreq/event/rockchip-dfi.txt   | 19 +++
 1 file changed, 19 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt

diff --git a/Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt 
b/Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt
new file mode 100644
index 000..f223313
--- /dev/null
+++ b/Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt
@@ -0,0 +1,19 @@
+
+* Rockchip rk3399 DFI device
+
+Required properties:
+- compatible: Must be "rockchip,rk3399-dfi".
+- reg: physical base address of each DFI and length of memory mapped region
+- rockchip,pmu: phandle to the syscon managing the "pmu general register files"
+- clocks: phandles for clock specified in "clock-names" property
+- clock-names : the name of clock used by the DFI, must be "pclk_ddr_mon";
+
+Example:
+   dfi: dfi at 0xff63 {
+   compatible = "rockchip,rk3399-dfi";
+   reg = <0x00 0xff63 0x00 0x4000>;
+   rockchip,pmu = <>;
+   clocks = < PCLK_DDR_MON>;
+   clock-names = "pclk_ddr_mon";
+   status = "disabled";
+   };
-- 
2.6.6



[PATCH v9 0/5] rk3399 support ddr frequency scaling

2016-09-03 Thread Lin Huang
rk3399 platform have dfi controller can monitor ddr load,
and dcf controller to handle ddr register so we can get the
right ddr frequency and make ddr controller happy work(which
will implement in bl31). So we do ddr frequency scaling with
following flow:

 kernelbl31

monitor ddr load
|
|
get_target_rate
|
|   pass rate to bl31
clk_set_rate(ddr) ->run dcf flow
|   |
|   |
wait dcf interrupt<---trigger dcf interrupt
|
|
  return


Lin Huang (5):
  Documentation: bindings: add dt documentation for dfi controller
  PM / devfreq: event: support rockchip dfi controller
  Documentation: bindings: add dt documentation for rk3399 dmc
  PM / devfreq: rockchip: add devfreq driver for rk3399 dmc
  drm/rockchip: Add dmc notifier in vop driver

Following patch:
clk: rockchip: add new clock-type for the ddrclk
clk: rockchip: rk3399: add SCLK_DDRCLK ID for ddrc
clk: rockchip: rk3399: add ddrc clock support
have applied to:
http://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git/v4.9-clk/next


 .../bindings/devfreq/event/rockchip-dfi.txt|  19 +
 .../devicetree/bindings/devfreq/rk3399_dmc.txt | 202 +
 drivers/devfreq/Kconfig|  11 +
 drivers/devfreq/Makefile   |   1 +
 drivers/devfreq/event/Kconfig  |   7 +
 drivers/devfreq/event/Makefile |   1 +
 drivers/devfreq/event/rockchip-dfi.c   | 256 +++
 drivers/devfreq/rk3399_dmc.c   | 480 +
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c| 116 +
 9 files changed, 1093 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt
 create mode 100644 Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt
 create mode 100644 drivers/devfreq/event/rockchip-dfi.c
 create mode 100644 drivers/devfreq/rk3399_dmc.c

-- 
2.6.6



[PATCH 1/5] Documentation: bindings: add dt documentation for dfi controller

2016-09-03 Thread Lin Huang
This patch adds the documentation for rockchip dfi devfreq-event driver.

Signed-off-by: Lin Huang 
---
Changes in v8:
- delete a unuse blank line

Changes in v7:
- None

Changes in v6:
- None

Changes in v5:
- None

Changes in v4:
- None

Changes in v3:
- None

Changes in v2:
- None 

Changes in v1:
- None

 .../bindings/devfreq/event/rockchip-dfi.txt   | 19 +++
 1 file changed, 19 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt

diff --git a/Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt 
b/Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt
new file mode 100644
index 000..d66aca6
--- /dev/null
+++ b/Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt
@@ -0,0 +1,19 @@
+
+* Rockchip rk3399 DFI device
+
+Required properties:
+- compatible: Must be "rockchip,rk3399-dfi".
+- reg: physical base address of each DFI and length of memory mapped region
+- rockchip,pmu: phandle to the syscon managing the "pmu general register files"
+- clocks: phandles for clock specified in "clock-names" property
+- clock-names : the name of clock used by the DFI, must be "pclk_ddr_mon";
+
+Example:
+   dfi: dfi at 0xff63 {
+   reg = <0x00 0xff63 0x00 0x4000>;
+   compatible = "rockchip,rk3399-dfi";
+   rockchip,pmu = <>;
+   clocks = < PCLK_DDR_MON>;
+   clock-names = "pclk_ddr_mon";
+   status = "disabled";
+   };
-- 
2.6.6



[PATCH 0/5] rk3399 support ddr frequency scaling

2016-09-03 Thread Lin Huang
rk3399 platform have dfi controller can monitor ddr load,
and dcf controller to handle ddr register so we can get the
right ddr frequency and make ddr controller happy work(which
will implement in bl31). So we do ddr frequency scaling with
following flow:

 kernelbl31

monitor ddr load
|
|
get_target_rate
|
|   pass rate to bl31
clk_set_rate(ddr) ->run dcf flow
|   |
|   |
wait dcf interrupt<---trigger dcf interrupt
|
|
  return


Lin Huang (5):
  Documentation: bindings: add dt documentation for dfi controller
  PM / devfreq: event: support rockchip dfi controller
  Documentation: bindings: add dt documentation for rk3399 dmc
  PM / devfreq: rockchip: add devfreq driver for rk3399 dmc
  drm/rockchip: Add dmc notifier in vop driver

Following patch:
clk: rockchip: add new clock-type for the ddrclk
clk: rockchip: rk3399: add SCLK_DDRCLK ID for ddrc
clk: rockchip: rk3399: add ddrc clock support
have applied to:
http://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git/v4.9-clk/next


 .../bindings/devfreq/event/rockchip-dfi.txt|  19 +
 .../devicetree/bindings/devfreq/rk3399_dmc.txt | 173 
 drivers/devfreq/Kconfig|  11 +
 drivers/devfreq/Makefile   |   1 +
 drivers/devfreq/event/Kconfig  |   7 +
 drivers/devfreq/event/Makefile |   1 +
 drivers/devfreq/event/rockchip-dfi.c   | 256 +++
 drivers/devfreq/rk3399_dmc.c   | 480 +
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c| 116 +
 9 files changed, 1064 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt
 create mode 100644 Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt
 create mode 100644 drivers/devfreq/event/rockchip-dfi.c
 create mode 100644 drivers/devfreq/rk3399_dmc.c

-- 
2.6.6



[PATCH 5/5] drm/rockchip: Add dmc notifier in vop driver

2016-09-02 Thread Lin Huang
when in ddr frequency scaling process, vop can not do enable or
disable operation, since in dcf we check vop clock to see whether
vop work. If vop work, dcf do ddr frequency scaling when vop
in vblank status, and we need to read vop register to check whether
vop go into vblank status. If vop not work, dcf can do ddr frequency
any time. So when do ddr frequency scaling, you disabled or enable
vop, there may two bad thing happen: 1, the panel flicker(when vop from
disable status change to enable). 2, kernel hang (when vop from enable
status change to disable, dcf need to read vblank status, but if you disable
vop clock, it can not get the status, it will lead soc dead) So we need
register to devfreq notifier, and we can get the dmc status. Also, when
there have two vop enabled, we need to disable dmc, since dcf only base
on one vop vblank time, so the other panel will flicker when do ddr
frequency scaling.

Signed-off-by: Lin Huang 
Reviewed-by: Chanwoo Choi 
---
Changes in v8:
- None

Changes in v7:
- None

Changes in v6:
- fix a build error

Changes in v5:
- improve some nits

Changes in v4:
- register notifier to devfreq_register_notifier
- use DEVFREQ_PRECHANGE and DEVFREQ_POSTCHANGE to get dmc status
- when two vop enable, disable dmc
- when two vop back to one vop, enable dmc

Changes in v3:
- when do vop eanble/disable, dmc will wait until it finish

Changes in v2:
- None

Changes in v1:
- use wait_event instead usleep

 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 116 
 1 file changed, 116 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index efbc41a..a73f3aa 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -19,6 +19,8 @@
 #include 
 #include 

+#include 
+#include 
 #include 
 #include 
 #include 
@@ -118,6 +120,13 @@ struct vop {

const struct vop_data *data;

+   struct devfreq *devfreq;
+   struct devfreq_event_dev *devfreq_event_dev;
+   struct notifier_block dmc_nb;
+   int dmc_in_process;
+   int vop_switch_status;
+   wait_queue_head_t wait_dmc_queue;
+   wait_queue_head_t wait_vop_switch_queue;
uint32_t *regsbak;
void __iomem *regs;

@@ -428,11 +437,47 @@ static void vop_dsp_hold_valid_irq_disable(struct vop 
*vop)
spin_unlock_irqrestore(>irq_lock, flags);
 }

+static int dmc_notify(struct notifier_block *nb, unsigned long event,
+ void *data)
+{
+   struct vop *vop = container_of(nb, struct vop, dmc_nb);
+
+   if (event == DEVFREQ_PRECHANGE) {
+   /*
+* check if vop in enable or disable process,
+* if yes, wait until it finishes, use 200ms as
+* timeout.
+*/
+   if (!wait_event_timeout(vop->wait_vop_switch_queue,
+   !vop->vop_switch_status, HZ / 5))
+   dev_warn(vop->dev,
+"Timeout waiting for vop swtich status\n");
+   vop->dmc_in_process = 1;
+   } else if (event == DEVFREQ_POSTCHANGE) {
+   vop->dmc_in_process = 0;
+   wake_up(>wait_dmc_queue);
+   }
+
+   return NOTIFY_OK;
+}
+
 static int vop_enable(struct drm_crtc *crtc)
 {
struct vop *vop = to_vop(crtc);
+   int num_enabled_crtc = 0;
int ret;

+   /*
+* if in dmc scaling frequency process, wait until it finishes
+* use 200ms as timeout time.
+*/
+   if (!wait_event_timeout(vop->wait_dmc_queue,
+   !vop->dmc_in_process, HZ / 5))
+   dev_warn(vop->dev,
+"Timeout waiting for dmc when vop enable\n");
+
+   vop->vop_switch_status = 1;
+
ret = pm_runtime_get_sync(vop->dev);
if (ret < 0) {
dev_err(vop->dev, "failed to get pm runtime: %d\n", ret);
@@ -479,6 +524,21 @@ static int vop_enable(struct drm_crtc *crtc)

drm_crtc_vblank_on(crtc);

+   vop->vop_switch_status = 0;
+   wake_up(>wait_vop_switch_queue);
+
+   /* check how many VOPs in use now */
+   drm_for_each_crtc(crtc, vop->drm_dev) {
+   if (crtc->state->enable)
+   num_enabled_crtc++;
+   }
+
+   /* if enable two vop, need to disable dmc */
+   if ((num_enabled_crtc > 1) && vop->devfreq) {
+   if (vop->devfreq_event_dev)
+   devfreq_event_disable_edev(vop->devfreq_event_dev);
+   devfreq_suspend_device(vop->devfreq);
+   }
return 0;

 err_disable_aclk:
@@ -489,17 +549,31 @@ err_disable_hclk:
clk_disable(vop->hclk);
 err_put_pm_runtime:
pm_runtime_put_sync(vop->dev);
+   vop->vop_switch_status = 

[PATCH 4/5] PM / devfreq: rockchip: add devfreq driver for rk3399 dmc

2016-09-02 Thread Lin Huang
base on dfi result, we do ddr frequency scaling, register
dmc driver to devfreq framework, and use simple-ondemand
policy.

Signed-off-by: Lin Huang 
Signed-off-by: MyngJoo Ham 
Reviewed-by: Chanwoo Choi 
---
Changes in v8:
- do not use ddr_timing node, get ddr timing directly

Changes in v7:
- remove a blank line

Changes in v6:
- fix some nit suggest by Chanwoo Choi

Changes in v5:
- improve dmc driver suggest by Chanwoo Choi

Changes in v4:
- use arm_smccc_smc() function talk to bl31
- delete rockchip_dmc.c file and config
- delete dmc_notify
- adjust probe order

Changes in v3:
- operate dram setting through sip call
- imporve set rate flow

Changes in v2:
- None

Changes in v1:
- move dfi controller to event
- fix set voltage sequence when set rate fail
- change Kconfig type from tristate to bool
- move unuse EXPORT_SYMBOL_GPL()

 drivers/devfreq/Kconfig  |  11 +
 drivers/devfreq/Makefile |   1 +
 drivers/devfreq/rk3399_dmc.c | 480 +++
 3 files changed, 492 insertions(+)
 create mode 100644 drivers/devfreq/rk3399_dmc.c

diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig
index a5be56e..e848121 100644
--- a/drivers/devfreq/Kconfig
+++ b/drivers/devfreq/Kconfig
@@ -100,6 +100,17 @@ config ARM_TEGRA_DEVFREQ
  It reads ACTMON counters of memory controllers and adjusts the
  operating frequencies and voltages with OPP support.

+config ARM_RK3399_DMC_DEVFREQ
+   tristate "ARM RK3399 DMC DEVFREQ Driver"
+   depends on ARCH_ROCKCHIP
+   select DEVFREQ_EVENT_ROCKCHIP_DFI
+   select DEVFREQ_GOV_SIMPLE_ONDEMAND
+   select PM_OPP
+   help
+  This adds the DEVFREQ driver for the RK3399 DMC(Dynamic Memory 
Controller).
+  It sets the frequency for the memory controller and reads the usage 
counts
+  from hardware.
+
 source "drivers/devfreq/event/Kconfig"

 endif # PM_DEVFREQ
diff --git a/drivers/devfreq/Makefile b/drivers/devfreq/Makefile
index 09f11d9..fbff40a 100644
--- a/drivers/devfreq/Makefile
+++ b/drivers/devfreq/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_DEVFREQ_GOV_PASSIVE)   += governor_passive.o

 # DEVFREQ Drivers
 obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ)   += exynos-bus.o
+obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ)   += rk3399_dmc.o
 obj-$(CONFIG_ARM_TEGRA_DEVFREQ)+= tegra-devfreq.o

 # DEVFREQ Event Drivers
diff --git a/drivers/devfreq/rk3399_dmc.c b/drivers/devfreq/rk3399_dmc.c
new file mode 100644
index 000..54d65f2
--- /dev/null
+++ b/drivers/devfreq/rk3399_dmc.c
@@ -0,0 +1,480 @@
+/*
+ * Copyright (c) 2016, Fuzhou Rockchip Electronics Co., Ltd.
+ * Author: Lin Huang 
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+struct dram_timing {
+   unsigned int ddr3_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 dram_dll_dis_freq;
+   unsigned int phy_dll_dis_freq;
+   unsigned int ddr3_odt_dis_freq;
+   unsigned int ddr3_drv;
+   unsigned int ddr3_odt;
+   unsigned int phy_ddr3_ca_drv;
+   unsigned int phy_ddr3_dq_drv;
+   unsigned int phy_ddr3_odt;
+   unsigned int lpddr3_odt_dis_freq;
+   unsigned int lpddr3_drv;
+   unsigned int lpddr3_odt;
+   unsigned int phy_lpddr3_ca_drv;
+   unsigned int phy_lpddr3_dq_drv;
+   unsigned int phy_lpddr3_odt;
+   unsigned int 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;
+};
+
+struct rk3399_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 dram_timing timing;
+
+   /*
+* DDR Converser of Frequency (DCF) is used to implement DDR frequency
+* conversion without the participation of CPU, we will implement and
+* control it in arm trust firmware.
+*/
+   wait_queue_head_t   wait_dcf_queue;
+   int irq;
+   int wait_dcf_flag;
+   

[PATCH 3/5] Documentation: bindings: add dt documentation for rk3399 dmc

2016-09-02 Thread Lin Huang
This patch adds the documentation for rockchip rk3399 dmc driver.

Signed-off-by: Lin Huang 
---
Changes in v8:
- add ddr timing properties

Changes in v7:
-None

Changes in v6:
-Add more detail in Documentation

Changes in v5:
-None

Changes in v4:
-None

Changes in v3:
-None

Changes in v2:
-None 

Changes in v1:
-None

 .../devicetree/bindings/devfreq/rk3399_dmc.txt | 173 +
 1 file changed, 173 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt

diff --git a/Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt 
b/Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt
new file mode 100644
index 000..1f39b5cb
--- /dev/null
+++ b/Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt
@@ -0,0 +1,173 @@
+* Rockchip rk3399 DMC(Dynamic Memory Controller) device
+
+Required properties:
+- compatible:   Must be "rockchip,rk3399-dmc".
+- devfreq-events:   Node to get DDR loading, Refer to
+Documentation/devicetree/bindings/devfreq/
+rockchip-dfi.txt
+- interrupts:   The interrupt number to the CPU. The interrupt
+specifier format depends on the interrupt controller.
+It should be DCF interrupts, when DDR dvfs finish,
+it will happen.
+- clocks:   Phandles for clock specified in "clock-names" property
+- clock-names : The name of clock used by the DFI, must be
+"pclk_ddr_mon";
+- operating-points-v2:  Refer to 
Documentation/devicetree/bindings/power/opp.txt
+for details.
+- center-supply:DMC supply node.
+- status:   Marks the node enabled/disabled.
+
+Following properties are ddr timing:
+
+- dram_speed_bin :  Value is defined at include/dt-bindings/clock/ddr.h,
+it select ddr3 cl-trp-trcd type, default value
+"DDR3_DEFAULT".it must selected according to
+"Speed Bin" in ddr3 datasheet, DO NOT use smaller
+"Speed Bin" than ddr3 exactly is.
+
+- pd_idle : Config the PD_IDLE value, defined the power-down idle
+period, memories are places into power-down mode if
+bus is idle for PD_IDLE DFI clocks.
+
+- sr_idle : Configure the SR_IDLE value, defined the selfrefresh
+idle period, memories are places into self-refresh
+mode if bus is idle for SR_IDLE*1024 DFI clocks
+(DFI clocks freq is half of dram's clocks), defaule
+value is "0".
+
+- sr_mc_gate_idle : Defined the self-refresh with memory and controller
+clock gating idle period, memories are places into
+self-refresh mode and memory controller clock arg
+gating if bus is idle for sr_mc_gate_idle*1024 DFI
+clocks.
+
+- srpd_lite_idle :  Defined the self-refresh power down idle period,
+memories are places into self-refresh power down
+mode if bus is idle for srpd_lite_idle*1024 DFI
+clocks. This parameter is for LPDDR4 only.
+
+- standby_idle :Defined the standby idle period, memories are places
+into self-refresh than controller, pi, phy and dram
+clock will gating if bus is idle for
+standby_idle * DFI clocks.
+
+- dram_dll_disb_freq :  It's defined the DDR3 dll bypass frequency in MHz
+when ddr freq less than DRAM_DLL_DISB_FREQ, ddr3
+dll will bypssed note: if dll was bypassed, the
+odt also stop working.
+
+- phy_dll_disb_freq :   Defined the PHY dll bypass frequency in MHz (Mega Hz),
+when ddr freq less than DRAM_DLL_DISB_FREQ, phy dll
+will bypssed. note: phy dll and phy odt are
+independent
+
+- ddr3_odt_disb_freq :  When dram type is DDR3, this parameter defined the
+odt disable frequency in MHz (Mega Hz), when ddr
+frequency less then ddr3_odt_disb_freq, the odt
+on dram side and controller side are both disabled.
+
+- ddr3_drv :When dram type is DDR3, this parameter define the
+dram side driver stength in ohm, default value is
+DDR3_DS_40ohm.
+
+- ddr3_odt :When dram type is DDR3, this parameter define the
+dram side ODT stength in ohm, default value is
+DDR3_ODT_120ohm.
+
+- phy_ddr3_ca_drv : When dram type is DDR3, this parameter

[PATCH 2/5] PM / devfreq: event: support rockchip dfi controller

2016-09-02 Thread Lin Huang
on rk3399 platform, there is dfi conroller can monitor
ddr load, base on this result, we can do ddr freqency
scaling.

Signed-off-by: Lin Huang 
Signed-off-by: MyungJoo Ham 
Acked-by: Chanwoo Choi 
---
Changes in v8:
-None

Changes in v7:
-access need to *4 to get right DDR loading

Changes in v6:
-None

Changes in v5:
-None

Changes in v4:
-None

Changes in v3:
-None

Changes in v2:
-None 

Changes in v1:
-None

 drivers/devfreq/event/Kconfig|   7 +
 drivers/devfreq/event/Makefile   |   1 +
 drivers/devfreq/event/rockchip-dfi.c | 256 +++
 3 files changed, 264 insertions(+)
 create mode 100644 drivers/devfreq/event/rockchip-dfi.c

diff --git a/drivers/devfreq/event/Kconfig b/drivers/devfreq/event/Kconfig
index eb6f74a..20d82c2 100644
--- a/drivers/devfreq/event/Kconfig
+++ b/drivers/devfreq/event/Kconfig
@@ -30,4 +30,11 @@ config DEVFREQ_EVENT_EXYNOS_PPMU
  (Platform Performance Monitoring Unit) counters to estimate the
  utilization of each module.

+config DEVFREQ_EVENT_ROCKCHIP_DFI
+   tristate "ROCKCHIP DFI DEVFREQ event Driver"
+   depends on ARCH_ROCKCHIP
+   help
+ This add the devfreq-event driver for Rockchip SoC. It provides DFI
+ (DDR Monitor Module) driver to count ddr load.
+
 endif # PM_DEVFREQ_EVENT
diff --git a/drivers/devfreq/event/Makefile b/drivers/devfreq/event/Makefile
index 3d6afd3..dda7090 100644
--- a/drivers/devfreq/event/Makefile
+++ b/drivers/devfreq/event/Makefile
@@ -2,3 +2,4 @@

 obj-$(CONFIG_DEVFREQ_EVENT_EXYNOS_NOCP) += exynos-nocp.o
 obj-$(CONFIG_DEVFREQ_EVENT_EXYNOS_PPMU) += exynos-ppmu.o
+obj-$(CONFIG_DEVFREQ_EVENT_ROCKCHIP_DFI) += rockchip-dfi.o
diff --git a/drivers/devfreq/event/rockchip-dfi.c 
b/drivers/devfreq/event/rockchip-dfi.c
new file mode 100644
index 000..43fcc5a
--- /dev/null
+++ b/drivers/devfreq/event/rockchip-dfi.c
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2016, Fuzhou Rockchip Electronics Co., Ltd
+ * Author: Lin Huang 
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define RK3399_DMC_NUM_CH  2
+
+/* DDRMON_CTRL */
+#define DDRMON_CTRL0x04
+#define CLR_DDRMON_CTRL(0x1f << 0)
+#define LPDDR4_EN  (0x10001 << 4)
+#define HARDWARE_EN(0x10001 << 3)
+#define LPDDR3_EN  (0x10001 << 2)
+#define SOFTWARE_EN(0x10001 << 1)
+#define SOFTWARE_DIS   (0x1 << 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
+#define DDRTYPE_SHIFT  13
+#define DDRTYPE_MASK   7
+
+enum {
+   DDR3 = 3,
+   LPDDR3 = 6,
+   LPDDR4 = 7,
+   UNUSED = 0xFF
+};
+
+struct dmc_usage {
+   u32 access;
+   u32 total;
+};
+
+/*
+ * The dfi controller can monitor DDR load. It has an upper and lower threshold
+ * for the operating points. Whenever the usage leaves these bounds an event is
+ * generated to indicate the DDR frequency should be changed.
+ */
+struct rockchip_dfi {
+   struct devfreq_event_dev *edev;
+   struct devfreq_event_desc *desc;
+   struct dmc_usage ch_usage[RK3399_DMC_NUM_CH];
+   struct device *dev;
+   void __iomem *regs;
+   struct regmap *regmap_pmu;
+   struct clk *clk;
+};
+
+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, PMUGRF_OS_REG2, );
+   ddr_type = (val >> DDRTYPE_SHIFT) & DDRTYPE_MASK;
+
+   /* clear DDRMON_CTRL setting */
+   writel_relaxed(CLR_DDRMON_CTRL, dfi_regs + DDRMON_CTRL);
+
+   /* set ddr type to dfi */
+   if (ddr_type == LPDDR3)
+   writel_relaxed(LPDDR3_EN, dfi_regs + DDRMON_CTRL);
+   else if (ddr_type == LPDDR4)
+   writel_relaxed(LPDDR4_EN, dfi_regs + DDRMON_CTRL);
+
+   /* enable count, use software mode */
+   writel_relaxed(SOFTWARE_EN, dfi_regs + DDRMON_CTRL);
+}
+
+static void rockchip_dfi_stop_hardware_counter(struct devfreq_event_dev *edev)
+{
+   struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
+

[PATCH 1/5] Documentation: bindings: add dt documentation for dfi controller

2016-09-02 Thread Lin Huang
This patch adds the documentation for rockchip dfi devfreq-event driver.

Signed-off-by: Lin Huang 
---
Changes in v8:
- delete a unuse blank line

Changes in v7:
- None

Changes in v6:
- None

Changes in v5:
- None

Changes in v4:
- None

Changes in v3:
- None

Changes in v2:
- None 

Changes in v1:
- None

 .../bindings/devfreq/event/rockchip-dfi.txt   | 19 +++
 1 file changed, 19 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt

diff --git a/Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt 
b/Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt
new file mode 100644
index 000..d66aca6
--- /dev/null
+++ b/Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt
@@ -0,0 +1,19 @@
+
+* Rockchip rk3399 DFI device
+
+Required properties:
+- compatible: Must be "rockchip,rk3399-dfi".
+- reg: physical base address of each DFI and length of memory mapped region
+- rockchip,pmu: phandle to the syscon managing the "pmu general register files"
+- clocks: phandles for clock specified in "clock-names" property
+- clock-names : the name of clock used by the DFI, must be "pclk_ddr_mon";
+
+Example:
+   dfi: dfi at 0xff63 {
+   reg = <0x00 0xff63 0x00 0x4000>;
+   compatible = "rockchip,rk3399-dfi";
+   rockchip,pmu = <>;
+   clocks = < PCLK_DDR_MON>;
+   clock-names = "pclk_ddr_mon";
+   status = "disabled";
+   };
-- 
2.6.6



[PATCH 0/5] rk3399 support ddr frequency scaling

2016-09-02 Thread Lin Huang
rk3399 platform have dfi controller can monitor ddr load,
and dcf controller to handle ddr register so we can get the
right ddr frequency and make ddr controller happy work(which
will implement in bl31). So we do ddr frequency scaling with
following flow:

 kernelbl31

monitor ddr load
|
|
get_target_rate
|
|   pass rate to bl31
clk_set_rate(ddr) ->run dcf flow
|   |
|   |
wait dcf interrupt<---trigger dcf interrupt
|
|
  return


Lin Huang (5):
  Documentation: bindings: add dt documentation for dfi controller
  PM / devfreq: event: support rockchip dfi controller
  Documentation: bindings: add dt documentation for rk3399 dmc
  PM / devfreq: rockchip: add devfreq driver for rk3399 dmc
  drm/rockchip: Add dmc notifier in vop driver

Following patch:
clk: rockchip: add new clock-type for the ddrclk
clk: rockchip: rk3399: add SCLK_DDRCLK ID for ddrc
clk: rockchip: rk3399: add ddrc clock support
have applied to:
http://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git/v4.9-clk/next


 .../bindings/devfreq/event/rockchip-dfi.txt|  19 +
 .../devicetree/bindings/devfreq/rk3399_dmc.txt | 173 
 drivers/devfreq/Kconfig|  11 +
 drivers/devfreq/Makefile   |   1 +
 drivers/devfreq/event/Kconfig  |   7 +
 drivers/devfreq/event/Makefile |   1 +
 drivers/devfreq/event/rockchip-dfi.c   | 256 +++
 drivers/devfreq/rk3399_dmc.c   | 480 +
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c| 116 +
 9 files changed, 1064 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt
 create mode 100644 Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt
 create mode 100644 drivers/devfreq/event/rockchip-dfi.c
 create mode 100644 drivers/devfreq/rk3399_dmc.c

-- 
2.6.6



[PATCH v7 8/8] drm/rockchip: Add dmc notifier in vop driver

2016-08-22 Thread Lin Huang
when in ddr frequency scaling process, vop can not do enable or
disable operation, since in dcf we check vop clock to see whether
vop work. If vop work, dcf do ddr frequency scaling when vop
in vblank status, and we need to read vop register to check whether
vop go into vblank status. If vop not work, dcf can do ddr frequency
any time. So when do ddr frequency scaling, you disabled or enable
vop, there may two bad thing happen: 1, the panel flicker(when vop from
disable status change to enable). 2, kernel hang (when vop from enable
status change to disable, dcf need to read vblank status, but if you disable
vop clock, it can not get the status, it will lead soc dead) So we need
register to devfreq notifier, and we can get the dmc status. Also, when
there have two vop enabled, we need to disable dmc, since dcf only base
on one vop vblank time, so the other panel will flicker when do ddr
frequency scaling.

Signed-off-by: Lin Huang 
Reviewed-by: Chanwoo Choi 
---
Changes in v7:
- None

Changes in v6:
- fix a build error

Changes in v5:
- improve some nits

Changes in v4:
- register notifier to devfreq_register_notifier
- use DEVFREQ_PRECHANGE and DEVFREQ_POSTCHANGE to get dmc status
- when two vop enable, disable dmc
- when two vop back to one vop, enable dmc

Changes in v3:
- when do vop eanble/disable, dmc will wait until it finish

Changes in v2:
- None

Changes in v1:
- use wait_event instead usleep

 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 127 ++--
 1 file changed, 122 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index ec8ad00..a76e70c 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -12,6 +12,8 @@
  * GNU General Public License for more details.
  */

+#include 
+#include 
 #include 
 #include 
 #include 
@@ -118,6 +120,13 @@ struct vop {

const struct vop_data *data;

+   struct devfreq *devfreq;
+   struct devfreq_event_dev *devfreq_event_dev;
+   struct notifier_block dmc_nb;
+   int dmc_in_process;
+   int vop_switch_status;
+   wait_queue_head_t wait_dmc_queue;
+   wait_queue_head_t wait_vop_switch_queue;
uint32_t *regsbak;
void __iomem *regs;

@@ -428,21 +437,59 @@ static void vop_dsp_hold_valid_irq_disable(struct vop 
*vop)
spin_unlock_irqrestore(>irq_lock, flags);
 }

+static int dmc_notify(struct notifier_block *nb, unsigned long event,
+ void *data)
+{
+   struct vop *vop = container_of(nb, struct vop, dmc_nb);
+
+   if (event == DEVFREQ_PRECHANGE) {
+   /*
+* check if vop in enable or disable process,
+* if yes, wait until it finishes, use 200ms as
+* timeout.
+*/
+   if (!wait_event_timeout(vop->wait_vop_switch_queue,
+   !vop->vop_switch_status, HZ / 5))
+   dev_warn(vop->dev,
+"Timeout waiting for vop swtich status\n");
+   vop->dmc_in_process = 1;
+   } else if (event == DEVFREQ_POSTCHANGE) {
+   vop->dmc_in_process = 0;
+   wake_up(>wait_dmc_queue);
+   }
+
+   return NOTIFY_OK;
+}
+
 static void vop_enable(struct drm_crtc *crtc)
 {
struct vop *vop = to_vop(crtc);
+   int num_enabled_crtc = 0;
int ret;

+   if (vop->is_enabled)
+   return;
+
+   /*
+* if in dmc scaling frequency process, wait until it finishes
+* use 100ms as timeout time.
+*/
+   if (!wait_event_timeout(vop->wait_dmc_queue,
+   !vop->dmc_in_process, HZ / 5))
+   dev_warn(vop->dev,
+"Timeout waiting for dmc when vop enable\n");
+
+   vop->vop_switch_status = 1;
ret = pm_runtime_get_sync(vop->dev);
if (ret < 0) {
dev_err(vop->dev, "failed to get pm runtime: %d\n", ret);
-   return;
+   goto err;
}

ret = clk_enable(vop->hclk);
if (ret < 0) {
dev_err(vop->dev, "failed to enable hclk - %d\n", ret);
-   return;
+   goto err;
}

ret = clk_enable(vop->dclk);
@@ -456,7 +503,6 @@ static void vop_enable(struct drm_crtc *crtc)
dev_err(vop->dev, "failed to enable aclk - %d\n", ret);
goto err_disable_dclk;
}
-
/*
 * Slave iommu shares power, irq and clock with vop.  It was associated
 * automatically with this master device via common driver code.
@@ -485,6 +531,21 @@ static void vop_enable(struct drm_crtc *crtc)

drm_crtc_vblank_on(crtc);

+   vop->vop_switch_status = 0;
+   wake_up(&g

[PATCH v7 7/8] PM / devfreq: rockchip: add devfreq driver for rk3399 dmc

2016-08-22 Thread Lin Huang
base on dfi result, we do ddr frequency scaling, register
dmc driver to devfreq framework, and use simple-ondemand
policy.

Signed-off-by: Lin Huang 
Reviewed-by: Chanwoo Choi 
---
Changes in v7:
- remove a blank line

Changes in v6:
- fix some nit suggest by Chanwoo Choi

Changes in v5:
- improve dmc driver suggest by Chanwoo Choi

Changes in v4:
- use arm_smccc_smc() function talk to bl31
- delete rockchip_dmc.c file and config
- delete dmc_notify
- adjust probe order

Changes in v3:
- operate dram setting through sip call
- imporve set rate flow

Changes in v2:
- None

Changes in v1:
- move dfi controller to event
- fix set voltage sequence when set rate fail
- change Kconfig type from tristate to bool
- move unuse EXPORT_SYMBOL_GPL()

 drivers/devfreq/Kconfig  |  11 +
 drivers/devfreq/Makefile |   1 +
 drivers/devfreq/rk3399_dmc.c | 499 +++
 3 files changed, 511 insertions(+)
 create mode 100644 drivers/devfreq/rk3399_dmc.c

diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig
index a5be56e..e848121 100644
--- a/drivers/devfreq/Kconfig
+++ b/drivers/devfreq/Kconfig
@@ -100,6 +100,17 @@ config ARM_TEGRA_DEVFREQ
  It reads ACTMON counters of memory controllers and adjusts the
  operating frequencies and voltages with OPP support.

+config ARM_RK3399_DMC_DEVFREQ
+   tristate "ARM RK3399 DMC DEVFREQ Driver"
+   depends on ARCH_ROCKCHIP
+   select DEVFREQ_EVENT_ROCKCHIP_DFI
+   select DEVFREQ_GOV_SIMPLE_ONDEMAND
+   select PM_OPP
+   help
+  This adds the DEVFREQ driver for the RK3399 DMC(Dynamic Memory 
Controller).
+  It sets the frequency for the memory controller and reads the usage 
counts
+  from hardware.
+
 source "drivers/devfreq/event/Kconfig"

 endif # PM_DEVFREQ
diff --git a/drivers/devfreq/Makefile b/drivers/devfreq/Makefile
index 09f11d9..fbff40a 100644
--- a/drivers/devfreq/Makefile
+++ b/drivers/devfreq/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_DEVFREQ_GOV_PASSIVE)   += governor_passive.o

 # DEVFREQ Drivers
 obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ)   += exynos-bus.o
+obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ)   += rk3399_dmc.o
 obj-$(CONFIG_ARM_TEGRA_DEVFREQ)+= tegra-devfreq.o

 # DEVFREQ Event Drivers
diff --git a/drivers/devfreq/rk3399_dmc.c b/drivers/devfreq/rk3399_dmc.c
new file mode 100644
index 000..b73a73c
--- /dev/null
+++ b/drivers/devfreq/rk3399_dmc.c
@@ -0,0 +1,499 @@
+/*
+ * Copyright (c) 2016, Fuzhou Rockchip Electronics Co., Ltd.
+ * Author: Lin Huang 
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+struct dram_timing {
+   unsigned int ddr3_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 dram_dll_dis_freq;
+   unsigned int phy_dll_dis_freq;
+   unsigned int ddr3_odt_dis_freq;
+   unsigned int ddr3_drv;
+   unsigned int ddr3_odt;
+   unsigned int phy_ddr3_ca_drv;
+   unsigned int phy_ddr3_dq_drv;
+   unsigned int phy_ddr3_odt;
+   unsigned int lpddr3_odt_dis_freq;
+   unsigned int lpddr3_drv;
+   unsigned int lpddr3_odt;
+   unsigned int phy_lpddr3_ca_drv;
+   unsigned int phy_lpddr3_dq_drv;
+   unsigned int phy_lpddr3_odt;
+   unsigned int 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;
+};
+
+struct rk3399_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 dram_timing *timing;
+
+   /*
+* DDR Converser of Frequency (DCF) is used to implement DDR frequency
+* conversion without the participation of CPU, we will implement and
+* control it in arm trust firmware.
+*/
+   wait_queue_head_t   wait_dcf_queue;
+   int irq;
+   int wait_dcf_flag;
+   struct regulator *vdd_center;
+   unsigned long rate, target_rate;
+   unsigned long volt, target_volt;
+   struct 

[PATCH v7 6/8] Documentation: bindings: add dt documentation for rk3399 dmc

2016-08-22 Thread Lin Huang
This patch adds the documentation for rockchip rk3399 dmc driver.

Signed-off-by: Lin Huang 
---
Changes in v7:
-None

Changes in v6:
-Add more detail in Documentation

Changes in v5:
-None

Changes in v4:
-None

Changes in v3:
-None

Changes in v2:
-None 

Changes in v1:
-None
 .../devicetree/bindings/devfreq/rk3399_dmc.txt | 85 ++
 1 file changed, 85 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt

diff --git a/Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt 
b/Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt
new file mode 100644
index 000..b787abb
--- /dev/null
+++ b/Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt
@@ -0,0 +1,85 @@
+* Rockchip rk3399 DMC(Dynamic Memory Controller) device
+
+Required properties:
+- compatible: Must be "rockchip,rk3399-dmc".
+- devfreq-events: Node to get DDR loading, Refer to
+ Documentation/devicetree/bindings/devfreq/rockchip-dfi.txt
+- interrupts: The interrupt number to the CPU. The interrupt specifier format
+ depends on the interrupt controller. It should be DCF interrupts,
+ when DDR dvfs finish, it will happen.
+- clocks: Phandles for clock specified in "clock-names" property
+- clock-names : The name of clock used by the DFI, must be "pclk_ddr_mon";
+- operating-points-v2: Refer to Documentation/devicetree/bindings/power/opp.txt
+  for details.
+- center-supply: DMC supply node.
+- status: Marks the node enabled/disabled.
+
+Optional properties:
+- ddr_timing:  DDR timing need to pass to arm trust firmware
+- upthreshold: The upthreshold to simpleondeamnd policy
+- downdifferential: The downdifferential to simpleondeamnd policy
+
+Example:
+
+   ddr_timing: ddr_timing {
+   compatible = "rockchip,ddr-timing";
+   ddr3_speed_bin = <21>;
+   pd_idle = <0>;
+   sr_idle = <0>;
+   sr_mc_gate_idle = <0>;
+   srpd_lite_idle  = <0>;
+   standby_idle = <0>;
+   dram_dll_dis_freq = <300>;
+   phy_dll_dis_freq = <125>;
+
+   ddr3_odt_dis_freq = <333>;
+   ddr3_drv = ;
+   ddr3_odt = ;
+   phy_ddr3_ca_drv = ;
+   phy_ddr3_dq_drv = ;
+   phy_ddr3_odt = ;
+
+   lpddr3_odt_dis_freq = <333>;
+   lpddr3_drv = ;
+   lpddr3_odt = ;
+   phy_lpddr3_ca_drv = ;
+   phy_lpddr3_dq_drv = ;
+   phy_lpddr3_odt = ;
+
+   lpddr4_odt_dis_freq = <333>;
+   lpddr4_drv = ;
+   lpddr4_dq_odt = ;
+   lpddr4_ca_odt = ;
+   phy_lpddr4_ca_drv = ;
+   phy_lpddr4_ck_cs_drv = ;
+   phy_lpddr4_dq_drv = ;
+   phy_lpddr4_odt = ;
+   };
+
+   dmc_opp_table: dmc_opp_table {
+   compatible = "operating-points-v2";
+
+   opp00 {
+   opp-hz = /bits/ 64 <3>;
+   opp-microvolt = <90>;
+   };
+   opp01 {
+   opp-hz = /bits/ 64 <66600>;
+   opp-microvolt = <90>;
+   };
+   };
+
+   dmc: dmc {
+   compatible = "rockchip,rk3399-dmc";
+   devfreq-events = <>;
+   interrupts = ;
+   clocks = < SCLK_DDRCLK>;
+   clock-names = "dmc_clk";
+   ddr_timing = <_timing>;
+   operating-points-v2 = <_opp_table>;
+   center-supply = <_centerlogic>;
+   upthreshold = <15>;
+   downdifferential = <10>;
+   status = "disabled";
+   };
+
-- 
2.6.6



[PATCH v7 5/8] PM / devfreq: event: support rockchip dfi controller

2016-08-22 Thread Lin Huang
on rk3399 platform, there is dfi conroller can monitor
ddr load, base on this result, we can do ddr freqency
scaling.

Signed-off-by: Lin Huang 
Acked-by: Chanwoo Choi 
---
Changes in v7:
-access need to *4 to get right DDR loading

Changes in v6:
-None

Changes in v5:
-None

Changes in v4:
-None

Changes in v3:
-None

Changes in v2:
-None 

Changes in v1:
-None

 drivers/devfreq/event/Kconfig|   7 +
 drivers/devfreq/event/Makefile   |   1 +
 drivers/devfreq/event/rockchip-dfi.c | 256 +++
 3 files changed, 264 insertions(+)
 create mode 100644 drivers/devfreq/event/rockchip-dfi.c

diff --git a/drivers/devfreq/event/Kconfig b/drivers/devfreq/event/Kconfig
index eb6f74a..20d82c2 100644
--- a/drivers/devfreq/event/Kconfig
+++ b/drivers/devfreq/event/Kconfig
@@ -30,4 +30,11 @@ config DEVFREQ_EVENT_EXYNOS_PPMU
  (Platform Performance Monitoring Unit) counters to estimate the
  utilization of each module.

+config DEVFREQ_EVENT_ROCKCHIP_DFI
+   tristate "ROCKCHIP DFI DEVFREQ event Driver"
+   depends on ARCH_ROCKCHIP
+   help
+ This add the devfreq-event driver for Rockchip SoC. It provides DFI
+ (DDR Monitor Module) driver to count ddr load.
+
 endif # PM_DEVFREQ_EVENT
diff --git a/drivers/devfreq/event/Makefile b/drivers/devfreq/event/Makefile
index 3d6afd3..dda7090 100644
--- a/drivers/devfreq/event/Makefile
+++ b/drivers/devfreq/event/Makefile
@@ -2,3 +2,4 @@

 obj-$(CONFIG_DEVFREQ_EVENT_EXYNOS_NOCP) += exynos-nocp.o
 obj-$(CONFIG_DEVFREQ_EVENT_EXYNOS_PPMU) += exynos-ppmu.o
+obj-$(CONFIG_DEVFREQ_EVENT_ROCKCHIP_DFI) += rockchip-dfi.o
diff --git a/drivers/devfreq/event/rockchip-dfi.c 
b/drivers/devfreq/event/rockchip-dfi.c
new file mode 100644
index 000..43fcc5a
--- /dev/null
+++ b/drivers/devfreq/event/rockchip-dfi.c
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2016, Fuzhou Rockchip Electronics Co., Ltd
+ * Author: Lin Huang 
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define RK3399_DMC_NUM_CH  2
+
+/* DDRMON_CTRL */
+#define DDRMON_CTRL0x04
+#define CLR_DDRMON_CTRL(0x1f << 0)
+#define LPDDR4_EN  (0x10001 << 4)
+#define HARDWARE_EN(0x10001 << 3)
+#define LPDDR3_EN  (0x10001 << 2)
+#define SOFTWARE_EN(0x10001 << 1)
+#define SOFTWARE_DIS   (0x1 << 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
+#define DDRTYPE_SHIFT  13
+#define DDRTYPE_MASK   7
+
+enum {
+   DDR3 = 3,
+   LPDDR3 = 6,
+   LPDDR4 = 7,
+   UNUSED = 0xFF
+};
+
+struct dmc_usage {
+   u32 access;
+   u32 total;
+};
+
+/*
+ * The dfi controller can monitor DDR load. It has an upper and lower threshold
+ * for the operating points. Whenever the usage leaves these bounds an event is
+ * generated to indicate the DDR frequency should be changed.
+ */
+struct rockchip_dfi {
+   struct devfreq_event_dev *edev;
+   struct devfreq_event_desc *desc;
+   struct dmc_usage ch_usage[RK3399_DMC_NUM_CH];
+   struct device *dev;
+   void __iomem *regs;
+   struct regmap *regmap_pmu;
+   struct clk *clk;
+};
+
+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, PMUGRF_OS_REG2, );
+   ddr_type = (val >> DDRTYPE_SHIFT) & DDRTYPE_MASK;
+
+   /* clear DDRMON_CTRL setting */
+   writel_relaxed(CLR_DDRMON_CTRL, dfi_regs + DDRMON_CTRL);
+
+   /* set ddr type to dfi */
+   if (ddr_type == LPDDR3)
+   writel_relaxed(LPDDR3_EN, dfi_regs + DDRMON_CTRL);
+   else if (ddr_type == LPDDR4)
+   writel_relaxed(LPDDR4_EN, dfi_regs + DDRMON_CTRL);
+
+   /* enable count, use software mode */
+   writel_relaxed(SOFTWARE_EN, dfi_regs + DDRMON_CTRL);
+}
+
+static void rockchip_dfi_stop_hardware_counter(struct devfreq_event_dev *edev)
+{
+   struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
+   void __iomem *dfi_regs = info->regs;
+
+  

[PATCH v7 4/8] Documentation: bindings: add dt documentation for dfi controller

2016-08-22 Thread Lin Huang
This patch adds the documentation for rockchip dfi devfreq-event driver.

Signed-off-by: Lin Huang 
---
Changes in v7:
-None

Changes in v6:
-None

Changes in v5:
-None

Changes in v4:
-None

Changes in v3:
-None

Changes in v2:
-None 

Changes in v1:
-None
 .../bindings/devfreq/event/rockchip-dfi.txt  | 20 
 1 file changed, 20 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt

diff --git a/Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt 
b/Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt
new file mode 100644
index 000..bf42255
--- /dev/null
+++ b/Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt
@@ -0,0 +1,20 @@
+
+* Rockchip rk3399 DFI device
+
+Required properties:
+- compatible: Must be "rockchip,rk3399-dfi".
+- reg: physical base address of each DFI and length of memory mapped region
+- rockchip,pmu: phandle to the syscon managing the "pmu general register files"
+- clocks: phandles for clock specified in "clock-names" property
+- clock-names : the name of clock used by the DFI, must be "pclk_ddr_mon";
+
+Example:
+   dfi: dfi at 0xff63 {
+   reg = <0x00 0xff63 0x00 0x4000>;
+   compatible = "rockchip,rk3399-dfi";
+   rockchip,pmu = <>;
+   clocks = < PCLK_DDR_MON>;
+   clock-names = "pclk_ddr_mon";
+   status = "disabled";
+   };
+
-- 
2.6.6



[PATCH v7 3/8] clk: rockchip: rk3399: add ddrc clock support

2016-08-22 Thread Lin Huang
add ddrc clock setting, so we can do ddr frequency
scaling on rk3399 platform in future.

Signed-off-by: Lin Huang 
---
Changes in v7:
- change SCLK_DDRC name from clk_ddrc to sclk_ddrc

Changes in v6:
- None

Changes in v5:
- fit for the ddr type

Changes in v4:
- None

Changes in v3:
- None

Changes in v2:
- remove clk_ddrc_dpll_src from critical clock list

Changes in v1:
- remove ddrc source CLK_IGNORE_UNUSED flag
- move clk_ddrc and clk_ddrc_dpll_src to critical

 drivers/clk/rockchip/clk-rk3399.c | 19 +++
 1 file changed, 19 insertions(+)

diff --git a/drivers/clk/rockchip/clk-rk3399.c 
b/drivers/clk/rockchip/clk-rk3399.c
index e445cd6..134bd18 100644
--- a/drivers/clk/rockchip/clk-rk3399.c
+++ b/drivers/clk/rockchip/clk-rk3399.c
@@ -120,6 +120,10 @@ PNAME(mux_armclkb_p)   = { 
"clk_core_b_lpll_src",
"clk_core_b_bpll_src",
"clk_core_b_dpll_src",
"clk_core_b_gpll_src" };
+PNAME(mux_ddrclk_p)= { "clk_ddrc_lpll_src",
+   "clk_ddrc_bpll_src",
+   "clk_ddrc_dpll_src",
+   "clk_ddrc_gpll_src" };
 PNAME(mux_aclk_cci_p)  = { "cpll_aclk_cci_src",
"gpll_aclk_cci_src",
"npll_aclk_cci_src",
@@ -1379,6 +1383,18 @@ static struct rockchip_clk_branch rk3399_clk_branches[] 
__initdata = {
COMPOSITE_NOMUX(0, "clk_test", "clk_test_pre", CLK_IGNORE_UNUSED,
RK3368_CLKSEL_CON(58), 0, 5, DFLAGS,
RK3368_CLKGATE_CON(13), 11, GFLAGS),
+
+   /* ddrc */
+   GATE(0, "clk_ddrc_lpll_src", "lpll", 0, RK3399_CLKGATE_CON(3),
+0, GFLAGS),
+   GATE(0, "clk_ddrc_bpll_src", "bpll", 0, RK3399_CLKGATE_CON(3),
+1, GFLAGS),
+   GATE(0, "clk_ddrc_dpll_src", "dpll", 0, RK3399_CLKGATE_CON(3),
+2, GFLAGS),
+   GATE(0, "clk_ddrc_gpll_src", "gpll", 0, RK3399_CLKGATE_CON(3),
+3, GFLAGS),
+   COMPOSITE_DDRCLK(SCLK_DDRC, "sclk_ddrc", mux_ddrclk_p, 0,
+  RK3399_CLKSEL_CON(6), 4, 2, 0, 0, ROCKCHIP_DDRCLK_SIP),
 };

 static struct rockchip_clk_branch rk3399_clk_pmu_branches[] __initdata = {
@@ -1493,6 +1509,9 @@ static const char *const rk3399_cru_critical_clocks[] 
__initconst = {
"gpll_aclk_perilp0_src",
"gpll_aclk_perihp_src",
"aclk_vio_noc",
+
+   /* ddrc */
+   "sclk_ddrc"
 };

 static const char *const rk3399_pmucru_critical_clocks[] __initconst = {
-- 
2.6.6



[PATCH v7 2/8] clk: rockchip: rk3399: add SCLK_DDRCLK ID for ddrc

2016-08-22 Thread Lin Huang
Signed-off-by: Lin Huang 
---
Changes in v7:
-None

Changes in v6:
-None

Changes in v5:
-None
Changes in v4:
-None

Changes in v3:
-None

Changes in v2:
-None 

Changes in v1:
-None

 include/dt-bindings/clock/rk3399-cru.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/dt-bindings/clock/rk3399-cru.h 
b/include/dt-bindings/clock/rk3399-cru.h
index 50a44cf..ce5f3e9 100644
--- a/include/dt-bindings/clock/rk3399-cru.h
+++ b/include/dt-bindings/clock/rk3399-cru.h
@@ -131,6 +131,7 @@
 #define SCLK_DPHY_RX0_CFG  165
 #define SCLK_RMII_SRC  166
 #define SCLK_PCIEPHY_REF100M   167
+#define SCLK_DDRC  168

 #define DCLK_VOP0  180
 #define DCLK_VOP1  181
-- 
2.6.6



[PATCH v7 1/8] clk: rockchip: add new clock-type for the ddrclk

2016-08-22 Thread Lin Huang
On new rockchip platform(rk3399 etc), there have dcf controller to
do ddr frequency scaling, and this controller will implement in
arm-trust-firmware. We add a special clock-type to handle that.

Signed-off-by: Lin Huang 
---
Changes in v7:
- add rockchip_ddrclk_sip_ops so we can distinguish other ddr clock operate
- add ROCKCHIP_SIP_CONFIG_* in rockchip_sip.h give constants a specific name

Changes in v6:
- none

Changes in v5:
- delete unuse mux_flag
- use div_flag to distinguish sip call and other operate

Changes in v4:
- use arm_smccc_smc() to set/read ddr rate

Changes in v3:
- use sip call to set/read ddr rate

Changes in v2:
- use GENMASK instead val_mask
- use divider_recalc_rate() instead DIV_ROUND_UP_ULL
- cleanup code

Changes in v1:
- none

 drivers/clk/rockchip/Makefile   |   1 +
 drivers/clk/rockchip/clk-ddr.c  | 157 
 drivers/clk/rockchip/clk.c  |   9 +++
 drivers/clk/rockchip/clk.h  |  35 
 include/soc/rockchip/rockchip_sip.h |  27 +++
 5 files changed, 229 insertions(+)
 create mode 100644 drivers/clk/rockchip/clk-ddr.c
 create mode 100644 include/soc/rockchip/rockchip_sip.h

diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile
index f47a2fa..b5f2c8e 100644
--- a/drivers/clk/rockchip/Makefile
+++ b/drivers/clk/rockchip/Makefile
@@ -8,6 +8,7 @@ obj-y   += clk-pll.o
 obj-y  += clk-cpu.o
 obj-y  += clk-inverter.o
 obj-y  += clk-mmc-phase.o
+obj-y  += clk-ddr.o
 obj-$(CONFIG_RESET_CONTROLLER) += softrst.o

 obj-y  += clk-rk3036.o
diff --git a/drivers/clk/rockchip/clk-ddr.c b/drivers/clk/rockchip/clk-ddr.c
new file mode 100644
index 000..224e07e
--- /dev/null
+++ b/drivers/clk/rockchip/clk-ddr.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2016 Rockchip Electronics Co. Ltd.
+ * Author: Lin Huang 
+ *
+ * This program 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 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+struct rockchip_ddrclk {
+   struct clk_hw   hw;
+   void __iomem*reg_base;
+   int mux_offset;
+   int mux_shift;
+   int mux_width;
+   int div_shift;
+   int div_width;
+   int ddr_flag;
+   spinlock_t  *lock;
+};
+
+#define to_rockchip_ddrclk_hw(hw) container_of(hw, struct rockchip_ddrclk, hw)
+
+static int rockchip_ddrclk_sip_set_rate(struct clk_hw *hw, unsigned long drate,
+   unsigned long prate)
+{
+   struct rockchip_ddrclk *ddrclk = to_rockchip_ddrclk_hw(hw);
+   unsigned long flags;
+   struct arm_smccc_res res;
+
+   spin_lock_irqsave(ddrclk->lock, flags);
+   arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, drate, 0,
+ ROCKCHIP_SIP_CONFIG_DRAM_SET_RATE,
+ 0, 0, 0, 0, );
+   spin_unlock_irqrestore(ddrclk->lock, flags);
+
+   return res.a0;
+}
+
+static unsigned long
+rockchip_ddrclk_sip_recalc_rate(struct clk_hw *hw,
+   unsigned long parent_rate)
+{
+   struct arm_smccc_res res;
+
+   arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, 0, 0,
+ ROCKCHIP_SIP_CONFIG_DRAM_GET_RATE,
+ 0, 0, 0, 0, );
+
+   return res.a0;
+}
+
+static long rockchip_ddrclk_sip_round_rate(struct clk_hw *hw,
+  unsigned long rate,
+  unsigned long *prate)
+{
+   struct arm_smccc_res res;
+
+   arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, rate, 0,
+ ROCKCHIP_SIP_CONFIG_DRAM_ROUND_RATE,
+ 0, 0, 0, 0, );
+
+   return res.a0;
+}
+
+static u8 rockchip_ddrclk_get_parent(struct clk_hw *hw)
+{
+   struct rockchip_ddrclk *ddrclk = to_rockchip_ddrclk_hw(hw);
+   int num_parents = clk_hw_get_num_parents(hw);
+   u32 val;
+
+   val = clk_readl(ddrclk->reg_base +
+   ddrclk->mux_offset) >> ddrclk->mux_shift;
+   val &= GENMASK(ddrclk->mux_width - 1, 0);
+
+   if (val >= num_parents)
+   return -EINVAL;
+
+   return val;
+}
+
+static const struct clk_ops rockchip_ddrclk_sip_ops = {
+   .recalc_rate = rockchip_ddrclk_sip_recalc_rate,
+   .set_rate = rockchip_ddrclk_sip_set_rate,
+   .round_rate = rockchip_ddrclk_sip_round_rate,
+   .get_parent = rockchip_ddrclk_get_parent,
+};
+
+struct clk *rockchip_clk_re

[PATCH v7 0/8] rk3399 support ddr frequency scaling

2016-08-22 Thread Lin Huang
rk3399 platform have dfi controller can monitor ddr load,
and dcf controller to handle ddr register so we can get the
right ddr frequency and make ddr controller happy work(which
will implement in bl31). So we do ddr frequency scaling with
following flow:

 kernelbl31

monitor ddr load
|
|
get_target_rate
|
|   pass rate to bl31
clk_set_rate(ddr) ->run dcf flow
|   |
|   |
wait dcf interrupt<---trigger dcf interrupt
|
|
  return

Lin Huang (8):
  clk: rockchip: add new clock-type for the ddrclk
  clk: rockchip: rk3399: add SCLK_DDRCLK ID for ddrc
  clk: rockchip: rk3399: add ddrc clock support
  Documentation: bindings: add dt documentation for dfi controller
  PM / devfreq: event: support rockchip dfi controller
  Documentation: bindings: add dt documentation for rk3399 dmc
  PM / devfreq: rockchip: add devfreq driver for rk3399 dmc
  drm/rockchip: Add dmc notifier in vop driver

 .../bindings/devfreq/event/rockchip-dfi.txt|  20 +
 .../devicetree/bindings/devfreq/rk3399_dmc.txt |  85 
 drivers/clk/rockchip/Makefile  |   1 +
 drivers/clk/rockchip/clk-ddr.c | 157 +++
 drivers/clk/rockchip/clk-rk3399.c  |  19 +
 drivers/clk/rockchip/clk.c |   9 +
 drivers/clk/rockchip/clk.h |  35 ++
 drivers/devfreq/Kconfig|  11 +
 drivers/devfreq/Makefile   |   1 +
 drivers/devfreq/event/Kconfig  |   7 +
 drivers/devfreq/event/Makefile |   1 +
 drivers/devfreq/event/rockchip-dfi.c   | 256 +++
 drivers/devfreq/rk3399_dmc.c   | 499 +
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c| 127 +-
 include/dt-bindings/clock/rk3399-cru.h |   1 +
 include/soc/rockchip/rockchip_sip.h|  27 ++
 16 files changed, 1251 insertions(+), 5 deletions(-)
 create mode 100644 
Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt
 create mode 100644 Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt
 create mode 100644 drivers/clk/rockchip/clk-ddr.c
 create mode 100644 drivers/devfreq/event/rockchip-dfi.c
 create mode 100644 drivers/devfreq/rk3399_dmc.c
 create mode 100644 include/soc/rockchip/rockchip_sip.h

-- 
2.6.6



[PATCH v6 8/8] drm/rockchip: Add dmc notifier in vop driver

2016-08-17 Thread Lin Huang
when in ddr frequency scaling process, vop can not do
enable or disable operation, since dcf will base on vop vblank
time to do frequency scaling and need to get vop irq if there
have vop enabled. So need register to devfreq notifier, and we can
get the dmc status. Also, when there have two vop enabled, we need
to disable dmc, since dcf only base on one vop vblank time, so the
other panel will flicker when do ddr frequency scaling.

Signed-off-by: Lin Huang 
Reviewed-by: Chanwoo Choi 
---
Changes in v6:
- fix a build error

Changes in v5:
- improve some nits

Changes in v4:
- register notifier to devfreq_register_notifier
- use DEVFREQ_PRECHANGE and DEVFREQ_POSTCHANGE to get dmc status
- when two vop enable, disable dmc
- when two vop back to one vop, enable dmc

Changes in v3:
- when do vop eanble/disable, dmc will wait until it finish

Changes in v2:
- None

Changes in v1:
- use wait_event instead usleep

 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 121 +++-
 1 file changed, 119 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 31744fe..199529e 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -12,6 +12,8 @@
  * GNU General Public License for more details.
  */

+#include 
+#include 
 #include 
 #include 
 #include 
@@ -118,6 +120,13 @@ struct vop {

const struct vop_data *data;

+   struct devfreq *devfreq;
+   struct devfreq_event_dev *devfreq_event_dev;
+   struct notifier_block dmc_nb;
+   int dmc_in_process;
+   int vop_switch_status;
+   wait_queue_head_t wait_dmc_queue;
+   wait_queue_head_t wait_vop_switch_queue;
uint32_t *regsbak;
void __iomem *regs;

@@ -428,21 +437,56 @@ static void vop_dsp_hold_valid_irq_disable(struct vop 
*vop)
spin_unlock_irqrestore(>irq_lock, flags);
 }

+static int dmc_notify(struct notifier_block *nb, unsigned long event,
+ void *data)
+{
+   struct vop *vop = container_of(nb, struct vop, dmc_nb);
+
+   if (event == DEVFREQ_PRECHANGE) {
+   /*
+* check if vop in enable or disable process,
+* if yes, wait until it finishes, use 200ms as
+* timeout.
+*/
+   if (!wait_event_timeout(vop->wait_vop_switch_queue,
+   !vop->vop_switch_status, HZ / 5))
+   dev_warn(vop->dev,
+"Timeout waiting for vop swtich status\n");
+   vop->dmc_in_process = 1;
+   } else if (event == DEVFREQ_POSTCHANGE) {
+   vop->dmc_in_process = 0;
+   wake_up(>wait_dmc_queue);
+   }
+
+   return NOTIFY_OK;
+}
+
 static void vop_enable(struct drm_crtc *crtc)
 {
struct vop *vop = to_vop(crtc);
+   int num_enabled_crtc = 0;
int ret;

+   /*
+* if in dmc scaling frequency process, wait until it finishes
+* use 100ms as timeout time.
+*/
+   if (!wait_event_timeout(vop->wait_dmc_queue,
+   !vop->dmc_in_process, HZ / 5))
+   dev_warn(vop->dev,
+"Timeout waiting for dmc when vop enable\n");
+
+   vop->vop_switch_status = 1;
ret = pm_runtime_get_sync(vop->dev);
if (ret < 0) {
dev_err(vop->dev, "failed to get pm runtime: %d\n", ret);
-   return;
+   goto err;
}

ret = clk_enable(vop->hclk);
if (ret < 0) {
dev_err(vop->dev, "failed to enable hclk - %d\n", ret);
-   return;
+   goto err;
}

ret = clk_enable(vop->dclk);
@@ -485,6 +529,21 @@ static void vop_enable(struct drm_crtc *crtc)

drm_crtc_vblank_on(crtc);

+   vop->vop_switch_status = 0;
+   wake_up(>wait_vop_switch_queue);
+
+   /* check how many vop we use now */
+   drm_for_each_crtc(crtc, vop->drm_dev) {
+   if (crtc->state->enable)
+   num_enabled_crtc++;
+   }
+
+   /* if enable two vop, need to disable dmc */
+   if ((num_enabled_crtc > 1) && vop->devfreq) {
+   if (vop->devfreq_event_dev)
+   devfreq_event_disable_edev(vop->devfreq_event_dev);
+   devfreq_suspend_device(vop->devfreq);
+   }
return;

 err_disable_aclk:
@@ -493,16 +552,32 @@ err_disable_dclk:
clk_disable(vop->dclk);
 err_disable_hclk:
clk_disable(vop->hclk);
+err:
+   vop->vop_switch_status = 0;
+   wake_up(>wait_vop_switch_queue);
+   return;
 }

 static void vop_crtc_disable(struct drm_crtc *crtc)
 {
struct vop *vop = to_vop(crtc);
+   int num

[PATCH v6 7/8] PM / devfreq: rockchip: add devfreq driver for rk3399 dmc

2016-08-17 Thread Lin Huang
base on dfi result, we do ddr frequency scaling, register
dmc driver to devfreq framework, and use simple-ondemand
policy.

Signed-off-by: Lin Huang 
Reviewed-by: Chanwoo Choi 
---
Changes in v6:
- fix some nit suggest by Chanwoo Choi

Changes in v5:
- improve dmc driver suggest by Chanwoo Choi

Changes in v4:
- use arm_smccc_smc() function talk to bl31
- delete rockchip_dmc.c file and config
- delete dmc_notify
- adjust probe order

Changes in v3:
- operate dram setting through sip call
- imporve set rate flow

Changes in v2:
- None

Changes in v1:
- move dfi controller to event
- fix set voltage sequence when set rate fail
- change Kconfig type from tristate to bool
- move unuse EXPORT_SYMBOL_GPL()

 drivers/devfreq/Kconfig  |  11 +
 drivers/devfreq/Makefile |   1 +
 drivers/devfreq/rk3399_dmc.c | 497 +++
 3 files changed, 509 insertions(+)
 create mode 100644 drivers/devfreq/rk3399_dmc.c

diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig
index a5be56e..e848121 100644
--- a/drivers/devfreq/Kconfig
+++ b/drivers/devfreq/Kconfig
@@ -100,6 +100,17 @@ config ARM_TEGRA_DEVFREQ
  It reads ACTMON counters of memory controllers and adjusts the
  operating frequencies and voltages with OPP support.

+config ARM_RK3399_DMC_DEVFREQ
+   tristate "ARM RK3399 DMC DEVFREQ Driver"
+   depends on ARCH_ROCKCHIP
+   select DEVFREQ_EVENT_ROCKCHIP_DFI
+   select DEVFREQ_GOV_SIMPLE_ONDEMAND
+   select PM_OPP
+   help
+  This adds the DEVFREQ driver for the RK3399 DMC(Dynamic Memory 
Controller).
+  It sets the frequency for the memory controller and reads the usage 
counts
+  from hardware.
+
 source "drivers/devfreq/event/Kconfig"

 endif # PM_DEVFREQ
diff --git a/drivers/devfreq/Makefile b/drivers/devfreq/Makefile
index 09f11d9..fbff40a 100644
--- a/drivers/devfreq/Makefile
+++ b/drivers/devfreq/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_DEVFREQ_GOV_PASSIVE)   += governor_passive.o

 # DEVFREQ Drivers
 obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ)   += exynos-bus.o
+obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ)   += rk3399_dmc.o
 obj-$(CONFIG_ARM_TEGRA_DEVFREQ)+= tegra-devfreq.o

 # DEVFREQ Event Drivers
diff --git a/drivers/devfreq/rk3399_dmc.c b/drivers/devfreq/rk3399_dmc.c
new file mode 100644
index 000..5f98f5e
--- /dev/null
+++ b/drivers/devfreq/rk3399_dmc.c
@@ -0,0 +1,497 @@
+/*
+ * Copyright (c) 2016, Fuzhou Rockchip Electronics Co., Ltd.
+ * Author: Lin Huang 
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+struct dram_timing {
+   unsigned int ddr3_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 dram_dll_dis_freq;
+   unsigned int phy_dll_dis_freq;
+   unsigned int ddr3_odt_dis_freq;
+   unsigned int ddr3_drv;
+   unsigned int ddr3_odt;
+   unsigned int phy_ddr3_ca_drv;
+   unsigned int phy_ddr3_dq_drv;
+   unsigned int phy_ddr3_odt;
+   unsigned int lpddr3_odt_dis_freq;
+   unsigned int lpddr3_drv;
+   unsigned int lpddr3_odt;
+   unsigned int phy_lpddr3_ca_drv;
+   unsigned int phy_lpddr3_dq_drv;
+   unsigned int phy_lpddr3_odt;
+   unsigned int 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;
+};
+
+struct rk3399_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 dram_timing *timing;
+
+   /*
+* DDR Converser of Frequency (DCF) is used to implement DDR frequency
+* conversion without the participation of CPU, we will implement and
+* control it in arm trust firmware.
+*/
+   wait_queue_head_t   wait_dcf_queue;
+   int irq;
+   int wait_dcf_flag;
+   struct regulator *vdd_center;
+   unsigned long rate, target_rate;
+   unsigned long volt, target_volt;
+   struct dev_pm_opp *curr_opp;
+};
+
+static int r

[PATCH v6 6/8] Documentation: bindings: add dt documentation for rk3399 dmc

2016-08-17 Thread Lin Huang
This patch adds the documentation for rockchip rk3399 dmc driver.

Signed-off-by: Lin Huang 
---
Changes in v6:
-Add more detail in Documentation

Changes in v5:
-None

Changes in v4:
-None

Changes in v3:
-None

Changes in v2:
-None 

Changes in v1:
-None
 .../devicetree/bindings/devfreq/rk3399_dmc.txt | 84 ++
 1 file changed, 84 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt

diff --git a/Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt 
b/Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt
new file mode 100644
index 000..e73067c
--- /dev/null
+++ b/Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt
@@ -0,0 +1,84 @@
+* Rockchip rk3399 DMC(Dynamic Memory Controller) device
+
+Required properties:
+- compatible: Must be "rockchip,rk3399-dmc".
+- devfreq-events: Node to get ddr loading, Refer to
+ Documentation/devicetree/bindings/devfreq/rockchip-dif.txt
+- interrupts: The interrupt number to the cpu. The interrupt specifier format
+ depends on the interrupt controller. it should be dcf interrupts,
+ when ddr dvfs finish, it will happen.
+- clocks: Phandles for clock specified in "clock-names" property
+- clock-names : The name of clock used by the DFI, must be "pclk_ddr_mon";
+- operating-points-v2: Refer to Documentation/devicetree/bindings/power/opp.txt
+  for details.
+- center-supply: Dmc supply node.
+- status: Marks the node enabled/disabled.
+
+Optional properties:
+- ddr_timing: ddr timing need to pass to arm trust firmware
+- upthreshold: the upthreshold to simpleondeamnd policy
+- downdifferential: The downdifferential to simpleondeamnd policy
+
+Example:
+   ddr_timing: ddr_timing {
+   compatible = "rockchip,ddr-timing";
+   ddr3_speed_bin = <21>;
+   pd_idle = <0>;
+   sr_idle = <0>;
+   sr_mc_gate_idle = <0>;
+   srpd_lite_idle  = <0>;
+   standby_idle = <0>;
+   dram_dll_dis_freq = <300>;
+   phy_dll_dis_freq = <125>;
+
+   ddr3_odt_dis_freq = <333>;
+   ddr3_drv = ;
+   ddr3_odt = ;
+   phy_ddr3_ca_drv = ;
+   phy_ddr3_dq_drv = ;
+   phy_ddr3_odt = ;
+
+   lpddr3_odt_dis_freq = <333>;
+   lpddr3_drv = ;
+   lpddr3_odt = ;
+   phy_lpddr3_ca_drv = ;
+   phy_lpddr3_dq_drv = ;
+   phy_lpddr3_odt = ;
+
+   lpddr4_odt_dis_freq = <333>;
+   lpddr4_drv = ;
+   lpddr4_dq_odt = ;
+   lpddr4_ca_odt = ;
+   phy_lpddr4_ca_drv = ;
+   phy_lpddr4_ck_cs_drv = ;
+   phy_lpddr4_dq_drv = ;
+   phy_lpddr4_odt = ;
+   };
+
+   dmc_opp_table: dmc_opp_table {
+   compatible = "operating-points-v2";
+
+   opp00 {
+   opp-hz = /bits/ 64 <3>;
+   opp-microvolt = <90>;
+   };
+   opp01 {
+   opp-hz = /bits/ 64 <66600>;
+   opp-microvolt = <90>;
+   };
+   };
+
+   dmc: dmc {
+   compatible = "rockchip,rk3399-dmc";
+   devfreq-events = <>;
+   interrupts = ;
+   clocks = < SCLK_DDRCLK>;
+   clock-names = "dmc_clk";
+   ddr_timing = <_timing>;
+   operating-points-v2 = <_opp_table>;
+   center-supply = <_centerlogic>;
+   upthreshold = <15>;
+   downdifferential = <10>;
+   status = "disabled";
+   };
+
-- 
2.6.6



[PATCH v6 5/8] PM / devfreq: event: support rockchip dfi controller

2016-08-17 Thread Lin Huang
on rk3399 platform, there is dfi conroller can monitor
ddr load, base on this result, we can do ddr freqency
scaling.

Signed-off-by: Lin Huang 
Acked-by: Chanwoo Choi 
---
Changes in v6:
-None

Changes in v5:
-None

Changes in v4:
-None

Changes in v3:
-None

Changes in v2:
-None 

Changes in v1:
-None
 drivers/devfreq/event/Kconfig|   7 +
 drivers/devfreq/event/Makefile   |   1 +
 drivers/devfreq/event/rockchip-dfi.c | 253 +++
 3 files changed, 261 insertions(+)
 create mode 100644 drivers/devfreq/event/rockchip-dfi.c

diff --git a/drivers/devfreq/event/Kconfig b/drivers/devfreq/event/Kconfig
index eb6f74a..20d82c2 100644
--- a/drivers/devfreq/event/Kconfig
+++ b/drivers/devfreq/event/Kconfig
@@ -30,4 +30,11 @@ config DEVFREQ_EVENT_EXYNOS_PPMU
  (Platform Performance Monitoring Unit) counters to estimate the
  utilization of each module.

+config DEVFREQ_EVENT_ROCKCHIP_DFI
+   tristate "ROCKCHIP DFI DEVFREQ event Driver"
+   depends on ARCH_ROCKCHIP
+   help
+ This add the devfreq-event driver for Rockchip SoC. It provides DFI
+ (DDR Monitor Module) driver to count ddr load.
+
 endif # PM_DEVFREQ_EVENT
diff --git a/drivers/devfreq/event/Makefile b/drivers/devfreq/event/Makefile
index 3d6afd3..dda7090 100644
--- a/drivers/devfreq/event/Makefile
+++ b/drivers/devfreq/event/Makefile
@@ -2,3 +2,4 @@

 obj-$(CONFIG_DEVFREQ_EVENT_EXYNOS_NOCP) += exynos-nocp.o
 obj-$(CONFIG_DEVFREQ_EVENT_EXYNOS_PPMU) += exynos-ppmu.o
+obj-$(CONFIG_DEVFREQ_EVENT_ROCKCHIP_DFI) += rockchip-dfi.o
diff --git a/drivers/devfreq/event/rockchip-dfi.c 
b/drivers/devfreq/event/rockchip-dfi.c
new file mode 100644
index 000..3f12be7
--- /dev/null
+++ b/drivers/devfreq/event/rockchip-dfi.c
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2016, Fuzhou Rockchip Electronics Co., Ltd
+ * Author: Lin Huang 
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define RK3399_DMC_NUM_CH  2
+
+/* DDRMON_CTRL */
+#define DDRMON_CTRL0x04
+#define CLR_DDRMON_CTRL(0x1f << 0)
+#define LPDDR4_EN  (0x10001 << 4)
+#define HARDWARE_EN(0x10001 << 3)
+#define LPDDR3_EN  (0x10001 << 2)
+#define SOFTWARE_EN(0x10001 << 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
+#define DDRTYPE_SHIFT  13
+#define DDRTYPE_MASK   7
+
+enum {
+   DDR3 = 3,
+   LPDDR3 = 6,
+   LPDDR4 = 7,
+   UNUSED = 0xFF
+};
+
+struct dmc_usage {
+   u32 access;
+   u32 total;
+};
+
+struct rockchip_dfi {
+   struct devfreq_event_dev *edev;
+   struct devfreq_event_desc *desc;
+   struct dmc_usage ch_usage[RK3399_DMC_NUM_CH];
+   struct device *dev;
+   void __iomem *regs;
+   struct regmap *regmap_pmu;
+   struct clk *clk;
+};
+
+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, PMUGRF_OS_REG2, );
+   ddr_type = (val >> DDRTYPE_SHIFT) & DDRTYPE_MASK;
+
+   /* clear DDRMON_CTRL setting */
+   writel_relaxed(CLR_DDRMON_CTRL, dfi_regs + DDRMON_CTRL);
+
+   /* set ddr type to dfi */
+   if (ddr_type == LPDDR3)
+   writel_relaxed(LPDDR3_EN, dfi_regs + DDRMON_CTRL);
+   else if (ddr_type == LPDDR4)
+   writel_relaxed(LPDDR4_EN, dfi_regs + DDRMON_CTRL);
+
+   /* enable count, use software mode */
+   writel_relaxed(SOFTWARE_EN, dfi_regs + DDRMON_CTRL);
+}
+
+static void rockchip_dfi_stop_hardware_counter(struct devfreq_event_dev *edev)
+{
+   struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
+   void __iomem *dfi_regs = info->regs;
+   u32 val;
+
+   val = readl_relaxed(dfi_regs + DDRMON_CTRL);
+   val &= ~SOFTWARE_EN;
+   writel_relaxed(val, dfi_regs + DDRMON_CTRL);
+}
+
+static int rockchip_dfi_get_busier_ch(struct devfreq_event_dev *edev)
+{
+   struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
+   u32 tmp, max = 0;
+   

[PATCH v6 4/8] Documentation: bindings: add dt documentation for dfi controller

2016-08-17 Thread Lin Huang
This patch adds the documentation for rockchip dfi devfreq-event driver.

Signed-off-by: Lin Huang 
---
Changes in v6:
-None

Changes in v5:
-None

Changes in v4:
-None

Changes in v3:
-None

Changes in v2:
-None 

Changes in v1:
-None

 .../bindings/devfreq/event/rockchip-dfi.txt  | 20 
 1 file changed, 20 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt

diff --git a/Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt 
b/Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt
new file mode 100644
index 000..bf42255
--- /dev/null
+++ b/Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt
@@ -0,0 +1,20 @@
+
+* Rockchip rk3399 DFI device
+
+Required properties:
+- compatible: Must be "rockchip,rk3399-dfi".
+- reg: physical base address of each DFI and length of memory mapped region
+- rockchip,pmu: phandle to the syscon managing the "pmu general register files"
+- clocks: phandles for clock specified in "clock-names" property
+- clock-names : the name of clock used by the DFI, must be "pclk_ddr_mon";
+
+Example:
+   dfi: dfi at 0xff63 {
+   reg = <0x00 0xff63 0x00 0x4000>;
+   compatible = "rockchip,rk3399-dfi";
+   rockchip,pmu = <>;
+   clocks = < PCLK_DDR_MON>;
+   clock-names = "pclk_ddr_mon";
+   status = "disabled";
+   };
+
-- 
2.6.6



[PATCH v6 3/8] clk: rockchip: rk3399: add ddrc clock support

2016-08-17 Thread Lin Huang
add ddrc clock setting, so we can do ddr frequency
scaling on rk3399 platform in future.

Signed-off-by: Lin Huang 
---
Changes in v6:
- None

Changes in v5:
- fit for the ddr type

Changes in v4:
- None

Changes in v3:
- None

Changes in v2:
- remove clk_ddrc_dpll_src from critical clock list

Changes in v1:
- remove ddrc source CLK_IGNORE_UNUSED flag
- move clk_ddrc and clk_ddrc_dpll_src to critical

 drivers/clk/rockchip/clk-rk3399.c | 19 +++
 1 file changed, 19 insertions(+)

diff --git a/drivers/clk/rockchip/clk-rk3399.c 
b/drivers/clk/rockchip/clk-rk3399.c
index e445cd6..01d4945 100644
--- a/drivers/clk/rockchip/clk-rk3399.c
+++ b/drivers/clk/rockchip/clk-rk3399.c
@@ -120,6 +120,10 @@ PNAME(mux_armclkb_p)   = { 
"clk_core_b_lpll_src",
"clk_core_b_bpll_src",
"clk_core_b_dpll_src",
"clk_core_b_gpll_src" };
+PNAME(mux_ddrclk_p)= { "clk_ddrc_lpll_src",
+   "clk_ddrc_bpll_src",
+   "clk_ddrc_dpll_src",
+   "clk_ddrc_gpll_src" };
 PNAME(mux_aclk_cci_p)  = { "cpll_aclk_cci_src",
"gpll_aclk_cci_src",
"npll_aclk_cci_src",
@@ -1379,6 +1383,18 @@ static struct rockchip_clk_branch rk3399_clk_branches[] 
__initdata = {
COMPOSITE_NOMUX(0, "clk_test", "clk_test_pre", CLK_IGNORE_UNUSED,
RK3368_CLKSEL_CON(58), 0, 5, DFLAGS,
RK3368_CLKGATE_CON(13), 11, GFLAGS),
+
+   /* ddrc */
+   GATE(0, "clk_ddrc_lpll_src", "lpll", 0, RK3399_CLKGATE_CON(3),
+0, GFLAGS),
+   GATE(0, "clk_ddrc_bpll_src", "bpll", 0, RK3399_CLKGATE_CON(3),
+1, GFLAGS),
+   GATE(0, "clk_ddrc_dpll_src", "dpll", 0, RK3399_CLKGATE_CON(3),
+2, GFLAGS),
+   GATE(0, "clk_ddrc_gpll_src", "gpll", 0, RK3399_CLKGATE_CON(3),
+3, GFLAGS),
+   COMPOSITE_DDRCLK(SCLK_DDRC, "clk_ddrc", mux_ddrclk_p, 0,
+  RK3399_CLKSEL_CON(6), 4, 2, 0, 0, ROCKCHIP_DDRCLK_SIP),
 };

 static struct rockchip_clk_branch rk3399_clk_pmu_branches[] __initdata = {
@@ -1493,6 +1509,9 @@ static const char *const rk3399_cru_critical_clocks[] 
__initconst = {
"gpll_aclk_perilp0_src",
"gpll_aclk_perihp_src",
"aclk_vio_noc",
+
+   /* ddrc */
+   "clk_ddrc"
 };

 static const char *const rk3399_pmucru_critical_clocks[] __initconst = {
-- 
2.6.6



[PATCH v6 2/8] clk: rockchip: rk3399: add SCLK_DDRCLK ID for ddrc

2016-08-17 Thread Lin Huang
Signed-off-by: Lin Huang 
---
Changes in v6:
-None

Changes in v5:
-None
Changes in v4:
-None

Changes in v3:
-None

Changes in v2:
-None 

Changes in v1:
-None

 include/dt-bindings/clock/rk3399-cru.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/dt-bindings/clock/rk3399-cru.h 
b/include/dt-bindings/clock/rk3399-cru.h
index 50a44cf..ce5f3e9 100644
--- a/include/dt-bindings/clock/rk3399-cru.h
+++ b/include/dt-bindings/clock/rk3399-cru.h
@@ -131,6 +131,7 @@
 #define SCLK_DPHY_RX0_CFG  165
 #define SCLK_RMII_SRC  166
 #define SCLK_PCIEPHY_REF100M   167
+#define SCLK_DDRC  168

 #define DCLK_VOP0  180
 #define DCLK_VOP1  181
-- 
2.6.6



[PATCH v6 1/8] clk: rockchip: add new clock-type for the ddrclk

2016-08-17 Thread Lin Huang
On new rockchip platform(rk3399 etc), there have dcf controller to
do ddr frequency scaling, and this controller will implement in
arm-trust-firmware. We add a special clock-type to handle that.

Signed-off-by: Lin Huang 
---
Changes in v6:
- none

Changes in v5:
- delete unuse mux_flag
- use div_flag to distinguish sip call and other operate

Changes in v4:
- use arm_smccc_smc() to set/read ddr rate

Changes in v3:
- use sip call to set/read ddr rate

Changes in v2:
- use GENMASK instead val_mask
- use divider_recalc_rate() instead DIV_ROUND_UP_ULL
- cleanup code

Changes in v1:
- none

 drivers/clk/rockchip/Makefile   |   1 +
 drivers/clk/rockchip/clk-ddr.c  | 150 
 drivers/clk/rockchip/clk.c  |   9 +++
 drivers/clk/rockchip/clk.h  |  33 
 include/soc/rockchip/rockchip_sip.h |  27 +++
 5 files changed, 220 insertions(+)
 create mode 100644 drivers/clk/rockchip/clk-ddr.c
 create mode 100644 include/soc/rockchip/rockchip_sip.h

diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile
index f47a2fa..b5f2c8e 100644
--- a/drivers/clk/rockchip/Makefile
+++ b/drivers/clk/rockchip/Makefile
@@ -8,6 +8,7 @@ obj-y   += clk-pll.o
 obj-y  += clk-cpu.o
 obj-y  += clk-inverter.o
 obj-y  += clk-mmc-phase.o
+obj-y  += clk-ddr.o
 obj-$(CONFIG_RESET_CONTROLLER) += softrst.o

 obj-y  += clk-rk3036.o
diff --git a/drivers/clk/rockchip/clk-ddr.c b/drivers/clk/rockchip/clk-ddr.c
new file mode 100644
index 000..7dbe8bff
--- /dev/null
+++ b/drivers/clk/rockchip/clk-ddr.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2016 Rockchip Electronics Co. Ltd.
+ * Author: Lin Huang 
+ *
+ * This program 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 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+struct rockchip_ddrclk {
+   struct clk_hw   hw;
+   void __iomem*reg_base;
+   int mux_offset;
+   int mux_shift;
+   int mux_width;
+   int div_shift;
+   int div_width;
+   int ddr_flag;
+   spinlock_t  *lock;
+};
+
+#define to_rockchip_ddrclk_hw(hw) container_of(hw, struct rockchip_ddrclk, hw)
+
+static int rockchip_ddrclk_set_rate(struct clk_hw *hw, unsigned long drate,
+   unsigned long prate)
+{
+   struct rockchip_ddrclk *ddrclk = to_rockchip_ddrclk_hw(hw);
+   unsigned long flags;
+   struct arm_smccc_res res;
+
+   spin_lock_irqsave(ddrclk->lock, flags);
+   if (ddrclk->ddr_flag == ROCKCHIP_DDRCLK_SIP) {
+   arm_smccc_smc(SIP_DRAM_FREQ, drate, 0, CONFIG_DRAM_SET_RATE,
+ 0, 0, 0, 0, );
+   return res.a0;
+   }
+   spin_unlock_irqrestore(ddrclk->lock, flags);
+
+   return 0;
+}
+
+static unsigned long
+rockchip_ddrclk_recalc_rate(struct clk_hw *hw,
+   unsigned long parent_rate)
+{
+   struct rockchip_ddrclk *ddrclk = to_rockchip_ddrclk_hw(hw);
+   struct arm_smccc_res res;
+
+   if (ddrclk->ddr_flag == ROCKCHIP_DDRCLK_SIP) {
+   arm_smccc_smc(SIP_DRAM_FREQ, 0, 0, CONFIG_DRAM_GET_RATE,
+ 0, 0, 0, 0, );
+   return res.a0;
+   }
+
+   return 0;
+}
+
+static long clk_ddrclk_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
+{
+   return rate;
+}
+
+static u8 rockchip_ddrclk_get_parent(struct clk_hw *hw)
+{
+   struct rockchip_ddrclk *ddrclk = to_rockchip_ddrclk_hw(hw);
+   int num_parents = clk_hw_get_num_parents(hw);
+   u32 val;
+
+   val = clk_readl(ddrclk->reg_base +
+   ddrclk->mux_offset) >> ddrclk->mux_shift;
+   val &= GENMASK(ddrclk->mux_width - 1, 0);
+
+   if (val >= num_parents)
+   return -EINVAL;
+
+   return val;
+}
+
+static const struct clk_ops rockchip_ddrclk_ops = {
+   .recalc_rate = rockchip_ddrclk_recalc_rate,
+   .set_rate = rockchip_ddrclk_set_rate,
+   .round_rate = clk_ddrclk_round_rate,
+   .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,
+int mux_shift, int mux_width,
+  

[PATCH v6 0/8] rk3399 support ddr frequency scaling

2016-08-17 Thread Lin Huang
rk3399 platform have dfi controller can monitor ddr load,
and dcf controller to handle ddr register so we can get the
right ddr frequency and make ddr controller happy work(which
will implement in bl31). So we do ddr frequency scaling with
following flow:

 kernelbl31

monitor ddr load
|
|
get_target_rate
|
|   pass rate to bl31
clk_set_rate(ddr) ->run dcf flow
|   |
|   |
wait dcf interrupt<---trigger dcf interrupt
|
|
  return

Lin Huang (8):
  clk: rockchip: add new clock-type for the ddrclk
  clk: rockchip: rk3399: add SCLK_DDRCLK ID for ddrc
  clk: rockchip: rk3399: add ddrc clock support
  Documentation: bindings: add dt documentation for dfi controller
  PM / devfreq: event: support rockchip dfi controller
  Documentation: bindings: add dt documentation for rk3399 dmc
  PM / devfreq: rockchip: add devfreq driver for rk3399 dmc
  drm/rockchip: Add dmc notifier in vop driver

 .../bindings/devfreq/event/rockchip-dfi.txt|  20 +
 .../devicetree/bindings/devfreq/rk3399_dmc.txt |  84 
 drivers/clk/rockchip/Makefile  |   1 +
 drivers/clk/rockchip/clk-ddr.c | 150 +++
 drivers/clk/rockchip/clk-rk3399.c  |  19 +
 drivers/clk/rockchip/clk.c |   9 +
 drivers/clk/rockchip/clk.h |  33 ++
 drivers/devfreq/Kconfig|  11 +
 drivers/devfreq/Makefile   |   1 +
 drivers/devfreq/event/Kconfig  |   7 +
 drivers/devfreq/event/Makefile |   1 +
 drivers/devfreq/event/rockchip-dfi.c   | 253 +++
 drivers/devfreq/rk3399_dmc.c   | 497 +
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c| 121 -
 include/dt-bindings/clock/rk3399-cru.h |   1 +
 include/soc/rockchip/rockchip_sip.h|  27 ++
 16 files changed, 1233 insertions(+), 2 deletions(-)
 create mode 100644 
Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt
 create mode 100644 Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt
 create mode 100644 drivers/clk/rockchip/clk-ddr.c
 create mode 100644 drivers/devfreq/event/rockchip-dfi.c
 create mode 100644 drivers/devfreq/rk3399_dmc.c
 create mode 100644 include/soc/rockchip/rockchip_sip.h

-- 
2.6.6
*


[PATCH v5 8/8] drm/rockchip: Add dmc notifier in vop driver

2016-08-10 Thread Lin Huang
when in ddr frequency scaling process, vop can not do
enable or disable operation, since dcf will base on vop vblank
time to do frequency scaling and need to get vop irq if there
have vop enabled. So need register to devfreq notifier, and we can
get the dmc status. Also, when there have two vop enabled, we need
to disable dmc, since dcf only base on one vop vblank time, so the
other panel will flicker when do ddr frequency scaling.

Signed-off-by: Lin Huang 
---
Changes in v5:
- improve some nits

Changes in v4:
- register notifier to devfreq_register_notifier
- use DEVFREQ_PRECHANGE and DEVFREQ_POSTCHANGE to get dmc status
- when two vop enable, disable dmc
- when two vop back to one vop, enable dmc

Changes in v3:
- when do vop eanble/disable, dmc will wait until it finish

Changes in v2:
- None

Changes in v1:
- use wait_event instead usleep

 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 128 +++-
 1 file changed, 125 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 31744fe..7ce3890 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -12,6 +12,8 @@
  * GNU General Public License for more details.
  */

+#include 
+#include 
 #include 
 #include 
 #include 
@@ -118,6 +120,13 @@ struct vop {

const struct vop_data *data;

+   struct devfreq *devfreq;
+   struct devfreq_event_dev *devfreq_event_dev;
+   struct notifier_block dmc_nb;
+   int dmc_in_process;
+   int vop_switch_status;
+   wait_queue_head_t wait_dmc_queue;
+   wait_queue_head_t wait_vop_switch_queue;
uint32_t *regsbak;
void __iomem *regs;

@@ -428,21 +437,59 @@ static void vop_dsp_hold_valid_irq_disable(struct vop 
*vop)
spin_unlock_irqrestore(>irq_lock, flags);
 }

+static int dmc_notify(struct notifier_block *nb, unsigned long event,
+ void *data)
+{
+   struct vop *vop = container_of(nb, struct vop, dmc_nb);
+
+   if (event == DEVFREQ_PRECHANGE) {
+   /*
+* check if vop in enable or disable process,
+* if yes, wait until it finishes, use 200ms as
+* timeout.
+*/
+   if (!wait_event_timeout(vop->wait_vop_switch_queue,
+   !vop->vop_switch_status, HZ / 5))
+   dev_warn(vop->dev,
+"Timeout waiting for vop swtich status\n");
+   vop->dmc_in_process = 1;
+   } else if (event == DEVFREQ_POSTCHANGE) {
+   vop->dmc_in_process = 0;
+   wake_up(>wait_dmc_queue);
+   }
+
+   return NOTIFY_OK;
+}
+
 static void vop_enable(struct drm_crtc *crtc)
 {
struct vop *vop = to_vop(crtc);
+   int num_enabled_crtc = 0;
int ret;

+   if (vop->is_enabled)
+   return;
+
+   /*
+* if in dmc scaling frequency process, wait until it finishes
+* use 100ms as timeout time.
+*/
+   if (!wait_event_timeout(vop->wait_dmc_queue,
+   !vop->dmc_in_process, HZ / 5))
+   dev_warn(vop->dev,
+"Timeout waiting for dmc when vop enable\n");
+
+   vop->vop_switch_status = 1;
ret = pm_runtime_get_sync(vop->dev);
if (ret < 0) {
dev_err(vop->dev, "failed to get pm runtime: %d\n", ret);
-   return;
+   goto err;
}

ret = clk_enable(vop->hclk);
if (ret < 0) {
dev_err(vop->dev, "failed to enable hclk - %d\n", ret);
-   return;
+   goto err;
}

ret = clk_enable(vop->dclk);
@@ -456,7 +503,6 @@ static void vop_enable(struct drm_crtc *crtc)
dev_err(vop->dev, "failed to enable aclk - %d\n", ret);
goto err_disable_dclk;
}
-
/*
 * Slave iommu shares power, irq and clock with vop.  It was associated
 * automatically with this master device via common driver code.
@@ -485,6 +531,21 @@ static void vop_enable(struct drm_crtc *crtc)

drm_crtc_vblank_on(crtc);

+   vop->vop_switch_status = 0;
+   wake_up(>wait_vop_switch_queue);
+
+   /* check how many vop we use now */
+   drm_for_each_crtc(crtc, vop->drm_dev) {
+   if (crtc->state->enable)
+   num_enabled_crtc++;
+   }
+
+   /* if enable two vop, need to disable dmc */
+   if ((num_enabled_crtc > 1) && vop->devfreq) {
+   if (vop->devfreq_event_dev)
+   devfreq_event_disable_edev(vop->devfreq_event_dev);
+   devfreq_suspend_device(vop->devfreq);
+   }
return;

 err_disabl

[PATCH v5 7/8] PM / devfreq: rockchip: add devfreq driver for rk3399 dmc

2016-08-10 Thread Lin Huang
base on dfi result, we do ddr frequency scaling, register
dmc driver to devfreq framework, and use simple-ondemand
policy.

Signed-off-by: Lin Huang 
---
Changes in v5:
- improve dmc driver suggest by Chanwoo Choi

Changes in v4:
- use arm_smccc_smc() function talk to bl31
- delete rockchip_dmc.c file and config
- delete dmc_notify
- adjust probe order

Changes in v3:
- operate dram setting through sip call
- imporve set rate flow

Changes in v2:
- None

Changes in v1:
- move dfi controller to event
- fix set voltage sequence when set rate fail
- change Kconfig type from tristate to bool
- move unuse EXPORT_SYMBOL_GPL()

 drivers/devfreq/Kconfig  |   9 +
 drivers/devfreq/Makefile |   1 +
 drivers/devfreq/rk3399_dmc.c | 512 +++
 3 files changed, 522 insertions(+)
 create mode 100644 drivers/devfreq/rk3399_dmc.c

diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig
index a5be56e..749499d 100644
--- a/drivers/devfreq/Kconfig
+++ b/drivers/devfreq/Kconfig
@@ -100,6 +100,15 @@ config ARM_TEGRA_DEVFREQ
  It reads ACTMON counters of memory controllers and adjusts the
  operating frequencies and voltages with OPP support.

+config ARM_RK3399_DMC_DEVFREQ
+   tristate "ARM RK3399 DMC DEVFREQ Driver"
+   select PM_OPP
+   select DEVFREQ_GOV_SIMPLE_ONDEMAND
+   help
+  This adds the DEVFREQ driver for the RK3399 dmc(Dynamic Memory 
Controller).
+  It sets the frequency for the memory controller and reads the usage 
counts
+  from hardware.
+
 source "drivers/devfreq/event/Kconfig"

 endif # PM_DEVFREQ
diff --git a/drivers/devfreq/Makefile b/drivers/devfreq/Makefile
index 09f11d9..70d9549 100644
--- a/drivers/devfreq/Makefile
+++ b/drivers/devfreq/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_DEVFREQ_GOV_PASSIVE)   += governor_passive.o
 # DEVFREQ Drivers
 obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ)   += exynos-bus.o
 obj-$(CONFIG_ARM_TEGRA_DEVFREQ)+= tegra-devfreq.o
+obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ)   += rk3399_dmc.o

 # DEVFREQ Event Drivers
 obj-$(CONFIG_PM_DEVFREQ_EVENT) += event/
diff --git a/drivers/devfreq/rk3399_dmc.c b/drivers/devfreq/rk3399_dmc.c
new file mode 100644
index 000..c1157ba
--- /dev/null
+++ b/drivers/devfreq/rk3399_dmc.c
@@ -0,0 +1,512 @@
+/*
+ * Copyright (c) 2016, Fuzhou Rockchip Electronics Co., Ltd.
+ * Author: Lin Huang 
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+struct dram_timing {
+   unsigned int ddr3_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 dram_dll_dis_freq;
+   unsigned int phy_dll_dis_freq;
+   unsigned int ddr3_odt_dis_freq;
+   unsigned int ddr3_drv;
+   unsigned int ddr3_odt;
+   unsigned int phy_ddr3_ca_drv;
+   unsigned int phy_ddr3_dq_drv;
+   unsigned int phy_ddr3_odt;
+   unsigned int lpddr3_odt_dis_freq;
+   unsigned int lpddr3_drv;
+   unsigned int lpddr3_odt;
+   unsigned int phy_lpddr3_ca_drv;
+   unsigned int phy_lpddr3_dq_drv;
+   unsigned int phy_lpddr3_odt;
+   unsigned int 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;
+};
+
+struct rk3399_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 dram_timing *timing;
+
+   /*
+* DDR Converser of Frequency (DCF) is used to implement DDR frequency
+* conversion without the participation of CPU, we will implement and
+* control it in arm trust firmware.
+*/
+   wait_queue_head_t   wait_dcf_queue;
+   int irq;
+   int wait_dcf_flag;
+   struct regulator *vdd_center;
+   unsigned long rate, target_rate;
+   unsigned long volt, target_volt;
+   struct dev_pm_opp *curr_opp;
+};
+
+static int rk3399_dmcfreq_target(struct device *dev, unsigned long *freq,
+u32 flag

[PATCH v5 6/8] Documentation: bindings: add dt documentation for rk3399 dmc

2016-08-10 Thread Lin Huang
This patch adds the documentation for rockchip rk3399 dmc driver.

Signed-off-by: Lin Huang 
---
Changes in v5:
-None

Changes in v4:
-None

Changes in v3:
-None

Changes in v2:
-None 

Changes in v1:
-None

 .../devicetree/bindings/devfreq/rk3399_dmc.txt | 35 ++
 1 file changed, 35 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt

diff --git a/Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt 
b/Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt
new file mode 100644
index 000..90e9581
--- /dev/null
+++ b/Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt
@@ -0,0 +1,35 @@
+* Rockchip rk3399 dmc device
+
+Required properties:
+- compatible: Must be "rockchip,rk3399-dmc".
+- devfreq-events: Node to get ddr loading, Refer to
+ Documentation/devicetree/bindings/devfreq/rockchip-dif.txt
+- interrupts: The interrupt number to the cpu. The interrupt specifier format
+ depends on the interrupt controller. 
+- clocks: Phandles for clock specified in "clock-names" property
+- clock-names : The name of clock used by the DFI, must be "pclk_ddr_mon";
+- operating-points-v2: Refer to Documentation/devicetree/bindings/power/opp.txt
+  for details.
+- center-supply: Dmc supply node.
+- status: Marks the node enabled/disabled.
+
+Optional properties:
+- ddr_timing: ddr timing need to pass to arm trust firmware
+- upthreshold: the upthreshold to simpleondeamnd policy
+- downdifferential: The downdifferential to simpleondeamnd policy
+
+Example:
+   dmc: dmc {
+   compatible = "rockchip,rk3399-dmc";
+   devfreq-events = <>;
+   interrupts = ;
+   clocks = < SCLK_DDRCLK>;
+   clock-names = "dmc_clk";
+   ddr_timing = <_timing>;
+   operating-points-v2 = <_opp_table>;
+   center-supply = <_centerlogic>;
+   upthreshold = <15>;
+   downdifferential = <10>;
+   status = "disabled";
+   };
+
-- 
1.9.1



[PATCH v5 5/8] PM / devfreq: event: support rockchip dfi controller

2016-08-10 Thread Lin Huang
on rk3399 platform, there is dfi conroller can monitor
ddr load, base on this result, we can do ddr freqency
scaling.

Signed-off-by: Lin Huang 
Acked-by: Chanwoo Choi 
---
Changes in v5:
-None

Changes in v4:
-None

Changes in v3:
-None

Changes in v2:
-None 

Changes in v1:
-None

 drivers/devfreq/event/Kconfig|   7 +
 drivers/devfreq/event/Makefile   |   1 +
 drivers/devfreq/event/rockchip-dfi.c | 253 +++
 3 files changed, 261 insertions(+)
 create mode 100644 drivers/devfreq/event/rockchip-dfi.c

diff --git a/drivers/devfreq/event/Kconfig b/drivers/devfreq/event/Kconfig
index eb6f74a..20d82c2 100644
--- a/drivers/devfreq/event/Kconfig
+++ b/drivers/devfreq/event/Kconfig
@@ -30,4 +30,11 @@ config DEVFREQ_EVENT_EXYNOS_PPMU
  (Platform Performance Monitoring Unit) counters to estimate the
  utilization of each module.

+config DEVFREQ_EVENT_ROCKCHIP_DFI
+   tristate "ROCKCHIP DFI DEVFREQ event Driver"
+   depends on ARCH_ROCKCHIP
+   help
+ This add the devfreq-event driver for Rockchip SoC. It provides DFI
+ (DDR Monitor Module) driver to count ddr load.
+
 endif # PM_DEVFREQ_EVENT
diff --git a/drivers/devfreq/event/Makefile b/drivers/devfreq/event/Makefile
index 3d6afd3..dda7090 100644
--- a/drivers/devfreq/event/Makefile
+++ b/drivers/devfreq/event/Makefile
@@ -2,3 +2,4 @@

 obj-$(CONFIG_DEVFREQ_EVENT_EXYNOS_NOCP) += exynos-nocp.o
 obj-$(CONFIG_DEVFREQ_EVENT_EXYNOS_PPMU) += exynos-ppmu.o
+obj-$(CONFIG_DEVFREQ_EVENT_ROCKCHIP_DFI) += rockchip-dfi.o
diff --git a/drivers/devfreq/event/rockchip-dfi.c 
b/drivers/devfreq/event/rockchip-dfi.c
new file mode 100644
index 000..3f12be7
--- /dev/null
+++ b/drivers/devfreq/event/rockchip-dfi.c
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2016, Fuzhou Rockchip Electronics Co., Ltd
+ * Author: Lin Huang 
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define RK3399_DMC_NUM_CH  2
+
+/* DDRMON_CTRL */
+#define DDRMON_CTRL0x04
+#define CLR_DDRMON_CTRL(0x1f << 0)
+#define LPDDR4_EN  (0x10001 << 4)
+#define HARDWARE_EN(0x10001 << 3)
+#define LPDDR3_EN  (0x10001 << 2)
+#define SOFTWARE_EN(0x10001 << 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
+#define DDRTYPE_SHIFT  13
+#define DDRTYPE_MASK   7
+
+enum {
+   DDR3 = 3,
+   LPDDR3 = 6,
+   LPDDR4 = 7,
+   UNUSED = 0xFF
+};
+
+struct dmc_usage {
+   u32 access;
+   u32 total;
+};
+
+struct rockchip_dfi {
+   struct devfreq_event_dev *edev;
+   struct devfreq_event_desc *desc;
+   struct dmc_usage ch_usage[RK3399_DMC_NUM_CH];
+   struct device *dev;
+   void __iomem *regs;
+   struct regmap *regmap_pmu;
+   struct clk *clk;
+};
+
+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, PMUGRF_OS_REG2, );
+   ddr_type = (val >> DDRTYPE_SHIFT) & DDRTYPE_MASK;
+
+   /* clear DDRMON_CTRL setting */
+   writel_relaxed(CLR_DDRMON_CTRL, dfi_regs + DDRMON_CTRL);
+
+   /* set ddr type to dfi */
+   if (ddr_type == LPDDR3)
+   writel_relaxed(LPDDR3_EN, dfi_regs + DDRMON_CTRL);
+   else if (ddr_type == LPDDR4)
+   writel_relaxed(LPDDR4_EN, dfi_regs + DDRMON_CTRL);
+
+   /* enable count, use software mode */
+   writel_relaxed(SOFTWARE_EN, dfi_regs + DDRMON_CTRL);
+}
+
+static void rockchip_dfi_stop_hardware_counter(struct devfreq_event_dev *edev)
+{
+   struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
+   void __iomem *dfi_regs = info->regs;
+   u32 val;
+
+   val = readl_relaxed(dfi_regs + DDRMON_CTRL);
+   val &= ~SOFTWARE_EN;
+   writel_relaxed(val, dfi_regs + DDRMON_CTRL);
+}
+
+static int rockchip_dfi_get_busier_ch(struct devfreq_event_dev *edev)
+{
+   struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
+   u32 tmp, max = 0;
+   

[PATCH v5 4/8] Documentation: bindings: add dt documentation for dfi controller

2016-08-10 Thread Lin Huang
This patch adds the documentation for rockchip dfi devfreq-event driver.

Signed-off-by: Lin Huang 
---
Changes in v5:
-None

Changes in v4:
-None

Changes in v3:
-None

Changes in v2:
-None 

Changes in v1:
-None

 .../bindings/devfreq/event/rockchip-dfi.txt  | 20 
 1 file changed, 20 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt

diff --git a/Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt 
b/Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt
new file mode 100644
index 000..bf42255
--- /dev/null
+++ b/Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt
@@ -0,0 +1,20 @@
+
+* Rockchip rk3399 DFI device
+
+Required properties:
+- compatible: Must be "rockchip,rk3399-dfi".
+- reg: physical base address of each DFI and length of memory mapped region
+- rockchip,pmu: phandle to the syscon managing the "pmu general register files"
+- clocks: phandles for clock specified in "clock-names" property
+- clock-names : the name of clock used by the DFI, must be "pclk_ddr_mon";
+
+Example:
+   dfi: dfi at 0xff63 {
+   reg = <0x00 0xff63 0x00 0x4000>;
+   compatible = "rockchip,rk3399-dfi";
+   rockchip,pmu = <>;
+   clocks = < PCLK_DDR_MON>;
+   clock-names = "pclk_ddr_mon";
+   status = "disabled";
+   };
+
-- 
1.9.1



[PATCH v5 3/8] clk: rockchip: rk3399: add ddrc clock support

2016-08-10 Thread Lin Huang
add ddrc clock setting, so we can do ddr frequency
scaling on rk3399 platform in future.

Signed-off-by: Lin Huang 
---
Changes in v5:
- fit for the ddr type

Changes in v4:
- None

Changes in v3:
- None

Changes in v2:
- remove clk_ddrc_dpll_src from critical clock list

Changes in v1:
- remove ddrc source CLK_IGNORE_UNUSED flag
- move clk_ddrc and clk_ddrc_dpll_src to critical

 drivers/clk/rockchip/clk-rk3399.c | 19 +++
 1 file changed, 19 insertions(+)

diff --git a/drivers/clk/rockchip/clk-rk3399.c 
b/drivers/clk/rockchip/clk-rk3399.c
index c109d80..b962aeb 100644
--- a/drivers/clk/rockchip/clk-rk3399.c
+++ b/drivers/clk/rockchip/clk-rk3399.c
@@ -118,6 +118,10 @@ PNAME(mux_armclkb_p)   = { 
"clk_core_b_lpll_src",
"clk_core_b_bpll_src",
"clk_core_b_dpll_src",
"clk_core_b_gpll_src" };
+PNAME(mux_ddrclk_p)= { "clk_ddrc_lpll_src",
+   "clk_ddrc_bpll_src",
+   "clk_ddrc_dpll_src",
+   "clk_ddrc_gpll_src" };
 PNAME(mux_aclk_cci_p)  = { "cpll_aclk_cci_src",
"gpll_aclk_cci_src",
"npll_aclk_cci_src",
@@ -1377,6 +1381,18 @@ static struct rockchip_clk_branch rk3399_clk_branches[] 
__initdata = {
COMPOSITE_NOMUX(0, "clk_test", "clk_test_pre", CLK_IGNORE_UNUSED,
RK3368_CLKSEL_CON(58), 0, 5, DFLAGS,
RK3368_CLKGATE_CON(13), 11, GFLAGS),
+
+   /* ddrc */
+   GATE(0, "clk_ddrc_lpll_src", "lpll", 0, RK3399_CLKGATE_CON(3),
+0, GFLAGS),
+   GATE(0, "clk_ddrc_bpll_src", "bpll", 0, RK3399_CLKGATE_CON(3),
+1, GFLAGS),
+   GATE(0, "clk_ddrc_dpll_src", "dpll", 0, RK3399_CLKGATE_CON(3),
+2, GFLAGS),
+   GATE(0, "clk_ddrc_gpll_src", "gpll", 0, RK3399_CLKGATE_CON(3),
+3, GFLAGS),
+   COMPOSITE_DDRCLK(SCLK_DDRC, "clk_ddrc", mux_ddrclk_p, 0,
+  RK3399_CLKSEL_CON(6), 4, 2, 0, 0, ROCKCHIP_DDRCLK_SIP),
 };

 static struct rockchip_clk_branch rk3399_clk_pmu_branches[] __initdata = {
@@ -1487,6 +1503,9 @@ static const char *const rk3399_cru_critical_clocks[] 
__initconst = {
"gpll_hclk_perilp1_src",
"gpll_aclk_perilp0_src",
"gpll_aclk_perihp_src",
+
+   /* ddrc */
+   "clk_ddrc"
 };

 static const char *const rk3399_pmucru_critical_clocks[] __initconst = {
-- 
1.9.1



[PATCH v5 2/8] clk: rockchip: rk3399: add SCLK_DDRCLK ID for ddrc

2016-08-10 Thread Lin Huang
Signed-off-by: Lin Huang 
---
Changes in v5:
-None
Changes in v4:
-None

Changes in v3:
-None

Changes in v2:
-None 

Changes in v1:
-None

 include/dt-bindings/clock/rk3399-cru.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/dt-bindings/clock/rk3399-cru.h 
b/include/dt-bindings/clock/rk3399-cru.h
index 50a44cf..ce5f3e9 100644
--- a/include/dt-bindings/clock/rk3399-cru.h
+++ b/include/dt-bindings/clock/rk3399-cru.h
@@ -131,6 +131,7 @@
 #define SCLK_DPHY_RX0_CFG  165
 #define SCLK_RMII_SRC  166
 #define SCLK_PCIEPHY_REF100M   167
+#define SCLK_DDRC  168

 #define DCLK_VOP0  180
 #define DCLK_VOP1  181
-- 
1.9.1



[PATCH v5 1/8] clk: rockchip: add new clock-type for the ddrclk

2016-08-10 Thread Lin Huang
On new rockchip platform(rk3399 etc), there have dcf controller to
do ddr frequency scaling, and this controller will implement in
arm-trust-firmware. We add a special clock-type to handle that.

Signed-off-by: Lin Huang 
---
Changes in v5:
- delete unuse mux_flag
- use div_flag to distinguish sip call and other operate

Changes in v4:
- use arm_smccc_smc() to set/read ddr rate

Changes in v3:
- use sip call to set/read ddr rate

Changes in v2:
- use GENMASK instead val_mask
- use divider_recalc_rate() instead DIV_ROUND_UP_ULL
- cleanup code

Changes in v1:
- None

 drivers/clk/rockchip/Makefile   |   1 +
 drivers/clk/rockchip/clk-ddr.c  | 152 
 drivers/clk/rockchip/clk.c  |   9 +++
 drivers/clk/rockchip/clk.h  |  33 
 include/soc/rockchip/rockchip_sip.h |  27 +++
 5 files changed, 222 insertions(+)
 create mode 100644 drivers/clk/rockchip/clk-ddr.c
 create mode 100644 include/soc/rockchip/rockchip_sip.h

diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile
index f47a2fa..b5f2c8e 100644
--- a/drivers/clk/rockchip/Makefile
+++ b/drivers/clk/rockchip/Makefile
@@ -8,6 +8,7 @@ obj-y   += clk-pll.o
 obj-y  += clk-cpu.o
 obj-y  += clk-inverter.o
 obj-y  += clk-mmc-phase.o
+obj-y  += clk-ddr.o
 obj-$(CONFIG_RESET_CONTROLLER) += softrst.o

 obj-y  += clk-rk3036.o
diff --git a/drivers/clk/rockchip/clk-ddr.c b/drivers/clk/rockchip/clk-ddr.c
new file mode 100644
index 000..756e1ad
--- /dev/null
+++ b/drivers/clk/rockchip/clk-ddr.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2016 Rockchip Electronics Co. Ltd.
+ * Author: Lin Huang 
+ *
+ * This program 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 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+struct rockchip_ddrclk {
+   struct clk_hw   hw;
+   void __iomem*reg_base;
+   int mux_offset;
+   int mux_shift;
+   int mux_width;
+   int div_shift;
+   int div_width;
+   int ddr_flag;
+   spinlock_t  *lock;
+};
+
+#define to_rockchip_ddrclk_hw(hw) container_of(hw, struct rockchip_ddrclk, hw)
+
+static int rockchip_ddrclk_set_rate(struct clk_hw *hw, unsigned long drate,
+   unsigned long prate)
+{
+   struct rockchip_ddrclk *ddrclk = to_rockchip_ddrclk_hw(hw);
+   unsigned long flags;
+   struct arm_smccc_res res;
+   int ret;
+
+   spin_lock_irqsave(ddrclk->lock, flags);
+   if (ddrclk->ddr_flag == ROCKCHIP_DDRCLK_SIP) {
+   arm_smccc_smc(SIP_DDR_FREQ, drate, 0, CONFIG_DRAM_SET_RATE,
+ 0, 0, 0, 0, );
+   ret = res.a0;
+   }
+   spin_unlock_irqrestore(ddrclk->lock, flags);
+
+   return ret;
+}
+
+static unsigned long
+rockchip_ddrclk_recalc_rate(struct clk_hw *hw,
+   unsigned long parent_rate)
+{
+   struct rockchip_ddrclk *ddrclk = to_rockchip_ddrclk_hw(hw);
+   struct arm_smccc_res res;
+   int ret;
+
+   if (ddrclk->ddr_flag == ROCKCHIP_DDRCLK_SIP) {
+   arm_smccc_smc(SIP_DDR_FREQ, 0, 0, CONFIG_DRAM_GET_RATE,
+ 0, 0, 0, 0, );
+   ret = res.a0;
+   }
+
+   return ret;
+}
+
+static long clk_ddrclk_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
+{
+   return rate;
+}
+
+static u8 rockchip_ddrclk_get_parent(struct clk_hw *hw)
+{
+   struct rockchip_ddrclk *ddrclk = to_rockchip_ddrclk_hw(hw);
+   int num_parents = clk_hw_get_num_parents(hw);
+   u32 val;
+
+   val = clk_readl(ddrclk->reg_base +
+   ddrclk->mux_offset) >> ddrclk->mux_shift;
+   val &= GENMASK(ddrclk->mux_width - 1, 0);
+
+   if (val >= num_parents)
+   return -EINVAL;
+
+   return val;
+}
+
+static const struct clk_ops rockchip_ddrclk_ops = {
+   .recalc_rate = rockchip_ddrclk_recalc_rate,
+   .set_rate = rockchip_ddrclk_set_rate,
+   .round_rate = clk_ddrclk_round_rate,
+   .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,
+int mux_shift, int mux_widt

[PATCH v5 0/8] rk3399 support ddr frequency scaling

2016-08-10 Thread Lin Huang
rk3399 platform have dfi controller can monitor ddr load,
and dcf controller to handle ddr register so we can get the
right ddr frequency and make ddr controller happy work(which
will implement in bl31). So we do ddr frequency scaling with
following flow:

 kernelbl31

monitor ddr load
|
|
get_target_rate
|
|   pass rate to bl31
clk_set_rate(ddr) ->run dcf flow
|   |
|   |
wait dcf interrupt<---trigger dcf interrupt
|
|
  return

Lin Huang (8):
  clk: rockchip: add new clock-type for the ddrclk
  clk: rockchip: rk3399: add SCLK_DDRCLK ID for ddrc
  clk: rockchip: rk3399: add ddrc clock support
  Documentation: bindings: add dt documentation for dfi controller
  PM / devfreq: event: support rockchip dfi controller
  Documentation: bindings: add dt documentation for rk3399 dmc
  PM / devfreq: rockchip: add devfreq driver for rk3399 dmc
  drm/rockchip: Add dmc notifier in vop driver

 .../bindings/devfreq/event/rockchip-dfi.txt|  20 +
 .../devicetree/bindings/devfreq/rk3399_dmc.txt |  35 ++
 drivers/clk/rockchip/Makefile  |   1 +
 drivers/clk/rockchip/clk-ddr.c | 152 ++
 drivers/clk/rockchip/clk-rk3399.c  |  19 +
 drivers/clk/rockchip/clk.c |   9 +
 drivers/clk/rockchip/clk.h |  33 ++
 drivers/devfreq/Kconfig|   9 +
 drivers/devfreq/Makefile   |   1 +
 drivers/devfreq/event/Kconfig  |   7 +
 drivers/devfreq/event/Makefile |   1 +
 drivers/devfreq/event/rockchip-dfi.c   | 253 ++
 drivers/devfreq/rk3399_dmc.c   | 512 +
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c| 128 +-
 include/dt-bindings/clock/rk3399-cru.h |   1 +
 include/soc/rockchip/rockchip_sip.h|  27 ++
 16 files changed, 1205 insertions(+), 3 deletions(-)
 create mode 100644 
Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt
 create mode 100644 Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt
 create mode 100644 drivers/clk/rockchip/clk-ddr.c
 create mode 100644 drivers/devfreq/event/rockchip-dfi.c
 create mode 100644 drivers/devfreq/rk3399_dmc.c
 create mode 100644 include/soc/rockchip/rockchip_sip.h

-- 
1.9.1



[PATCH v4 7/7] drm/rockchip: Add dmc notifier in vop driver

2016-07-29 Thread Lin Huang
when in ddr frequency scaling process, vop can not do
enable or disable operation, since dcf will base on vop vblank
time to do frequency scaling and need to get vop irq if there
have vop enabled. So need register to devfreq notifier, and we can
get the dmc status. Also, when there have two vop enabled, we need
to disable dmc, since dcf only base on one vop vblank time, so the
other panel will flicker when do ddr frequency scaling.

Signed-off-by: Lin Huang 
---
Changes in v4:
- register notifier to devfreq_register_notifier
- use DEVFREQ_PRECHANGE and DEVFREQ_POSTCHANGE to get dmc status
- when two vop enable, disable dmc
- when two vop back to one vop, enable dmc

Changes in v3:
- when do vop eanble/disable, dmc will wait until it finish

Changes in v2:
- None

Changes in v1:
- use wait_event instead usleep

 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 124 ++--
 1 file changed, 119 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index c179933..3b251d1 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -12,6 +12,8 @@
  * GNU General Public License for more details.
  */

+#include 
+#include 
 #include 
 #include 
 #include 
@@ -127,6 +129,13 @@ struct vop {

const struct vop_data *data;

+   struct devfreq *devfreq;
+   struct devfreq_event_dev *devfreq_event_dev;
+   struct notifier_block dmc_nb;
+   int dmc_in_process;
+   int vop_switch_status;
+   wait_queue_head_t wait_dmc_queue;
+   wait_queue_head_t wait_vop_switch_queue;
uint32_t *regsbak;
void __iomem *regs;

@@ -500,24 +509,60 @@ static void vop_line_flag_irq_disable(struct vop *vop)
spin_unlock_irqrestore(>irq_lock, flags);
 }

+static int dmc_notify(struct notifier_block *nb, unsigned long event,
+ void *data)
+{
+   struct vop *vop = container_of(nb, struct vop, dmc_nb);
+
+   if (event == DEVFREQ_PRECHANGE) {
+
+   /*
+* check if vop in enable or disable process,
+* if yes, wait until it finish, use 200ms as
+* timeout.
+*/
+   if (!wait_event_timeout(vop->wait_vop_switch_queue,
+   !vop->vop_switch_status, HZ / 5))
+   dev_warn(vop->dev,
+"Timeout waiting for vop swtich status\n");
+   vop->dmc_in_process = 1;
+   } else if (event == DEVFREQ_POSTCHANGE) {
+   vop->dmc_in_process = 0;
+   wake_up(>wait_dmc_queue);
+   }
+
+   return NOTIFY_OK;
+}
+
 static void vop_enable(struct drm_crtc *crtc)
 {
struct vop *vop = to_vop(crtc);
+   int num_enabled_crtc = 0;
int ret;

if (vop->is_enabled)
return;

+   /*
+* if in dmc scaling frequency process, wait until it finishes
+* use 100ms as timeout time.
+*/
+   if (!wait_event_timeout(vop->wait_dmc_queue,
+   !vop->dmc_in_process, HZ / 5))
+   dev_warn(vop->dev,
+"Timeout waiting for dmc when vop enable\n");
+
+   vop->vop_switch_status = 1;
ret = pm_runtime_get_sync(vop->dev);
if (ret < 0) {
dev_err(vop->dev, "failed to get pm runtime: %d\n", ret);
-   return;
+   goto err;
}

ret = clk_enable(vop->hclk);
if (ret < 0) {
dev_err(vop->dev, "failed to enable hclk - %d\n", ret);
-   return;
+   goto err;
}

ret = clk_enable(vop->dclk);
@@ -531,7 +576,6 @@ static void vop_enable(struct drm_crtc *crtc)
dev_err(vop->dev, "failed to enable aclk - %d\n", ret);
goto err_disable_dclk;
}
-
/*
 * Slave iommu shares power, irq and clock with vop.  It was associated
 * automatically with this master device via common driver code.
@@ -560,6 +604,21 @@ static void vop_enable(struct drm_crtc *crtc)

drm_crtc_vblank_on(crtc);

+   vop->vop_switch_status = 0;
+   wake_up(>wait_vop_switch_queue);
+
+   /* check how many vop we use now */
+   drm_for_each_crtc(crtc, vop->drm_dev) {
+   if (crtc->state->enable)
+   num_enabled_crtc++;
+   }
+
+   /* if enable two vop, need to disable dmc */
+   if ((num_enabled_crtc > 1) && vop->devfreq) {
+   if (vop->devfreq_event_dev)
+   devfreq_event_disable_edev(vop->devfreq_event_dev);
+   devfreq_suspend_device(vop->devfreq);
+   }
return;

 err_disable_aclk:
@@ -568,17 +627,33 @@ err_disabl

[PATCH v4 6/7] PM / devfreq: rockchip: add devfreq driver for rk3399 dmc

2016-07-29 Thread Lin Huang
base on dfi result, we do ddr frequency scaling, register
dmc driver to devfreq framework, and use simple-ondemand
policy.

Signed-off-by: Lin Huang 
---
Changes in v4:
- use arm_smccc_smc() function talk to bl31
- delete rockchip_dmc.c file and config
- delete dmc_notify
- adjust probe order

Changes in v3:
- operate dram setting through sip call
- imporve set rate flow

Changes in v2:
- None

Changes in v1:
- move dfi controller to event
- fix set voltage sequence when set rate fail
- change Kconfig type from tristate to bool
- move unuse EXPORT_SYMBOL_GPL()

 drivers/devfreq/Kconfig   |   1 +
 drivers/devfreq/Makefile  |   1 +
 drivers/devfreq/rockchip/Kconfig  |   8 +
 drivers/devfreq/rockchip/Makefile |   1 +
 drivers/devfreq/rockchip/rk3399_dmc.c | 473 ++
 5 files changed, 484 insertions(+)
 create mode 100644 drivers/devfreq/rockchip/Kconfig
 create mode 100644 drivers/devfreq/rockchip/Makefile
 create mode 100644 drivers/devfreq/rockchip/rk3399_dmc.c

diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig
index 64281bb..acb2a57 100644
--- a/drivers/devfreq/Kconfig
+++ b/drivers/devfreq/Kconfig
@@ -99,5 +99,6 @@ config ARM_TEGRA_DEVFREQ
  operating frequencies and voltages with OPP support.

 source "drivers/devfreq/event/Kconfig"
+source "drivers/devfreq/rockchip/Kconfig"

 endif # PM_DEVFREQ
diff --git a/drivers/devfreq/Makefile b/drivers/devfreq/Makefile
index 5134f9e..d844e23 100644
--- a/drivers/devfreq/Makefile
+++ b/drivers/devfreq/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_DEVFREQ_GOV_USERSPACE) += governor_userspace.o
 obj-$(CONFIG_ARM_EXYNOS4_BUS_DEVFREQ)  += exynos/
 obj-$(CONFIG_ARM_EXYNOS5_BUS_DEVFREQ)  += exynos/
 obj-$(CONFIG_ARM_TEGRA_DEVFREQ)+= tegra-devfreq.o
+obj-$(CONFIG_ARCH_ROCKCHIP)+= rockchip/

 # DEVFREQ Event Drivers
 obj-$(CONFIG_PM_DEVFREQ_EVENT) += event/
diff --git a/drivers/devfreq/rockchip/Kconfig b/drivers/devfreq/rockchip/Kconfig
new file mode 100644
index 000..d8f9e66
--- /dev/null
+++ b/drivers/devfreq/rockchip/Kconfig
@@ -0,0 +1,8 @@
+config ARM_RK3399_DMC_DEVFREQ
+   tristate "ARM RK3399 DMC DEVFREQ Driver"
+   select PM_OPP
+   select DEVFREQ_GOV_SIMPLE_ONDEMAND
+   help
+  This adds the DEVFREQ driver for the RK3399 dmc. It sets the 
frequency
+  for the memory controller and reads the usage counts from hardware.
+
diff --git a/drivers/devfreq/rockchip/Makefile 
b/drivers/devfreq/rockchip/Makefile
new file mode 100644
index 000..c62c105
--- /dev/null
+++ b/drivers/devfreq/rockchip/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ)   += rk3399_dmc.o
diff --git a/drivers/devfreq/rockchip/rk3399_dmc.c 
b/drivers/devfreq/rockchip/rk3399_dmc.c
new file mode 100644
index 000..527aa11
--- /dev/null
+++ b/drivers/devfreq/rockchip/rk3399_dmc.c
@@ -0,0 +1,473 @@
+/*
+ * Copyright (c) 2016, Fuzhou Rockchip Electronics Co., Ltd
+ * Author: Lin Huang 
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+struct dram_timing {
+   unsigned int ddr3_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 dram_dll_dis_freq;
+   unsigned int phy_dll_dis_freq;
+   unsigned int ddr3_odt_dis_freq;
+   unsigned int ddr3_drv;
+   unsigned int ddr3_odt;
+   unsigned int phy_ddr3_ca_drv;
+   unsigned int phy_ddr3_dq_drv;
+   unsigned int phy_ddr3_odt;
+   unsigned int lpddr3_odt_dis_freq;
+   unsigned int lpddr3_drv;
+   unsigned int lpddr3_odt;
+   unsigned int phy_lpddr3_ca_drv;
+   unsigned int phy_lpddr3_dq_drv;
+   unsigned int phy_lpddr3_odt;
+   unsigned int 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;
+};
+
+struct rk3399_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;
+   

[PATCH v4 5/7] PM / devfreq: event: support rockchip dfi controller

2016-07-29 Thread Lin Huang
on rk3399 platform, there is dfi conroller can monitor
ddr load, base on this result, we can do ddr freqency
scaling.

Signed-off-by: Lin Huang 
Acked-by: Chanwoo Choi 
---
Changes in v4:
- None

Changes in v3:
- None

Changes in v2:
- use clk_disable_unprepare and clk_enable_prepare
- remove clk_enable_prepare in probe
- remove rockchip_dfi_remove function

Changes in v1:
- None

 drivers/devfreq/event/Kconfig|   7 +
 drivers/devfreq/event/Makefile   |   1 +
 drivers/devfreq/event/rockchip-dfi.c | 253 +++
 3 files changed, 261 insertions(+)
 create mode 100644 drivers/devfreq/event/rockchip-dfi.c

diff --git a/drivers/devfreq/event/Kconfig b/drivers/devfreq/event/Kconfig
index a11720a..ff9279f 100644
--- a/drivers/devfreq/event/Kconfig
+++ b/drivers/devfreq/event/Kconfig
@@ -22,4 +22,11 @@ config DEVFREQ_EVENT_EXYNOS_PPMU
  (Platform Performance Monitoring Unit) counters to estimate the
  utilization of each module.

+config DEVFREQ_EVENT_ROCKCHIP_DFI
+   tristate "ROCKCHIP DFI DEVFREQ event Driver"
+   depends on ARCH_ROCKCHIP
+   help
+ This add the devfreq-event driver for Rockchip SoC. It provides DFI
+ (DDR Monitor Module) driver to count ddr load.
+
 endif # PM_DEVFREQ_EVENT
diff --git a/drivers/devfreq/event/Makefile b/drivers/devfreq/event/Makefile
index be146ea..e3f88fc 100644
--- a/drivers/devfreq/event/Makefile
+++ b/drivers/devfreq/event/Makefile
@@ -1,2 +1,3 @@
 # Exynos DEVFREQ Event Drivers
 obj-$(CONFIG_DEVFREQ_EVENT_EXYNOS_PPMU) += exynos-ppmu.o
+obj-$(CONFIG_DEVFREQ_EVENT_ROCKCHIP_DFI) += rockchip-dfi.o
diff --git a/drivers/devfreq/event/rockchip-dfi.c 
b/drivers/devfreq/event/rockchip-dfi.c
new file mode 100644
index 000..96a0307
--- /dev/null
+++ b/drivers/devfreq/event/rockchip-dfi.c
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2016, Fuzhou Rockchip Electronics Co., Ltd
+ * Author: Lin Huang 
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define RK3399_DMC_NUM_CH  2
+
+/* DDRMON_CTRL */
+#define DDRMON_CTRL0x04
+#define CLR_DDRMON_CTRL(0x1f << 0)
+#define LPDDR4_EN  (0x10001 << 4)
+#define HARDWARE_EN(0x10001 << 3)
+#define LPDDR3_EN  (0x10001 << 2)
+#define SOFTWARE_EN(0x10001 << 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
+#define DDRTYPE_SHIFT  13
+#define DDRTYPE_MASK   7
+
+enum {
+   DDR3 = 3,
+   LPDDR3 = 6,
+   LPDDR4 = 7,
+   UNUSED = 0xFF
+};
+
+struct dmc_usage {
+   u32 access;
+   u32 total;
+};
+
+struct rockchip_dfi {
+   struct devfreq_event_dev *edev;
+   struct devfreq_event_desc *desc;
+   struct dmc_usage ch_usage[RK3399_DMC_NUM_CH];
+   struct device *dev;
+   void __iomem *regs;
+   struct regmap *regmap_pmu;
+   struct clk *clk;
+};
+
+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, PMUGRF_OS_REG2, );
+   ddr_type = (val >> DDRTYPE_SHIFT) & DDRTYPE_MASK;
+
+   /* clear DDRMON_CTRL setting */
+   writel_relaxed(CLR_DDRMON_CTRL, dfi_regs + DDRMON_CTRL);
+
+   /* set ddr type to dfi */
+   if (ddr_type == LPDDR3)
+   writel_relaxed(LPDDR3_EN, dfi_regs + DDRMON_CTRL);
+   else if (ddr_type == LPDDR4)
+   writel_relaxed(LPDDR4_EN, dfi_regs + DDRMON_CTRL);
+
+   /* enable count, use software mode */
+   writel_relaxed(SOFTWARE_EN, dfi_regs + DDRMON_CTRL);
+}
+
+static void rockchip_dfi_stop_hardware_counter(struct devfreq_event_dev *edev)
+{
+   struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
+   void __iomem *dfi_regs = info->regs;
+   u32 val;
+
+   val = readl_relaxed(dfi_regs + DDRMON_CTRL);
+   val &= ~SOFTWARE_EN;
+   writel_relaxed(val, dfi_regs + DDRMON_CTRL);
+}
+
+static int rockchip_dfi_get_busier_ch(struct devfreq_event_dev *edev)
+{
+   struct rockchip_dfi *info = devfreq_event_get_

[PATCH v4 4/7] clk: rockchip: rk3399: add ddrc clock support

2016-07-29 Thread Lin Huang
add ddrc clock setting, so we can do ddr frequency
scaling on rk3399 platform in future.

Signed-off-by: Lin Huang 
---
Changes in v4:
- None

Changes in v3:
- None

Changes in v2:
- remove clk_ddrc_dpll_src from critical clock list

Changes in v1:
- remove ddrc source CLK_IGNORE_UNUSED flag
- move clk_ddrc and clk_ddrc_dpll_src to critical

 drivers/clk/rockchip/clk-rk3399.c | 19 +++
 1 file changed, 19 insertions(+)

diff --git a/drivers/clk/rockchip/clk-rk3399.c 
b/drivers/clk/rockchip/clk-rk3399.c
index d4a1cf0..b7b42d9 100644
--- a/drivers/clk/rockchip/clk-rk3399.c
+++ b/drivers/clk/rockchip/clk-rk3399.c
@@ -118,6 +118,10 @@ PNAME(mux_armclkb_p)   = { 
"clk_core_b_lpll_src",
"clk_core_b_bpll_src",
"clk_core_b_dpll_src",
"clk_core_b_gpll_src" };
+PNAME(mux_ddrclk_p)= { "clk_ddrc_lpll_src",
+   "clk_ddrc_bpll_src",
+   "clk_ddrc_dpll_src",
+   "clk_ddrc_gpll_src" };
 PNAME(mux_aclk_cci_p)  = { "cpll_aclk_cci_src",
"gpll_aclk_cci_src",
"npll_aclk_cci_src",
@@ -1377,6 +1381,18 @@ static struct rockchip_clk_branch rk3399_clk_branches[] 
__initdata = {
COMPOSITE_NOMUX(0, "clk_test", "clk_test_pre", CLK_IGNORE_UNUSED,
RK3368_CLKSEL_CON(58), 0, 5, DFLAGS,
RK3368_CLKGATE_CON(13), 11, GFLAGS),
+
+   /* ddrc */
+   GATE(0, "clk_ddrc_lpll_src", "lpll", 0, RK3399_CLKGATE_CON(3),
+0, GFLAGS),
+   GATE(0, "clk_ddrc_bpll_src", "bpll", 0, RK3399_CLKGATE_CON(3),
+1, GFLAGS),
+   GATE(0, "clk_ddrc_dpll_src", "dpll", 0, RK3399_CLKGATE_CON(3),
+2, GFLAGS),
+   GATE(0, "clk_ddrc_gpll_src", "gpll", 0, RK3399_CLKGATE_CON(3),
+3, GFLAGS),
+   COMPOSITE_DDRC(SCLK_DDRCLK, "clk_ddrc", mux_ddrclk_p, 0,
+  RK3399_CLKSEL_CON(6), 4, 2, MFLAGS, 0, 3, DFLAGS),
 };

 static struct rockchip_clk_branch rk3399_clk_pmu_branches[] __initdata = {
@@ -1487,6 +1503,9 @@ static const char *const rk3399_cru_critical_clocks[] 
__initconst = {
"gpll_hclk_perilp1_src",
"gpll_aclk_perilp0_src",
"gpll_aclk_perihp_src",
+
+   /* ddrc */
+   "clk_ddrc"
 };

 static const char *const rk3399_pmucru_critical_clocks[] __initconst = {
-- 
1.9.1



[PATCH v4 3/7] clk: rockchip: rk3399: add SCLK_DDRCLK ID for ddrc

2016-07-29 Thread Lin Huang
Signed-off-by: Lin Huang 
---
Changes in v4:
-None

Changes in v3:
-None

Changes in v2:
- None 
Changes in v1:
- None

 include/dt-bindings/clock/rk3399-cru.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/dt-bindings/clock/rk3399-cru.h 
b/include/dt-bindings/clock/rk3399-cru.h
index 50a44cf..8a0f0442 100644
--- a/include/dt-bindings/clock/rk3399-cru.h
+++ b/include/dt-bindings/clock/rk3399-cru.h
@@ -131,6 +131,7 @@
 #define SCLK_DPHY_RX0_CFG  165
 #define SCLK_RMII_SRC  166
 #define SCLK_PCIEPHY_REF100M   167
+#define SCLK_DDRCLK168

 #define DCLK_VOP0  180
 #define DCLK_VOP1  181
-- 
1.9.1



[PATCH v4 2/7] clk: rockchip: add new clock-type for the ddrclk

2016-07-29 Thread Lin Huang
On new rockchip platform(rk3399 etc), there have dcf controller to
do ddr frequency scaling, and this controller will implement in
arm-trust-firmware. We add a special clock-type to handle that.

Signed-off-by: Lin Huang 
---
Changes in v4:
- use arm_smccc_smc() to set/read ddr rate

Changes in v3:
- use sip call to set/read ddr rate

Changes in v2:
- use GENMASK instead val_mask
- use divider_recalc_rate() instead DIV_ROUND_UP_ULL
- cleanup code

Changes in v1:
- None

 drivers/clk/rockchip/Makefile   |   1 +
 drivers/clk/rockchip/clk-ddr.c  | 146 
 drivers/clk/rockchip/clk.c  |   9 +++
 drivers/clk/rockchip/clk.h  |  27 +++
 include/soc/rockchip/rockchip_sip.h |  27 +++
 5 files changed, 210 insertions(+)
 create mode 100644 drivers/clk/rockchip/clk-ddr.c
 create mode 100644 include/soc/rockchip/rockchip_sip.h

diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile
index f47a2fa..b5f2c8e 100644
--- a/drivers/clk/rockchip/Makefile
+++ b/drivers/clk/rockchip/Makefile
@@ -8,6 +8,7 @@ obj-y   += clk-pll.o
 obj-y  += clk-cpu.o
 obj-y  += clk-inverter.o
 obj-y  += clk-mmc-phase.o
+obj-y  += clk-ddr.o
 obj-$(CONFIG_RESET_CONTROLLER) += softrst.o

 obj-y  += clk-rk3036.o
diff --git a/drivers/clk/rockchip/clk-ddr.c b/drivers/clk/rockchip/clk-ddr.c
new file mode 100644
index 000..dd657c6
--- /dev/null
+++ b/drivers/clk/rockchip/clk-ddr.c
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2016 Rockchip Electronics Co. Ltd.
+ * Author: Lin Huang 
+ *
+ * This program 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 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+struct rockchip_ddrclk {
+   struct clk_hw   hw;
+   void __iomem*reg_base;
+   int mux_offset;
+   int mux_shift;
+   int mux_width;
+   int mux_flag;
+   int div_shift;
+   int div_width;
+   int div_flag;
+   spinlock_t  *lock;
+};
+
+#define to_rockchip_ddrclk_hw(hw) container_of(hw, struct rockchip_ddrclk, hw)
+
+static int rockchip_ddrclk_set_rate(struct clk_hw *hw, unsigned long drate,
+   unsigned long prate)
+{
+   struct rockchip_ddrclk *ddrclk = to_rockchip_ddrclk_hw(hw);
+   unsigned long flags;
+   struct arm_smccc_res res;
+
+   spin_lock_irqsave(ddrclk->lock, flags);
+   arm_smccc_smc(SIP_DDR_FREQ, drate, 0, CONFIG_DRAM_SET_RATE,
+ 0, 0, 0, 0, );
+   spin_unlock_irqrestore(ddrclk->lock, flags);
+
+   return res.a0;
+}
+
+static unsigned long
+rockchip_ddrclk_recalc_rate(struct clk_hw *hw,
+   unsigned long parent_rate)
+{
+   struct arm_smccc_res res;
+
+   arm_smccc_smc(SIP_DDR_FREQ, 0, 0, CONFIG_DRAM_GET_RATE,
+ 0, 0, 0, 0, );
+
+   return res.a0;
+}
+
+static long clk_ddrclk_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
+{
+   return rate;
+}
+
+static u8 rockchip_ddrclk_get_parent(struct clk_hw *hw)
+{
+   struct rockchip_ddrclk *ddrclk = to_rockchip_ddrclk_hw(hw);
+   int num_parents = clk_hw_get_num_parents(hw);
+   u32 val;
+
+   val = clk_readl(ddrclk->reg_base +
+   ddrclk->mux_offset) >> ddrclk->mux_shift;
+   val &= GENMASK(ddrclk->mux_width - 1, 0);
+
+   if (val >= num_parents)
+   return -EINVAL;
+
+   return val;
+}
+
+static const struct clk_ops rockchip_ddrclk_ops = {
+   .recalc_rate = rockchip_ddrclk_recalc_rate,
+   .set_rate = rockchip_ddrclk_set_rate,
+   .round_rate = clk_ddrclk_round_rate,
+   .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,
+int mux_shift, int mux_width,
+int mux_flag, int div_shift,
+int div_width, int div_flag,
+void __iomem *reg_base,
+spinlock_t *lock)
+{
+   struct rockchip_ddrclk *ddrclk;
+   struct clk_init_data init;
+   struct clk *clk;
+
+   ddr

[PATCH v4 1/7] clk: rockchip: add clock flag parameter when register pll

2016-07-29 Thread Lin Huang
From: Heiko Stübner <he...@sntech.de>

add clock flag parameter so we can pass specific clock flag
(like CLK_GET_RATE_NOCACHE etc..)to pll driver.

Signed-off-by: Heiko Stübner 
Signed-off-by: Lin Huang 
---
Changes in v4:
- None

Changes in v3:
- None

Changes in v2:
- None

Changes in v1:
- None

 drivers/clk/rockchip/clk-pll.c | 4 ++--
 drivers/clk/rockchip/clk.c | 2 +-
 drivers/clk/rockchip/clk.h | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c
index 8ac73bc..d824c36 100644
--- a/drivers/clk/rockchip/clk-pll.c
+++ b/drivers/clk/rockchip/clk-pll.c
@@ -864,7 +864,7 @@ struct clk *rockchip_clk_register_pll(struct 
rockchip_clk_provider *ctx,
u8 num_parents, int con_offset, int grf_lock_offset,
int lock_shift, int mode_offset, int mode_shift,
struct rockchip_pll_rate_table *rate_table,
-   u8 clk_pll_flags)
+   unsigned long flags, u8 clk_pll_flags)
 {
const char *pll_parents[3];
struct clk_init_data init;
@@ -919,7 +919,7 @@ struct clk *rockchip_clk_register_pll(struct 
rockchip_clk_provider *ctx,
init.name = pll_name;

/* keep all plls untouched for now */
-   init.flags = CLK_IGNORE_UNUSED;
+   init.flags = flags | CLK_IGNORE_UNUSED;

init.parent_names = _names[0];
init.num_parents = 1;
diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
index f0a8be1..9a046f1 100644
--- a/drivers/clk/rockchip/clk.c
+++ b/drivers/clk/rockchip/clk.c
@@ -390,7 +390,7 @@ void __init rockchip_clk_register_plls(struct 
rockchip_clk_provider *ctx,
list->con_offset, grf_lock_offset,
list->lock_shift, list->mode_offset,
list->mode_shift, list->rate_table,
-   list->pll_flags);
+   list->flags, list->pll_flags);
if (IS_ERR(clk)) {
pr_err("%s: failed to register clock %s\n", __func__,
list->name);
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
index 1abb7d0..bac775d 100644
--- a/drivers/clk/rockchip/clk.h
+++ b/drivers/clk/rockchip/clk.h
@@ -238,7 +238,7 @@ struct clk *rockchip_clk_register_pll(struct 
rockchip_clk_provider *ctx,
u8 num_parents, int con_offset, int grf_lock_offset,
int lock_shift, int mode_offset, int mode_shift,
struct rockchip_pll_rate_table *rate_table,
-   u8 clk_pll_flags);
+   unsigned long flags, u8 clk_pll_flags);

 struct rockchip_cpuclk_clksel {
int reg;
-- 
1.9.1



[PATCH v4 0/7] rk3399 support ddr frequency scaling

2016-07-29 Thread Lin Huang
rk3399 platform have dfi controller can monitor ddr load,
and dcf controller to handle ddr register so we can get the
right ddr frequency and make ddr controller happy work(which
will implement in bl31). So we do ddr frequency scaling with
following flow:

 kernelbl31

monitor ddr load
|
|
get_target_rate
|
|   pass rate to bl31
clk_set_rate(ddr) ->run dcf flow
|   |
|   |
wait dcf interrupt<---trigger dcf interrupt  
|
|
  return

Lin Huang (6):
  clk: rockchip: add new clock-type for the ddrclk
  clk: rockchip: rk3399: add SCLK_DDRCLK ID for ddrc
  clk: rockchip: rk3399: add ddrc clock support
  PM / devfreq: event: support rockchip dfi controller
  PM / devfreq: rockchip: add devfreq driver for rk3399 dmc
  drm/rockchip: Add dmc notifier in vop driver


Heiko Stübner (1):
  clk: rockchip: add clock flag parameter when register pll

Lin Huang (6):
  clk: rockchip: add new clock-type for the ddrclk
  clk: rockchip: rk3399: add SCLK_DDRCLK ID for ddrc
  clk: rockchip: rk3399: add ddrc clock support
  PM / devfreq: event: support rockchip dfi controller
  PM / devfreq: rockchip: add devfreq driver for rk3399 dmc
  drm/rockchip: Add dmc notifier in vop driver

 drivers/clk/rockchip/Makefile   |   1 +
 drivers/clk/rockchip/clk-ddr.c  | 146 +
 drivers/clk/rockchip/clk-pll.c  |   4 +-
 drivers/clk/rockchip/clk-rk3399.c   |  19 ++
 drivers/clk/rockchip/clk.c  |  11 +-
 drivers/clk/rockchip/clk.h  |  29 +-
 drivers/devfreq/Kconfig |   1 +
 drivers/devfreq/Makefile|   1 +
 drivers/devfreq/event/Kconfig   |   7 +
 drivers/devfreq/event/Makefile  |   1 +
 drivers/devfreq/event/rockchip-dfi.c| 253 +++
 drivers/devfreq/rockchip/Kconfig|   8 +
 drivers/devfreq/rockchip/Makefile   |   1 +
 drivers/devfreq/rockchip/rk3399_dmc.c   | 473 
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 124 +++-
 include/dt-bindings/clock/rk3399-cru.h  |   1 +
 include/soc/rockchip/rockchip_sip.h |  27 ++
 17 files changed, 1098 insertions(+), 9 deletions(-)
 create mode 100644 drivers/clk/rockchip/clk-ddr.c
 create mode 100644 drivers/devfreq/event/rockchip-dfi.c
 create mode 100644 drivers/devfreq/rockchip/Kconfig
 create mode 100644 drivers/devfreq/rockchip/Makefile
 create mode 100644 drivers/devfreq/rockchip/rk3399_dmc.c
 create mode 100644 include/soc/rockchip/rockchip_sip.h

-- 
1.9.1



  1   2   >