diff --git a/config/kernel/linux-rockchip-default.config b/config/kernel/linux-rockchip-default.config index e84ef75e0..746dd3bc1 100644 --- a/config/kernel/linux-rockchip-default.config +++ b/config/kernel/linux-rockchip-default.config @@ -3818,6 +3818,8 @@ CONFIG_MMC=y # CONFIG_MMC_DEBUG is not set # CONFIG_MMC_EMBEDDED_SDIO is not set # CONFIG_MMC_PARANOID_SD_INIT is not set +CONFIG_PWRSEQ_EMMC=y +CONFIG_PWRSEQ_SIMPLE=y # # MMC/SD/SDIO Card Drivers diff --git a/patch/kernel/rockchip-default/linux-0000-Revert-rk-add-gcc-wrapper.patch b/patch/kernel/rockchip-default/01-linux-0000-Revert-rk-add-gcc-wrapper.patch similarity index 100% rename from patch/kernel/rockchip-default/linux-0000-Revert-rk-add-gcc-wrapper.patch rename to patch/kernel/rockchip-default/01-linux-0000-Revert-rk-add-gcc-wrapper.patch diff --git a/patch/kernel/rockchip-default/01-linux-0001-rockchip.patch b/patch/kernel/rockchip-default/01-linux-0001-rockchip.patch new file mode 100644 index 000000000..dc2fe1dca --- /dev/null +++ b/patch/kernel/rockchip-default/01-linux-0001-rockchip.patch @@ -0,0 +1,1092 @@ +From 00ddf696ea9a7e980ea8e6ff895defe392db0c11 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 17 Apr 2017 13:09:16 +0200 +Subject: [PATCH] sound/usb/quirks-table: add Realtek ALC4040 + +--- + sound/usb/quirks-table.h | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h +index 69bf5cf1e91e..00672a818145 100644 +--- a/sound/usb/quirks-table.h ++++ b/sound/usb/quirks-table.h +@@ -3324,4 +3324,13 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"), + } + }, + ++{ ++ USB_DEVICE(0x0bda, 0x481a), ++ .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { ++ .vendor_name = "Realtek", ++ .product_name = "ALC4040", ++ .ifnum = QUIRK_NO_INTERFACE ++ } ++}, ++ + #undef USB_DEVICE_VENDOR_SPEC + +From 55a67a2125f372eed3281cec9914ecd66283955b Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 28 May 2017 09:08:50 +0200 +Subject: [PATCH] gpu/arm/mali400: default to performance gpu governor + +--- + drivers/gpu/arm/mali400/mali/linux/mali_devfreq.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_devfreq.c b/drivers/gpu/arm/mali400/mali/linux/mali_devfreq.c +index c9b8652f100d..6c97c530a2ae 100644 +--- a/drivers/gpu/arm/mali400/mali/linux/mali_devfreq.c ++++ b/drivers/gpu/arm/mali400/mali/linux/mali_devfreq.c +@@ -259,7 +259,7 @@ int mali_devfreq_init(struct mali_device *mdev) + return -EFAULT; + + mdev->devfreq = devfreq_add_device(mdev->dev, dp, +- "simple_ondemand", NULL); ++ "performance", NULL); + if (IS_ERR(mdev->devfreq)) { + mali_devfreq_term_freq_table(mdev); + return PTR_ERR(mdev->devfreq); + +From 188e9f097216cd73fa78abf9545837464dd70231 Mon Sep 17 00:00:00 2001 +From: LongChair +Date: Fri, 21 Apr 2017 13:39:12 +0200 +Subject: [PATCH] drm/rockchip: remove unsupported 4K freqs + +--- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +index a58edabe600c..7273561fe6b1 100644 +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -510,9 +510,15 @@ dw_hdmi_rockchip_mode_valid(struct drm_connector *connector, + return MODE_BAD; + + hdmi = to_rockchip_hdmi(encoder); +- if (hdmi->dev_type == RK3368_HDMI && mode->clock > 340000 && ++ if ((hdmi->dev_type == RK3368_HDMI || hdmi->dev_type == RK3328_HDMI) && ++ mode->clock > 340000 && + !drm_mode_is_420(&connector->display_info, mode)) + return MODE_BAD; ++ ++ /* Skip bad clocks for RK3288 */ ++ if (hdmi->dev_type == RK3288_HDMI && (mode->clock < 27500 || mode->clock > 340000)) ++ return MODE_CLOCK_RANGE; ++ + /* + * ensure all drm display mode can work, if someone want support more + * resolutions, please limit the possible_crtc, only connect to + +From cde112e9f9e564806b49bbe317b783e78a6b5c3a Mon Sep 17 00:00:00 2001 +From: xuhuicong +Date: Fri, 23 Jun 2017 18:56:17 +0800 +Subject: [PATCH] drm/rockchip: hdmi: fix no sound some time + +Change-Id: Ic9f931d9a5b7bca954363293a20ca242eb0bfa6f +Signed-off-by: xuhuicong +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index d57d999c50a5..ae498d097b61 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -1991,10 +1991,6 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi, + HDMI_FC_INVIDCONF_IN_I_P_INTERLACED : + HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE; + +- inv_val |= hdmi->sink_is_hdmi ? +- HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE : +- HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE; +- + hdmi_writeb(hdmi, inv_val, HDMI_FC_INVIDCONF); + + hdisplay = mode->hdisplay; +@@ -2292,6 +2288,9 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode) + /* not for DVI mode */ + if (hdmi->sink_is_hdmi) { + dev_dbg(hdmi->dev, "%s HDMI mode\n", __func__); ++ hdmi_modb(hdmi, HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE, ++ HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE, ++ HDMI_FC_INVIDCONF); + + /* HDMI Initialization Step F - Configure AVI InfoFrame */ + hdmi_config_AVI(hdmi, mode); + +From e56478758d232f503414c1e004f6f52973aeb0c4 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sat, 18 Nov 2017 11:09:39 +0100 +Subject: [PATCH] rockchip: vop: force skip lines if image too big + +--- + drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +index a2c1d85bba95..784e83537692 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +@@ -1649,6 +1649,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane, + int ymirror, xmirror; + uint32_t val; + bool rb_swap, global_alpha_en; ++ int skip_lines = 0; + + #if defined(CONFIG_ROCKCHIP_DRM_DEBUG) + bool AFBC_flag = false; +@@ -1685,8 +1686,14 @@ static void vop_plane_atomic_update(struct drm_plane *plane, + } + + mode = &crtc->state->adjusted_mode; ++ ++ /* ++ * force skip lines if image too big. ++ */ + actual_w = drm_rect_width(src) >> 16; +- actual_h = drm_rect_height(src) >> 16; ++ if (actual_w == 3840 && is_yuv_support(fb->pixel_format)) ++ skip_lines = 1; ++ actual_h = drm_rect_height(src) >> (16 + skip_lines); + act_info = (actual_h - 1) << 16 | ((actual_w - 1) & 0xffff); + + dsp_info = (drm_rect_height(dest) - 1) << 16; +@@ -1708,10 +1715,10 @@ static void vop_plane_atomic_update(struct drm_plane *plane, + VOP_WIN_SET(vop, win, xmirror, xmirror); + VOP_WIN_SET(vop, win, ymirror, ymirror); + VOP_WIN_SET(vop, win, format, vop_plane_state->format); +- VOP_WIN_SET(vop, win, yrgb_vir, fb->pitches[0] >> 2); ++ VOP_WIN_SET(vop, win, yrgb_vir, fb->pitches[0] >> (2 - skip_lines)); + VOP_WIN_SET(vop, win, yrgb_mst, vop_plane_state->yrgb_mst); + if (is_yuv_support(fb->pixel_format)) { +- VOP_WIN_SET(vop, win, uv_vir, fb->pitches[1] >> 2); ++ VOP_WIN_SET(vop, win, uv_vir, fb->pitches[1] >> (2 - skip_lines)); + VOP_WIN_SET(vop, win, uv_mst, vop_plane_state->uv_mst); + } + VOP_WIN_SET(vop, win, fmt_10, is_yuv_10bit(fb->pixel_format)); + +From d1cc2fb593abab7510948339db9cf4b9a59926c6 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sat, 18 Nov 2017 23:17:24 +0100 +Subject: [PATCH] gpu/arm/midgard: default to performance gpu governor + +--- + drivers/gpu/arm/midgard/backend/gpu/mali_kbase_devfreq.c | 5 ++--- + drivers/gpu/arm/midgard/mali_kbase_config_defaults.h | 3 +-- + 2 files changed, 3 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_devfreq.c b/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_devfreq.c +index 1495f06cd9b9..a6d2e0121015 100644 +--- a/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_devfreq.c ++++ b/drivers/gpu/arm/midgard/backend/gpu/mali_kbase_devfreq.c +@@ -348,8 +348,7 @@ int kbase_devfreq_init(struct kbase_device *kbdev) + dp = &kbdev->devfreq_profile; + + dp->initial_freq = kbdev->current_freq; +- /* .KP : set devfreq_dvfs_interval_in_ms */ +- dp->polling_ms = 20; ++ dp->polling_ms = 100; + dp->target = kbase_devfreq_target; + dp->get_dev_status = kbase_devfreq_status; + dp->get_cur_freq = kbase_devfreq_cur_freq; +@@ -363,7 +362,7 @@ int kbase_devfreq_init(struct kbase_device *kbdev) + return err; + + kbdev->devfreq = devfreq_add_device(kbdev->dev, dp, +- "simple_ondemand", NULL); ++ "performance", NULL); + if (IS_ERR(kbdev->devfreq)) { + kbase_devfreq_term_freq_table(kbdev); + return PTR_ERR(kbdev->devfreq); +diff --git a/drivers/gpu/arm/midgard/mali_kbase_config_defaults.h b/drivers/gpu/arm/midgard/mali_kbase_config_defaults.h +index 1cf44b3500cf..a6a1a52f0463 100644 +--- a/drivers/gpu/arm/midgard/mali_kbase_config_defaults.h ++++ b/drivers/gpu/arm/midgard/mali_kbase_config_defaults.h +@@ -109,8 +109,7 @@ enum { + /* + * Default period for DVFS sampling + */ +-// #define DEFAULT_PM_DVFS_PERIOD 100 /* 100ms */ +-#define DEFAULT_PM_DVFS_PERIOD 20 /* 20 ms */ ++#define DEFAULT_PM_DVFS_PERIOD 100 /* 100ms */ + + /* + * Power Management poweroff tick granuality. This is in nanoseconds to + +From fd3c597dd56bca81fc642d918343ab2f9435628f Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 10 Dec 2017 14:16:09 +0100 +Subject: [PATCH] uapi: install rockchip_drm header + +--- + include/uapi/drm/Kbuild | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/include/uapi/drm/Kbuild b/include/uapi/drm/Kbuild +index 38d437096c35..b7ae9969d41e 100644 +--- a/include/uapi/drm/Kbuild ++++ b/include/uapi/drm/Kbuild +@@ -11,6 +11,7 @@ header-y += nouveau_drm.h + header-y += qxl_drm.h + header-y += r128_drm.h + header-y += radeon_drm.h ++header-y += rockchip_drm.h + header-y += savage_drm.h + header-y += sis_drm.h + header-y += tegra_drm.h + +From b5afb970037ac69a22f6d514c34175835f6078fc Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 10 Dec 2017 18:03:53 +0100 +Subject: [PATCH] phy: rockchip-inno-hdmi-phy: add vesa dmt pixel clocks + +--- + drivers/phy/rockchip/phy-rockchip-inno-hdmi-phy.c | 64 +++++++++++++++++++++++ + 1 file changed, 64 insertions(+) + +diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi-phy.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi-phy.c +index 0161f80ab964..6cf391405ad6 100644 +--- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi-phy.c ++++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi-phy.c +@@ -278,6 +278,70 @@ static const struct pre_pll_config pre_pll_cfg_table[] = { + {594000000, 371250000, 4, 495, 1, 2, 0, 1, 3, 1, 1, 1, 0}, + {593407000, 593407000, 1, 98, 0, 2, 0, 1, 0, 1, 1, 0, 0xE6AE6B}, + {594000000, 594000000, 1, 99, 0, 2, 0, 1, 0, 1, 1, 0, 0}, ++ { 25175000, 25175000, 30, 1007, 1, 2, 2, 1, 2, 3, 4, 0, 0}, ++ { 31500000, 31500000, 1, 21, 1, 1, 1, 1, 2, 2, 2, 0, 0}, ++ { 33750000, 33750000, 1, 45, 1, 2, 2, 1, 2, 3, 4, 0, 0}, ++ { 35500000, 35500000, 3, 71, 1, 1, 1, 1, 2, 2, 2, 0, 0}, ++ { 36000000, 36000000, 1, 12, 0, 1, 1, 1, 0, 2, 2, 0, 0}, ++ { 49500000, 49500000, 1, 33, 1, 1, 1, 1, 2, 2, 2, 0, 0}, ++ { 50000000, 50000000, 3, 50, 0, 1, 1, 1, 0, 2, 2, 0, 0}, ++ { 56250000, 56250000, 1, 75, 1, 2, 2, 1, 2, 3, 4, 0, 0}, ++ { 68250000, 68250000, 1, 91, 1, 2, 2, 1, 2, 3, 4, 0, 0}, ++ { 72000000, 72000000, 1, 24, 0, 1, 1, 1, 0, 2, 2, 0, 0}, ++ { 73250000, 73250000, 3, 293, 1, 2, 2, 1, 2, 3, 4, 0, 0}, ++ { 75000000, 75000000, 1, 25, 0, 1, 1, 1, 0, 2, 2, 0, 0}, ++ { 78750000, 78750000, 1, 105, 1, 2, 2, 1, 2, 3, 4, 0, 0}, ++ { 79500000, 79500000, 1, 53, 1, 1, 1, 1, 2, 2, 2, 0, 0}, ++ { 85500000, 85500000, 1, 57, 1, 1, 1, 1, 2, 2, 2, 0, 0}, ++ { 94500000, 94500000, 1, 63, 1, 1, 1, 1, 2, 2, 2, 0, 0}, ++ {101000000, 101000000, 3, 101, 0, 1, 1, 1, 0, 2, 2, 0, 0}, ++ {102250000, 102250000, 3, 409, 1, 2, 2, 1, 2, 3, 4, 0, 0}, ++ {106500000, 106500000, 1, 71, 1, 1, 1, 1, 2, 2, 2, 0, 0}, ++ {115500000, 115500000, 1, 77, 1, 1, 1, 1, 2, 2, 2, 0, 0}, ++ {117500000, 117500000, 3, 235, 1, 1, 1, 1, 2, 2, 2, 0, 0}, ++ {121750000, 121750000, 3, 487, 1, 2, 2, 1, 2, 3, 4, 0, 0}, ++ {122500000, 122500000, 3, 245, 1, 1, 1, 1, 2, 2, 2, 0, 0}, ++ {135000000, 135000000, 1, 45, 0, 1, 1, 1, 0, 2, 2, 0, 0}, ++ {136750000, 136750000, 3, 547, 1, 2, 2, 1, 2, 3, 4, 0, 0}, ++ {140250000, 140250000, 1, 187, 1, 2, 2, 1, 2, 3, 4, 0, 0}, ++ {146250000, 146250000, 1, 195, 1, 2, 2, 1, 2, 3, 4, 0, 0}, ++ {148250000, 148250000, 3, 593, 1, 2, 2, 1, 2, 3, 4, 0, 0}, ++ {154000000, 154000000, 3, 154, 0, 1, 1, 1, 0, 2, 2, 0, 0}, ++ {156000000, 156000000, 1, 52, 0, 1, 1, 1, 0, 2, 2, 0, 0}, ++ {156750000, 156750000, 1, 209, 1, 2, 2, 1, 2, 3, 4, 0, 0}, ++ {157000000, 157000000, 3, 157, 0, 1, 1, 1, 0, 2, 2, 0, 0}, ++ {157500000, 157500000, 1, 105, 1, 1, 1, 1, 2, 2, 2, 0, 0}, ++ {175500000, 175500000, 1, 117, 1, 1, 1, 1, 2, 2, 2, 0, 0}, ++ {179500000, 179500000, 3, 359, 1, 1, 1, 1, 2, 2, 2, 0, 0}, ++ {182750000, 182750000, 3, 731, 1, 2, 2, 1, 2, 3, 4, 0, 0}, ++ {187000000, 187000000, 3, 187, 0, 1, 1, 1, 0, 2, 2, 0, 0}, ++ {187250000, 187250000, 3, 749, 1, 2, 2, 1, 2, 3, 4, 0, 0}, ++ {189000000, 189000000, 1, 63, 0, 1, 1, 1, 0, 2, 2, 0, 0}, ++ {193250000, 193250000, 3, 773, 1, 2, 2, 1, 2, 3, 4, 0, 0}, ++ {202500000, 202500000, 1, 135, 1, 1, 1, 1, 2, 2, 2, 0, 0}, ++ {204750000, 204750000, 1, 273, 1, 2, 2, 1, 2, 3, 4, 0, 0}, ++ {208000000, 208000000, 3, 208, 0, 1, 1, 1, 0, 2, 2, 0, 0}, ++ {214750000, 214750000, 3, 859, 1, 2, 2, 1, 2, 3, 4, 0, 0}, ++ {218250000, 218250000, 1, 291, 1, 2, 2, 1, 2, 3, 4, 0, 0}, ++ {229500000, 229500000, 1, 153, 1, 1, 1, 1, 2, 2, 2, 0, 0}, ++ {234000000, 234000000, 1, 78, 0, 1, 1, 1, 0, 2, 2, 0, 0}, ++ {241500000, 241500000, 1, 161, 1, 1, 1, 1, 2, 2, 2, 0, 0}, ++ {245250000, 245250000, 1, 327, 1, 2, 2, 1, 2, 3, 4, 0, 0}, ++ {245500000, 245500000, 3, 491, 1, 1, 1, 1, 2, 2, 2, 0, 0}, ++ {261000000, 261000000, 1, 87, 0, 1, 1, 1, 0, 2, 2, 0, 0}, ++ {268250000, 268250000, 3, 1073, 1, 2, 2, 1, 2, 3, 4, 0, 0}, ++ {268500000, 268500000, 1, 179, 1, 1, 1, 1, 2, 2, 2, 0, 0}, ++ {281250000, 281250000, 1, 375, 1, 2, 2, 1, 2, 3, 4, 0, 0}, ++ {288000000, 288000000, 1, 96, 0, 1, 1, 1, 0, 2, 2, 0, 0}, ++ {312250000, 312250000, 3, 1249, 1, 2, 2, 1, 2, 3, 4, 0, 0}, ++ {317000000, 317000000, 3, 317, 0, 1, 1, 1, 0, 2, 2, 0, 0}, ++ {333250000, 333250000, 3, 1333, 1, 2, 2, 1, 2, 3, 4, 0, 0}, ++ {348500000, 348500000, 3, 697, 1, 1, 1, 1, 2, 2, 2, 0, 0}, ++ {356500000, 356500000, 3, 713, 1, 1, 1, 1, 2, 2, 2, 0, 0}, ++ {380500000, 380500000, 3, 761, 1, 1, 1, 1, 2, 2, 2, 0, 0}, ++ {443250000, 443250000, 1, 591, 1, 2, 2, 1, 2, 3, 4, 0, 0}, ++ {505250000, 505250000, 3, 2021, 1, 2, 2, 1, 2, 3, 4, 0, 0}, ++ {552750000, 552750000, 1, 737, 1, 2, 2, 1, 2, 3, 4, 0, 0}, + { ~0UL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + }; + + +From 0377b8c27f4b56b0b6f1fc8af11cde6ab8517c3b Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Tue, 12 Dec 2017 00:37:27 +0100 +Subject: [PATCH] clk: rockchip: fix round rate + +--- + drivers/clk/rockchip/clk-pll.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c +index addcdb07553a..e3d7a9ee1078 100644 +--- a/drivers/clk/rockchip/clk-pll.c ++++ b/drivers/clk/rockchip/clk-pll.c +@@ -356,6 +356,17 @@ static const struct rockchip_pll_rate_table *rockchip_get_pll_settings( + static long rockchip_pll_round_rate(struct clk_hw *hw, + unsigned long drate, unsigned long *prate) + { ++ struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); ++ const struct rockchip_pll_rate_table *rate; ++ ++ /* Get required rate settings from table */ ++ rate = rockchip_get_pll_settings(pll, drate); ++ if (!rate) { ++ pr_debug("%s: Invalid rate : %lu for pll clk %s\n", __func__, ++ drate, __clk_get_name(hw->clk)); ++ return -EINVAL; ++ } ++ + return drate; + } + + +From c4bc7e7f44f76a7f6f2374956fd68cab657f1eb3 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 21 Jan 2018 17:20:00 +0100 +Subject: [PATCH] drm: fix HDR metadata infoframe length + +HDR metadata infoframe length is 26 bytes (not 30) according to [1] +(CTA-861-G: 6.9 Dynamic Range and Mastering InfoFrame) + +Fixes activation of HDR mode on my LG OLED + +[1] https://standards.cta.tech/kwspub/published_docs/CTA-861-G_FINAL_revised_2017.pdf +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 2 +- + drivers/gpu/drm/drm_edid.c | 4 ++-- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index ae498d097b61..018bef374dc3 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -1857,7 +1857,7 @@ static void hdmi_config_hdr_infoframe(struct dw_hdmi *hdmi) + return; + } + +- hdmi_writeb(hdmi, 1, HDMI_FC_DRM_HB0); ++ hdmi_writeb(hdmi, frame.version, HDMI_FC_DRM_HB0); + hdmi_writeb(hdmi, frame.length, HDMI_FC_DRM_HB1); + hdmi_writeb(hdmi, frame.eotf, HDMI_FC_DRM_PB0); + hdmi_writeb(hdmi, frame.metadata_type, HDMI_FC_DRM_PB1); +diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c +index bfe671071d9f..e3a0f561e8f0 100644 +--- a/drivers/gpu/drm/drm_edid.c ++++ b/drivers/gpu/drm/drm_edid.c +@@ -4735,10 +4735,10 @@ drm_hdmi_infoframe_set_hdr_metadata(struct hdmi_drm_infoframe *frame, + + hdr_source_metadata = (struct hdr_static_metadata *)hdr_metadata; + +- frame->length = sizeof(struct hdr_static_metadata); ++ frame->length = 26; + + frame->eotf = hdr_source_metadata->eotf; +- frame->type = hdr_source_metadata->type; ++ frame->metadata_type = hdr_source_metadata->type; + + for (i = 0; i < 3; i++) { + frame->display_primaries_x[i] = + +From 3b4e87792660182b9f0093e016d41a7be53fe59e Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sat, 27 Jan 2018 09:39:09 +0100 +Subject: [PATCH] drm: add edid detection for Hybrid Log-Gamma EOTF + +--- + drivers/gpu/drm/drm_edid.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c +index e3a0f561e8f0..f7d41950614e 100644 +--- a/drivers/gpu/drm/drm_edid.c ++++ b/drivers/gpu/drm/drm_edid.c +@@ -2740,7 +2740,7 @@ add_detailed_modes(struct drm_connector *connector, struct edid *edid, + #define TRADITIONAL_GAMMA_SDR (0x1 << 0) + #define TRADITIONAL_GAMMA_HDR (0x1 << 1) + #define SMPTE_ST2084 (0x1 << 2) +-#define FUTURE_EOTF (0x1 << 3) ++#define HYBRID_LOG_GAMMA (0x1 << 3) + #define RESERVED_EOTF (0x3 << 4) + + #define STATIC_METADATA_TYPE1 (0x1 << 0) +@@ -3710,6 +3710,8 @@ static uint16_t eotf_supported(const u8 *edid_ext) + val |= TRADITIONAL_GAMMA_HDR; + if (edid_ext[2] & SMPTE_ST2084) + val |= SMPTE_ST2084; ++ if (edid_ext[2] & HYBRID_LOG_GAMMA) ++ val |= HYBRID_LOG_GAMMA; + + return val; + } + +From a11ad9338755a57859c7ca1b54b7719fb644a5ef Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 11 Feb 2018 19:21:41 +0100 +Subject: [PATCH] drm: bridge: dw-hdmi: default to underscan mode + +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index 018bef374dc3..d0866baa75fc 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -1691,7 +1691,7 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode) + break; + } + +- frame.scan_mode = HDMI_SCAN_MODE_NONE; ++ frame.scan_mode = HDMI_SCAN_MODE_UNDERSCAN; + + /* + * The Designware IP uses a different byte format from standard + +From cb40442a2cd891541ac55381a2610f61f9d56fa9 Mon Sep 17 00:00:00 2001 +From: David Carrillo-Cisneros +Date: Tue, 18 Jul 2017 18:18:37 -0700 +Subject: [PATCH] UPSTREAM: perf tools: Add EXCLUDE_EXTLIBS and EXTRA_PERFLIBS + to makefile + +The goal is to allow users to override linking of libraries that +were automatically added to PERFLIBS. + +EXCLUDE_EXTLIBS contains linker flags to be removed from LIBS +while EXTRA_PERFLIBS contains linker flags to be added. + +My use case is to force certain library to be build statically, +e.g. for libelf: + + EXCLUDE_EXTLIBS=-lelf EXTRA_PERFLIBS=path/libelf.a + +Signed-off-by: David Carrillo-Cisneros +Acked-by: Jiri Olsa +Cc: Alexander Shishkin +Cc: Elena Reshetova +Cc: Kees Kook +Cc: Paul Turner +Cc: Stephane Eranian +Cc: Sudeep Holla +Cc: Wang Nan +Link: http://lkml.kernel.org/r/20170719011839.99399-3-davidcc@google.com +Signed-off-by: Arnaldo Carvalho de Melo +(cherry picked from commit cb281fea4b0a326d2a2104f8ffae2b6895c561fd) +--- + tools/perf/Makefile.perf | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf +index fb1c9ddc3478..9b3b9bd50d54 100644 +--- a/tools/perf/Makefile.perf ++++ b/tools/perf/Makefile.perf +@@ -33,6 +33,11 @@ include config/utilities.mak + # + # Define EXTRA_CFLAGS=-m64 or EXTRA_CFLAGS=-m32 as appropriate for cross-builds. + # ++# Define EXCLUDE_EXTLIBS=-lmylib to exclude libmylib from the auto-generated ++# EXTLIBS. ++# ++# Define EXTRA_PERFLIBS to pass extra libraries to PERFLIBS. ++# + # Define NO_DWARF if you do not want debug-info analysis feature at all. + # + # Define WERROR=0 to disable treating any warnings as errors. +@@ -289,7 +294,8 @@ ifdef ASCIIDOC8 + export ASCIIDOC8 + endif + +-LIBS = -Wl,--whole-archive $(PERFLIBS) -Wl,--no-whole-archive -Wl,--start-group $(EXTLIBS) -Wl,--end-group ++EXTLIBS := $(call filter-out,$(EXCLUDE_EXTLIBS),$(EXTLIBS)) ++LIBS = -Wl,--whole-archive $(PERFLIBS) $(EXTRA_PERFLIBS) -Wl,--no-whole-archive -Wl,--start-group $(EXTLIBS) -Wl,--end-group + + export INSTALL SHELL_PATH + + +From 6f95e5cdd43756df0bc1caa983f0f326a38bb9ff Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Tue, 27 Feb 2018 20:49:00 +0100 +Subject: [PATCH] net: wireless: rockchip_wlan: rtl8723bs: do not accept all + sdio wlan id + +--- + drivers/net/wireless/rockchip_wlan/rtl8723bs/Makefile | 2 +- + drivers/net/wireless/rockchip_wlan/rtl8723bs/os_dep/linux/sdio_intf.c | 3 +++ + 2 files changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/Makefile b/drivers/net/wireless/rockchip_wlan/rtl8723bs/Makefile +index 0ff707fd37eb..ca79c18b8eb8 100644 +--- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/Makefile ++++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/Makefile +@@ -1347,7 +1347,7 @@ EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN -DCONFIG_PLATFORM_ANDROID -DCONFIG_PLATFO + EXTRA_CFLAGS += -DCONFIG_IOCTL_CFG80211 -DRTW_USE_CFG80211_STA_EVENT + EXTRA_CFLAGS += -DCONFIG_CONCURRENT_MODE + # default setting for Power control +-EXTRA_CFLAGS += -DRTW_ENABLE_WIFI_CONTROL_FUNC ++#EXTRA_CFLAGS += -DRTW_ENABLE_WIFI_CONTROL_FUNC + EXTRA_CFLAGS += -DRTW_SUPPORT_PLATFORM_SHUTDOWN + EXTRA_CFLAGS += -DCONFIG_RESUME_IN_WORKQUEUE + # default setting for Special function +diff --git a/drivers/net/wireless/rockchip_wlan/rtl8723bs/os_dep/linux/sdio_intf.c b/drivers/net/wireless/rockchip_wlan/rtl8723bs/os_dep/linux/sdio_intf.c +index b4654d229634..48b6cf61d436 100644 +--- a/drivers/net/wireless/rockchip_wlan/rtl8723bs/os_dep/linux/sdio_intf.c ++++ b/drivers/net/wireless/rockchip_wlan/rtl8723bs/os_dep/linux/sdio_intf.c +@@ -45,6 +45,9 @@ static struct mmc_host *mmc_host = NULL; + + static const struct sdio_device_id sdio_ids[] = { + #ifdef CONFIG_RTL8723B ++ { SDIO_DEVICE(0x024c, 0x0523), .driver_data = RTL8723B}, ++ { SDIO_DEVICE(0x024c, 0x0623), .driver_data = RTL8723B}, ++ { SDIO_DEVICE(0x024c, 0x0626), .driver_data = RTL8723B}, + { SDIO_DEVICE(0x024c, 0xB723), .driver_data = RTL8723B}, + #endif + #ifdef CONFIG_RTL8188E + +From 157645ba1282857bf4440707620c9ca91d8f8913 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Fri, 2 Mar 2018 20:53:32 +0100 +Subject: [PATCH] net: wireless: rockchip_wlan: bcmdhd: detect broadcom sdio + device id + +--- + drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/bcmsdh_sdmmc_linux.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/bcmsdh_sdmmc_linux.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/bcmsdh_sdmmc_linux.c +index 8864582b1706..b5a388cc3cbe 100755 +--- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/bcmsdh_sdmmc_linux.c ++++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/bcmsdh_sdmmc_linux.c +@@ -225,7 +225,7 @@ static const struct sdio_device_id bcmsdh_sdmmc_ids[] = { + { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4334) }, + { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4324) }, + { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43239) }, +- { SDIO_DEVICE_CLASS(SDIO_CLASS_NONE) }, ++ { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_ANY_ID) }, + { 0, 0, 0, 0 /* end: all zeroes */ + }, + }; + +From 00c9d5749537dacbd745ce3456f1335cbe019d54 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 1 Jul 2018 23:17:47 +0200 +Subject: [PATCH] drm/rockchip: clip yuv + +--- + drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 2 ++ + drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 2 ++ + drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 3 +++ + 3 files changed, 7 insertions(+) + +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +index 784e83537692..7073ea91c349 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +@@ -1712,6 +1712,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane, + + spin_lock(&vop->reg_lock); + ++ VOP_WIN_SET(vop, win, yuv_clip, 1); + VOP_WIN_SET(vop, win, xmirror, xmirror); + VOP_WIN_SET(vop, win, ymirror, ymirror); + VOP_WIN_SET(vop, win, format, vop_plane_state->format); +@@ -2512,6 +2513,7 @@ static void vop_update_csc(struct drm_crtc *crtc) + VOP_CTRL_SET(vop, dsp_data_swap, 0); + + VOP_CTRL_SET(vop, out_mode, s->output_mode); ++ VOP_CTRL_SET(vop, yuv_clip, 1); + + switch (s->bus_format) { + case MEDIA_BUS_FMT_RGB565_1X16: +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +index 5850572b40ff..b465c08876f8 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +@@ -171,6 +171,7 @@ struct vop_ctrl { + struct vop_reg dsp_lut_en; + + struct vop_reg out_mode; ++ struct vop_reg yuv_clip; + + struct vop_reg xmirror; + struct vop_reg ymirror; +@@ -395,6 +396,7 @@ struct vop_win_phy { + struct vop_reg format; + struct vop_reg fmt_10; + struct vop_reg csc_mode; ++ struct vop_reg yuv_clip; + struct vop_reg xmirror; + struct vop_reg ymirror; + struct vop_reg rb_swap; +diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +index 5f517e193cc8..f03009e304f8 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c ++++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +@@ -110,6 +110,7 @@ static const struct vop_win_phy rk3288_win01_data = { + .fmt_10 = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 4), + .csc_mode = VOP_REG_VER(RK3288_WIN0_CTRL0, 0x3, 10, 3, 2, -1), + .rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12), ++ .yuv_clip = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 20), + .xmirror = VOP_REG_VER(RK3368_WIN0_CTRL0, 0x1, 21, 3, 2, -1), + .ymirror = VOP_REG_VER(RK3368_WIN0_CTRL0, 0x1, 22, 3, 2, -1), + .act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0), +@@ -277,6 +278,7 @@ static const struct vop_ctrl rk3288_ctrl_data = { + .bcsh_color_bar = VOP_REG(RK3288_BCSH_COLOR_BAR, 0xffffff, 8), + .bcsh_en = VOP_REG(RK3288_BCSH_COLOR_BAR, 0x1, 0), + ++ .yuv_clip = VOP_REG(RK3288_DSP_CTRL0, 0x1, 21), + .xmirror = VOP_REG(RK3288_DSP_CTRL0, 0x1, 22), + .ymirror = VOP_REG(RK3288_DSP_CTRL0, 0x1, 23), + +@@ -955,6 +957,7 @@ static const struct vop_ctrl rk3328_ctrl_data = { + .dsp_lut_en = VOP_REG(RK3328_DSP_CTRL1, 0x1, 0), + .out_mode = VOP_REG(RK3328_DSP_CTRL0, 0xf, 0), + ++ .yuv_clip = VOP_REG(RK3328_DSP_CTRL0, 0x1, 21), + .xmirror = VOP_REG(RK3328_DSP_CTRL0, 0x1, 22), + .ymirror = VOP_REG(RK3328_DSP_CTRL0, 0x1, 23), + + +From 93fb1cdc962e44ce72fec1191e0bf200c9aaf130 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 8 Jul 2018 12:38:00 +0200 +Subject: [PATCH] drm/atomic: use active_only flag for connector atomic + begin/flush + +--- + drivers/gpu/drm/drm_atomic_helper.c | 20 ++++++++++---------- + 1 file changed, 10 insertions(+), 10 deletions(-) + +diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c +index f77d4aa1e58b..4da489b54dc5 100644 +--- a/drivers/gpu/drm/drm_atomic_helper.c ++++ b/drivers/gpu/drm/drm_atomic_helper.c +@@ -1563,15 +1563,15 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev, + for_each_connector_in_state(old_state, connector, old_conn_state, i) { + const struct drm_connector_helper_funcs *funcs; + +- if (!connector->state->crtc) +- continue; ++ funcs = connector->helper_private; + +- if (!connector->state->crtc->state->active) ++ if (!funcs || !funcs->atomic_begin) + continue; + +- funcs = connector->helper_private; ++ if (!connector->state->crtc) ++ continue; + +- if (!funcs || !funcs->atomic_begin) ++ if (active_only && !connector->state->crtc->state->active) + continue; + + DRM_DEBUG_ATOMIC("flush beginning [CONNECTOR:%d:%s]\n", +@@ -1645,15 +1645,15 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev, + for_each_connector_in_state(old_state, connector, old_conn_state, i) { + const struct drm_connector_helper_funcs *funcs; + +- if (!connector->state->crtc) +- continue; ++ funcs = connector->helper_private; + +- if (!connector->state->crtc->state->active) ++ if (!funcs || !funcs->atomic_flush) + continue; + +- funcs = connector->helper_private; ++ if (!connector->state->crtc) ++ continue; + +- if (!funcs || !funcs->atomic_flush) ++ if (active_only && !connector->state->crtc->state->active) + continue; + + DRM_DEBUG_ATOMIC("flushing [CONNECTOR:%d:%s]\n", + +From d0f8100f82203017bac6617d3f0e30b524956d36 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 22 Jul 2018 14:51:58 +0200 +Subject: [PATCH] drm: rockchip: dw-hdmi: only force YCbCr422 when max tmds is + up to 340Mhz + +--- + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +index 7273561fe6b1..e2aad6e2149b 100644 +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -728,7 +728,9 @@ dw_hdmi_rockchip_select_output(struct drm_connector_state *conn_state, + /* BT2020 require color depth at lest 10bit */ + *color_depth = 10; + /* We prefer use YCbCr422 to send 10bit */ +- if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422) ++ if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422 && ++ info->max_tmds_clock <= 340000 && ++ hdmi->dev_type != RK3288_HDMI) + *color_format = DRM_HDMI_OUTPUT_YCBCR422; + } + + +From d093be3d79b5c781719298676282e44b7d7bb290 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 22 Jul 2018 15:09:16 +0200 +Subject: [PATCH] drm: bridge: dw-hdmi: signal full range for rgb output + +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index d0866baa75fc..520f87b88130 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -1693,6 +1693,14 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode) + + frame.scan_mode = HDMI_SCAN_MODE_UNDERSCAN; + ++ if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format)) { ++ frame.quantization_range = HDMI_QUANTIZATION_RANGE_FULL; ++ frame.ycc_quantization_range = HDMI_YCC_QUANTIZATION_RANGE_FULL; ++ } else { ++ frame.quantization_range = HDMI_QUANTIZATION_RANGE_LIMITED; ++ frame.ycc_quantization_range = HDMI_YCC_QUANTIZATION_RANGE_LIMITED; ++ } ++ + /* + * The Designware IP uses a different byte format from standard + * AVI info frames, though generally the bits are in the correct + +From 623aaf53edd860816297c9230d39b5b96b0146f3 Mon Sep 17 00:00:00 2001 +From: Myy Miouyouyou +Date: Mon, 21 May 2018 22:32:59 +0200 +Subject: [PATCH] GPU: ARM: Midgard: Adapt to the new mmap call checks. + +Now, I don't know if this driver is just one of these "buggy" drivers +Linus is talking about, or if this is just standard GPU procedure. + +Anyway, this patch is due to this change by Linus Torvalds : +https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=be83bbf806822b1b89e0a0f23cd87cddc409e429 + +And the fix is inspired by : +https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=76ef6b28ea4f81c3d511866a9b31392caa833126 + +Signed-off-by: Myy Miouyouyou +--- + drivers/gpu/arm/midgard/mali_kbase_core_linux.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/arm/midgard/mali_kbase_core_linux.c b/drivers/gpu/arm/midgard/mali_kbase_core_linux.c +index 3a6e5aae0bce..2b24e415dfa6 100644 +--- a/drivers/gpu/arm/midgard/mali_kbase_core_linux.c ++++ b/drivers/gpu/arm/midgard/mali_kbase_core_linux.c +@@ -1155,6 +1155,7 @@ static int kbase_open(struct inode *inode, struct file *filp) + + init_waitqueue_head(&kctx->event_queue); + filp->private_data = kctx; ++ filp->f_mode |= FMODE_UNSIGNED_OFFSET; + kctx->filp = filp; + + if (kbdev->infinite_cache_active_default) + +From d0e509162ace165ab24c8a005a2666c6c17e4d69 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sat, 28 Jul 2018 10:41:40 +0200 +Subject: [PATCH] WIP: mm: dma-mapping: increase dma pool size + +--- + arch/arm/mm/dma-mapping.c | 2 +- + arch/arm64/mm/dma-mapping.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c +index d539dee3c78d..689961153d71 100644 +--- a/arch/arm/mm/dma-mapping.c ++++ b/arch/arm/mm/dma-mapping.c +@@ -301,7 +301,7 @@ static void __dma_free_remap(void *cpu_addr, size_t size) + VM_ARM_DMA_CONSISTENT | VM_USERMAP); + } + +-#define DEFAULT_DMA_COHERENT_POOL_SIZE SZ_256K ++#define DEFAULT_DMA_COHERENT_POOL_SIZE SZ_2M + static struct gen_pool *atomic_pool; + + static size_t atomic_pool_size = DEFAULT_DMA_COHERENT_POOL_SIZE; +diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c +index 2b05653e8156..2ad8515cd4da 100644 +--- a/arch/arm64/mm/dma-mapping.c ++++ b/arch/arm64/mm/dma-mapping.c +@@ -32,7 +32,7 @@ + + static struct gen_pool *atomic_pool; + +-#define DEFAULT_DMA_COHERENT_POOL_SIZE SZ_256K ++#define DEFAULT_DMA_COHERENT_POOL_SIZE SZ_2M + static size_t atomic_pool_size __initdata = DEFAULT_DMA_COHERENT_POOL_SIZE; + + static int __init early_coherent_pool(char *p) + +From 9cfc544f5914ccf2a44da96e491195eea763d70f Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sat, 4 Aug 2018 15:19:39 +0200 +Subject: [PATCH] drm: add picture_aspect_ratio to hdmi 1.4 4k modes + +--- + drivers/gpu/drm/drm_edid.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c +index f7d41950614e..69a1eb4ee382 100644 +--- a/drivers/gpu/drm/drm_edid.c ++++ b/drivers/gpu/drm/drm_edid.c +@@ -1233,25 +1233,25 @@ static const struct drm_display_mode edid_4k_modes[] = { + 3840, 4016, 4104, 4400, 0, + 2160, 2168, 2178, 2250, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), +- .vrefresh = 30, }, ++ .vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, }, + /* 2 - 3840x2160@25Hz */ + { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, + 3840, 4896, 4984, 5280, 0, + 2160, 2168, 2178, 2250, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), +- .vrefresh = 25, }, ++ .vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, }, + /* 3 - 3840x2160@24Hz */ + { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, + 3840, 5116, 5204, 5500, 0, + 2160, 2168, 2178, 2250, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), +- .vrefresh = 24, }, ++ .vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, }, + /* 4 - 4096x2160@24Hz (SMPTE) */ + { DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 297000, + 4096, 5116, 5204, 5500, 0, + 2160, 2168, 2178, 2250, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), +- .vrefresh = 24, }, ++ .vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135, }, + }; + + /*** DDC fetch and block validation ***/ + +From 728a068901826027cf45d404f49b58f6cf02156a Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sat, 4 Aug 2018 16:26:47 +0200 +Subject: [PATCH] drm: bridge: dw-hdmi: signal none colorimetry for rgb output + +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index 520f87b88130..c6ef3d43f997 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -1694,6 +1694,8 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode) + frame.scan_mode = HDMI_SCAN_MODE_UNDERSCAN; + + if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format)) { ++ frame.colorimetry = HDMI_COLORIMETRY_NONE; ++ frame.extended_colorimetry = 0; + frame.quantization_range = HDMI_QUANTIZATION_RANGE_FULL; + frame.ycc_quantization_range = HDMI_YCC_QUANTIZATION_RANGE_FULL; + } else { + +From bc7d29237337d1506fe63bbb421d64710e176537 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sat, 4 Aug 2018 16:27:08 +0200 +Subject: [PATCH] drm: bridge: dw-hdmi: signal it content and content type + +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index c6ef3d43f997..a0e25278232b 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -1692,6 +1692,8 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode) + } + + frame.scan_mode = HDMI_SCAN_MODE_UNDERSCAN; ++ frame.content_type = HDMI_CONTENT_TYPE_GRAPHICS; ++ frame.itc = true; + + if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format)) { + frame.colorimetry = HDMI_COLORIMETRY_NONE; + +From d0b82f5649ddb897cbf92f5e06030244ffc4e9eb Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sat, 4 Aug 2018 16:27:40 +0200 +Subject: [PATCH] drm: bridge: dw-hdmi: log infoframes + +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index a0e25278232b..f56f3224a1c9 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -1705,6 +1705,8 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode) + frame.ycc_quantization_range = HDMI_YCC_QUANTIZATION_RANGE_LIMITED; + } + ++ hdmi_infoframe_log(KERN_INFO, hdmi->dev, &frame); ++ + /* + * The Designware IP uses a different byte format from standard + * AVI info frames, though generally the bits are in the correct +@@ -1798,6 +1800,8 @@ static void hdmi_config_vendor_specific_infoframe(struct dw_hdmi *hdmi, + return; + } + ++ hdmi_infoframe_log(KERN_INFO, hdmi->dev, &frame); ++ + /* Set the length of HDMI vendor specific InfoFrame payload */ + hdmi_writeb(hdmi, buffer[2], HDMI_FC_VSDSIZE); + +@@ -1838,7 +1842,7 @@ static void hdmi_config_hdr_infoframe(struct dw_hdmi *hdmi) + + /* Dynamic Range and Mastering Infoframe is introduced in v2.11a. */ + if (hdmi->version < 0x211a) { +- DRM_ERROR("Not support DRM Infoframe\n"); ++ DRM_DEBUG("Not support DRM Infoframe\n"); + return; + } + +@@ -1869,6 +1873,8 @@ static void hdmi_config_hdr_infoframe(struct dw_hdmi *hdmi) + return; + } + ++ hdmi_infoframe_log(KERN_INFO, hdmi->dev, &frame); ++ + hdmi_writeb(hdmi, frame.version, HDMI_FC_DRM_HB0); + hdmi_writeb(hdmi, frame.length, HDMI_FC_DRM_HB1); + hdmi_writeb(hdmi, frame.eotf, HDMI_FC_DRM_PB0); + +From 13040ab461d79e1dc720677eb462ace745b33b84 Mon Sep 17 00:00:00 2001 +From: Nickey Yang +Date: Mon, 17 Jul 2017 16:35:34 +0800 +Subject: [PATCH] MINIARM: set npll be used for hdmi only + +Change-Id: I8bebfb2cfb68e3dad172e5547d3886526ad5e912 +Signed-off-by: Nickey Yang +--- + arch/arm/boot/dts/rk3288.dtsi | 4 +++- + drivers/clk/rockchip/clk-rk3288.c | 4 ++-- + 2 files changed, 5 insertions(+), 3 deletions(-) + +diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi +index 8e51132ef7e4..66962169da17 100644 +--- a/arch/arm/boot/dts/rk3288.dtsi ++++ b/arch/arm/boot/dts/rk3288.dtsi +@@ -1052,7 +1052,7 @@ + <&cru PCLK_PERI>; + assigned-clock-rates = <594000000>, + <500000000>, <300000000>, +- <150000000>, <75000000>, ++ <0>, <75000000>, + <300000000>, <150000000>, + <75000000>; + }; +@@ -1303,6 +1303,8 @@ + resets = <&cru SRST_LCDC0_AXI>, <&cru SRST_LCDC0_AHB>, <&cru SRST_LCDC0_DCLK>; + reset-names = "axi", "ahb", "dclk"; + iommus = <&vopb_mmu>; ++ assigned-clocks = <&cru DCLK_VOP0>; ++ assigned-clock-parents = <&cru PLL_NPLL>; + status = "disabled"; + + vopb_out: port { +diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c +index ca6c2ad3de96..415df387a5d6 100644 +--- a/drivers/clk/rockchip/clk-rk3288.c ++++ b/drivers/clk/rockchip/clk-rk3288.c +@@ -214,7 +214,7 @@ static struct rockchip_pll_clock rk3288_pll_clks[] __initdata = { + [gpll] = PLL(pll_rk3066, PLL_GPLL, "gpll", mux_pll_p, 0, RK3288_PLL_CON(12), + RK3288_MODE_CON, 12, 8, 0, rk3288_pll_rates), + [npll] = PLL(pll_rk3066, PLL_NPLL, "npll", mux_pll_p, 0, RK3288_PLL_CON(16), +- RK3288_MODE_CON, 14, 9, ROCKCHIP_PLL_SYNC_RATE, rk3288_pll_rates), ++ RK3288_MODE_CON, 14, 9, 0, rk3288_pll_rates), + }; + + static struct clk_div_table div_hclk_cpu_t[] = { +@@ -429,7 +429,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { + RK3288_CLKSEL_CON(30), 14, 2, MFLAGS, 8, 5, DFLAGS, + RK3288_CLKGATE_CON(3), 4, GFLAGS), + +- COMPOSITE(DCLK_VOP0, "dclk_vop0", mux_pll_src_cpll_gpll_npll_p, 0, ++ COMPOSITE(DCLK_VOP0, "dclk_vop0", mux_pll_src_cpll_gpll_npll_p, CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT, + RK3288_CLKSEL_CON(27), 0, 2, MFLAGS, 8, 8, DFLAGS, + RK3288_CLKGATE_CON(3), 1, GFLAGS), + COMPOSITE(DCLK_VOP1, "dclk_vop1", mux_pll_src_cpll_gpll_npll_p, 0, + +From fbefbd0989cf14e3d8f7864437a2264ab94c9b3f Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sat, 4 Aug 2018 14:51:14 +0200 +Subject: [PATCH] clk: rockchip: rk3288: use npll table to to improve HDMI + compatibility + +Based on https://github.com/TinkerBoard/debian_kernel/commit/3d90870530b8a2901681f7b7fa598ee7381e49f3 +--- + drivers/clk/rockchip/clk-rk3288.c | 23 ++++++++++++++++++++++- + 1 file changed, 22 insertions(+), 1 deletion(-) + +diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c +index 415df387a5d6..f748a292b7f4 100644 +--- a/drivers/clk/rockchip/clk-rk3288.c ++++ b/drivers/clk/rockchip/clk-rk3288.c +@@ -105,6 +105,27 @@ static struct rockchip_pll_rate_table rk3288_pll_rates[] = { + { /* sentinel */ }, + }; + ++static struct rockchip_pll_rate_table rk3288_npll_rates[] = { ++ RK3066_PLL_RATE_NB(594000000, 1, 99, 4, 32), ++ RK3066_PLL_RATE_NB(585000000, 6, 585, 4, 32), ++ RK3066_PLL_RATE_NB(432000000, 3, 216, 4, 32), ++ RK3066_PLL_RATE_NB(426000000, 3, 213, 4, 32), ++ RK3066_PLL_RATE_NB(400000000, 1, 100, 6, 32), ++ RK3066_PLL_RATE_NB(342000000, 3, 171, 4, 32), ++ RK3066_PLL_RATE_NB(297000000, 2, 198, 8, 16), ++ RK3066_PLL_RATE_NB(270000000, 1, 135, 12, 32), ++ RK3066_PLL_RATE_NB(260000000, 1, 130, 12, 32), ++ RK3066_PLL_RATE_NB(148500000, 1, 99, 16, 32), ++ RK3066_PLL_RATE(148352000, 13, 1125, 14), ++ RK3066_PLL_RATE_NB(146250000, 6, 585, 16, 32), ++ RK3066_PLL_RATE_NB(108000000, 1, 54, 12, 32), ++ RK3066_PLL_RATE_NB(106500000, 4, 213, 12, 32), ++ RK3066_PLL_RATE_NB(85500000, 4, 171, 12, 32), ++ RK3066_PLL_RATE_NB(74250000, 4, 198, 16, 32), ++ RK3066_PLL_RATE(74176000, 26, 1125, 14), ++ { /* sentinel */ }, ++}; ++ + #define RK3288_DIV_ACLK_CORE_M0_MASK 0xf + #define RK3288_DIV_ACLK_CORE_M0_SHIFT 0 + #define RK3288_DIV_ACLK_CORE_MP_MASK 0xf +@@ -214,7 +235,7 @@ static struct rockchip_pll_clock rk3288_pll_clks[] __initdata = { + [gpll] = PLL(pll_rk3066, PLL_GPLL, "gpll", mux_pll_p, 0, RK3288_PLL_CON(12), + RK3288_MODE_CON, 12, 8, 0, rk3288_pll_rates), + [npll] = PLL(pll_rk3066, PLL_NPLL, "npll", mux_pll_p, 0, RK3288_PLL_CON(16), +- RK3288_MODE_CON, 14, 9, 0, rk3288_pll_rates), ++ RK3288_MODE_CON, 14, 9, 0, rk3288_npll_rates), + }; + + static struct clk_div_table div_hclk_cpu_t[] = { diff --git a/patch/kernel/rockchip-default/linux-0003-cec.patch b/patch/kernel/rockchip-default/01-linux-0003-cec.patch similarity index 100% rename from patch/kernel/rockchip-default/linux-0003-cec.patch rename to patch/kernel/rockchip-default/01-linux-0003-cec.patch diff --git a/patch/kernel/rockchip-default/01-linux-0004-audio.patch b/patch/kernel/rockchip-default/01-linux-0004-audio.patch new file mode 100644 index 000000000..9c3608ae6 --- /dev/null +++ b/patch/kernel/rockchip-default/01-linux-0004-audio.patch @@ -0,0 +1,1597 @@ +From dabace918ba0543c5a12e03fb823886891cd82dc Mon Sep 17 00:00:00 2001 +From: Chris Zhong +Date: Mon, 18 Jul 2016 22:34:34 +0800 +Subject: [PATCH] UPSTREAM: ASoC: rockchip: correct the spdif clk + +The spdif mclk should be 128 times of sample rate, and there is a +internal divider, the real rate of spdif mclk is mclk / (div + 1). +Hence, the original driver always get the good frequency for +48000/96000/44100/192000. But for 32000, the mclk is incorrect, +it should be 32000*128, but get 48000*128. Do not use the internal +divider here, just set all mclk to 128 * sample rate directly. + +Signed-off-by: Chris Zhong +Signed-off-by: Mark Brown +(cherry picked from commit 46dd2e28a90e48fbf1b7e253933fa3b7242e9b1b) +--- + sound/soc/rockchip/rockchip_spdif.c | 17 +---------------- + 1 file changed, 1 insertion(+), 16 deletions(-) + +diff --git a/sound/soc/rockchip/rockchip_spdif.c b/sound/soc/rockchip/rockchip_spdif.c +index c211750b54ee..784941ca2408 100644 +--- a/sound/soc/rockchip/rockchip_spdif.c ++++ b/sound/soc/rockchip/rockchip_spdif.c +@@ -105,21 +105,7 @@ static int rk_spdif_hw_params(struct snd_pcm_substream *substream, + int ret; + + srate = params_rate(params); +- switch (srate) { +- case 32000: +- case 48000: +- case 96000: +- mclk = 96000 * 128; /* 12288000 hz */ +- break; +- case 44100: +- mclk = 44100 * 256; /* 11289600 hz */ +- break; +- case 192000: +- mclk = 192000 * 128; /* 24576000 hz */ +- break; +- default: +- return -EINVAL; +- } ++ mclk = srate * 128; + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: +@@ -143,7 +129,6 @@ static int rk_spdif_hw_params(struct snd_pcm_substream *substream, + return ret; + } + +- val |= SPDIF_CFGR_CLK_DIV(mclk/(srate * 256)); + ret = regmap_update_bits(spdif->regmap, SPDIF_CFGR, + SPDIF_CFGR_CLK_DIV_MASK | SPDIF_CFGR_HALFWORD_ENABLE | + SDPIF_CFGR_VDW_MASK, + +From 3069a5725338532939d13e3dc329f2b3d183b260 Mon Sep 17 00:00:00 2001 +From: Sugar Zhang +Date: Wed, 7 Sep 2016 14:30:21 +0800 +Subject: [PATCH] UPSTREAM: ASoC: rockchip: spdif: restore register during + runtime_suspend/resume cycle + +when step into runtime_suspend, spdif pd will be disabled and loss state. +so need to restore register when runtime_resume. + +Signed-off-by: Sugar Zhang +Signed-off-by: Mark Brown +(cherry picked from commit 3628c6987fb45d719cd963805bbba9f15017290e) +--- + sound/soc/rockchip/rockchip_spdif.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/rockchip/rockchip_spdif.c b/sound/soc/rockchip/rockchip_spdif.c +index 784941ca2408..831e4caf29d3 100644 +--- a/sound/soc/rockchip/rockchip_spdif.c ++++ b/sound/soc/rockchip/rockchip_spdif.c +@@ -69,6 +69,7 @@ static int __maybe_unused rk_spdif_runtime_suspend(struct device *dev) + { + struct rk_spdif_dev *spdif = dev_get_drvdata(dev); + ++ regcache_cache_only(spdif->regmap, true); + clk_disable_unprepare(spdif->mclk); + clk_disable_unprepare(spdif->hclk); + +@@ -92,7 +93,16 @@ static int __maybe_unused rk_spdif_runtime_resume(struct device *dev) + return ret; + } + +- return 0; ++ regcache_cache_only(spdif->regmap, false); ++ regcache_mark_dirty(spdif->regmap); ++ ++ ret = regcache_sync(spdif->regmap); ++ if (ret) { ++ clk_disable_unprepare(spdif->mclk); ++ clk_disable_unprepare(spdif->hclk); ++ } ++ ++ return ret; + } + + static int rk_spdif_hw_params(struct snd_pcm_substream *substream, + +From d852c659ff563456480c55cfea53c578399c04ff Mon Sep 17 00:00:00 2001 +From: Arnaud Pouliquen +Date: Tue, 3 Jan 2017 16:52:50 +0100 +Subject: [PATCH] UPSTREAM: DRM: add help to get ELD speaker allocation + +Add helper to allow users to retrieve the speaker allocations without +knowledge of the ELD structure. + +Signed-off-by: Arnaud Pouliquen +Reviewed-by: Jani Nikula +Signed-off-by: Mark Brown +(cherry picked from commit c82dbe5c055e4d246bd07c4d7b24801c9445c241) +--- + include/drm/drm_edid.h | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h +index 85861b63e77a..55201e7e2ede 100644 +--- a/include/drm/drm_edid.h ++++ b/include/drm/drm_edid.h +@@ -254,6 +254,7 @@ struct detailed_timing { + # define DRM_ELD_AUD_SYNCH_DELAY_MAX 0xfa /* 500 ms */ + + #define DRM_ELD_SPEAKER 7 ++# define DRM_ELD_SPEAKER_MASK 0x7f + # define DRM_ELD_SPEAKER_RLRC (1 << 6) + # define DRM_ELD_SPEAKER_FLRC (1 << 5) + # define DRM_ELD_SPEAKER_RC (1 << 4) +@@ -417,6 +418,18 @@ static inline int drm_eld_size(const uint8_t *eld) + return DRM_ELD_HEADER_BLOCK_SIZE + eld[DRM_ELD_BASELINE_ELD_LEN] * 4; + } + ++/** ++ * drm_eld_get_spk_alloc - Get speaker allocation ++ * @eld: pointer to an ELD memory structure ++ * ++ * The returned value is the speakers mask. User has to use %DRM_ELD_SPEAKER ++ * field definitions to identify speakers. ++ */ ++static inline u8 drm_eld_get_spk_alloc(const uint8_t *eld) ++{ ++ return eld[DRM_ELD_SPEAKER] & DRM_ELD_SPEAKER_MASK; ++} ++ + struct edid *drm_do_get_edid(struct drm_connector *connector, + int (*get_edid_block)(void *data, u8 *buf, unsigned int block, + size_t len), + +From 4e08e72298c858a65950b98ca62613fb95cd0a35 Mon Sep 17 00:00:00 2001 +From: Arnaud Pouliquen +Date: Tue, 3 Jan 2017 16:52:51 +0100 +Subject: [PATCH] UPSTREAM: ASoC: core: add optional pcm_new callback for DAI + driver + +During probe, DAIs can need to perform some actions that requests +the knowledge of the pcm runtime handle. +The callback is called during DAIs linking, after PCM device creation. +For instance this can be used to add relationship between a DAI pcm +control and the pcm device. + +Signed-off-by: Arnaud Pouliquen +Signed-off-by: Mark Brown +(cherry picked from commit 25f7b701c20db3e9ae09e28dd652949bd977e5cd) +--- + include/sound/soc-dai.h | 3 +++ + sound/soc/soc-core.c | 28 ++++++++++++++++++++++++++++ + 2 files changed, 31 insertions(+) + +diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h +index 212eaaf172ed..345e4f8ee93f 100644 +--- a/include/sound/soc-dai.h ++++ b/include/sound/soc-dai.h +@@ -230,6 +230,9 @@ struct snd_soc_dai_driver { + int (*resume)(struct snd_soc_dai *dai); + /* compress dai */ + int (*compress_new)(struct snd_soc_pcm_runtime *rtd, int num); ++ /* Optional Callback used at pcm creation*/ ++ int (*pcm_new)(struct snd_soc_pcm_runtime *rtd, ++ struct snd_soc_dai *dai); + /* DAI is also used for the control bus */ + bool bus_control; + +diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c +index 3c6713da3ad9..e46e80c0e07d 100644 +--- a/sound/soc/soc-core.c ++++ b/sound/soc/soc-core.c +@@ -1289,6 +1289,27 @@ static int soc_probe_dai(struct snd_soc_dai *dai, int order) + return 0; + } + ++static int soc_link_dai_pcm_new(struct snd_soc_dai **dais, int num_dais, ++ struct snd_soc_pcm_runtime *rtd) ++{ ++ int i, ret = 0; ++ ++ for (i = 0; i < num_dais; ++i) { ++ struct snd_soc_dai_driver *drv = dais[i]->driver; ++ ++ if (!rtd->dai_link->no_pcm && drv->pcm_new) ++ ret = drv->pcm_new(rtd, dais[i]); ++ if (ret < 0) { ++ dev_err(dais[i]->dev, ++ "ASoC: Failed to bind %s with pcm device\n", ++ dais[i]->name); ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ + static int soc_link_dai_widgets(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_link, + struct snd_soc_pcm_runtime *rtd) +@@ -1400,6 +1421,13 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order) + dai_link->stream_name, ret); + return ret; + } ++ ret = soc_link_dai_pcm_new(&cpu_dai, 1, rtd); ++ if (ret < 0) ++ return ret; ++ ret = soc_link_dai_pcm_new(rtd->codec_dais, ++ rtd->num_codecs, rtd); ++ if (ret < 0) ++ return ret; + } else { + INIT_DELAYED_WORK(&rtd->delayed_work, + codec2codec_close_delayed_work); + +From 900f1d7bb2cddd1f445e0f3ef92fb0f7056a4c5a Mon Sep 17 00:00:00 2001 +From: Arnaud Pouliquen +Date: Tue, 3 Jan 2017 16:52:52 +0100 +Subject: [PATCH] UPSTREAM: ASoC: hdmi-codec: add channel mapping control + +Add user interface to provide channel mapping. +In a first step this control is read only. + +As TLV type, the control provides all configuration available for +HDMI sink(ELD), and provides current channel mapping selected by codec +based on ELD and number of channels specified by user on open. +When control is called before the number of the channel is specified +(i.e. hw_params is set), it returns all channels set to UNKNOWN. + +Signed-off-by: Arnaud Pouliquen +Signed-off-by: Mark Brown +(cherry picked from commit cd6111b26280a2f38a9fb8e6630c63a96477e4bf) +--- + sound/soc/codecs/hdmi-codec.c | 377 +++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 376 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c +index 028d60c196ae..cb78d8971b41 100644 +--- a/sound/soc/codecs/hdmi-codec.c ++++ b/sound/soc/codecs/hdmi-codec.c +@@ -21,12 +21,264 @@ + #include + #include + #include ++#include + #include + #include + #include + + #include /* This is only to get MAX_ELD_BYTES */ + ++#define HDMI_CODEC_CHMAP_IDX_UNKNOWN -1 ++ ++struct hdmi_codec_channel_map_table { ++ unsigned char map; /* ALSA API channel map position */ ++ unsigned long spk_mask; /* speaker position bit mask */ ++}; ++ ++/* ++ * CEA speaker placement for HDMI 1.4: ++ * ++ * FL FLC FC FRC FR FRW ++ * ++ * LFE ++ * ++ * RL RLC RC RRC RR ++ * ++ * Speaker placement has to be extended to support HDMI 2.0 ++ */ ++enum hdmi_codec_cea_spk_placement { ++ FL = BIT(0), /* Front Left */ ++ FC = BIT(1), /* Front Center */ ++ FR = BIT(2), /* Front Right */ ++ FLC = BIT(3), /* Front Left Center */ ++ FRC = BIT(4), /* Front Right Center */ ++ RL = BIT(5), /* Rear Left */ ++ RC = BIT(6), /* Rear Center */ ++ RR = BIT(7), /* Rear Right */ ++ RLC = BIT(8), /* Rear Left Center */ ++ RRC = BIT(9), /* Rear Right Center */ ++ LFE = BIT(10), /* Low Frequency Effect */ ++}; ++ ++/* ++ * cea Speaker allocation structure ++ */ ++struct hdmi_codec_cea_spk_alloc { ++ const int ca_id; ++ unsigned int n_ch; ++ unsigned long mask; ++}; ++ ++/* Channel maps stereo HDMI */ ++const struct snd_pcm_chmap_elem hdmi_codec_stereo_chmaps[] = { ++ { .channels = 2, ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } }, ++ { } ++}; ++ ++/* Channel maps for multi-channel playbacks, up to 8 n_ch */ ++const struct snd_pcm_chmap_elem hdmi_codec_8ch_chmaps[] = { ++ { .channels = 2, /* CA_ID 0x00 */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } }, ++ { .channels = 4, /* CA_ID 0x01 */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, ++ SNDRV_CHMAP_NA } }, ++ { .channels = 4, /* CA_ID 0x02 */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_FC } }, ++ { .channels = 4, /* CA_ID 0x03 */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, ++ SNDRV_CHMAP_FC } }, ++ { .channels = 6, /* CA_ID 0x04 */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_NA, SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } }, ++ { .channels = 6, /* CA_ID 0x05 */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, ++ SNDRV_CHMAP_NA, SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } }, ++ { .channels = 6, /* CA_ID 0x06 */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_FC, SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } }, ++ { .channels = 6, /* CA_ID 0x07 */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, ++ SNDRV_CHMAP_FC, SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } }, ++ { .channels = 6, /* CA_ID 0x08 */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } }, ++ { .channels = 6, /* CA_ID 0x09 */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, ++ SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } }, ++ { .channels = 6, /* CA_ID 0x0A */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } }, ++ { .channels = 6, /* CA_ID 0x0B */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, ++ SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } }, ++ { .channels = 8, /* CA_ID 0x0C */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR, ++ SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } }, ++ { .channels = 8, /* CA_ID 0x0D */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, ++ SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR, ++ SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } }, ++ { .channels = 8, /* CA_ID 0x0E */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR, ++ SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } }, ++ { .channels = 8, /* CA_ID 0x0F */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, ++ SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR, ++ SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } }, ++ { .channels = 8, /* CA_ID 0x10 */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR, ++ SNDRV_CHMAP_RLC, SNDRV_CHMAP_RRC } }, ++ { .channels = 8, /* CA_ID 0x11 */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, ++ SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR, ++ SNDRV_CHMAP_RLC, SNDRV_CHMAP_RRC } }, ++ { .channels = 8, /* CA_ID 0x12 */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR, ++ SNDRV_CHMAP_RLC, SNDRV_CHMAP_RRC } }, ++ { .channels = 8, /* CA_ID 0x13 */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, ++ SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR, ++ SNDRV_CHMAP_RLC, SNDRV_CHMAP_RRC } }, ++ { .channels = 8, /* CA_ID 0x14 */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, ++ { .channels = 8, /* CA_ID 0x15 */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, ++ SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, ++ { .channels = 8, /* CA_ID 0x16 */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_FC, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, ++ { .channels = 8, /* CA_ID 0x17 */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, ++ SNDRV_CHMAP_FC, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, ++ { .channels = 8, /* CA_ID 0x18 */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, ++ { .channels = 8, /* CA_ID 0x19 */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, ++ SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, ++ { .channels = 8, /* CA_ID 0x1A */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_FC, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, ++ { .channels = 8, /* CA_ID 0x1B */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, ++ SNDRV_CHMAP_FC, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, ++ { .channels = 8, /* CA_ID 0x1C */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, ++ { .channels = 8, /* CA_ID 0x1D */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, ++ SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, ++ { .channels = 8, /* CA_ID 0x1E */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_FC, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, ++ { .channels = 8, /* CA_ID 0x1F */ ++ .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE, ++ SNDRV_CHMAP_FC, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, ++ SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } }, ++ { } ++}; ++ ++/* ++ * hdmi_codec_channel_alloc: speaker configuration available for CEA ++ * ++ * This is an ordered list that must match with hdmi_codec_8ch_chmaps struct ++ * The preceding ones have better chances to be selected by ++ * hdmi_codec_get_ch_alloc_table_idx(). ++ */ ++static const struct hdmi_codec_cea_spk_alloc hdmi_codec_channel_alloc[] = { ++ { .ca_id = 0x00, .n_ch = 2, ++ .mask = FL | FR}, ++ /* 2.1 */ ++ { .ca_id = 0x01, .n_ch = 4, ++ .mask = FL | FR | LFE}, ++ /* Dolby Surround */ ++ { .ca_id = 0x02, .n_ch = 4, ++ .mask = FL | FR | FC }, ++ /* surround51 */ ++ { .ca_id = 0x0b, .n_ch = 6, ++ .mask = FL | FR | LFE | FC | RL | RR}, ++ /* surround40 */ ++ { .ca_id = 0x08, .n_ch = 6, ++ .mask = FL | FR | RL | RR }, ++ /* surround41 */ ++ { .ca_id = 0x09, .n_ch = 6, ++ .mask = FL | FR | LFE | RL | RR }, ++ /* surround50 */ ++ { .ca_id = 0x0a, .n_ch = 6, ++ .mask = FL | FR | FC | RL | RR }, ++ /* 6.1 */ ++ { .ca_id = 0x0f, .n_ch = 8, ++ .mask = FL | FR | LFE | FC | RL | RR | RC }, ++ /* surround71 */ ++ { .ca_id = 0x13, .n_ch = 8, ++ .mask = FL | FR | LFE | FC | RL | RR | RLC | RRC }, ++ /* others */ ++ { .ca_id = 0x03, .n_ch = 8, ++ .mask = FL | FR | LFE | FC }, ++ { .ca_id = 0x04, .n_ch = 8, ++ .mask = FL | FR | RC}, ++ { .ca_id = 0x05, .n_ch = 8, ++ .mask = FL | FR | LFE | RC }, ++ { .ca_id = 0x06, .n_ch = 8, ++ .mask = FL | FR | FC | RC }, ++ { .ca_id = 0x07, .n_ch = 8, ++ .mask = FL | FR | LFE | FC | RC }, ++ { .ca_id = 0x0c, .n_ch = 8, ++ .mask = FL | FR | RC | RL | RR }, ++ { .ca_id = 0x0d, .n_ch = 8, ++ .mask = FL | FR | LFE | RL | RR | RC }, ++ { .ca_id = 0x0e, .n_ch = 8, ++ .mask = FL | FR | FC | RL | RR | RC }, ++ { .ca_id = 0x10, .n_ch = 8, ++ .mask = FL | FR | RL | RR | RLC | RRC }, ++ { .ca_id = 0x11, .n_ch = 8, ++ .mask = FL | FR | LFE | RL | RR | RLC | RRC }, ++ { .ca_id = 0x12, .n_ch = 8, ++ .mask = FL | FR | FC | RL | RR | RLC | RRC }, ++ { .ca_id = 0x14, .n_ch = 8, ++ .mask = FL | FR | FLC | FRC }, ++ { .ca_id = 0x15, .n_ch = 8, ++ .mask = FL | FR | LFE | FLC | FRC }, ++ { .ca_id = 0x16, .n_ch = 8, ++ .mask = FL | FR | FC | FLC | FRC }, ++ { .ca_id = 0x17, .n_ch = 8, ++ .mask = FL | FR | LFE | FC | FLC | FRC }, ++ { .ca_id = 0x18, .n_ch = 8, ++ .mask = FL | FR | RC | FLC | FRC }, ++ { .ca_id = 0x19, .n_ch = 8, ++ .mask = FL | FR | LFE | RC | FLC | FRC }, ++ { .ca_id = 0x1a, .n_ch = 8, ++ .mask = FL | FR | RC | FC | FLC | FRC }, ++ { .ca_id = 0x1b, .n_ch = 8, ++ .mask = FL | FR | LFE | RC | FC | FLC | FRC }, ++ { .ca_id = 0x1c, .n_ch = 8, ++ .mask = FL | FR | RL | RR | FLC | FRC }, ++ { .ca_id = 0x1d, .n_ch = 8, ++ .mask = FL | FR | LFE | RL | RR | FLC | FRC }, ++ { .ca_id = 0x1e, .n_ch = 8, ++ .mask = FL | FR | FC | RL | RR | FLC | FRC }, ++ { .ca_id = 0x1f, .n_ch = 8, ++ .mask = FL | FR | LFE | FC | RL | RR | FLC | FRC }, ++}; ++ + struct hdmi_codec_priv { + struct hdmi_codec_pdata hcd; + struct snd_soc_dai_driver *daidrv; +@@ -41,6 +293,8 @@ struct hdmi_codec_priv { + struct notifier_block nb; + unsigned int jack_status; + unsigned int mode; ++ struct snd_pcm_chmap *chmap_info; ++ unsigned int chmap_idx; + }; + + static const struct snd_soc_dapm_widget hdmi_widgets[] = { +@@ -109,6 +363,83 @@ static int hdmi_audio_mode_put(struct snd_kcontrol *kcontrol, + return 0; + } + ++static unsigned long hdmi_codec_spk_mask_from_alloc(int spk_alloc) ++{ ++ int i; ++ const unsigned long hdmi_codec_eld_spk_alloc_bits[] = { ++ [0] = FL | FR, [1] = LFE, [2] = FC, [3] = RL | RR, ++ [4] = RC, [5] = FLC | FRC, [6] = RLC | RRC, ++ }; ++ unsigned long spk_mask = 0; ++ ++ for (i = 0; i < ARRAY_SIZE(hdmi_codec_eld_spk_alloc_bits); i++) { ++ if (spk_alloc & (1 << i)) ++ spk_mask |= hdmi_codec_eld_spk_alloc_bits[i]; ++ } ++ ++ return spk_mask; ++} ++ ++void hdmi_codec_eld_chmap(struct hdmi_codec_priv *hcp) ++{ ++ u8 spk_alloc; ++ unsigned long spk_mask; ++ ++ spk_alloc = drm_eld_get_spk_alloc(hcp->eld); ++ spk_mask = hdmi_codec_spk_mask_from_alloc(spk_alloc); ++ ++ /* Detect if only stereo supported, else return 8 channels mappings */ ++ if ((spk_mask & ~(FL | FR)) && hcp->chmap_info->max_channels > 2) ++ hcp->chmap_info->chmap = hdmi_codec_8ch_chmaps; ++ else ++ hcp->chmap_info->chmap = hdmi_codec_stereo_chmaps; ++} ++ ++static int hdmi_codec_get_ch_alloc_table_idx(struct hdmi_codec_priv *hcp, ++ unsigned char channels) ++{ ++ int i; ++ u8 spk_alloc; ++ unsigned long spk_mask; ++ const struct hdmi_codec_cea_spk_alloc *cap = hdmi_codec_channel_alloc; ++ ++ spk_alloc = drm_eld_get_spk_alloc(hcp->eld); ++ spk_mask = hdmi_codec_spk_mask_from_alloc(spk_alloc); ++ ++ for (i = 0; i < ARRAY_SIZE(hdmi_codec_channel_alloc); i++, cap++) { ++ /* If spk_alloc == 0, HDMI is unplugged return stereo config*/ ++ if (!spk_alloc && cap->ca_id == 0) ++ return i; ++ if (cap->n_ch != channels) ++ continue; ++ if (!(cap->mask == (spk_mask & cap->mask))) ++ continue; ++ return i; ++ } ++ ++ return -EINVAL; ++} ++static int hdmi_codec_chmap_ctl_get(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ unsigned const char *map; ++ unsigned int i; ++ struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); ++ struct hdmi_codec_priv *hcp = info->private_data; ++ ++ map = info->chmap[hcp->chmap_idx].map; ++ ++ for (i = 0; i < info->max_channels; i++) { ++ if (hcp->chmap_idx == HDMI_CODEC_CHMAP_IDX_UNKNOWN) ++ ucontrol->value.integer.value[i] = 0; ++ else ++ ucontrol->value.integer.value[i] = map[i]; ++ } ++ ++ return 0; ++} ++ ++ + static const struct snd_kcontrol_new hdmi_controls[] = { + { + .access = SNDRV_CTL_ELEM_ACCESS_READ | +@@ -184,6 +515,9 @@ static int hdmi_codec_startup(struct snd_pcm_substream *substream, + ret = snd_pcm_hw_constraint_eld(substream->runtime, + hcp->eld); + mutex_unlock(&hcp->eld_lock); ++ ++ /* Select chmap supported */ ++ hdmi_codec_eld_chmap(hcp); + } + return ret; + } +@@ -201,6 +535,7 @@ static void hdmi_codec_shutdown(struct snd_pcm_substream *substream, + + WARN_ON(hcp->current_stream != substream); + ++ hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN; + hcp->hcd.ops->audio_shutdown(dai->dev->parent, hcp->hcd.data); + + mutex_lock(&hcp->current_stream_lock); +@@ -221,7 +556,7 @@ static int hdmi_codec_hw_params(struct snd_pcm_substream *substream, + .dig_subframe = { 0 }, + } + }; +- int ret; ++ int ret, idx; + + dev_dbg(dai->dev, "%s() width %d rate %d channels %d\n", __func__, + params_width(params), params_rate(params), +@@ -248,6 +583,17 @@ static int hdmi_codec_hw_params(struct snd_pcm_substream *substream, + hp.cea.sample_size = HDMI_AUDIO_SAMPLE_SIZE_STREAM; + hp.cea.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM; + ++ /* Select a channel allocation that matches with ELD and pcm channels */ ++ idx = hdmi_codec_get_ch_alloc_table_idx(hcp, hp.cea.channels); ++ if (idx < 0) { ++ dev_err(dai->dev, "Not able to map channels to speakers (%d)\n", ++ idx); ++ hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN; ++ return idx; ++ } ++ hp.cea.channel_allocation = hdmi_codec_channel_alloc[idx].ca_id; ++ hcp->chmap_idx = hdmi_codec_channel_alloc[idx].ca_id; ++ + hp.sample_width = params_width(params); + hp.sample_rate = params_rate(params); + hp.channels = params_channels(params); +@@ -377,6 +723,32 @@ static const struct snd_soc_dai_ops hdmi_dai_ops = { + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE |\ + SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE) + ++static int hdmi_codec_pcm_new(struct snd_soc_pcm_runtime *rtd, ++ struct snd_soc_dai *dai) ++{ ++ struct snd_soc_dai_driver *drv = dai->driver; ++ struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai); ++ int ret; ++ ++ dev_dbg(dai->dev, "%s()\n", __func__); ++ ++ ret = snd_pcm_add_chmap_ctls(rtd->pcm, SNDRV_PCM_STREAM_PLAYBACK, ++ NULL, drv->playback.channels_max, 0, ++ &hcp->chmap_info); ++ if (ret < 0) ++ return ret; ++ ++ /* override handlers */ ++ hcp->chmap_info->private_data = hcp; ++ hcp->chmap_info->kctl->get = hdmi_codec_chmap_ctl_get; ++ ++ /* default chmap supported is stereo */ ++ hcp->chmap_info->chmap = hdmi_codec_stereo_chmaps; ++ hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN; ++ ++ return 0; ++} ++ + static struct snd_soc_dai_driver hdmi_i2s_dai = { + .name = "i2s-hifi", + .id = DAI_ID_I2S, +@@ -389,6 +761,7 @@ static struct snd_soc_dai_driver hdmi_i2s_dai = { + .sig_bits = 24, + }, + .ops = &hdmi_dai_ops, ++ .pcm_new = hdmi_codec_pcm_new, + }; + + static const struct snd_soc_dai_driver hdmi_spdif_dai = { +@@ -402,6 +775,7 @@ static const struct snd_soc_dai_driver hdmi_spdif_dai = { + .formats = SPDIF_FORMATS, + }, + .ops = &hdmi_dai_ops, ++ .pcm_new = hdmi_codec_pcm_new, + }; + + static struct snd_soc_codec_driver hdmi_codec = { +@@ -534,6 +908,7 @@ static int hdmi_codec_remove(struct platform_device *pdev) + { + struct hdmi_codec_priv *hcp = platform_get_drvdata(pdev); + ++ kfree(hcp->chmap_info); + hdmi_unregister_notifier(&hcp->nb); + snd_soc_unregister_codec(&pdev->dev); + return 0; + +From 5ad6154eea74dec3635e2417f06ad12d3f0a36c4 Mon Sep 17 00:00:00 2001 +From: Christophe Jaillet +Date: Thu, 15 Jun 2017 07:53:11 +0200 +Subject: [PATCH] UPSTREAM: ASoC: rockchip: Fix an error handling in + 'rockchip_i2s_probe' + +If this memory allocation fail, we must disable what has been enabled. +Do not return immediately but go thrue the error handling path instead. + +Also use 'devm_kmemdup' instead of 'devm_kzalloc+memcpy' to simplify code. + +Signed-off-by: Christophe JAILLET +Signed-off-by: Mark Brown +(cherry picked from commit c3a3d3c41b74b05267bab6173f2a8224a1443ba6) +--- + sound/soc/rockchip/rockchip_i2s.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c +index b359639c1038..02ff642499bf 100644 +--- a/sound/soc/rockchip/rockchip_i2s.c ++++ b/sound/soc/rockchip/rockchip_i2s.c +@@ -658,12 +658,13 @@ static int rockchip_i2s_probe(struct platform_device *pdev) + goto err_pm_disable; + } + +- soc_dai = devm_kzalloc(&pdev->dev, ++ soc_dai = devm_kmemdup(&pdev->dev, &rockchip_i2s_dai, + sizeof(*soc_dai), GFP_KERNEL); +- if (!soc_dai) +- return -ENOMEM; ++ if (!soc_dai) { ++ ret = -ENOMEM; ++ goto err_pm_disable; ++ } + +- memcpy(soc_dai, &rockchip_i2s_dai, sizeof(*soc_dai)); + if (!of_property_read_u32(node, "rockchip,playback-channels", &val)) { + if (val >= 2 && val <= 8) + soc_dai->playback.channels_max = val; + +From 9aeca2222a8f8a700c446fc9a38235ab2e3a4efd Mon Sep 17 00:00:00 2001 +From: Markus Elfring +Date: Thu, 10 Aug 2017 18:38:09 +0200 +Subject: [PATCH] UPSTREAM: ASoC: rockchip: Delete an error message for a + failed memory allocation in rockchip_i2s_probe() + +Omit an extra message for a memory allocation failure in this function. + +This issue was detected by using the Coccinelle software. + +Link: http://events.linuxfoundation.org/sites/events/files/slides/LCJ16-Refactor_Strings-WSang_0.pdf +Signed-off-by: Markus Elfring +Signed-off-by: Mark Brown +(cherry picked from commit b48b2710913d583ff93c365413532e1a7cd60d84) +--- + sound/soc/rockchip/rockchip_i2s.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c +index 02ff642499bf..16ff8d5e0033 100644 +--- a/sound/soc/rockchip/rockchip_i2s.c ++++ b/sound/soc/rockchip/rockchip_i2s.c +@@ -594,10 +594,8 @@ static int rockchip_i2s_probe(struct platform_device *pdev) + int val; + + i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL); +- if (!i2s) { +- dev_err(&pdev->dev, "Can't allocate rk_i2s_dev\n"); ++ if (!i2s) + return -ENOMEM; +- } + + i2s->dev = &pdev->dev; + + +From dad1bc0769692d7fd45701a4ab3fb55be012e01e Mon Sep 17 00:00:00 2001 +From: John Keeping +Date: Thu, 14 Sep 2017 16:58:55 +0100 +Subject: [PATCH] UPSTREAM: ASoC: rockchip: i2s: fix unbalanced clk_disable + +mclk is enabled and disabled only in i2s_runtime_{resume,suspend}() and +we ensure that the device is runtime suspended before reaching this +clk_disable_unprepare() call, so it is wrong to call it again here. + +Signed-off-by: John Keeping +Signed-off-by: Mark Brown +(cherry picked from commit 32debfcd3ff0939c93238ddde03ffcc96cca5c60) +--- + sound/soc/rockchip/rockchip_i2s.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c +index 16ff8d5e0033..986ad2efc8e9 100644 +--- a/sound/soc/rockchip/rockchip_i2s.c ++++ b/sound/soc/rockchip/rockchip_i2s.c +@@ -727,7 +727,6 @@ static int rockchip_i2s_remove(struct platform_device *pdev) + if (!pm_runtime_status_suspended(&pdev->dev)) + i2s_runtime_suspend(&pdev->dev); + +- clk_disable_unprepare(i2s->mclk); + clk_disable_unprepare(i2s->hclk); + + return 0; + +From 20b260f46771f7313ecd6e296ec6c08a43967eb4 Mon Sep 17 00:00:00 2001 +From: John Keeping +Date: Mon, 8 Jan 2018 16:01:04 +0000 +Subject: [PATCH] UPSTREAM: ASoC: rockchip: i2s: fix playback after runtime + resume + +When restoring registers during runtime resume, we must not write to +I2S_TXDR which is the transmit FIFO as this queues up a sample to be +output and pushes all of the output channels down by one. + +This can be demonstrated with the speaker-test utility: + + for i in a b c; do speaker-test -c 2 -s 1; done + +which should play a test through the left speaker three times but if the +I2S hardware starts runtime suspended the first sample will be played +through the right speaker. + +Fix this by marking I2S_TXDR as volatile (which also requires marking it +as readble, even though it technically isn't). This seems to be the +most robust fix, the alternative of giving I2S_TXDR a default value is +more fragile since it does not prevent regcache writing to the register +in all circumstances. + +While here, also fix the configuration of I2S_RXDR and I2S_FIFOLR; these +are not writable so they do not suffer from the same problem as I2S_TXDR +but reading from I2S_RXDR does suffer from a similar problem. + +Fixes: f0447f6cbb20 ("ASoC: rockchip: i2s: restore register during runtime_suspend/resume cycle", 2016-09-07) +Signed-off-by: John Keeping +(cherry picked from commit c66234cfedfc3e6e3b62563a5f2c1562be09a35d) +--- + sound/soc/rockchip/rockchip_i2s.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c +index 986ad2efc8e9..5297373fe6c4 100644 +--- a/sound/soc/rockchip/rockchip_i2s.c ++++ b/sound/soc/rockchip/rockchip_i2s.c +@@ -514,6 +514,7 @@ static bool rockchip_i2s_rd_reg(struct device *dev, unsigned int reg) + case I2S_INTCR: + case I2S_XFER: + case I2S_CLR: ++ case I2S_TXDR: + case I2S_RXDR: + case I2S_FIFOLR: + case I2S_INTSR: +@@ -528,6 +529,9 @@ static bool rockchip_i2s_volatile_reg(struct device *dev, unsigned int reg) + switch (reg) { + case I2S_INTSR: + case I2S_CLR: ++ case I2S_FIFOLR: ++ case I2S_TXDR: ++ case I2S_RXDR: + return true; + default: + return false; +@@ -537,6 +541,8 @@ static bool rockchip_i2s_volatile_reg(struct device *dev, unsigned int reg) + static bool rockchip_i2s_precious_reg(struct device *dev, unsigned int reg) + { + switch (reg) { ++ case I2S_RXDR: ++ return true; + default: + return false; + } + +From fa8e48f2fd0abe00ee0f04128a2e9b4fed184c3f Mon Sep 17 00:00:00 2001 +From: Romain Perier +Date: Fri, 14 Apr 2017 10:31:12 +0200 +Subject: [PATCH] UPSTREAM: drm: dw-hdmi: add specific I2S and AHB functions + for stream handling + +Currently, CTS+N is forced to zero as a workaround of the IP block for +i.MX platforms. This is requested in the datasheet of the corresponding +IP for AHB mode only. However, we have seen that it introduces glitches +or delays when playing a sound on HDMI for I2S mode. This proves that we +cannot keep the current functions for handling audio stream as-is if +these contain workaround that are specific to a mode. + +This commit introduces two callbacks, one for each variant. +dw_hdmi_setup defines the right function depending on the detected +variant. Then, the exported functions dw_hdmi_audio_enable and +dw_hdmi_audio_disable calls the corresponding callbacks + +Reviewed-by: Neil Armstrong +Signed-off-by: Romain Perier +Signed-off-by: Archit Taneja +Link: http://patchwork.freedesktop.org/patch/msgid/20170414083113.4255-2-romain.perier@collabora.com +(cherry picked from commit a7d555d2f2bd675d641e742a202a5e4b37d4d019) +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 27 +++++++++++++++++++++++++-- + 1 file changed, 25 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index d57d999c50a5..0541d96be662 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -263,6 +263,9 @@ struct dw_hdmi { + u8 (*read)(struct dw_hdmi *hdmi, int offset); + + bool initialized; /* hdmi is enabled before bind */ ++ ++ void (*enable_audio)(struct dw_hdmi *hdmi); ++ void (*disable_audio)(struct dw_hdmi *hdmi); + }; + + #define HDMI_IH_PHY_STAT0_RX_SENSE \ +@@ -821,13 +824,29 @@ void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate) + } + EXPORT_SYMBOL_GPL(dw_hdmi_set_sample_rate); + ++static void dw_hdmi_ahb_audio_enable(struct dw_hdmi *hdmi) ++{ ++ hdmi_set_cts_n(hdmi, hdmi->audio_cts, hdmi->audio_n); ++} ++ ++static void dw_hdmi_ahb_audio_disable(struct dw_hdmi *hdmi) ++{ ++ hdmi_set_cts_n(hdmi, hdmi->audio_cts, 0); ++} ++ ++static void dw_hdmi_i2s_audio_enable(struct dw_hdmi *hdmi) ++{ ++ hdmi_set_cts_n(hdmi, hdmi->audio_cts, hdmi->audio_n); ++} ++ + void dw_hdmi_audio_enable(struct dw_hdmi *hdmi) + { + unsigned long flags; + + spin_lock_irqsave(&hdmi->audio_lock, flags); + hdmi->audio_enable = true; +- hdmi_set_cts_n(hdmi, hdmi->audio_cts, hdmi->audio_n); ++ if (hdmi->enable_audio) ++ hdmi->enable_audio(hdmi); + spin_unlock_irqrestore(&hdmi->audio_lock, flags); + } + EXPORT_SYMBOL_GPL(dw_hdmi_audio_enable); +@@ -838,7 +857,8 @@ void dw_hdmi_audio_disable(struct dw_hdmi *hdmi) + + spin_lock_irqsave(&hdmi->audio_lock, flags); + hdmi->audio_enable = false; +- hdmi_set_cts_n(hdmi, hdmi->audio_cts, 0); ++ if (hdmi->disable_audio) ++ hdmi->disable_audio(hdmi); + spin_unlock_irqrestore(&hdmi->audio_lock, flags); + } + EXPORT_SYMBOL_GPL(dw_hdmi_audio_disable); +@@ -3706,6 +3726,8 @@ int dw_hdmi_bind(struct device *dev, struct device *master, + audio.irq = irq; + audio.hdmi = hdmi; + audio.eld = hdmi->connector.eld; ++ hdmi->enable_audio = dw_hdmi_ahb_audio_enable; ++ hdmi->disable_audio = dw_hdmi_ahb_audio_disable; + + pdevinfo.name = "dw-hdmi-ahb-audio"; + pdevinfo.data = &audio; +@@ -3719,6 +3741,7 @@ int dw_hdmi_bind(struct device *dev, struct device *master, + audio.write = hdmi_writeb; + audio.read = hdmi_readb; + audio.mod = hdmi_modb; ++ hdmi->enable_audio = dw_hdmi_i2s_audio_enable; + + pdevinfo.name = "dw-hdmi-i2s-audio"; + pdevinfo.data = &audio; + +From f856228e8933ba1e6375dbda53cc59da8d71647a Mon Sep 17 00:00:00 2001 +From: Romain Perier +Date: Thu, 20 Apr 2017 14:34:34 +0530 +Subject: [PATCH] UPSTREAM: drm: dw-hdmi: gate audio clock from the I2S + enablement callbacks + +Currently, the audio sampler clock is enabled from dw_hdmi_setup() at +step E. and is kept enabled for later use. This clock should be enabled +and disabled along with the actual audio stream and not always on (that +is bad for PM). Furthermore, as described by the datasheet, the I2S +variant needs to gate/ungate the clock when the stream is +enabled/disabled. + +This commit adds a parameter to hdmi_audio_enable_clk() that controls +when the audio sample clock must be enabled or disabled. Then, it adds +the call to this function from dw_hdmi_i2s_audio_enable() and +dw_hdmi_i2s_audio_disable(). + +Reviewed-by: Neil Armstrong +Signed-off-by: Romain Perier +Link: http://patchwork.freedesktop.org/patch/msgid/20170414083113.4255-3-romain.perier@collabora.com +Signed-off-by: Archit Taneja +(cherry picked from commit 57fbc05585a9c841c910677228f1e3f8a3a62801) +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 24 +++++++++++++++++------- + 1 file changed, 17 insertions(+), 7 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index 0541d96be662..f3a2034a0883 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -824,6 +824,15 @@ void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate) + } + EXPORT_SYMBOL_GPL(dw_hdmi_set_sample_rate); + ++static void hdmi_enable_audio_clk(struct dw_hdmi *hdmi, bool enable) ++{ ++ if (enable) ++ hdmi->mc_clkdis &= ~HDMI_MC_CLKDIS_AUDCLK_DISABLE; ++ else ++ hdmi->mc_clkdis |= HDMI_MC_CLKDIS_AUDCLK_DISABLE; ++ hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS); ++} ++ + static void dw_hdmi_ahb_audio_enable(struct dw_hdmi *hdmi) + { + hdmi_set_cts_n(hdmi, hdmi->audio_cts, hdmi->audio_n); +@@ -837,6 +846,12 @@ static void dw_hdmi_ahb_audio_disable(struct dw_hdmi *hdmi) + static void dw_hdmi_i2s_audio_enable(struct dw_hdmi *hdmi) + { + hdmi_set_cts_n(hdmi, hdmi->audio_cts, hdmi->audio_n); ++ hdmi_enable_audio_clk(hdmi, true); ++} ++ ++static void dw_hdmi_i2s_audio_disable(struct dw_hdmi *hdmi) ++{ ++ hdmi_enable_audio_clk(hdmi, false); + } + + void dw_hdmi_audio_enable(struct dw_hdmi *hdmi) +@@ -2149,12 +2164,6 @@ static void dw_hdmi_enable_video_path(struct dw_hdmi *hdmi) + HDMI_MC_FLOWCTRL); + } + +-static void hdmi_enable_audio_clk(struct dw_hdmi *hdmi) +-{ +- hdmi->mc_clkdis &= ~HDMI_MC_CLKDIS_AUDCLK_DISABLE; +- hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS); +-} +- + /* Workaround to clear the overflow condition */ + static void dw_hdmi_clear_overflow(struct dw_hdmi *hdmi) + { +@@ -2306,7 +2315,7 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode) + + /* HDMI Initialization Step E - Configure audio */ + hdmi_clk_regenerator_update_pixel_clock(hdmi); +- hdmi_enable_audio_clk(hdmi); ++ hdmi_enable_audio_clk(hdmi, true); + } + + /* not for DVI mode */ +@@ -3742,6 +3751,7 @@ int dw_hdmi_bind(struct device *dev, struct device *master, + audio.read = hdmi_readb; + audio.mod = hdmi_modb; + hdmi->enable_audio = dw_hdmi_i2s_audio_enable; ++ hdmi->disable_audio = dw_hdmi_i2s_audio_disable; + + pdevinfo.name = "dw-hdmi-i2s-audio"; + pdevinfo.data = &audio; + +From 5736074e471dc5306e07581bf0958043cf434341 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 7 Aug 2017 22:24:15 +0200 +Subject: [PATCH] drm: dw-hdmi-i2s: sync with upstream + +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h | 1 - + drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c | 20 +++++++++++++------- + 2 files changed, 13 insertions(+), 8 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h +index 3930ba04977b..af7f39c85ba4 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h +@@ -14,7 +14,6 @@ struct dw_hdmi_audio_data { + + struct dw_hdmi_i2s_audio_data { + struct dw_hdmi *hdmi; +- struct platform_device *pdev; + + void (*write)(struct dw_hdmi *hdmi, u8 val, int offset); + u8 (*read)(struct dw_hdmi *hdmi, int offset); +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c +index f1f62d8c1d16..5ff993a35ab6 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c +@@ -16,7 +16,8 @@ + + #define DRIVER_NAME "dw-hdmi-i2s-audio" + +-static inline void hdmi_write(struct dw_hdmi_i2s_audio_data *audio, u8 val, int offset) ++static inline void hdmi_write(struct dw_hdmi_i2s_audio_data *audio, ++ u8 val, int offset) + { + struct dw_hdmi *hdmi = audio->hdmi; + +@@ -220,6 +221,7 @@ static int snd_dw_hdmi_probe(struct platform_device *pdev) + struct dw_hdmi_i2s_audio_data *audio = pdev->dev.platform_data; + struct platform_device_info pdevinfo; + struct hdmi_codec_pdata pdata; ++ struct platform_device *platform; + + pdata.ops = &dw_hdmi_i2s_ops; + pdata.i2s = 1; +@@ -234,23 +236,27 @@ static int snd_dw_hdmi_probe(struct platform_device *pdev) + pdevinfo.size_data = sizeof(pdata); + pdevinfo.dma_mask = DMA_BIT_MASK(32); + +- audio->pdev = platform_device_register_full(&pdevinfo); +- return IS_ERR_OR_NULL(audio->pdev); ++ platform = platform_device_register_full(&pdevinfo); ++ if (IS_ERR(platform)) ++ return PTR_ERR(platform); ++ ++ dev_set_drvdata(&pdev->dev, platform); ++ ++ return 0; + } + + static int snd_dw_hdmi_remove(struct platform_device *pdev) + { +- struct dw_hdmi_i2s_audio_data *audio = pdev->dev.platform_data; ++ struct platform_device *platform = dev_get_drvdata(&pdev->dev); + +- if (!IS_ERR_OR_NULL(audio->pdev)) +- platform_device_unregister(audio->pdev); ++ platform_device_unregister(platform); + + return 0; + } + + static struct platform_driver snd_dw_hdmi_driver = { + .probe = snd_dw_hdmi_probe, +- .remove = snd_dw_hdmi_remove, ++ .remove = snd_dw_hdmi_remove, + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + +From d2f29756df76806c12fa12b668aeb8ac5f626bdd Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 2 Apr 2017 11:33:39 +0200 +Subject: [PATCH] drm: dw-hdmi-i2s: implement get_eld + +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h | 1 + + drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c | 12 ++++++++++++ + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 1 + + 3 files changed, 14 insertions(+) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h +index af7f39c85ba4..c5ace7808fdf 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h +@@ -14,6 +14,7 @@ struct dw_hdmi_audio_data { + + struct dw_hdmi_i2s_audio_data { + struct dw_hdmi *hdmi; ++ u8 *eld; + + void (*write)(struct dw_hdmi *hdmi, u8 val, int offset); + u8 (*read)(struct dw_hdmi *hdmi, int offset); +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c +index 5ff993a35ab6..e7312571e2cb 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c +@@ -11,6 +11,8 @@ + + #include + ++#include /* This is only to get MAX_ELD_BYTES */ ++ + #include "dw-hdmi.h" + #include "dw-hdmi-audio.h" + +@@ -211,9 +213,19 @@ static void dw_hdmi_i2s_audio_shutdown(struct device *dev, void *data) + hdmi_write(audio, HDMI_AUD_CONF0_SW_RESET, HDMI_AUD_CONF0); + } + ++static int dw_hdmi_i2s_get_eld(struct device *dev, void *data, u8 *buf, size_t len) ++{ ++ struct dw_hdmi_i2s_audio_data *audio = data; ++ ++ memcpy(buf, audio->eld, min(len, (size_t)MAX_ELD_BYTES)); ++ ++ return 0; ++} ++ + static struct hdmi_codec_ops dw_hdmi_i2s_ops = { + .hw_params = dw_hdmi_i2s_hw_params, + .audio_shutdown = dw_hdmi_i2s_audio_shutdown, ++ .get_eld = dw_hdmi_i2s_get_eld, + }; + + static int snd_dw_hdmi_probe(struct platform_device *pdev) +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index f3a2034a0883..c222b6455f03 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -3750,6 +3750,7 @@ int dw_hdmi_bind(struct device *dev, struct device *master, + audio.write = hdmi_writeb; + audio.read = hdmi_readb; + audio.mod = hdmi_modb; ++ audio.eld = hdmi->connector.eld; + hdmi->enable_audio = dw_hdmi_i2s_audio_enable; + hdmi->disable_audio = dw_hdmi_i2s_audio_disable; + + +From 18a9fcdb5cbde0462179d04336622cb4f97c2a7e Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 17 Apr 2017 13:09:16 +0200 +Subject: [PATCH] drm: dw-hdmi-i2s: configure channel allocation + +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c +index e7312571e2cb..1d4570e3fbed 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c +@@ -188,7 +188,7 @@ static int dw_hdmi_i2s_hw_params(struct device *dev, void *data, + hdmi_write(audio, 0x00, HDMI_FC_AUDICONF1); + + /* Set Channel Allocation */ +- hdmi_write(audio, 0x00, HDMI_FC_AUDICONF2); ++ hdmi_write(audio, hparms->cea.channel_allocation, HDMI_FC_AUDICONF2); + + /* Set LFEPBLDOWN-MIX INH and LSV */ + hdmi_write(audio, 0x00, HDMI_FC_AUDICONF3); + +From c19ba12d08a8c491d21a1daf305b1b58231ca362 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Mon, 14 Aug 2017 00:14:05 +0200 +Subject: [PATCH] ASoC: hdmi-codec: reorder channel map + +--- + sound/soc/codecs/hdmi-codec.c | 113 +++++++++++++++++++----------------------- + 1 file changed, 52 insertions(+), 61 deletions(-) + +diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c +index cb78d8971b41..b74659bc3bbc 100644 +--- a/sound/soc/codecs/hdmi-codec.c ++++ b/sound/soc/codecs/hdmi-codec.c +@@ -205,78 +205,69 @@ const struct snd_pcm_chmap_elem hdmi_codec_8ch_chmaps[] = { + */ + static const struct hdmi_codec_cea_spk_alloc hdmi_codec_channel_alloc[] = { + { .ca_id = 0x00, .n_ch = 2, +- .mask = FL | FR}, +- /* 2.1 */ +- { .ca_id = 0x01, .n_ch = 4, +- .mask = FL | FR | LFE}, +- /* Dolby Surround */ ++ .mask = FL | FR }, ++ { .ca_id = 0x03, .n_ch = 4, ++ .mask = FL | FR | LFE | FC }, + { .ca_id = 0x02, .n_ch = 4, + .mask = FL | FR | FC }, +- /* surround51 */ ++ { .ca_id = 0x01, .n_ch = 4, ++ .mask = FL | FR | LFE }, + { .ca_id = 0x0b, .n_ch = 6, +- .mask = FL | FR | LFE | FC | RL | RR}, +- /* surround40 */ +- { .ca_id = 0x08, .n_ch = 6, +- .mask = FL | FR | RL | RR }, +- /* surround41 */ +- { .ca_id = 0x09, .n_ch = 6, +- .mask = FL | FR | LFE | RL | RR }, +- /* surround50 */ ++ .mask = FL | FR | LFE | FC | RL | RR }, + { .ca_id = 0x0a, .n_ch = 6, + .mask = FL | FR | FC | RL | RR }, +- /* 6.1 */ +- { .ca_id = 0x0f, .n_ch = 8, +- .mask = FL | FR | LFE | FC | RL | RR | RC }, +- /* surround71 */ ++ { .ca_id = 0x09, .n_ch = 6, ++ .mask = FL | FR | LFE | RL | RR }, ++ { .ca_id = 0x08, .n_ch = 6, ++ .mask = FL | FR | RL | RR }, ++ { .ca_id = 0x07, .n_ch = 6, ++ .mask = FL | FR | LFE | FC | RC }, ++ { .ca_id = 0x06, .n_ch = 6, ++ .mask = FL | FR | FC | RC }, ++ { .ca_id = 0x05, .n_ch = 6, ++ .mask = FL | FR | LFE | RC }, ++ { .ca_id = 0x04, .n_ch = 6, ++ .mask = FL | FR | RC }, + { .ca_id = 0x13, .n_ch = 8, + .mask = FL | FR | LFE | FC | RL | RR | RLC | RRC }, +- /* others */ +- { .ca_id = 0x03, .n_ch = 8, +- .mask = FL | FR | LFE | FC }, +- { .ca_id = 0x04, .n_ch = 8, +- .mask = FL | FR | RC}, +- { .ca_id = 0x05, .n_ch = 8, +- .mask = FL | FR | LFE | RC }, +- { .ca_id = 0x06, .n_ch = 8, +- .mask = FL | FR | FC | RC }, +- { .ca_id = 0x07, .n_ch = 8, +- .mask = FL | FR | LFE | FC | RC }, +- { .ca_id = 0x0c, .n_ch = 8, +- .mask = FL | FR | RC | RL | RR }, +- { .ca_id = 0x0d, .n_ch = 8, +- .mask = FL | FR | LFE | RL | RR | RC }, +- { .ca_id = 0x0e, .n_ch = 8, +- .mask = FL | FR | FC | RL | RR | RC }, +- { .ca_id = 0x10, .n_ch = 8, +- .mask = FL | FR | RL | RR | RLC | RRC }, +- { .ca_id = 0x11, .n_ch = 8, +- .mask = FL | FR | LFE | RL | RR | RLC | RRC }, ++ { .ca_id = 0x1f, .n_ch = 8, ++ .mask = FL | FR | LFE | FC | RL | RR | FLC | FRC }, + { .ca_id = 0x12, .n_ch = 8, + .mask = FL | FR | FC | RL | RR | RLC | RRC }, +- { .ca_id = 0x14, .n_ch = 8, +- .mask = FL | FR | FLC | FRC }, +- { .ca_id = 0x15, .n_ch = 8, +- .mask = FL | FR | LFE | FLC | FRC }, +- { .ca_id = 0x16, .n_ch = 8, +- .mask = FL | FR | FC | FLC | FRC }, +- { .ca_id = 0x17, .n_ch = 8, +- .mask = FL | FR | LFE | FC | FLC | FRC }, +- { .ca_id = 0x18, .n_ch = 8, +- .mask = FL | FR | RC | FLC | FRC }, +- { .ca_id = 0x19, .n_ch = 8, +- .mask = FL | FR | LFE | RC | FLC | FRC }, +- { .ca_id = 0x1a, .n_ch = 8, +- .mask = FL | FR | RC | FC | FLC | FRC }, +- { .ca_id = 0x1b, .n_ch = 8, +- .mask = FL | FR | LFE | RC | FC | FLC | FRC }, +- { .ca_id = 0x1c, .n_ch = 8, +- .mask = FL | FR | RL | RR | FLC | FRC }, +- { .ca_id = 0x1d, .n_ch = 8, +- .mask = FL | FR | LFE | RL | RR | FLC | FRC }, + { .ca_id = 0x1e, .n_ch = 8, + .mask = FL | FR | FC | RL | RR | FLC | FRC }, +- { .ca_id = 0x1f, .n_ch = 8, +- .mask = FL | FR | LFE | FC | RL | RR | FLC | FRC }, ++ { .ca_id = 0x11, .n_ch = 8, ++ .mask = FL | FR | LFE | RL | RR | RLC | RRC }, ++ { .ca_id = 0x1d, .n_ch = 8, ++ .mask = FL | FR | LFE | RL | RR | FLC | FRC }, ++ { .ca_id = 0x10, .n_ch = 8, ++ .mask = FL | FR | RL | RR | RLC | RRC }, ++ { .ca_id = 0x1c, .n_ch = 8, ++ .mask = FL | FR | RL | RR | FLC | FRC }, ++ { .ca_id = 0x0f, .n_ch = 8, ++ .mask = FL | FR | LFE | FC | RL | RR | RC }, ++ { .ca_id = 0x1b, .n_ch = 8, ++ .mask = FL | FR | LFE | RC | FC | FLC | FRC }, ++ { .ca_id = 0x0e, .n_ch = 8, ++ .mask = FL | FR | FC | RL | RR | RC }, ++ { .ca_id = 0x1a, .n_ch = 8, ++ .mask = FL | FR | RC | FC | FLC | FRC }, ++ { .ca_id = 0x0d, .n_ch = 8, ++ .mask = FL | FR | LFE | RL | RR | RC }, ++ { .ca_id = 0x19, .n_ch = 8, ++ .mask = FL | FR | LFE | RC | FLC | FRC }, ++ { .ca_id = 0x0c, .n_ch = 8, ++ .mask = FL | FR | RC | RL | RR }, ++ { .ca_id = 0x18, .n_ch = 8, ++ .mask = FL | FR | RC | FLC | FRC }, ++ { .ca_id = 0x17, .n_ch = 8, ++ .mask = FL | FR | LFE | FC | FLC | FRC }, ++ { .ca_id = 0x16, .n_ch = 8, ++ .mask = FL | FR | FC | FLC | FRC }, ++ { .ca_id = 0x15, .n_ch = 8, ++ .mask = FL | FR | LFE | FLC | FRC }, ++ { .ca_id = 0x14, .n_ch = 8, ++ .mask = FL | FR | FLC | FRC }, + }; + + struct hdmi_codec_priv { + +From 0b22ce2a2766052fe28a3162623d19ba38adaef5 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 27 Aug 2017 23:32:40 +0200 +Subject: [PATCH] ASoC: codecs: rk3328: limit to working rates + +--- + sound/soc/codecs/rk3328_codec.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/codecs/rk3328_codec.c b/sound/soc/codecs/rk3328_codec.c +index af1b7429b6d4..d0b4578ffa0e 100644 +--- a/sound/soc/codecs/rk3328_codec.c ++++ b/sound/soc/codecs/rk3328_codec.c +@@ -354,7 +354,12 @@ static struct snd_soc_dai_driver rk3328_dai[] = { + .stream_name = "HIFI Playback", + .channels_min = 1, + .channels_max = 2, +- .rates = SNDRV_PCM_RATE_8000_96000, ++ .rates = (SNDRV_PCM_RATE_8000 | ++ SNDRV_PCM_RATE_16000 | ++ SNDRV_PCM_RATE_32000 | ++ SNDRV_PCM_RATE_48000 | ++ SNDRV_PCM_RATE_64000 | ++ SNDRV_PCM_RATE_96000), + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S20_3LE | + SNDRV_PCM_FMTBIT_S24_LE | + +From f96be8cf25bfda88d5c492f42e1f6ca5951356f3 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 8 Jul 2018 12:34:43 +0200 +Subject: [PATCH] drm: dw-hdmi: change audio config + +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c | 9 ++------- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 15 ++++++++++++--- + 2 files changed, 14 insertions(+), 10 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c +index 1d4570e3fbed..d0904f6b7a82 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c +@@ -110,8 +110,7 @@ static int dw_hdmi_i2s_hw_params(struct device *dev, void *data, + HDMI_AUD_INT_FIFO_FULL_MSK, HDMI_AUD_INT); + hdmi_update_bits(audio, HDMI_AUD_CONF0_SW_RESET, + HDMI_AUD_CONF0_SW_RESET, HDMI_AUD_CONF0); +- hdmi_update_bits(audio, HDMI_MC_SWRSTZ_I2S_RESET_MSK, +- HDMI_MC_SWRSTZ_I2S_RESET_MSK, HDMI_MC_SWRSTZ); ++ hdmi_write(audio, (u8)~HDMI_MC_SWRSTZ_I2S_RESET_MSK, HDMI_MC_SWRSTZ); + + switch (hparms->mode) { + case NLPCM: +@@ -193,11 +192,6 @@ static int dw_hdmi_i2s_hw_params(struct device *dev, void *data, + /* Set LFEPBLDOWN-MIX INH and LSV */ + hdmi_write(audio, 0x00, HDMI_FC_AUDICONF3); + +- hdmi_update_bits(audio, HDMI_AUD_CONF0_SW_RESET, +- HDMI_AUD_CONF0_SW_RESET, HDMI_AUD_CONF0); +- hdmi_update_bits(audio, HDMI_MC_SWRSTZ_I2S_RESET_MSK, +- HDMI_MC_SWRSTZ_I2S_RESET_MSK, HDMI_MC_SWRSTZ); +- + dw_hdmi_audio_enable(hdmi); + + return 0; +@@ -211,6 +205,7 @@ static void dw_hdmi_i2s_audio_shutdown(struct device *dev, void *data) + dw_hdmi_audio_disable(hdmi); + + hdmi_write(audio, HDMI_AUD_CONF0_SW_RESET, HDMI_AUD_CONF0); ++ hdmi_write(audio, (u8)~HDMI_MC_SWRSTZ_I2S_RESET_MSK, HDMI_MC_SWRSTZ); + } + + static int dw_hdmi_i2s_get_eld(struct device *dev, void *data, u8 *buf, size_t len) +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index c222b6455f03..065723179791 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -89,6 +89,7 @@ static const struct dw_hdmi_audio_tmds_n common_tmds_n_table[] = { + { .tmds = 71000000, .n_32k = 4096, .n_44k1 = 7056, .n_48k = 6144, }, + { .tmds = 72000000, .n_32k = 4096, .n_44k1 = 5635, .n_48k = 6144, }, + { .tmds = 73250000, .n_32k = 4096, .n_44k1 = 14112, .n_48k = 6144, }, ++ { .tmds = 74176000, .n_32k = 11648, .n_44k1 = 17836, .n_48k = 11648, }, + { .tmds = 74250000, .n_32k = 4096, .n_44k1 = 6272, .n_48k = 6144, }, + { .tmds = 75000000, .n_32k = 4096, .n_44k1 = 5880, .n_48k = 6144, }, + { .tmds = 78750000, .n_32k = 4096, .n_44k1 = 5600, .n_48k = 6144, }, +@@ -105,13 +106,16 @@ static const struct dw_hdmi_audio_tmds_n common_tmds_n_table[] = { + { .tmds = 119000000, .n_32k = 4096, .n_44k1 = 5544, .n_48k = 6144, }, + { .tmds = 135000000, .n_32k = 4096, .n_44k1 = 5488, .n_48k = 6144, }, + { .tmds = 146250000, .n_32k = 4096, .n_44k1 = 6272, .n_48k = 6144, }, +- { .tmds = 148500000, .n_32k = 4096, .n_44k1 = 5488, .n_48k = 6144, }, ++ { .tmds = 148352000, .n_32k = 11648, .n_44k1 = 8918, .n_48k = 5824, }, ++ { .tmds = 148500000, .n_32k = 4096, .n_44k1 = 6272, .n_48k = 6144, }, + { .tmds = 154000000, .n_32k = 4096, .n_44k1 = 5544, .n_48k = 6144, }, + { .tmds = 162000000, .n_32k = 4096, .n_44k1 = 5684, .n_48k = 6144, }, + + /* For 297 MHz+ HDMI spec have some other rule for setting N */ +- { .tmds = 297000000, .n_32k = 3073, .n_44k1 = 4704, .n_48k = 5120, }, +- { .tmds = 594000000, .n_32k = 3073, .n_44k1 = 9408, .n_48k = 10240, }, ++ { .tmds = 296703000, .n_32k = 5824, .n_44k1 = 4459, .n_48k = 5824, }, ++ { .tmds = 297000000, .n_32k = 3072, .n_44k1 = 4704, .n_48k = 5120, }, ++ { .tmds = 593407000, .n_32k = 5824, .n_44k1 = 8918, .n_48k = 5824, }, ++ { .tmds = 594000000, .n_32k = 3072, .n_44k1 = 9408, .n_48k = 6144, }, + + /* End of table */ + { .tmds = 0, .n_32k = 0, .n_44k1 = 0, .n_48k = 0, }, +@@ -831,6 +835,11 @@ static void hdmi_enable_audio_clk(struct dw_hdmi *hdmi, bool enable) + else + hdmi->mc_clkdis |= HDMI_MC_CLKDIS_AUDCLK_DISABLE; + hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS); ++ ++ if (enable) { ++ hdmi_set_cts_n(hdmi, 0, 0); ++ hdmi_set_cts_n(hdmi, hdmi->audio_cts, hdmi->audio_n); ++ } + } + + static void dw_hdmi_ahb_audio_enable(struct dw_hdmi *hdmi) + +From ed2e01d46f3bbf3eda4d37ce2a6e8874b15a478a Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 8 Jul 2018 12:56:51 +0200 +Subject: [PATCH] WIP: drm: dw-hdmi: use Auto CTS mode + +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 52 ++++++++++++++++++------------- + 1 file changed, 31 insertions(+), 21 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index 065723179791..841bdfcae3e0 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -643,14 +643,18 @@ static struct i2c_adapter *dw_hdmi_i2c_adapter(struct dw_hdmi *hdmi) + static void hdmi_set_cts_n(struct dw_hdmi *hdmi, unsigned int cts, + unsigned int n) + { +- /* Must be set/cleared first */ +- hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3); +- +- /* nshift factor = 0 */ +- hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_N_SHIFT_MASK, HDMI_AUD_CTS3); +- +- hdmi_writeb(hdmi, ((cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK) | +- HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3); ++ /* Use Auto CTS mode with CTS is unknown */ ++ if (cts) { ++ /* Must be set/cleared first */ ++ hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3); ++ ++ /* nshift factor = 0 */ ++ hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_N_SHIFT_MASK, HDMI_AUD_CTS3); ++ ++ hdmi_writeb(hdmi, ((cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK) | ++ HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3); ++ } else ++ hdmi_writeb(hdmi, 0, HDMI_AUD_CTS3); + hdmi_writeb(hdmi, (cts >> 8) & 0xff, HDMI_AUD_CTS2); + hdmi_writeb(hdmi, cts & 0xff, HDMI_AUD_CTS1); + +@@ -777,24 +781,30 @@ static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi, + { + unsigned long ftdms = pixel_clk; + unsigned int n, cts; ++ u8 config3; + u64 tmp; + + n = hdmi_find_n(hdmi, pixel_clk, sample_rate); + +- /* +- * Compute the CTS value from the N value. Note that CTS and N +- * can be up to 20 bits in total, so we need 64-bit math. Also +- * note that our TDMS clock is not fully accurate; it is accurate +- * to kHz. This can introduce an unnecessary remainder in the +- * calculation below, so we don't try to warn about that. +- */ +- tmp = (u64)ftdms * n; +- do_div(tmp, 128 * sample_rate); +- cts = tmp; ++ config3 = hdmi_readb(hdmi, HDMI_CONFIG3_ID); + +- dev_dbg(hdmi->dev, "%s: fs=%uHz ftdms=%lu.%03luMHz N=%d cts=%d\n", +- __func__, sample_rate, ftdms / 1000000, (ftdms / 1000) % 1000, +- n, cts); ++ if (config3 & HDMI_CONFIG3_AHBAUDDMA) { ++ /* ++ * Compute the CTS value from the N value. Note that CTS and N ++ * can be up to 20 bits in total, so we need 64-bit math. Also ++ * note that our TDMS clock is not fully accurate; it is accurate ++ * to kHz. This can introduce an unnecessary remainder in the ++ * calculation below, so we don't try to warn about that. ++ */ ++ tmp = (u64)ftdms * n; ++ do_div(tmp, 128 * sample_rate); ++ cts = tmp; ++ ++ dev_dbg(hdmi->dev, "%s: fs=%uHz ftdms=%lu.%03luMHz N=%d cts=%d\n", ++ __func__, sample_rate, ftdms / 1000000, (ftdms / 1000) % 1000, ++ n, cts); ++ } else ++ cts = 0; + + spin_lock_irq(&hdmi->audio_lock); + hdmi->audio_n = n; diff --git a/patch/kernel/rockchip-default/01-linux-0005-dts.patch b/patch/kernel/rockchip-default/01-linux-0005-dts.patch new file mode 100644 index 000000000..1e7463a87 --- /dev/null +++ b/patch/kernel/rockchip-default/01-linux-0005-dts.patch @@ -0,0 +1,7032 @@ +From cf1a1299ed4c29012b0cf0476d93f45d49629b18 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 1 Jul 2018 23:22:32 +0200 +Subject: [PATCH] arm: dts: rockchip: rk3288: update dtsi + +--- + arch/arm/boot/dts/rk3288.dtsi | 20 +++++++++++++++----- + 1 file changed, 15 insertions(+), 5 deletions(-) + +diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi +index 8e51132ef7e4..54b785278956 100644 +--- a/arch/arm/boot/dts/rk3288.dtsi ++++ b/arch/arm/boot/dts/rk3288.dtsi +@@ -352,49 +352,57 @@ + + sdmmc: dwmmc@ff0c0000 { + compatible = "rockchip,rk3288-dw-mshc"; +- clock-freq-min-max = <400000 150000000>; ++ max-frequency = <150000000>; + clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>, + <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>; + clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; + fifo-depth = <0x100>; + interrupts = ; + reg = <0x0 0xff0c0000 0x0 0x4000>; ++ resets = <&cru SRST_MMC0>; ++ reset-names = "reset"; + status = "disabled"; + }; + + sdio0: dwmmc@ff0d0000 { + compatible = "rockchip,rk3288-dw-mshc"; +- clock-freq-min-max = <400000 150000000>; ++ max-frequency = <150000000>; + clocks = <&cru HCLK_SDIO0>, <&cru SCLK_SDIO0>, + <&cru SCLK_SDIO0_DRV>, <&cru SCLK_SDIO0_SAMPLE>; + clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; + fifo-depth = <0x100>; + interrupts = ; + reg = <0x0 0xff0d0000 0x0 0x4000>; ++ resets = <&cru SRST_SDIO0>; ++ reset-names = "reset"; + status = "disabled"; + }; + + sdio1: dwmmc@ff0e0000 { + compatible = "rockchip,rk3288-dw-mshc"; +- clock-freq-min-max = <400000 150000000>; ++ max-frequency = <150000000>; + clocks = <&cru HCLK_SDIO1>, <&cru SCLK_SDIO1>, + <&cru SCLK_SDIO1_DRV>, <&cru SCLK_SDIO1_SAMPLE>; + clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; + fifo-depth = <0x100>; + interrupts = ; + reg = <0x0 0xff0e0000 0x0 0x4000>; ++ resets = <&cru SRST_SDIO1>; ++ reset-names = "reset"; + status = "disabled"; + }; + + emmc: dwmmc@ff0f0000 { + compatible = "rockchip,rk3288-dw-mshc"; +- clock-freq-min-max = <400000 150000000>; ++ max-frequency = <150000000>; + clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>, + <&cru SCLK_EMMC_DRV>, <&cru SCLK_EMMC_SAMPLE>; + clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; + fifo-depth = <0x100>; + interrupts = ; + reg = <0x0 0xff0f0000 0x0 0x4000>; ++ resets = <&cru SRST_EMMC>; ++ reset-names = "reset"; + status = "disabled"; + supports-emmc; + }; +@@ -638,6 +646,7 @@ + compatible = "rockchip,rk3288-tsadc"; + reg = <0x0 0xff280000 0x0 0x100>; + interrupts = ; ++ rockchip,grf = <&grf>; + clocks = <&cru SCLK_TSADC>, <&cru PCLK_TSADC>; + clock-names = "tsadc", "apb_pclk"; + assigned-clocks = <&cru SCLK_TSADC>; +@@ -646,7 +655,7 @@ + reset-names = "tsadc-apb"; + pinctrl-names = "init", "default", "sleep"; + pinctrl-0 = <&otp_gpio>; +- pinctrl-1 = <&otp_gpio>; ++ pinctrl-1 = <&otp_out>; + pinctrl-2 = <&otp_gpio>; + #thermal-sensor-cells = <1>; + rockchip,hw-tshut-temp = <120000>; +@@ -1699,6 +1708,7 @@ + operating-points-v2 = <&gpu_opp_table>; + #cooling-cells = <2>; /* min followed by max */ + power-domains = <&power RK3288_PD_GPU>; ++ power-off-delay-ms = <200>; + status = "disabled"; + + upthreshold = <75>; + +From 25d521533a524ec201dd8b0e38a32989f8c00bfc Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 13 Aug 2017 10:24:19 +0200 +Subject: [PATCH] arm: dts: rk3288-miniarm: update dts + +--- + arch/arm/boot/dts/rk3288-miniarm.dts | 55 ++++++++++++++++++++++++++++-------- + 1 file changed, 44 insertions(+), 11 deletions(-) + +diff --git a/arch/arm/boot/dts/rk3288-miniarm.dts b/arch/arm/boot/dts/rk3288-miniarm.dts +index a5c5300797ab..7fc92c037dfd 100644 +--- a/arch/arm/boot/dts/rk3288-miniarm.dts ++++ b/arch/arm/boot/dts/rk3288-miniarm.dts +@@ -42,11 +42,22 @@ + #include + #include "rk3288.dtsi" + #include "rk3288-rkisp1.dtsi" +-#include "rk3288-linux.dtsi" ++#include "rk3288cg-opp.dtsi" + + / { ++ model = "ASUS Tinker Board"; + compatible = "rockchip,rk3288-miniarm", "rockchip,rk3288"; + ++ chosen { ++ bootargs = "earlyprintk=uart8250-32bit,0xff690000"; ++ }; ++ ++ cpuinfo { ++ compatible = "rockchip,cpuinfo"; ++ nvmem-cells = <&efuse_id>; ++ nvmem-cell-names = "id"; ++ }; ++ + memory { + device_type = "memory"; + reg = <0x0 0x0 0x0 0x80000000>; +@@ -67,7 +78,7 @@ + wireless-wlan { + compatible = "wlan-platdata"; + rockchip,grf = <&grf>; +- wifi_chip_type = "ap6212"; ++ wifi_chip_type = "rtl8723bs"; + sdio_vref = <1800>; + WIFI,host_wake_irq = <&gpio4 30 GPIO_ACTIVE_HIGH>; + status = "okay"; +@@ -129,16 +140,16 @@ + linux,default-trigger="mmc0"; + }; + +- led1-led { ++ heartbeat-led { + gpios=<&gpio1 25 GPIO_ACTIVE_HIGH>; +- linux,default-trigger="default-off"; ++ linux,default-trigger="heartbeat"; + }; + }; + + sound { + compatible = "simple-audio-card"; + simple-audio-card,format = "i2s"; +- simple-audio-card,name = "rockchip,miniarm-codec"; ++ simple-audio-card,name = "HDMI"; + simple-audio-card,mclk-fs = <512>; + simple-audio-card,cpu { + sound-dai = <&i2s>; +@@ -204,20 +215,33 @@ + cpu0-supply = <&vdd_cpu>; + }; + ++&emmc { ++ bus-width = <8>; ++ cap-mmc-highspeed; ++ disable-wp; ++ mmc-ddr-1_8v; ++ mmc-hs200-1_8v; ++ non-removable; ++ num-slots = <1>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_pwr &emmc_bus8>; ++ status = "okay"; ++}; ++ + &gmac { + phy-supply = <&vcc33_lan>; + phy-mode = "rgmii"; + clock_in_out = "input"; + snps,reset-gpio = <&gpio4 7 0>; + snps,reset-active-low; +- snps,reset-delays-us = <0 10000 1000000>; ++ snps,reset-delays-us = <0 10000 50000>; + assigned-clocks = <&cru SCLK_MAC>; + assigned-clock-parents = <&ext_gmac>; + pinctrl-names = "default"; + pinctrl-0 = <&rgmii_pins>; + tx_delay = <0x30>; + rx_delay = <0x10>; +- status = "ok"; ++ status = "okay"; + }; + + &dsi0 { +@@ -238,6 +262,11 @@ + #address-cells = <1>; + #size-cells = <0>; + #sound-dai-cells = <0>; ++ rockchip,phy-table = ++ <74250000 0x8009 0x0004 0x0272>, ++ <165000000 0x802b 0x0004 0x0209>, ++ <371250000 0x802d 0x0001 0x0149>, ++ <0 0x0000 0x0000 0x0000>; + status = "okay"; + /* Don't use vopl for HDMI */ + ports { +@@ -545,6 +574,7 @@ + + &i2s { + #sound-dai-cells = <0>; ++ rockchip,bclk-fs = <128>; + status = "okay"; + }; + +@@ -558,7 +588,7 @@ + &sdio0 { + status = "okay"; + clock-frequency = <50000000>; +- clock-freq-min-max = <200000 50000000>; ++ max-frequency = <50000000>; + bus-width = <4>; + cap-sd-highspeed; + cap-sdio-irq; +@@ -579,7 +609,7 @@ + + &saradc { + vref-supply = <&vcc18_ldo1>; +- status ="okay"; ++ status = "okay"; + }; + + &sdmmc { +@@ -604,7 +634,6 @@ + &tsadc { + rockchip,hw-tshut-mode = <1>; /* tshut mode 0:CRU 1:GPIO */ + rockchip,hw-tshut-polarity = <1>; /* tshut polarity 0:LOW 1:HIGH */ +- pinctrl-1 = <&otp_out>; + status = "okay"; + }; + +@@ -615,6 +644,8 @@ + }; + + &uart1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart1_xfer>, <&uart1_cts>, <&uart1_rts>; + status = "okay"; + }; + +@@ -627,6 +658,8 @@ + }; + + &uart4 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart4_xfer>, <&uart4_cts>, <&uart4_rts>; + status = "okay"; + }; + +@@ -644,7 +677,7 @@ + }; + + &usb_otg { +- status= "okay"; ++ status = "okay"; + }; + + &vopb { + +From 6cf3332dd491b1898930ff53e3cdd3b9f2a4a190 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Thu, 2 Nov 2017 23:17:46 +0100 +Subject: [PATCH] arm: dts: rk3288-miqi: update dts + +--- + arch/arm/boot/dts/rk3288-miqi.dts | 69 ++++++++++++++++++++++++--------------- + 1 file changed, 43 insertions(+), 26 deletions(-) + +diff --git a/arch/arm/boot/dts/rk3288-miqi.dts b/arch/arm/boot/dts/rk3288-miqi.dts +index a2862c6a17f1..18f2a9f96d71 100644 +--- a/arch/arm/boot/dts/rk3288-miqi.dts ++++ b/arch/arm/boot/dts/rk3288-miqi.dts +@@ -43,10 +43,21 @@ + /dts-v1/; + #include + #include "rk3288.dtsi" +-#include "rk3288-linux.dtsi" ++#include "rk3288cg-opp.dtsi" + + / { +- compatible = "rockchip,rk3288-miqi", "rockchip,rk3288"; ++ model = "mqmaker MiQi"; ++ compatible = "rockchip,rk3288-miqi", "rockchip,rk3288w", "rockchip,rk3288"; ++ ++ chosen { ++ bootargs = "earlyprintk=uart8250-32bit,0xff690000"; ++ }; ++ ++ cpuinfo { ++ compatible = "rockchip,cpuinfo"; ++ nvmem-cells = <&efuse_id>; ++ nvmem-cell-names = "id"; ++ }; + + memory { + device_type = "memory"; +@@ -56,29 +67,14 @@ + sound { + compatible = "simple-audio-card"; + simple-audio-card,format = "i2s"; +- simple-audio-card,name = "DW-HDMI"; ++ simple-audio-card,name = "HDMI"; + simple-audio-card,mclk-fs = <512>; +- +- simple-audio-card,dai-link@0 { /* I2S - S/PDIF */ +- format = "i2s"; +- cpu { +- sound-dai = <&i2s>; +- }; +- codec { +- sound-dai = <&hdmi>; +- }; ++ simple-audio-card,cpu { ++ sound-dai = <&i2s>; ++ }; ++ simple-audio-card,codec { ++ sound-dai = <&hdmi>; + }; +- +- /* +- * If you want to support more cards, +- * you can add more dai-link node, +- * such as +- * +- * simple-audio-card,dai-link@1 { +- * ...... +- * } +- */ +- + }; + + ext_gmac: external-gmac-clock { +@@ -204,6 +200,12 @@ + #size-cells = <0>; + #sound-dai-cells = <0>; + status = "okay"; ++ /* Don't use vopl for HDMI */ ++ ports { ++ hdmi_in: port { ++ /delete-node/ endpoint@1; ++ }; ++ }; + }; + + &hevc_service { +@@ -235,14 +237,14 @@ + clock_in_out = "input"; + snps,reset-gpio = <&gpio4 7 0>; + snps,reset-active-low; +- snps,reset-delays-us = <0 10000 1000000>; ++ snps,reset-delays-us = <0 10000 50000>; + assigned-clocks = <&cru SCLK_MAC>; + assigned-clock-parents = <&ext_gmac>; + pinctrl-names = "default"; + pinctrl-0 = <&rgmii_pins>; + tx_delay = <0x30>; + rx_delay = <0x10>; +- status = "ok"; ++ status = "okay"; + }; + + /* ---------------------------------------------------------------------------------- +@@ -414,6 +416,7 @@ I2C + + &i2s { + #sound-dai-cells = <0>; ++ rockchip,bclk-fs = <128>; + status = "okay"; + }; + +@@ -439,6 +442,17 @@ I2C + status = "okay"; + }; + ++&saradc { ++ vref-supply = <&vcc_18>; ++ status = "okay"; ++}; ++ ++&tsadc { ++ rockchip,hw-tshut-mode = <0>; ++ rockchip,hw-tshut-polarity = <0>; ++ status = "okay"; ++}; ++ + /* + * Debug Serial Port + */ +@@ -472,6 +486,10 @@ I2C + + &vopl { + status = "okay"; ++ /* Don't use vopl for HDMI */ ++ vopl_out: port { ++ /delete-node/ endpoint@0; ++ }; + }; + + &vopl_mmu { +@@ -546,4 +564,3 @@ I2C + }; + + }; +- + +From 1ddf61b01fbfc5602cb09ba2e97e78d7846e3c32 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Wed, 17 Jan 2018 22:17:45 +0100 +Subject: [PATCH] arm64: dts: rockchip: rk3328: update dtsi + +--- + arch/arm64/boot/dts/rockchip/rk3328.dtsi | 57 +++++++++++++++++++++++++------- + 1 file changed, 45 insertions(+), 12 deletions(-) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi +index 0d2251c903b1..45b7baba390c 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi +@@ -88,6 +88,8 @@ + device_type = "cpu"; + compatible = "arm,cortex-a53", "arm,armv8"; + reg = <0x0 0x1>; ++ clocks = <&cru ARMCLK>; ++ dynamic-power-coefficient = <120>; + enable-method = "psci"; + operating-points-v2 = <&cpu0_opp_table>; + }; +@@ -95,6 +97,8 @@ + device_type = "cpu"; + compatible = "arm,cortex-a53", "arm,armv8"; + reg = <0x0 0x2>; ++ clocks = <&cru ARMCLK>; ++ dynamic-power-coefficient = <120>; + enable-method = "psci"; + operating-points-v2 = <&cpu0_opp_table>; + }; +@@ -102,6 +106,8 @@ + device_type = "cpu"; + compatible = "arm,cortex-a53", "arm,armv8"; + reg = <0x0 0x3>; ++ clocks = <&cru ARMCLK>; ++ dynamic-power-coefficient = <120>; + enable-method = "psci"; + operating-points-v2 = <&cpu0_opp_table>; + }; +@@ -161,6 +167,22 @@ + opp-microvolt-L1 = <1300000 1300000 1350000>; + clock-latency-ns = <40000>; + }; ++ /* ++ opp-1392000000 { ++ opp-hz = /bits/ 64 <1392000000>; ++ opp-microvolt = <1350000 1350000 1350000>; ++ opp-microvolt-L0 = <1350000 1350000 1350000>; ++ opp-microvolt-L1 = <1325000 1325000 1350000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-1512000000 { ++ opp-hz = /bits/ 64 <1512000000>; ++ opp-microvolt = <1350000 1350000 1350000>; ++ opp-microvolt-L0 = <1350000 1350000 1350000>; ++ opp-microvolt-L1 = <1325000 1325000 1350000>; ++ clock-latency-ns = <40000>; ++ }; ++ */ + }; + + arm-pmu { +@@ -704,9 +726,9 @@ + }; + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; +- opp-microvolt = <975000>; +- opp-microvolt-L0 = <975000>; +- opp-microvolt-L1 = <950000>; ++ opp-microvolt = <1050000>; ++ opp-microvolt-L0 = <1050000>; ++ opp-microvolt-L1 = <1025000>; + }; + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; +@@ -720,6 +742,14 @@ + opp-microvolt-L0 = <1150000>; + opp-microvolt-L1 = <1100000>; + }; ++ /* ++ opp-600000000 { ++ opp-hz = /bits/ 64 <600000000>; ++ opp-microvolt = <1150000>; ++ opp-microvolt-L0 = <1150000>; ++ opp-microvolt-L1 = <1125000>; ++ }; ++ */ + }; + + vdpu: vpu_service@ff350000 { +@@ -843,7 +873,7 @@ + interrupts = ; + interrupt-names = "rkvdec_mmu"; + clocks = <&cru ACLK_RKVDEC>, <&cru HCLK_RKVDEC>; +- clock-names = "aclk_vcodec", "hclk_vcodec"; ++ clock-names = "aclk", "hclk"; + power-domains = <&power RK3328_PD_VIDEO>; + #iommu-cells = <0>; + }; +@@ -921,6 +951,8 @@ + vop: vop@ff370000 { + compatible = "rockchip,rk3328-vop"; + reg = <0x0 0xff370000 0x0 0x3efc>; ++ reg-names = "regs", "gamma_lut"; ++ rockchip,grf = <&grf>; + interrupts = ; + clocks = <&cru ACLK_VOP>, <&cru DCLK_LCDC>, <&cru HCLK_VOP>; + clock-names = "aclk_vop", "dclk_vop", "hclk_vop"; +@@ -1226,10 +1258,10 @@ + sdmmc: dwmmc@ff500000 { + compatible = "rockchip,rk3328-dw-mshc", "rockchip,rk3288-dw-mshc"; + reg = <0x0 0xff500000 0x0 0x4000>; +- clock-freq-min-max = <400000 150000000>; ++ max-frequency = <150000000>; + clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>, + <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>; +- clock-names = "biu", "ciu", "ciu-drv", "ciu-sample"; ++ clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; + fifo-depth = <0x100>; + interrupts = ; + status = "disabled"; +@@ -1238,10 +1270,10 @@ + sdio: dwmmc@ff510000 { + compatible = "rockchip,rk3328-dw-mshc", "rockchip,rk3288-dw-mshc"; + reg = <0x0 0xff510000 0x0 0x4000>; +- clock-freq-min-max = <400000 150000000>; ++ max-frequency = <150000000>; + clocks = <&cru HCLK_SDIO>, <&cru SCLK_SDIO>, + <&cru SCLK_SDIO_DRV>, <&cru SCLK_SDIO_SAMPLE>; +- clock-names = "biu", "ciu", "ciu-drv", "ciu-sample"; ++ clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; + fifo-depth = <0x100>; + interrupts = ; + status = "disabled"; +@@ -1250,10 +1282,10 @@ + emmc: dwmmc@ff520000 { + compatible = "rockchip,rk3328-dw-mshc", "rockchip,rk3288-dw-mshc"; + reg = <0x0 0xff520000 0x0 0x4000>; +- clock-freq-min-max = <400000 150000000>; ++ max-frequency = <150000000>; + clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>, + <&cru SCLK_EMMC_DRV>, <&cru SCLK_EMMC_SAMPLE>; +- clock-names = "biu", "ciu", "ciu-drv", "ciu-sample"; ++ clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; + fifo-depth = <0x100>; + interrupts = ; + status = "disabled"; +@@ -1275,6 +1307,7 @@ + "pclk_mac"; + resets = <&cru SRST_GMAC2IO_A>; + reset-names = "stmmaceth"; ++ snps,force_thresh_dma_mode; + status = "disabled"; + }; + +@@ -1345,10 +1378,10 @@ + sdmmc_ext: dwmmc@ff5f0000 { + compatible = "rockchip,rk3328-dw-mshc", "rockchip,rk3288-dw-mshc"; + reg = <0x0 0xff5f0000 0x0 0x4000>; +- clock-freq-min-max = <400000 150000000>; ++ max-frequency = <150000000>; + clocks = <&cru HCLK_SDMMC_EXT>, <&cru SCLK_SDMMC_EXT>, + <&cru SCLK_SDMMC_EXT_DRV>, <&cru SCLK_SDMMC_EXT_SAMPLE>; +- clock-names = "biu", "ciu", "ciu-drv", "ciu-sample"; ++ clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; + fifo-depth = <0x100>; + interrupts = ; + status = "disabled"; + +From 914752b8e8d56dd0fc7b7bd2fa789abacc9e93ad Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Wed, 17 Jan 2018 22:17:45 +0100 +Subject: [PATCH] arm64: dts: rockchip: rk3328-rock64: update dts + +--- + arch/arm64/boot/dts/rockchip/rk3328-rock64.dts | 250 ++++++++++++++++--------- + 1 file changed, 158 insertions(+), 92 deletions(-) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts +index ea8cd77333a8..68795d255309 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts +@@ -48,20 +48,15 @@ + compatible = "pine64,rock64", "rockchip,rk3328"; + + chosen { +- bootargs = "rockchip_jtag earlyprintk=uart8250-32bit,0xff130000"; ++ bootargs = "earlyprintk=uart8250-32bit,0xff130000"; + stdout-path = "serial2:1500000n8"; + }; + +- fiq-debugger { +- compatible = "rockchip,fiq-debugger"; +- rockchip,serial-id = <2>; +- rockchip,signal-irq = <159>; +- rockchip,wake-irq = <0>; +- /* If enable uart uses irq instead of fiq */ +- rockchip,irq-mode-enable = <0>; +- rockchip,baudrate = <1500000>; /* Only 115200 and 1500000 */ +- interrupts = ; +- status = "okay"; ++ xin32k: xin32k { ++ compatible = "fixed-clock"; ++ clock-frequency = <32768>; ++ clock-output-names = "xin32k"; ++ #clock-cells = <0>; + }; + + gmac_clkin: external-gmac-clock { +@@ -71,9 +66,25 @@ + #clock-cells = <0>; + }; + ++ vcc_phy: vcc-phy-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc_phy"; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ vcc_sys: vcc-sys { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc_sys"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ }; ++ + vcc_sd: sdmmc-regulator { + compatible = "regulator-fixed"; +- gpio = <&gpio0 30 GPIO_ACTIVE_LOW>; ++ gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc0m1_gpio>; + regulator-name = "vcc_sd"; +@@ -82,56 +93,58 @@ + vin-supply = <&vcc_io>; + }; + +- vcc_host_5v: vcc-host-5v-regulator { ++ vcc_host_5v: vcc_otg_5v: vcc-host-5v-regulator { + compatible = "regulator-fixed"; +- enable-active-high; +- gpio = <&gpio0 0 GPIO_ACTIVE_HIGH>; ++ gpio = <&gpio0 RK_PA2 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; +- pinctrl-0 = <&usb30_host_drv>; ++ pinctrl-0 = <&usb_host_drv>; + regulator-name = "vcc_host_5v"; +- regulator-always-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; + vin-supply = <&vcc_sys>; + }; + +- vcc_host1_5v: vcc_otg_5v: vcc-host1-5v-regulator { +- compatible = "regulator-fixed"; +- enable-active-high; +- gpio = <&gpio0 27 GPIO_ACTIVE_HIGH>; +- pinctrl-names = "default"; +- pinctrl-0 = <&usb20_host_drv>; +- regulator-name = "vcc_host1_5v"; +- regulator-always-on; +- vin-supply = <&vcc_sys>; +- }; ++ leds { ++ compatible = "gpio-leds"; + +- vcc_sys: vcc-sys { +- compatible = "regulator-fixed"; +- regulator-name = "vcc_sys"; +- regulator-always-on; +- regulator-boot-on; +- regulator-min-microvolt = <5000000>; +- regulator-max-microvolt = <5000000>; +- }; ++ standby-led { ++ gpios = <&rk805 0 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "heartbeat"; ++ }; + +- xin32k: xin32k { +- compatible = "fixed-clock"; +- clock-frequency = <32768>; +- clock-output-names = "xin32k"; +- #clock-cells = <0>; ++ power-led { ++ gpios = <&rk805 1 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "mmc0"; ++ }; + }; + + ir-receiver { + compatible = "gpio-ir-receiver"; ++ gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>; ++ linux,rc-map-name = "rc-pine64"; + pinctrl-0 = <&ir_int>; + pinctrl-names = "default"; + status = "okay"; + }; + ++ hdmi-sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,format = "i2s"; ++ simple-audio-card,mclk-fs = <128>; ++ simple-audio-card,name = "HDMI"; ++ simple-audio-card,cpu { ++ sound-dai = <&i2s0>; ++ }; ++ simple-audio-card,codec { ++ sound-dai = <&hdmi>; ++ }; ++ }; ++ + sound { + compatible = "simple-audio-card"; + simple-audio-card,format = "i2s"; + simple-audio-card,mclk-fs = <256>; +- simple-audio-card,name = "rockchip,rk3328"; ++ simple-audio-card,name = "I2S"; + simple-audio-card,cpu { + sound-dai = <&i2s1>; + }; +@@ -140,18 +153,21 @@ + }; + }; + +- hdmi-sound { ++ spdif-sound { + compatible = "simple-audio-card"; +- simple-audio-card,format = "i2s"; +- simple-audio-card,mclk-fs = <128>; +- simple-audio-card,name = "rockchip,hdmi"; ++ simple-audio-card,name = "SPDIF"; + simple-audio-card,cpu { +- sound-dai = <&i2s0>; ++ sound-dai = <&spdif>; + }; + simple-audio-card,codec { +- sound-dai = <&hdmi>; ++ sound-dai = <&spdif_out>; + }; + }; ++ ++ spdif_out: spdif-out { ++ compatible = "linux,spdif-dit"; ++ #sound-dai-cells = <0>; ++ }; + }; + + &codec { +@@ -175,6 +191,15 @@ + cpu-supply = <&vdd_arm>; + }; + ++&dfi { ++ status = "okay"; ++}; ++ ++&dmc { ++ center-supply = <&vdd_logic>; ++ status = "okay"; ++}; ++ + &display_subsystem { + status = "okay"; + }; +@@ -184,30 +209,40 @@ + cap-mmc-highspeed; + mmc-hs200-1_8v; + non-removable; +- supports-emmc; + pinctrl-names = "default"; + pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>; ++ supports-emmc; + vmmc-supply = <&vcc_io>; + vqmmc-supply = <&vcc18_emmc>; + status = "okay"; + }; + + &gmac2io { +- phy-supply = <&vcc_io>; +- phy-mode = "rgmii"; + assigned-clocks = <&cru SCLK_MAC2IO>, <&cru SCLK_MAC2IO_EXT>; + assigned-clock-parents = <&gmac_clkin>, <&gmac_clkin>; + clock_in_out = "input"; +- snps,reset-gpio = <&gpio1 18 GPIO_ACTIVE_LOW>; +- snps,reset-active-low; +- snps,reset-delays-us = <0 10000 50000>; ++ phy-supply = <&vcc_phy>; ++ phy-mode = "rgmii"; + pinctrl-names = "default"; + pinctrl-0 = <&rgmiim1_pins>; +- tx_delay = <0x26>; +- rx_delay = <0x11>; ++ snps,reset-gpio = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; ++ snps,reset-active-low; ++ snps,reset-delays-us = <0 10000 50000>; ++ tx_delay = <0x24>; ++ rx_delay = <0x18>; + status = "okay"; + }; + ++&gmac2phy { ++ phy-supply = <&vcc_phy>; ++ assigned-clocks = <&cru SCLK_MAC2PHY_SRC>; ++ assigned-clock-rate = <50000000>; ++ assigned-clocks = <&cru SCLK_MAC2PHY>; ++ assigned-clock-parents = <&cru SCLK_MAC2PHY_SRC>; ++ clock_in_out = "output"; ++ status = "disabled"; ++}; ++ + &gpu { + status = "okay"; + mali-supply = <&vdd_logic>; +@@ -223,6 +258,8 @@ + + &hdmi { + #sound-dai-cells = <0>; ++ ddc-i2c-scl-high-time-ns = <9625>; ++ ddc-i2c-scl-low-time-ns = <10000>; + status = "okay"; + }; + +@@ -239,14 +276,14 @@ + reg = <0x18>; + interrupt-parent = <&gpio2>; + interrupts = <6 IRQ_TYPE_LEVEL_LOW>; ++ #clock-cells = <1>; ++ clock-output-names = "rk805-clkout1", "rk805-clkout2"; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int_l>; + rockchip,system-power-controller; + wakeup-source; + gpio-controller; +- clock-output-names = "rk805-clkout1", "rk805-clkout2"; + #gpio-cells = <2>; +- #clock-cells = <1>; + + vcc1-supply = <&vcc_sys>; + vcc2-supply = <&vcc_sys>; +@@ -256,11 +293,11 @@ + vcc6-supply = <&vcc_sys>; + + rtc { +- status = "disabled"; ++ status = "okay"; + }; + + pwrkey { +- status = "disabled"; ++ status = "okay"; + }; + + gpio { +@@ -280,8 +317,8 @@ + regulator-max-microvolt = <1450000>; + regulator-initial-mode = <0x1>; + regulator-ramp-delay = <12500>; +- regulator-boot-on; + regulator-always-on; ++ regulator-boot-on; + regulator-state-mem { + regulator-mode = <0x2>; + regulator-on-in-suspend; +@@ -292,12 +329,13 @@ + vdd_arm: RK805_DCDC2 { + regulator-compatible = "RK805_DCDC2"; + regulator-name = "vdd_arm"; ++ regulator-init-microvolt = <1225000>; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1450000>; + regulator-initial-mode = <0x1>; + regulator-ramp-delay = <12500>; +- regulator-boot-on; + regulator-always-on; ++ regulator-boot-on; + regulator-state-mem { + regulator-mode = <0x2>; + regulator-on-in-suspend; +@@ -309,8 +347,8 @@ + regulator-compatible = "RK805_DCDC3"; + regulator-name = "vcc_ddr"; + regulator-initial-mode = <0x1>; +- regulator-boot-on; + regulator-always-on; ++ regulator-boot-on; + regulator-state-mem { + regulator-mode = <0x2>; + regulator-on-in-suspend; +@@ -323,8 +361,8 @@ + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-initial-mode = <0x1>; +- regulator-boot-on; + regulator-always-on; ++ regulator-boot-on; + regulator-state-mem { + regulator-mode = <0x2>; + regulator-on-in-suspend; +@@ -332,13 +370,13 @@ + }; + }; + +- vdd_18: RK805_LDO1 { ++ vcc_18: RK805_LDO1 { + regulator-compatible = "RK805_LDO1"; +- regulator-name = "vdd_18"; ++ regulator-name = "vcc_18"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; +- regulator-boot-on; + regulator-always-on; ++ regulator-boot-on; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; +@@ -350,8 +388,8 @@ + regulator-name = "vcc18_emmc"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; +- regulator-boot-on; + regulator-always-on; ++ regulator-boot-on; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; +@@ -363,8 +401,8 @@ + regulator-name = "vdd_10"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; +- regulator-boot-on; + regulator-always-on; ++ regulator-boot-on; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; +@@ -381,6 +419,16 @@ + }; + + &i2s1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2s1_mclk ++ &i2s1_sclk ++ &i2s1_lrcktx ++ &i2s1_lrckrx ++ &i2s1_sdo ++ &i2s1_sdi ++ &i2s1_sdio1 ++ &i2s1_sdio2 ++ &i2s1_sdio3>; + #sound-dai-cells = <0>; + status = "okay"; + }; +@@ -391,7 +439,7 @@ + vccio1-supply = <&vcc_io>; + vccio2-supply = <&vcc18_emmc>; + vccio3-supply = <&vcc_io>; +- vccio4-supply = <&vdd_18>; ++ vccio4-supply = <&vcc_18>; + vccio5-supply = <&vcc_io>; + vccio6-supply = <&vcc_io>; + pmuio-supply = <&vcc_io>; +@@ -400,37 +448,26 @@ + &pinctrl { + ir { + ir_int: ir-int { +- rockchip,pins = <2 2 RK_FUNC_GPIO &pcfg_pull_none>; ++ rockchip,pins = <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pmic { + pmic_int_l: pmic-int-l { +- rockchip,pins = <2 6 RK_FUNC_GPIO &pcfg_pull_up>; +- }; +- }; +- +- sdio-pwrseq { +- wifi_enable_h: wifi-enable-h { +- rockchip,pins = <1 18 RK_FUNC_GPIO &pcfg_pull_none>; +- }; +- }; +- +- usb2 { +- usb20_host_drv: usb20-host-drv { +- rockchip,pins = <0 27 RK_FUNC_GPIO &pcfg_pull_none>; ++ rockchip,pins = <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + +- usb3 { +- usb30_host_drv: usb30-host-drv { +- rockchip,pins = <0 0 RK_FUNC_GPIO &pcfg_pull_none>; ++ usb { ++ usb_host_drv: usb-host-drv { ++ rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + }; + + &rkvdec { + status = "okay"; ++ vcodec-supply = <&vdd_logic>; + }; + + &rkvdec_mmu { +@@ -445,8 +482,15 @@ + max-frequency = <150000000>; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_dectn &sdmmc0_bus4>; +- vmmc-supply = <&vcc_sd>; + supports-sd; ++ vmmc-supply = <&vcc_sd>; ++ status = "okay"; ++}; ++ ++&spdif { ++ #sound-dai-cells = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spdifm0_tx>; + status = "okay"; + }; + +@@ -454,19 +498,43 @@ + status = "okay"; + + flash@0 { +- compatible = "gigadevice,gd25q128", "jedec,spi-nor"; ++ compatible = "jedec,spi-nor"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0>; + m25p,fast-read; + /* The max SCLK of the flash 104/80 MHZ */ + spi-max-frequency = <50000000>; ++ ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ loader@8000 { ++ label = "loader"; ++ reg = <0x8000 0x3F0000>; ++ }; ++ }; + }; + }; + ++&threshold { ++ temperature = <80000>; /* millicelsius */ ++}; ++ ++&target { ++ temperature = <95000>; /* millicelsius */ ++}; ++ ++&soc_crit { ++ temperature = <100000>; /* millicelsius */ ++}; ++ + &tsadc { + rockchip,hw-tshut-mode = <0>; + rockchip,hw-tshut-polarity = <0>; ++ rockchip,hw-tshut-temp = <110000>; + status = "okay"; + }; + +@@ -476,21 +544,19 @@ + + &u2phy { + status = "okay"; +- + }; + + &u2phy_host { +- phy-supply = <&vcc_host1_5v>; + status = "okay"; + }; + + &u2phy_otg { +- phy-supply = <&vcc_otg_5v>; ++ vbus-supply = <&vcc_otg_5v>; + status = "okay"; + }; + + &u3phy { +- phy-supply = <&vcc_host_5v>; ++ vbus-supply = <&vcc_host_5v>; + status = "okay"; + }; + + +From 32c9398d320241a59a18bb1be65ba685e168ccd4 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Wed, 17 Jan 2018 22:17:45 +0100 +Subject: [PATCH] arm64: dts: rockchip: add rk3328-box board + +--- + arch/arm64/boot/dts/rockchip/rk3328-box.dts | 642 ++++++++++++++++++++++++++++ + 1 file changed, 642 insertions(+) + create mode 100644 arch/arm64/boot/dts/rockchip/rk3328-box.dts + +diff --git a/arch/arm64/boot/dts/rockchip/rk3328-box.dts b/arch/arm64/boot/dts/rockchip/rk3328-box.dts +new file mode 100644 +index 000000000000..3587126087e5 +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/rk3328-box.dts +@@ -0,0 +1,642 @@ ++/* ++ * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd ++ * ++ * This file is dual-licensed: you can use it either under the terms ++ * of the GPL or the X11 license, at your option. Note that this dual ++ * licensing only applies to this file, and not this project as a ++ * whole. ++ * ++ * a) This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of the ++ * License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * Or, alternatively, ++ * ++ * b) Permission is hereby granted, free of charge, to any person ++ * obtaining a copy of this software and associated documentation ++ * files (the "Software"), to deal in the Software without ++ * restriction, including without limitation the rights to use, ++ * copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following ++ * conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES ++ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT ++ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, ++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++/dts-v1/; ++#include "rk3328.dtsi" ++ ++/ { ++ model = "Rockchip RK3328 BOX"; ++ compatible = "rockchip,rk3328-box", "rockchip,rk3328"; ++ ++ chosen { ++ bootargs = "earlyprintk=uart8250-32bit,0xff130000"; ++ stdout-path = "serial2:1500000n8"; ++ }; ++ ++ xin32k: xin32k { ++ compatible = "fixed-clock"; ++ clock-frequency = <32768>; ++ clock-output-names = "xin32k"; ++ #clock-cells = <0>; ++ }; ++ ++ sdio_pwrseq: sdio-pwrseq { ++ compatible = "mmc-pwrseq-simple"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&wifi_enable_h>; ++ ++ /* ++ * On the module itself this is one of these (depending ++ * on the actual card populated): ++ * - SDIO_RESET_L_WL_REG_ON ++ * - PDN (power down when low) ++ */ ++ reset-gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; ++ }; ++ ++ vcc_phy: vcc-phy-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc_phy"; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ vcc_sys: vcc-sys { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc_sys"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ }; ++ ++ vcc_sd: sdmmc-regulator { ++ compatible = "regulator-fixed"; ++ gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_LOW>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc0m1_gpio>; ++ regulator-name = "vcc_sd"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ vin-supply = <&vcc_io>; ++ }; ++ ++ vcc_host_5v: vcc-host-5v-regulator { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&usb30_host_drv>; ++ regulator-name = "vcc_host_5v"; ++ regulator-always-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc_sys>; ++ }; ++ ++ vcc_host1_5v: vcc_otg_5v: vcc-host1-5v-regulator { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&usb20_host_drv>; ++ regulator-name = "vcc_host1_5v"; ++ regulator-always-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc_sys>; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led1 { ++ gpios = <&rk805 0 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "heartbeat"; ++ }; ++ ++ led2 { ++ gpios = <&rk805 1 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "mmc0"; ++ }; ++ }; ++ ++ ir-receiver { ++ compatible = "gpio-ir-receiver"; ++ gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>; ++ pinctrl-0 = <&ir_int>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ }; ++ ++ hdmi-sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,format = "i2s"; ++ simple-audio-card,mclk-fs = <128>; ++ simple-audio-card,name = "HDMI"; ++ simple-audio-card,cpu { ++ sound-dai = <&i2s0>; ++ }; ++ simple-audio-card,codec { ++ sound-dai = <&hdmi>; ++ }; ++ }; ++ ++ spdif-sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,name = "SPDIF"; ++ simple-audio-card,cpu { ++ sound-dai = <&spdif>; ++ }; ++ simple-audio-card,codec { ++ sound-dai = <&spdif_out>; ++ }; ++ }; ++ ++ spdif_out: spdif-out { ++ compatible = "linux,spdif-dit"; ++ #sound-dai-cells = <0>; ++ }; ++ ++ wireless-bluetooth { ++ compatible = "bluetooth-platdata"; ++ uart_rts_gpios = <&gpio1 RK_PB2 GPIO_ACTIVE_LOW>; ++ pinctrl-names = "default", "rts_gpio"; ++ pinctrl-0 = <&uart0_rts>; ++ pinctrl-1 = <&uart0_gpios>; ++ BT,power_gpio = <&gpio1 RK_PC5 GPIO_ACTIVE_HIGH>; ++ BT,wake_host_irq = <&gpio1 RK_PD2 GPIO_ACTIVE_HIGH>; ++ status = "okay"; ++ }; ++ ++ wireless-wlan { ++ compatible = "wlan-platdata"; ++ rockchip,grf = <&grf>; ++ wifi_chip_type = "rtl8723bs"; ++ WIFI,host_wake_irq = <&gpio1 RK_PC3 GPIO_ACTIVE_HIGH>; ++ status = "okay"; ++ }; ++}; ++ ++&codec { ++ #sound-dai-cells = <0>; ++ status = "okay"; ++}; ++ ++&cpu0 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu1 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu2 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu3 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&dfi { ++ status = "okay"; ++}; ++ ++&dmc { ++ center-supply = <&vdd_logic>; ++ status = "okay"; ++}; ++ ++&display_subsystem { ++ status = "okay"; ++}; ++ ++&emmc { ++ bus-width = <8>; ++ cap-mmc-highspeed; ++ mmc-hs200-1_8v; ++ non-removable; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>; ++ supports-emmc; ++ vmmc-supply = <&vcc_io>; ++ vqmmc-supply = <&vcc18_emmc>; ++ status = "okay"; ++}; ++ ++&gmac2phy { ++ phy-supply = <&vcc_phy>; ++ assigned-clocks = <&cru SCLK_MAC2PHY_SRC>; ++ assigned-clock-rate = <50000000>; ++ assigned-clocks = <&cru SCLK_MAC2PHY>; ++ assigned-clock-parents = <&cru SCLK_MAC2PHY_SRC>; ++ clock_in_out = "output"; ++ status = "okay"; ++}; ++ ++&gpu { ++ status = "okay"; ++ mali-supply = <&vdd_logic>; ++}; ++ ++&h265e { ++ status = "okay"; ++}; ++ ++&h265e_mmu { ++ status = "okay"; ++}; ++ ++&hdmi { ++ #sound-dai-cells = <0>; ++ ddc-i2c-scl-high-time-ns = <9625>; ++ ddc-i2c-scl-low-time-ns = <10000>; ++ status = "okay"; ++}; ++ ++&hdmiphy { ++ status = "okay"; ++}; ++ ++&i2c1 { ++ status = "okay"; ++ ++ rk805: rk805@18 { ++ compatible = "rockchip,rk805"; ++ status = "okay"; ++ reg = <0x18>; ++ interrupt-parent = <&gpio2>; ++ interrupts = <6 IRQ_TYPE_LEVEL_LOW>; ++ #clock-cells = <1>; ++ clock-output-names = "rk805-clkout1", "rk805-clkout2"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pmic_int_l>; ++ rockchip,system-power-controller; ++ wakeup-source; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ vcc1-supply = <&vcc_sys>; ++ vcc2-supply = <&vcc_sys>; ++ vcc3-supply = <&vcc_sys>; ++ vcc4-supply = <&vcc_sys>; ++ vcc5-supply = <&vcc_io>; ++ vcc6-supply = <&vcc_sys>; ++ ++ rtc { ++ status = "okay"; ++ }; ++ ++ pwrkey { ++ status = "okay"; ++ }; ++ ++ gpio { ++ status = "okay"; ++ }; ++ ++ regulators { ++ compatible = "rk805-regulator"; ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ vdd_logic: RK805_DCDC1 { ++ regulator-compatible = "RK805_DCDC1"; ++ regulator-name = "vdd_logic"; ++ regulator-min-microvolt = <712500>; ++ regulator-max-microvolt = <1450000>; ++ regulator-initial-mode = <0x1>; ++ regulator-ramp-delay = <12500>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-mode = <0x2>; ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1000000>; ++ }; ++ }; ++ ++ vdd_arm: RK805_DCDC2 { ++ regulator-compatible = "RK805_DCDC2"; ++ regulator-name = "vdd_arm"; ++ regulator-init-microvolt = <1225000>; ++ regulator-min-microvolt = <712500>; ++ regulator-max-microvolt = <1450000>; ++ regulator-initial-mode = <0x1>; ++ regulator-ramp-delay = <12500>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-mode = <0x2>; ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <950000>; ++ }; ++ }; ++ ++ vcc_ddr: RK805_DCDC3 { ++ regulator-compatible = "RK805_DCDC3"; ++ regulator-name = "vcc_ddr"; ++ regulator-initial-mode = <0x1>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-mode = <0x2>; ++ regulator-on-in-suspend; ++ }; ++ }; ++ ++ vcc_io: RK805_DCDC4 { ++ regulator-compatible = "RK805_DCDC4"; ++ regulator-name = "vcc_io"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-initial-mode = <0x1>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-mode = <0x2>; ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3300000>; ++ }; ++ }; ++ ++ vcc_18: RK805_LDO1 { ++ regulator-compatible = "RK805_LDO1"; ++ regulator-name = "vcc_18"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vcc18_emmc: RK805_LDO2 { ++ regulator-compatible = "RK805_LDO2"; ++ regulator-name = "vcc18_emmc"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vdd_10: RK805_LDO3 { ++ regulator-compatible = "RK805_LDO3"; ++ regulator-name = "vdd_10"; ++ regulator-min-microvolt = <1000000>; ++ regulator-max-microvolt = <1000000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1000000>; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&i2s0 { ++ #sound-dai-cells = <0>; ++ rockchip,bclk-fs = <128>; ++ status = "okay"; ++}; ++ ++&io_domains { ++ status = "okay"; ++ ++ vccio1-supply = <&vcc_io>; ++ vccio2-supply = <&vcc18_emmc>; ++ vccio3-supply = <&vcc_io>; ++ vccio4-supply = <&vcc_18>; ++ vccio5-supply = <&vcc_io>; ++ vccio6-supply = <&vcc_io>; ++ pmuio-supply = <&vcc_io>; ++}; ++ ++&pinctrl { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&clk_32k_out>; ++ ++ clk_32k { ++ clk_32k_out: clk-32k-out { ++ rockchip,pins = <1 RK_PD4 RK_FUNC_1 &pcfg_pull_none>; ++ }; ++ }; ++ ++ ir { ++ ir_int: ir-int { ++ rockchip,pins = <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ pmic { ++ pmic_int_l: pmic-int-l { ++ rockchip,pins = <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++ ++ sdio-pwrseq { ++ wifi_enable_h: wifi-enable-h { ++ rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ usb2 { ++ usb20_host_drv: usb20-host-drv { ++ rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ usb3 { ++ usb30_host_drv: usb30-host-drv { ++ rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ wireless-bluetooth { ++ uart0_gpios: uart0-gpios { ++ rockchip,pins = <1 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++}; ++ ++&rkvdec { ++ status = "okay"; ++ vcodec-supply = <&vdd_logic>; ++}; ++ ++&rkvdec_mmu { ++ status = "okay"; ++}; ++ ++&sdio { ++ bus-width = <4>; ++ cap-sd-highspeed; ++ cap-sdio-irq; ++ disable-wp; ++ keep-power-in-suspend; ++ max-frequency = <150000000>; ++ mmc-pwrseq = <&sdio_pwrseq>; ++ non-removable; ++ num-slots = <1>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc1_bus4 &sdmmc1_cmd &sdmmc1_clk>; ++ sd-uhs-sdr104; ++ supports-sdio; ++ status = "okay"; ++}; ++ ++&sdmmc { ++ bus-width = <4>; ++ cap-mmc-highspeed; ++ cap-sd-highspeed; ++ disable-wp; ++ max-frequency = <150000000>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_dectn &sdmmc0_bus4>; ++ supports-sd; ++ vmmc-supply = <&vcc_sd>; ++ status = "okay"; ++}; ++ ++&spdif { ++ #sound-dai-cells = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spdifm0_tx>; ++ status = "okay"; ++}; ++ ++&threshold { ++ temperature = <80000>; /* millicelsius */ ++}; ++ ++&target { ++ temperature = <95000>; /* millicelsius */ ++}; ++ ++&soc_crit { ++ temperature = <100000>; /* millicelsius */ ++}; ++ ++&tsadc { ++ rockchip,hw-tshut-mode = <0>; ++ rockchip,hw-tshut-polarity = <0>; ++ rockchip,hw-tshut-temp = <110000>; ++ status = "okay"; ++}; ++ ++&uart0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart0_xfer &uart0_cts>; ++ status = "okay"; ++}; ++ ++&uart2 { ++ status = "okay"; ++}; ++ ++&u2phy { ++ status = "okay"; ++ ++}; ++ ++&u2phy_host { ++ phy-supply = <&vcc_host1_5v>; ++ status = "okay"; ++}; ++ ++&u2phy_otg { ++ phy-supply = <&vcc_otg_5v>; ++ status = "okay"; ++}; ++ ++&u3phy { ++ status = "okay"; ++}; ++ ++&u3phy_utmi { ++ phy-supply = <&vcc_host_5v>; ++ status = "okay"; ++}; ++ ++&u3phy_pipe { ++ phy-supply = <&vcc_host_5v>; ++ status = "okay"; ++}; ++ ++&usb20_otg { ++ dr_mode = "host"; ++ status = "okay"; ++}; ++ ++&usb_host0_ehci { ++ status = "okay"; ++}; ++ ++&usb_host0_ohci { ++ status = "okay"; ++}; ++ ++&usbdrd3 { ++ status = "okay"; ++}; ++ ++&usbdrd_dwc3 { ++ status = "okay"; ++}; ++ ++&vop { ++ status = "okay"; ++}; ++ ++&vop_mmu { ++ status = "okay"; ++}; ++ ++&vpu_service { ++ status = "okay"; ++}; ++ ++&vpu_mmu { ++ status = "okay"; ++}; ++ ++&vepu { ++ status = "okay"; ++}; ++ ++&vepu_mmu { ++ status = "okay"; ++}; ++ ++&venc_srv { ++ status = "okay"; ++}; + +From 626c5888be5e46805d0319796bb395acf77e905e Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Wed, 17 Jan 2018 22:17:45 +0100 +Subject: [PATCH] arm64: dts: rockchip: add rk3328-rockbox board + +--- + arch/arm64/boot/dts/rockchip/rk3328-rockbox.dts | 582 ++++++++++++++++++++++++ + 1 file changed, 582 insertions(+) + create mode 100644 arch/arm64/boot/dts/rockchip/rk3328-rockbox.dts + +diff --git a/arch/arm64/boot/dts/rockchip/rk3328-rockbox.dts b/arch/arm64/boot/dts/rockchip/rk3328-rockbox.dts +new file mode 100644 +index 000000000000..75f890e548e5 +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/rk3328-rockbox.dts +@@ -0,0 +1,582 @@ ++/* ++ * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd ++ * ++ * This file is dual-licensed: you can use it either under the terms ++ * of the GPL or the X11 license, at your option. Note that this dual ++ * licensing only applies to this file, and not this project as a ++ * whole. ++ * ++ * a) This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of the ++ * License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * Or, alternatively, ++ * ++ * b) Permission is hereby granted, free of charge, to any person ++ * obtaining a copy of this software and associated documentation ++ * files (the "Software"), to deal in the Software without ++ * restriction, including without limitation the rights to use, ++ * copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following ++ * conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES ++ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT ++ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, ++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++/dts-v1/; ++#include "rk3328.dtsi" ++ ++/ { ++ model = "Pine64 RockBox"; ++ compatible = "pine64,rockbox", "rockchip,rk3328"; ++ ++ chosen { ++ bootargs = "earlyprintk=uart8250-32bit,0xff130000"; ++ stdout-path = "serial2:1500000n8"; ++ }; ++ ++ xin32k: xin32k { ++ compatible = "fixed-clock"; ++ clock-frequency = <32768>; ++ clock-output-names = "xin32k"; ++ #clock-cells = <0>; ++ }; ++ ++ sdio_pwrseq: sdio-pwrseq { ++ compatible = "mmc-pwrseq-simple"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&wifi_enable_h>; ++ ++ /* ++ * On the module itself this is one of these (depending ++ * on the actual card populated): ++ * - SDIO_RESET_L_WL_REG_ON ++ * - PDN (power down when low) ++ */ ++ reset-gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; ++ }; ++ ++ vcc_phy: vcc-phy-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc_phy"; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ vcc_sys: vcc-sys { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc_sys"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ }; ++ ++ vcc_sd: sdmmc-regulator { ++ compatible = "regulator-fixed"; ++ gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_LOW>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc0m1_gpio>; ++ regulator-name = "vcc_sd"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ vin-supply = <&vcc_io>; ++ }; ++ ++ vcc_host_5v: vcc_host1_5v: vcc_otg_5v: vcc-host-5v-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc_host_5v"; ++ regulator-always-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc_sys>; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led1 { ++ gpios = <&rk805 0 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "heartbeat"; ++ }; ++ ++ led2 { ++ gpios = <&rk805 1 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "mmc0"; ++ }; ++ }; ++ ++ ir-receiver { ++ compatible = "gpio-ir-receiver"; ++ gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>; ++ linux,rc-map-name = "rc-pine64"; ++ pinctrl-0 = <&ir_int>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ }; ++ ++ hdmi-sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,format = "i2s"; ++ simple-audio-card,mclk-fs = <128>; ++ simple-audio-card,name = "HDMI"; ++ simple-audio-card,cpu { ++ sound-dai = <&i2s0>; ++ }; ++ simple-audio-card,codec { ++ sound-dai = <&hdmi>; ++ }; ++ }; ++ ++ spdif-sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,name = "SPDIF"; ++ simple-audio-card,cpu { ++ sound-dai = <&spdif>; ++ }; ++ simple-audio-card,codec { ++ sound-dai = <&spdif_out>; ++ }; ++ }; ++ ++ spdif_out: spdif-out { ++ compatible = "linux,spdif-dit"; ++ #sound-dai-cells = <0>; ++ }; ++ ++ wireless-wlan { ++ compatible = "wlan-platdata"; ++ rockchip,grf = <&grf>; ++ wifi_chip_type = "rtl8189fs"; ++ WIFI,host_wake_irq = <&gpio1 RK_PC3 GPIO_ACTIVE_HIGH>; ++ status = "okay"; ++ }; ++}; ++ ++&codec { ++ #sound-dai-cells = <0>; ++ status = "okay"; ++}; ++ ++&cpu0 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu1 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu2 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu3 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&dfi { ++ status = "okay"; ++}; ++ ++&dmc { ++ center-supply = <&vdd_logic>; ++ status = "okay"; ++}; ++ ++&display_subsystem { ++ status = "okay"; ++}; ++ ++&emmc { ++ bus-width = <8>; ++ cap-mmc-highspeed; ++ mmc-hs200-1_8v; ++ non-removable; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>; ++ supports-emmc; ++ vmmc-supply = <&vcc_io>; ++ vqmmc-supply = <&vcc18_emmc>; ++ status = "okay"; ++}; ++ ++&gmac2phy { ++ phy-supply = <&vcc_phy>; ++ assigned-clocks = <&cru SCLK_MAC2PHY_SRC>; ++ assigned-clock-rate = <50000000>; ++ assigned-clocks = <&cru SCLK_MAC2PHY>; ++ assigned-clock-parents = <&cru SCLK_MAC2PHY_SRC>; ++ clock_in_out = "output"; ++ status = "okay"; ++}; ++ ++&gpu { ++ status = "okay"; ++ mali-supply = <&vdd_logic>; ++}; ++ ++&h265e { ++ status = "okay"; ++}; ++ ++&h265e_mmu { ++ status = "okay"; ++}; ++ ++&hdmi { ++ #sound-dai-cells = <0>; ++ ddc-i2c-scl-high-time-ns = <9625>; ++ ddc-i2c-scl-low-time-ns = <10000>; ++ status = "okay"; ++}; ++ ++&hdmiphy { ++ status = "okay"; ++}; ++ ++&i2c1 { ++ status = "okay"; ++ ++ rk805: rk805@18 { ++ compatible = "rockchip,rk805"; ++ status = "okay"; ++ reg = <0x18>; ++ interrupt-parent = <&gpio2>; ++ interrupts = <6 IRQ_TYPE_LEVEL_LOW>; ++ #clock-cells = <1>; ++ clock-output-names = "rk805-clkout1", "rk805-clkout2"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pmic_int_l>; ++ rockchip,system-power-controller; ++ wakeup-source; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ vcc1-supply = <&vcc_sys>; ++ vcc2-supply = <&vcc_sys>; ++ vcc3-supply = <&vcc_sys>; ++ vcc4-supply = <&vcc_sys>; ++ vcc5-supply = <&vcc_io>; ++ vcc6-supply = <&vcc_sys>; ++ ++ rtc { ++ status = "okay"; ++ }; ++ ++ pwrkey { ++ status = "okay"; ++ }; ++ ++ gpio { ++ status = "okay"; ++ }; ++ ++ regulators { ++ compatible = "rk805-regulator"; ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ vdd_logic: RK805_DCDC1 { ++ regulator-compatible = "RK805_DCDC1"; ++ regulator-name = "vdd_logic"; ++ regulator-min-microvolt = <712500>; ++ regulator-max-microvolt = <1450000>; ++ regulator-initial-mode = <0x1>; ++ regulator-ramp-delay = <12500>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-mode = <0x2>; ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1000000>; ++ }; ++ }; ++ ++ vdd_arm: RK805_DCDC2 { ++ regulator-compatible = "RK805_DCDC2"; ++ regulator-name = "vdd_arm"; ++ regulator-init-microvolt = <1225000>; ++ regulator-min-microvolt = <712500>; ++ regulator-max-microvolt = <1450000>; ++ regulator-initial-mode = <0x1>; ++ regulator-ramp-delay = <12500>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-mode = <0x2>; ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <950000>; ++ }; ++ }; ++ ++ vcc_ddr: RK805_DCDC3 { ++ regulator-compatible = "RK805_DCDC3"; ++ regulator-name = "vcc_ddr"; ++ regulator-initial-mode = <0x1>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-mode = <0x2>; ++ regulator-on-in-suspend; ++ }; ++ }; ++ ++ vcc_io: RK805_DCDC4 { ++ regulator-compatible = "RK805_DCDC4"; ++ regulator-name = "vcc_io"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-initial-mode = <0x1>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-mode = <0x2>; ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3300000>; ++ }; ++ }; ++ ++ vcc_18: RK805_LDO1 { ++ regulator-compatible = "RK805_LDO1"; ++ regulator-name = "vcc_18"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vcc18_emmc: RK805_LDO2 { ++ regulator-compatible = "RK805_LDO2"; ++ regulator-name = "vcc18_emmc"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vdd_10: RK805_LDO3 { ++ regulator-compatible = "RK805_LDO3"; ++ regulator-name = "vdd_10"; ++ regulator-min-microvolt = <1000000>; ++ regulator-max-microvolt = <1000000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1000000>; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&i2s0 { ++ #sound-dai-cells = <0>; ++ rockchip,bclk-fs = <128>; ++ status = "okay"; ++}; ++ ++&io_domains { ++ status = "okay"; ++ ++ vccio1-supply = <&vcc_io>; ++ vccio2-supply = <&vcc18_emmc>; ++ vccio3-supply = <&vcc_io>; ++ vccio4-supply = <&vcc_io>; ++ vccio5-supply = <&vcc_io>; ++ vccio6-supply = <&vcc_io>; ++ pmuio-supply = <&vcc_io>; ++}; ++ ++&pinctrl { ++ ir { ++ ir_int: ir-int { ++ rockchip,pins = <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ pmic { ++ pmic_int_l: pmic-int-l { ++ rockchip,pins = <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++ ++ sdio-pwrseq { ++ wifi_enable_h: wifi-enable-h { ++ rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++}; ++ ++&rkvdec { ++ status = "okay"; ++ vcodec-supply = <&vdd_logic>; ++}; ++ ++&rkvdec_mmu { ++ status = "okay"; ++}; ++ ++&sdio { ++ bus-width = <4>; ++ cap-sd-highspeed; ++ cap-sdio-irq; ++ disable-wp; ++ keep-power-in-suspend; ++ max-frequency = <150000000>; ++ mmc-pwrseq = <&sdio_pwrseq>; ++ non-removable; ++ num-slots = <1>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc1_bus4 &sdmmc1_cmd &sdmmc1_clk>; ++ sd-uhs-sdr104; ++ supports-sdio; ++ status = "okay"; ++}; ++ ++&sdmmc { ++ bus-width = <4>; ++ cap-mmc-highspeed; ++ cap-sd-highspeed; ++ disable-wp; ++ max-frequency = <150000000>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_dectn &sdmmc0_bus4>; ++ supports-sd; ++ vmmc-supply = <&vcc_sd>; ++ status = "okay"; ++}; ++ ++&spdif { ++ #sound-dai-cells = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spdifm0_tx>; ++ status = "okay"; ++}; ++ ++&threshold { ++ temperature = <80000>; /* millicelsius */ ++}; ++ ++&target { ++ temperature = <95000>; /* millicelsius */ ++}; ++ ++&soc_crit { ++ temperature = <100000>; /* millicelsius */ ++}; ++ ++&tsadc { ++ rockchip,hw-tshut-mode = <0>; ++ rockchip,hw-tshut-polarity = <0>; ++ rockchip,hw-tshut-temp = <110000>; ++ status = "okay"; ++}; ++ ++&uart2 { ++ status = "okay"; ++}; ++ ++&u2phy { ++ status = "okay"; ++ ++}; ++ ++&u2phy_host { ++ phy-supply = <&vcc_host1_5v>; ++ status = "okay"; ++}; ++ ++&u2phy_otg { ++ phy-supply = <&vcc_otg_5v>; ++ status = "okay"; ++}; ++ ++&u3phy { ++ status = "okay"; ++}; ++ ++&u3phy_utmi { ++ phy-supply = <&vcc_host_5v>; ++ status = "okay"; ++}; ++ ++&u3phy_pipe { ++ phy-supply = <&vcc_host_5v>; ++ status = "okay"; ++}; ++ ++&usb20_otg { ++ dr_mode = "host"; ++ status = "okay"; ++}; ++ ++&usb_host0_ehci { ++ status = "okay"; ++}; ++ ++&usb_host0_ohci { ++ status = "okay"; ++}; ++ ++&usbdrd3 { ++ status = "okay"; ++}; ++ ++&usbdrd_dwc3 { ++ status = "okay"; ++}; ++ ++&vop { ++ status = "okay"; ++}; ++ ++&vop_mmu { ++ status = "okay"; ++}; ++ ++&vpu_service { ++ status = "okay"; ++}; ++ ++&vpu_mmu { ++ status = "okay"; ++}; ++ ++&vepu { ++ status = "okay"; ++}; ++ ++&vepu_mmu { ++ status = "okay"; ++}; ++ ++&venc_srv { ++ status = "okay"; ++}; + +From 5495be2c49de4ea44de1df19ba19d7d515fa46e5 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Wed, 17 Jan 2018 22:17:45 +0100 +Subject: [PATCH] arm64: dts: rockchip: add rk3328-roc-cc board + +--- + arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts | 571 +++++++++++++++++++++++++ + 1 file changed, 571 insertions(+) + create mode 100644 arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts + +diff --git a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts +new file mode 100644 +index 000000000000..cd0b377977ab +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts +@@ -0,0 +1,571 @@ ++/* ++ * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd ++ * ++ * This file is dual-licensed: you can use it either under the terms ++ * of the GPL or the X11 license, at your option. Note that this dual ++ * licensing only applies to this file, and not this project as a ++ * whole. ++ * ++ * a) This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of the ++ * License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * Or, alternatively, ++ * ++ * b) Permission is hereby granted, free of charge, to any person ++ * obtaining a copy of this software and associated documentation ++ * files (the "Software"), to deal in the Software without ++ * restriction, including without limitation the rights to use, ++ * copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following ++ * conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES ++ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT ++ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, ++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++/dts-v1/; ++#include "rk3328.dtsi" ++ ++/ { ++ model = "Firefly ROC-RK3328-CC Board"; ++ compatible = "firefly,roc-rk3328-cc", "rockchip,rk3328"; ++ ++ chosen { ++ bootargs = "earlyprintk=uart8250-32bit,0xff130000"; ++ stdout-path = "serial2:1500000n8"; ++ }; ++ ++ xin32k: xin32k { ++ compatible = "fixed-clock"; ++ clock-frequency = <32768>; ++ clock-output-names = "xin32k"; ++ #clock-cells = <0>; ++ }; ++ ++ gmac_clkin: external-gmac-clock { ++ compatible = "fixed-clock"; ++ clock-frequency = <125000000>; ++ clock-output-names = "gmac_clkin"; ++ #clock-cells = <0>; ++ }; ++ ++ vcc_phy: vcc-phy-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc_phy"; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ vcc_sys: vcc-sys { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc_sys"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ }; ++ ++ vcc_sd: sdmmc-regulator { ++ compatible = "regulator-fixed"; ++ gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_LOW>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc0m1_gpio>; ++ regulator-name = "vcc_sd"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ vin-supply = <&vcc_io>; ++ }; ++ ++ vccio_sd: sdmmcio-regulator { ++ compatible = "regulator-gpio"; ++ gpios = <&gpio0 RK_PD1 GPIO_ACTIVE_HIGH>; ++ states = <1800000 0x1 ++ 3300000 0x0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sd_pwr_1800_sel>; ++ regulator-name = "vccio_sd"; ++ regulator-type = "voltage"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; ++ }; ++ ++ vcc_host_5v: vcc_host1_5v: vcc_otg_5v: vcc-host-5v-regulator { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio1 RK_PD2 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&usb_host_drv>; ++ regulator-name = "vcc_host_5v"; ++ regulator-always-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc_sys>; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ power { ++ gpios = <&rk805 1 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "heartbeat"; ++ }; ++ ++ user { ++ gpios = <&rk805 0 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "mmc0"; ++ }; ++ }; ++ ++ ir-receiver { ++ compatible = "gpio-ir-receiver"; ++ gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>; ++ linux,rc-map-name = "rc-roc-cc"; ++ pinctrl-0 = <&ir_int>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ }; ++ ++ hdmi-sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,format = "i2s"; ++ simple-audio-card,mclk-fs = <128>; ++ simple-audio-card,name = "HDMI"; ++ simple-audio-card,cpu { ++ sound-dai = <&i2s0>; ++ }; ++ simple-audio-card,codec { ++ sound-dai = <&hdmi>; ++ }; ++ }; ++ ++ sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,format = "i2s"; ++ simple-audio-card,mclk-fs = <256>; ++ simple-audio-card,name = "I2S"; ++ simple-audio-card,cpu { ++ sound-dai = <&i2s1>; ++ }; ++ simple-audio-card,codec { ++ sound-dai = <&codec>; ++ }; ++ }; ++}; ++ ++&codec { ++ #sound-dai-cells = <0>; ++ status = "okay"; ++}; ++ ++&cpu0 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu1 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu2 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu3 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&dfi { ++ status = "okay"; ++}; ++ ++&dmc { ++ center-supply = <&vdd_logic>; ++ status = "okay"; ++}; ++ ++&display_subsystem { ++ status = "okay"; ++}; ++ ++&emmc { ++ bus-width = <8>; ++ cap-mmc-highspeed; ++ mmc-hs200-1_8v; ++ non-removable; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>; ++ supports-emmc; ++ vmmc-supply = <&vcc_io>; ++ vqmmc-supply = <&vcc18_emmc>; ++ status = "okay"; ++}; ++ ++&gmac2io { ++ assigned-clocks = <&cru SCLK_MAC2IO>, <&cru SCLK_MAC2IO_EXT>; ++ assigned-clock-parents = <&gmac_clkin>, <&gmac_clkin>; ++ clock_in_out = "input"; ++ phy-supply = <&vcc_phy>; ++ phy-mode = "rgmii"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&rgmiim1_pins>; ++ snps,reset-gpio = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; ++ snps,reset-active-low; ++ snps,reset-delays-us = <0 10000 50000>; ++ tx_delay = <0x25>; ++ rx_delay = <0x11>; ++ status = "okay"; ++}; ++ ++&gpu { ++ status = "okay"; ++ mali-supply = <&vdd_logic>; ++}; ++ ++&h265e { ++ status = "okay"; ++}; ++ ++&h265e_mmu { ++ status = "okay"; ++}; ++ ++&hdmi { ++ #sound-dai-cells = <0>; ++ ddc-i2c-scl-high-time-ns = <9625>; ++ ddc-i2c-scl-low-time-ns = <10000>; ++ status = "okay"; ++}; ++ ++&hdmiphy { ++ status = "okay"; ++}; ++ ++&i2c1 { ++ status = "okay"; ++ ++ rk805: rk805@18 { ++ compatible = "rockchip,rk805"; ++ status = "okay"; ++ reg = <0x18>; ++ interrupt-parent = <&gpio1>; ++ interrupts = <24 IRQ_TYPE_LEVEL_LOW>; ++ #clock-cells = <1>; ++ clock-output-names = "rk805-clkout1", "rk805-clkout2"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pmic_int_l>; ++ rockchip,system-power-controller; ++ wakeup-source; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ vcc1-supply = <&vcc_sys>; ++ vcc2-supply = <&vcc_sys>; ++ vcc3-supply = <&vcc_sys>; ++ vcc4-supply = <&vcc_sys>; ++ vcc5-supply = <&vcc_io>; ++ vcc6-supply = <&vcc_sys>; ++ ++ rtc { ++ status = "okay"; ++ }; ++ ++ pwrkey { ++ status = "okay"; ++ }; ++ ++ gpio { ++ status = "okay"; ++ }; ++ ++ regulators { ++ compatible = "rk805-regulator"; ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ vdd_logic: RK805_DCDC1 { ++ regulator-compatible = "RK805_DCDC1"; ++ regulator-name = "vdd_logic"; ++ regulator-min-microvolt = <712500>; ++ regulator-max-microvolt = <1450000>; ++ regulator-initial-mode = <0x1>; ++ regulator-ramp-delay = <12500>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-mode = <0x2>; ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1000000>; ++ }; ++ }; ++ ++ vdd_arm: RK805_DCDC2 { ++ regulator-compatible = "RK805_DCDC2"; ++ regulator-name = "vdd_arm"; ++ regulator-init-microvolt = <1225000>; ++ regulator-min-microvolt = <712500>; ++ regulator-max-microvolt = <1450000>; ++ regulator-initial-mode = <0x1>; ++ regulator-ramp-delay = <12500>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-mode = <0x2>; ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <950000>; ++ }; ++ }; ++ ++ vcc_ddr: RK805_DCDC3 { ++ regulator-compatible = "RK805_DCDC3"; ++ regulator-name = "vcc_ddr"; ++ regulator-initial-mode = <0x1>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-mode = <0x2>; ++ regulator-on-in-suspend; ++ }; ++ }; ++ ++ vcc_io: RK805_DCDC4 { ++ regulator-compatible = "RK805_DCDC4"; ++ regulator-name = "vcc_io"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-initial-mode = <0x1>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-mode = <0x2>; ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3300000>; ++ }; ++ }; ++ ++ vcc_18: RK805_LDO1 { ++ regulator-compatible = "RK805_LDO1"; ++ regulator-name = "vcc_18"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vcc18_emmc: RK805_LDO2 { ++ regulator-compatible = "RK805_LDO2"; ++ regulator-name = "vcc18_emmc"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vdd_10: RK805_LDO3 { ++ regulator-compatible = "RK805_LDO3"; ++ regulator-name = "vdd_10"; ++ regulator-min-microvolt = <1000000>; ++ regulator-max-microvolt = <1000000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1000000>; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&i2s0 { ++ #sound-dai-cells = <0>; ++ rockchip,bclk-fs = <128>; ++ status = "okay"; ++}; ++ ++&io_domains { ++ status = "okay"; ++ ++ vccio1-supply = <&vcc_io>; ++ vccio2-supply = <&vcc18_emmc>; ++ vccio3-supply = <&vccio_sd>; ++ vccio4-supply = <&vcc_io>; ++ vccio5-supply = <&vcc_io>; ++ vccio6-supply = <&vcc_io>; ++ pmuio-supply = <&vcc_io>; ++}; ++ ++&pinctrl { ++ ir { ++ ir_int: ir-int { ++ rockchip,pins = <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ sd-pwerset { ++ sd_pwr_1800_sel: sd-pwr-1800-sel { ++ rockchip,pins = <0 RK_PD1 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ pmic { ++ pmic_int_l: pmic-int-l { ++ rockchip,pins = <1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++ ++ usb { ++ usb_host_drv: usb-host-drv { ++ rockchip,pins = <1 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++}; ++ ++&rkvdec { ++ status = "okay"; ++ vcodec-supply = <&vdd_logic>; ++}; ++ ++&rkvdec_mmu { ++ status = "okay"; ++}; ++ ++&sdmmc { ++ bus-width = <4>; ++ cap-mmc-highspeed; ++ cap-sd-highspeed; ++ disable-wp; ++ max-frequency = <100000000>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_dectn &sdmmc0_bus4>; ++ sd-uhs-sdr104; ++ supports-sd; ++ vmmc-supply = <&vcc_sd>; ++ vqmmc-supply = <&vccio_sd>; ++ status = "okay"; ++}; ++ ++&threshold { ++ temperature = <80000>; /* millicelsius */ ++}; ++ ++&target { ++ temperature = <95000>; /* millicelsius */ ++}; ++ ++&soc_crit { ++ temperature = <100000>; /* millicelsius */ ++}; ++ ++&tsadc { ++ rockchip,hw-tshut-mode = <0>; ++ rockchip,hw-tshut-polarity = <0>; ++ rockchip,hw-tshut-temp = <110000>; ++ status = "okay"; ++}; ++ ++&uart2 { ++ status = "okay"; ++}; ++ ++&u2phy { ++ status = "okay"; ++ ++}; ++ ++&u2phy_host { ++ phy-supply = <&vcc_host1_5v>; ++ status = "okay"; ++}; ++ ++&u2phy_otg { ++ phy-supply = <&vcc_otg_5v>; ++ status = "okay"; ++}; ++ ++&u3phy { ++ status = "okay"; ++}; ++ ++&u3phy_utmi { ++ phy-supply = <&vcc_host_5v>; ++ status = "okay"; ++}; ++ ++&u3phy_pipe { ++ phy-supply = <&vcc_host_5v>; ++ status = "okay"; ++}; ++ ++&usb20_otg { ++ dr_mode = "host"; ++ status = "okay"; ++}; ++ ++&usb_host0_ehci { ++ status = "okay"; ++}; ++ ++&usb_host0_ohci { ++ status = "okay"; ++}; ++ ++&usbdrd3 { ++ status = "okay"; ++}; ++ ++&usbdrd_dwc3 { ++ status = "okay"; ++}; ++ ++&vop { ++ status = "okay"; ++}; ++ ++&vop_mmu { ++ status = "okay"; ++}; ++ ++&vpu_service { ++ status = "okay"; ++}; ++ ++&vpu_mmu { ++ status = "okay"; ++}; ++ ++&vepu { ++ status = "okay"; ++}; ++ ++&vepu_mmu { ++ status = "okay"; ++}; ++ ++&venc_srv { ++ status = "okay"; ++}; + +From 1b76ca54016d0279669714bb1aba63fcb401cd97 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 3 Sep 2017 11:19:19 +0200 +Subject: [PATCH] arm64: dts: rockchip: rk3328-rock64: use two dai-link for i2s + sound + +--- + arch/arm64/boot/dts/rockchip/rk3328-rock64.dts | 26 +++++++++++++++++++++----- + sound/soc/soc-utils.c | 10 ++++++++++ + 2 files changed, 31 insertions(+), 5 deletions(-) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts +index 68795d255309..ea68f0a892bc 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts +@@ -127,6 +127,11 @@ + status = "okay"; + }; + ++ dummy_codec: dummy-codec { ++ compatible = "linux,snd-soc-dummy"; ++ #sound-dai-cells = <0>; ++ }; ++ + hdmi-sound { + compatible = "simple-audio-card"; + simple-audio-card,format = "i2s"; +@@ -142,14 +147,25 @@ + + sound { + compatible = "simple-audio-card"; +- simple-audio-card,format = "i2s"; + simple-audio-card,mclk-fs = <256>; + simple-audio-card,name = "I2S"; +- simple-audio-card,cpu { +- sound-dai = <&i2s1>; ++ simple-audio-card,dai-link@0 { ++ format = "i2s"; ++ cpu { ++ sound-dai = <&i2s1>; ++ }; ++ codec { ++ sound-dai = <&codec>; ++ }; + }; +- simple-audio-card,codec { +- sound-dai = <&codec>; ++ simple-audio-card,dai-link@1 { ++ format = "i2s"; ++ cpu { ++ sound-dai = <&i2s1>; ++ }; ++ codec { ++ sound-dai = <&dummy_codec>; ++ }; + }; + }; + +diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c +index 53dd085d3ee2..bf7ce34084a9 100644 +--- a/sound/soc/soc-utils.c ++++ b/sound/soc/soc-utils.c +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + + int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots) + { +@@ -160,9 +161,18 @@ static int snd_soc_dummy_remove(struct platform_device *pdev) + return 0; + } + ++#ifdef CONFIG_OF ++static const struct of_device_id soc_dummy_ids[] = { ++ { .compatible = "linux,snd-soc-dummy", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, soc_dummy_ids); ++#endif ++ + static struct platform_driver soc_dummy_driver = { + .driver = { + .name = "snd-soc-dummy", ++ .of_match_table = of_match_ptr(soc_dummy_ids), + }, + .probe = snd_soc_dummy_probe, + .remove = snd_soc_dummy_remove, + +From 8dcb6652da2094e4ae5e6b2e404d1c0c2bee3e7a Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Fri, 26 Jan 2018 00:03:46 +0100 +Subject: [PATCH] arm64: dts: rockchip: rk3328-roc-cc: disable sd-card voltage + select + +Voltage select should set GRF_SOC_CON10 bit 1, +vendor kernel repurpose GPIO0_D1 to signal this, +RK kernel uses GRF_SOC_CON10 bit 1 to mute avcodec. +--- + arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts | 12 +----------- + 1 file changed, 1 insertion(+), 11 deletions(-) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts +index cd0b377977ab..fadb35d978a9 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts +@@ -98,8 +98,6 @@ + gpios = <&gpio0 RK_PD1 GPIO_ACTIVE_HIGH>; + states = <1800000 0x1 + 3300000 0x0>; +- pinctrl-names = "default"; +- pinctrl-0 = <&sd_pwr_1800_sel>; + regulator-name = "vccio_sd"; + regulator-type = "voltage"; + regulator-min-microvolt = <1800000>; +@@ -426,12 +424,6 @@ + }; + }; + +- sd-pwerset { +- sd_pwr_1800_sel: sd-pwr-1800-sel { +- rockchip,pins = <0 RK_PD1 RK_FUNC_GPIO &pcfg_pull_none>; +- }; +- }; +- + pmic { + pmic_int_l: pmic-int-l { + rockchip,pins = <1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_up>; +@@ -459,13 +451,11 @@ + cap-mmc-highspeed; + cap-sd-highspeed; + disable-wp; +- max-frequency = <100000000>; ++ max-frequency = <150000000>; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_dectn &sdmmc0_bus4>; +- sd-uhs-sdr104; + supports-sd; + vmmc-supply = <&vcc_sd>; +- vqmmc-supply = <&vccio_sd>; + status = "okay"; + }; + + +From 4231b11639756b66c5f974fe894cbf74d5538187 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 28 Jan 2018 15:17:34 +0100 +Subject: [PATCH] arm64: dts: rockchip: add rk3399-sapphire board + +--- + arch/arm64/boot/dts/rockchip/rk3399-sapphire.dts | 142 +++++++++++++++++++++++ + 1 file changed, 142 insertions(+) + create mode 100644 arch/arm64/boot/dts/rockchip/rk3399-sapphire.dts + +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dts b/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dts +new file mode 100644 +index 000000000000..36613de5c68e +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dts +@@ -0,0 +1,142 @@ ++/* ++ * Copyright (c) 2016 Fuzhou Rockchip Electronics Co., Ltd ++ * ++ * This file is dual-licensed: you can use it either under the terms ++ * of the GPL or the X11 license, at your option. Note that this dual ++ * licensing only applies to this file, and not this project as a ++ * whole. ++ * ++ * a) This file 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 file is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * Or, alternatively, ++ * ++ * b) Permission is hereby granted, free of charge, to any person ++ * obtaining a copy of this software and associated documentation ++ * files (the "Software"), to deal in the Software without ++ * restriction, including without limitation the rights to use, ++ * copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following ++ * conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES ++ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT ++ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, ++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++/dts-v1/; ++ ++#include "rk3399-sapphire.dtsi" ++#include "rk3399-linux.dtsi" ++#include ++ ++/ { ++ model = "Rockchip RK3399 Sapphire Board"; ++ compatible = "rockchip,rk3399-sapphire", "rockchip,rk3399"; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ autorepeat; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pwrbtn>; ++ ++ button@0 { ++ gpios = <&gpio0 5 GPIO_ACTIVE_LOW>; ++ linux,code = ; ++ label = "GPIO Key Power"; ++ linux,input-type = <1>; ++ gpio-key,wakeup = <1>; ++ debounce-interval = <100>; ++ }; ++ }; ++ ++ vccadc_ref: vccadc-ref { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc1v8_sys"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ }; ++}; ++ ++&hdmi_sound { ++ simple-audio-card,mclk-fs = <128>; ++ simple-audio-card,name = "HDMI"; ++ status = "okay"; ++}; ++ ++&i2s2 { ++ #sound-dai-cells = <0>; ++ rockchip,bclk-fs = <128>; ++ status = "okay"; ++}; ++ ++&saradc { ++ vref-supply = <&vccadc_ref>; ++}; ++ ++&vpu { ++ status = "okay"; ++ /* 0 means ion, 1 means drm */ ++ //allocator = <0>; ++}; ++ ++&rkvdec { ++ status = "okay"; ++ /* 0 means ion, 1 means drm */ ++ //allocator = <0>; ++}; ++ ++&display_subsystem { ++ status = "okay"; ++}; ++ ++&hdmi { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ #sound-dai-cells = <0>; ++ status = "okay"; ++}; ++ ++&vopb { ++ status = "okay"; ++}; ++ ++&vopb_mmu { ++ status = "okay"; ++}; ++ ++&pinctrl { ++ sdio-pwrseq { ++ wifi_enable_h: wifi-enable-h { ++ rockchip,pins = ++ <0 10 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ buttons { ++ pwrbtn: pwrbtn { ++ rockchip,pins = <0 5 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++}; + +From 938db3e94ff5115d4882f444d1c791ce51fa7243 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 28 Jan 2018 15:17:53 +0100 +Subject: [PATCH] arm64: dts: rockchip: add rk3399-rock960 board + +--- + arch/arm64/boot/dts/rockchip/rk3399-rock960.dts | 983 ++++++++++++++++++++++++ + 1 file changed, 983 insertions(+) + create mode 100644 arch/arm64/boot/dts/rockchip/rk3399-rock960.dts + +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rock960.dts b/arch/arm64/boot/dts/rockchip/rk3399-rock960.dts +new file mode 100644 +index 000000000000..a5c906dd5961 +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/rk3399-rock960.dts +@@ -0,0 +1,983 @@ ++/* ++ * Copyright (c) 2016 Fuzhou Rockchip Electronics Co., Ltd ++ * ++ * This file is dual-licensed: you can use it either under the terms ++ * of the GPL or the X11 license, at your option. Note that this dual ++ * licensing only applies to this file, and not this project as a ++ * whole. ++ * ++ * a) This file 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 file is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * Or, alternatively, ++ * ++ * b) Permission is hereby granted, free of charge, to any person ++ * obtaining a copy of this software and associated documentation ++ * files (the "Software"), to deal in the Software without ++ * restriction, including without limitation the rights to use, ++ * copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following ++ * conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES ++ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT ++ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, ++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++/dts-v1/; ++ ++#include ++#include ++#include "rk3399.dtsi" ++#include "rk3399-linux.dtsi" ++#include "rk3399-opp.dtsi" ++ ++ ++/ { ++ model = "ROCK960"; ++ compatible = "96rocks,rock960", "rockchip,rk3399"; ++ ++ vcc1v8_s0: vcc1v8-s0 { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc1v8_s0"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ }; ++ ++ vcc_sys: vcc-sys { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc_sys"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ regulator-always-on; ++ }; ++ ++ vcc_phy: vcc-phy-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc_phy"; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ vcc3v3_sys: vcc3v3-sys { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc3v3_sys"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-always-on; ++ vin-supply = <&vcc_sys>; ++ }; ++ ++ vcc3v3_pcie: vcc3v3-pcie-regulator { ++ compatible = "regulator-fixed"; ++ gpio = <&gpio3 11 GPIO_ACTIVE_LOW>; ++ //gpio = <&gpio3 8 GPIO_ACTIVE_LOW>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pcie_drv>; ++ regulator-boot-on; ++ regulator-name = "vcc3v3_pcie"; ++ vin-supply = <&vcc3v3_sys>; ++ startup-delay-us = <70000>; ++ }; ++ ++ vcc5v0_host: vcc5v0-host-regulator { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio4 25 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&host_vbus_drv>; ++ regulator-name = "vcc5v0_host"; ++ regulator-always-on; ++ }; ++ ++ vdd_log: vdd-log { ++ compatible = "pwm-regulator"; ++ pwms = <&pwm2 0 25000 1>; ++ regulator-name = "vdd_log"; ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <1400000>; ++ regulator-always-on; ++ regulator-boot-on; ++ ++ /* for rockchip boot on */ ++ rockchip,pwm_id= <2>; ++ rockchip,pwm_voltage = <900000>; ++ ++ vin-supply = <&vcc_sys>; ++ }; ++ ++ clkin_gmac: external-gmac-clock { ++ compatible = "fixed-clock"; ++ clock-frequency = <125000000>; ++ clock-output-names = "clkin_gmac"; ++ #clock-cells = <0>; ++ }; ++ ++ hdmi-sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,format = "i2s"; ++ simple-audio-card,mclk-fs = <128>; ++ simple-audio-card,name = "HDMI"; ++ simple-audio-card,cpu { ++ sound-dai = <&i2s2>; ++ }; ++ simple-audio-card,codec { ++ sound-dai = <&hdmi>; ++ }; ++ }; ++ ++ spdif-sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,name = "SPDIF"; ++ simple-audio-card,cpu { ++ sound-dai = <&spdif>; ++ }; ++ simple-audio-card,codec { ++ sound-dai = <&spdif_out>; ++ }; ++ }; ++ ++ spdif_out: spdif-out { ++ compatible = "linux,spdif-dit"; ++ #sound-dai-cells = <0>; ++ }; ++ ++ sdio_pwrseq: sdio-pwrseq { ++ compatible = "mmc-pwrseq-simple"; ++ clocks = <&rk808 1>; ++ clock-names = "ext_clock"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&wifi_enable_h>; ++ post-power-on-delay-ms = <200>; ++ power-off-delay-us = <10>; ++ ++ /* ++ * On the module itself this is one of these (depending ++ * on the actual card populated): ++ * - SDIO_RESET_L_WL_REG_ON ++ * - PDN (power down when low) ++ */ ++ reset-gpios = <&gpio0 10 GPIO_ACTIVE_LOW>; ++ }; ++ ++ wireless-wlan { ++ compatible = "wlan-platdata"; ++ rockchip,grf = <&grf>; ++ wifi_chip_type = "ap6354"; ++ sdio_vref = <1800>; ++ WIFI,host_wake_irq = <&gpio0 3 GPIO_ACTIVE_HIGH>; ++ status = "okay"; ++ }; ++ ++ wireless-bluetooth { ++ compatible = "bluetooth-platdata"; ++ clocks = <&rk808 1>; ++ clock-names = "ext_clock"; ++ /* wifi-bt-power-toggle; */ ++ uart_rts_gpios = <&gpio2 19 GPIO_ACTIVE_LOW>; ++ pinctrl-names = "default", "rts_gpio"; ++ pinctrl-0 = <&uart0_rts>; ++ pinctrl-1 = <&uart0_gpios>; ++ /* BT,power_gpio = <&gpio3 19 GPIO_ACTIVE_HIGH>; */ ++ BT,reset_gpio = <&gpio0 9 GPIO_ACTIVE_HIGH>; ++ BT,wake_gpio = <&gpio2 27 GPIO_ACTIVE_HIGH>; ++ BT,wake_host_irq = <&gpio0 4 GPIO_ACTIVE_HIGH>; ++ status = "okay"; ++ }; ++ ++ test-power { ++ status = "okay"; ++ }; ++}; ++ ++&hdmi { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ #sound-dai-cells = <0>; ++ status = "okay"; ++}; ++ ++&sdmmc { ++ clock-frequency = <100000000>; ++ clock-freq-min-max = <100000 100000000>; ++ supports-sd; ++ bus-width = <4>; ++ cap-mmc-highspeed; ++ cap-sd-highspeed; ++ disable-wp; ++ num-slots = <1>; ++ //sd-uhs-sdr104; ++ vqmmc-supply = <&vcc_sd>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd &sdmmc_bus4>; ++ card-detect-delay = <800>; ++ status = "okay"; ++}; ++ ++&sdio0 { ++ clock-frequency = <100000000>; ++ clock-freq-min-max = <200000 100000000>; ++ supports-sdio; ++ bus-width = <4>; ++ disable-wp; ++ cap-sd-highspeed; ++ cap-sdio-irq; ++ keep-power-in-suspend; ++ mmc-pwrseq = <&sdio_pwrseq>; ++ non-removable; ++ num-slots = <1>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdio0_bus4 &sdio0_cmd &sdio0_clk>; ++ sd-uhs-sdr104; ++ status = "okay"; ++}; ++ ++&emmc_phy { ++ status = "okay"; ++}; ++ ++&sdhci { ++ bus-width = <8>; ++ mmc-hs400-1_8v; ++ supports-emmc; ++ non-removable; ++ mmc-hs400-enhanced-strobe; ++ status = "okay"; ++}; ++ ++&i2s0 { ++ status = "okay"; ++ rockchip,i2s-broken-burst-len; ++ rockchip,playback-channels = <8>; ++ rockchip,capture-channels = <8>; ++ #sound-dai-cells = <0>; ++}; ++ ++&i2s2 { ++ #sound-dai-cells = <0>; ++ rockchip,bclk-fs = <128>; ++ status = "okay"; ++}; ++ ++&spdif { ++ pinctrl-0 = <&spdif_bus_1>; ++ status = "okay"; ++ #sound-dai-cells = <0>; ++}; ++ ++&i2c0 { ++ status = "okay"; ++ i2c-scl-rising-time-ns = <168>; ++ i2c-scl-falling-time-ns = <4>; ++ clock-frequency = <400000>; ++ ++ vdd_cpu_b: syr827@40 { ++ compatible = "silergy,syr827"; ++ reg = <0x40>; ++ regulator-compatible = "fan53555-reg"; ++ pinctrl-0 = <&vsel1_gpio>; ++ vsel-gpios = <&gpio1 17 GPIO_ACTIVE_HIGH>; ++ regulator-name = "vdd_cpu_b"; ++ regulator-min-microvolt = <712500>; ++ regulator-max-microvolt = <1500000>; ++ regulator-ramp-delay = <1000>; ++ fcs,suspend-voltage-selector = <1>; ++ regulator-always-on; ++ regulator-boot-on; ++ vin-supply = <&vcc_sys>; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_gpu: syr828@41 { ++ compatible = "silergy,syr828"; ++ reg = <0x41>; ++ regulator-compatible = "fan53555-reg"; ++ pinctrl-0 = <&vsel2_gpio>; ++ vsel-gpios = <&gpio1 14 GPIO_ACTIVE_HIGH>; ++ regulator-name = "vdd_gpu"; ++ regulator-min-microvolt = <712500>; ++ regulator-max-microvolt = <1500000>; ++ regulator-ramp-delay = <1000>; ++ fcs,suspend-voltage-selector = <1>; ++ regulator-always-on; ++ regulator-boot-on; ++ vin-supply = <&vcc_sys>; ++ regulator-initial-mode = <1>; /* 1:force PWM 2:auto */ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ rk808: pmic@1b { ++ compatible = "rockchip,rk808"; ++ reg = <0x1b>; ++ interrupt-parent = <&gpio1>; ++ interrupts = <21 IRQ_TYPE_LEVEL_LOW>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pmic_int_l>; ++ rockchip,system-power-controller; ++ wakeup-source; ++ #clock-cells = <1>; ++ clock-output-names = "xin32k", "rk808-clkout2"; ++ ++ vcc1-supply = <&vcc_sys>; ++ vcc2-supply = <&vcc_sys>; ++ vcc3-supply = <&vcc_sys>; ++ vcc4-supply = <&vcc_sys>; ++ vcc6-supply = <&vcc_sys>; ++ vcc7-supply = <&vcc_sys>; ++ vcc8-supply = <&vcc3v3_sys>; ++ vcc9-supply = <&vcc_sys>; ++ vcc10-supply = <&vcc_sys>; ++ vcc11-supply = <&vcc_sys>; ++ vcc12-supply = <&vcc3v3_sys>; ++ vddio-supply = <&vcc_1v8>; ++ ++ regulators { ++ vdd_center: DCDC_REG1 { ++ regulator-name = "vdd_center"; ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <1350000>; ++ regulator-ramp-delay = <6001>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_cpu_l: DCDC_REG2 { ++ regulator-name = "vdd_cpu_l"; ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <1350000>; ++ regulator-ramp-delay = <6001>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_ddr: DCDC_REG3 { ++ regulator-name = "vcc_ddr"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ }; ++ }; ++ ++ vcc_1v8: DCDC_REG4 { ++ regulator-name = "vcc_1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vcc1v8_dvp: LDO_REG1 { ++ regulator-name = "vcc1v8_dvp"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vcca1v8_hdmi: LDO_REG2 { ++ regulator-name = "vcca1v8_hdmi"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vcca_1v8: LDO_REG3 { ++ regulator-name = "vcca_1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vcc_sd: LDO_REG4 { ++ regulator-name = "vcc_sd"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3300000>; ++ }; ++ }; ++ ++ vcc3v0_sd: LDO_REG5 { ++ regulator-name = "vcc3v0_sd"; ++ regulator-min-microvolt = <3000000>; ++ regulator-max-microvolt = <3000000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3000000>; ++ }; ++ }; ++ ++ vcc_1v5: LDO_REG6 { ++ regulator-name = "vcc_1v5"; ++ regulator-min-microvolt = <1500000>; ++ regulator-max-microvolt = <1500000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1500000>; ++ }; ++ }; ++ ++ vcca0v9_hdmi: LDO_REG7 { ++ regulator-name = "vcca0v9_hdmi"; ++ regulator-min-microvolt = <900000>; ++ regulator-max-microvolt = <900000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <900000>; ++ }; ++ }; ++ ++ vcc_3v0: LDO_REG8 { ++ regulator-name = "vcc_3v0"; ++ regulator-min-microvolt = <3000000>; ++ regulator-max-microvolt = <3000000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3000000>; ++ }; ++ }; ++ ++ vcc3v3_s3: SWITCH_REG1 { ++ regulator-name = "vcc3v3_s3"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ }; ++ }; ++ ++ vcc3v3_s0: SWITCH_REG2 { ++ regulator-name = "vcc3v3_s0"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&i2c1 { ++ status = "okay"; ++}; ++ ++&i2c7 { ++ status = "okay"; ++}; ++ ++&i2c4 { ++ status = "okay"; ++ fusb0: fusb30x@22 { ++ compatible = "fairchild,fusb302"; ++ reg = <0x22>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&fusb0_int>; ++ vbus-5v-gpios = <&gpio1 3 GPIO_ACTIVE_LOW>; ++ int-n-gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>; ++ status = "okay"; ++ }; ++}; ++ ++&i2c2 { ++ status = "okay"; ++ camera0: camera-module@10 { ++ status = "disabled"; ++ compatible = "omnivision,ov13850-v4l2-i2c-subdev"; ++ reg = < 0x10 >; ++ device_type = "v4l2-i2c-subdev"; ++ clocks = <&cru SCLK_CIF_OUT>; ++ clock-names = "clk_cif_out"; ++ pinctrl-names = "rockchip,camera_default", ++ "rockchip,camera_sleep"; ++ pinctrl-0 = <&cam0_default_pins>; ++ pinctrl-1 = <&cam0_sleep_pins>; ++ //rockchip,pd-gpio = <&gpio4 4 GPIO_ACTIVE_LOW>; ++ rockchip,pwr-gpio = <&gpio4 4 GPIO_ACTIVE_HIGH>; ++ rockchip,rst-gpio = <&gpio3 29 GPIO_ACTIVE_LOW>; ++ rockchip,camera-module-mclk-name = "clk_cif_out"; ++ rockchip,camera-module-facing = "back"; ++ rockchip,camera-module-name = "cmk-cb0695-fv1"; ++ rockchip,camera-module-len-name = "lg9569a2"; ++ rockchip,camera-module-fov-h = "66.0"; ++ rockchip,camera-module-fov-v = "50.1"; ++ rockchip,camera-module-orientation = <0>; ++ rockchip,camera-module-iq-flip = <0>; ++ rockchip,camera-module-iq-mirror = <0>; ++ rockchip,camera-module-flip = <1>; ++ rockchip,camera-module-mirror = <0>; ++ ++ rockchip,camera-module-defrect0 = <2112 1568 0 0 2112 1568>; ++ rockchip,camera-module-defrect1 = <4224 3136 0 0 4224 3136>; ++ rockchip,camera-module-defrect3 = <3264 2448 0 0 3264 2448>; ++ rockchip,camera-module-flash-support = <1>; ++ rockchip,camera-module-mipi-dphy-index = <0>; ++ }; ++ ++ camera1: camera-module@36 { ++ status = "disabled"; ++ compatible = "omnivision,ov4690-v4l2-i2c-subdev"; ++ reg = <0x36>; ++ device_type = "v4l2-i2c-subdev"; ++ clocks = <&cru SCLK_CIF_OUT>; ++ clock-names = "clk_cif_out"; ++ pinctrl-names = "rockchip,camera_default", ++ "rockchip,camera_sleep"; ++ pinctrl-0 = <&cam0_default_pins>; ++ pinctrl-1 = <&cam0_sleep_pins>; ++ rockchip,pd-gpio = <&gpio3 4 GPIO_ACTIVE_LOW>; ++ //rockchip,pwr-gpio = <&gpio3 13 0>; ++ rockchip,rst-gpio = <&gpio2 10 GPIO_ACTIVE_LOW>; ++ rockchip,camera-module-mclk-name = "clk_cif_out"; ++ rockchip,camera-module-facing = "back"; ++ rockchip,camera-module-name = "LA6111PA"; ++ rockchip,camera-module-len-name = "YM6011P"; ++ rockchip,camera-module-fov-h = "116"; ++ rockchip,camera-module-fov-v = "61"; ++ rockchip,camera-module-orientation = <0>; ++ rockchip,camera-module-iq-flip = <0>; ++ rockchip,camera-module-iq-mirror = <0>; ++ rockchip,camera-module-flip = <0>; ++ rockchip,camera-module-mirror = <1>; ++ ++ rockchip,camera-module-defrect0 = <2688 1520 0 0 2688 1520>; ++ rockchip,camera-module-flash-support = <0>; ++ rockchip,camera-module-mipi-dphy-index = <0>; ++ }; ++ ++}; ++ ++&i2c7 { ++ status = "okay"; ++}; ++ ++&cpu_l0 { ++ cpu-supply = <&vdd_cpu_l>; ++}; ++ ++&cpu_l1 { ++ cpu-supply = <&vdd_cpu_l>; ++}; ++ ++&cpu_l2 { ++ cpu-supply = <&vdd_cpu_l>; ++}; ++ ++&cpu_l3 { ++ cpu-supply = <&vdd_cpu_l>; ++}; ++ ++&cpu_b0 { ++ cpu-supply = <&vdd_cpu_b>; ++}; ++ ++&cpu_b1 { ++ cpu-supply = <&vdd_cpu_b>; ++}; ++ ++&gpu { ++ status = "okay"; ++ mali-supply = <&vdd_gpu>; ++}; ++ ++&threshold { ++ temperature = <85000>; ++}; ++ ++&target { ++ temperature = <100000>; ++}; ++ ++&soc_crit { ++ temperature = <105000>; ++}; ++ ++&tcphy0 { ++ extcon = <&fusb0>; ++ status = "okay"; ++}; ++ ++&tcphy1 { ++ status = "okay"; ++}; ++ ++&tsadc { ++ /* tshut mode 0:CRU 1:GPIO */ ++ rockchip,hw-tshut-mode = <1>; ++ /* tshut polarity 0:LOW 1:HIGH */ ++ rockchip,hw-tshut-polarity = <1>; ++ rockchip,hw-tshut-temp = <110000>; ++ status = "okay"; ++}; ++ ++&u2phy0 { ++ status = "okay"; ++ extcon = <&fusb0>; ++ ++ u2phy0_otg: otg-port { ++ status = "okay"; ++ }; ++ ++ u2phy0_host: host-port { ++ phy-supply = <&vcc5v0_host>; ++ status = "okay"; ++ }; ++}; ++ ++&u2phy1 { ++ status = "okay"; ++ ++ u2phy1_otg: otg-port { ++ status = "okay"; ++ }; ++ ++ u2phy1_host: host-port { ++ phy-supply = <&vcc5v0_host>; ++ status = "okay"; ++ }; ++}; ++ ++&uart0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart0_xfer &uart0_cts>; ++ status = "okay"; ++}; ++ ++&uart2 { ++ status = "okay"; ++}; ++ ++&usb_host0_ehci { ++ status = "okay"; ++}; ++ ++&usb_host0_ohci { ++ status = "okay"; ++}; ++ ++&usb_host1_ehci { ++ status = "okay"; ++}; ++ ++&usb_host1_ohci { ++ status = "okay"; ++}; ++ ++&usbdrd3_0 { ++ extcon = <&fusb0>; ++ status = "okay"; ++}; ++ ++&usbdrd_dwc3_0 { ++ dr_mode = "otg"; ++ status = "okay"; ++}; ++ ++&usbdrd3_1 { ++ status = "okay"; ++}; ++ ++&usbdrd_dwc3_1 { ++ dr_mode = "host"; ++ status = "okay"; ++}; ++ ++&pwm2 { ++ status = "okay"; ++}; ++ ++&gmac { ++ phy-supply = <&vcc_phy>; ++ phy-mode = "rgmii"; ++ clock_in_out = "input"; ++ snps,reset-gpio = <&gpio3 15 GPIO_ACTIVE_LOW>; ++ snps,reset-active-low; ++ snps,reset-delays-us = <0 10000 50000>; ++ assigned-clocks = <&cru SCLK_RMII_SRC>; ++ assigned-clock-parents = <&clkin_gmac>; ++ pinctrl-names = "default", "sleep"; ++ pinctrl-0 = <&rgmii_pins>; ++ pinctrl-1 = <&rgmii_sleep_pins>; ++ tx_delay = <0x28>; ++ rx_delay = <0x11>; ++ status = "disabled"; ++}; ++ ++&saradc { ++ status = "okay"; ++}; ++ ++&io_domains { ++ status = "okay"; ++ ++ bt656-supply = <&vcc1v8_s0>; /* bt656_gpio2ab_ms */ ++ audio-supply = <&vcc1v8_s0>; /* audio_gpio3d4a_ms */ ++ sdmmc-supply = <&vcc_sd>; /* sdmmc_gpio4b_ms */ ++ gpio1830-supply = <&vcc_3v0>; /* gpio1833_gpio4cd_ms */ ++}; ++ ++&pcie_phy { ++ status = "okay"; ++}; ++ ++&pcie0 { ++ ep-gpios = <&gpio3 9 GPIO_ACTIVE_HIGH>; ++ num-lanes = <4>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pcie_clkreqn_cpm>; ++ status = "okay"; ++}; ++ ++&pinctrl { ++ ++ sdio0 { ++ sdio0_bus1: sdio0-bus1 { ++ rockchip,pins = ++ <2 20 RK_FUNC_1 &pcfg_pull_up_20ma>; ++ }; ++ ++ sdio0_bus4: sdio0-bus4 { ++ rockchip,pins = ++ <2 20 RK_FUNC_1 &pcfg_pull_up_20ma>, ++ <2 21 RK_FUNC_1 &pcfg_pull_up_20ma>, ++ <2 22 RK_FUNC_1 &pcfg_pull_up_20ma>, ++ <2 23 RK_FUNC_1 &pcfg_pull_up_20ma>; ++ }; ++ ++ sdio0_cmd: sdio0-cmd { ++ rockchip,pins = ++ <2 24 RK_FUNC_1 &pcfg_pull_up_20ma>; ++ }; ++ ++ sdio0_clk: sdio0-clk { ++ rockchip,pins = ++ <2 25 RK_FUNC_1 &pcfg_pull_none_20ma>; ++ }; ++ }; ++ ++ sdmmc { ++ sdmmc_bus1: sdmmc-bus1 { ++ rockchip,pins = ++ <4 8 RK_FUNC_1 &pcfg_pull_up_8ma>; ++ }; ++ ++ sdmmc_bus4: sdmmc-bus4 { ++ rockchip,pins = ++ <4 8 RK_FUNC_1 &pcfg_pull_up_8ma>, ++ <4 9 RK_FUNC_1 &pcfg_pull_up_8ma>, ++ <4 10 RK_FUNC_1 &pcfg_pull_up_8ma>, ++ <4 11 RK_FUNC_1 &pcfg_pull_up_8ma>; ++ }; ++ ++ sdmmc_clk: sdmmc-clk { ++ rockchip,pins = ++ <4 12 RK_FUNC_1 &pcfg_pull_none_18ma>; ++ }; ++ ++ sdmmc_cmd: sdmmc-cmd { ++ rockchip,pins = ++ <4 13 RK_FUNC_1 &pcfg_pull_up_8ma>; ++ }; ++ }; ++ ++ sdio-pwrseq { ++ wifi_enable_h: wifi-enable-h { ++ rockchip,pins = ++ <0 9 RK_FUNC_GPIO &pcfg_pull_none>, ++ <0 10 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ wireless-bluetooth { ++ uart0_gpios: uart0-gpios { ++ rockchip,pins = ++ <2 19 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ usb2 { ++ host_vbus_drv: host-vbus-drv { ++ rockchip,pins = ++ <4 25 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ pcie { ++ pcie_drv: pcie-drv { ++ rockchip,pins = ++ <3 11 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ pmic { ++ pmic_int_l: pmic-int-l { ++ rockchip,pins = ++ <1 21 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ ++ vsel1_gpio: vsel1-gpio { ++ rockchip,pins = ++ <1 17 RK_FUNC_GPIO &pcfg_pull_down>; ++ }; ++ ++ vsel2_gpio: vsel2-gpio { ++ rockchip,pins = ++ <1 14 RK_FUNC_GPIO &pcfg_pull_down>; ++ }; ++ }; ++ ++ gmac { ++ rgmii_sleep_pins: rgmii-sleep-pins { ++ rockchip,pins = ++ <3 15 RK_FUNC_GPIO &pcfg_output_low>; ++ }; ++ }; ++ ++ fusb30x { ++ fusb0_int: fusb0-int { ++ rockchip,pins = ++ <1 2 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++}; ++ ++&pvtm { ++ status = "okay"; ++}; ++ ++&pmu_pvtm { ++ status = "okay"; ++}; ++ ++&pmu_io_domains { ++ status = "okay"; ++ pmu1830-supply = <&vcc_1v8>; ++}; ++ ++&rockchip_suspend { ++ status = "okay"; ++ rockchip,sleep-debug-en = <0>; ++ rockchip,sleep-mode-config = < ++ (0 ++ | RKPM_SLP_ARMPD ++ | RKPM_SLP_PERILPPD ++ | RKPM_SLP_DDR_RET ++ | RKPM_SLP_PLLPD ++ | RKPM_SLP_CENTER_PD ++ | RKPM_SLP_AP_PWROFF ++ ) ++ >; ++ rockchip,wakeup-config = < ++ (0 ++ | RKPM_GPIO_WKUP_EN ++ | RKPM_PWM_WKUP_EN ++ ) ++ >; ++ rockchip,pwm-regulator-config = < ++ (0 ++ | PWM2_REGULATOR_EN ++ ) ++ >; ++ rockchip,power-ctrl = ++ <&gpio1 17 GPIO_ACTIVE_HIGH>, ++ <&gpio1 14 GPIO_ACTIVE_HIGH>; ++}; ++ ++&vopb { ++ status = "okay"; ++}; ++ ++&vopb_mmu { ++ status = "okay"; ++}; ++ ++&cif_isp0 { ++ rockchip,camera-modules-attached = <&camera0>; ++ status = "okay"; ++}; ++ ++&isp0_mmu { ++ status = "okay"; ++}; ++ ++&cif_isp1 { ++ rockchip,camera-modules-attached = <&camera1>; ++ status = "disabled"; ++}; ++ ++&isp1_mmu { ++ status = "okay"; ++}; ++ ++&vpu { ++ status = "okay"; ++ /* 0 means ion, 1 means drm */ ++ //allocator = <0>; ++}; ++ ++&rkvdec { ++ status = "okay"; ++ /* 0 means ion, 1 means drm */ ++ //allocator = <0>; ++}; ++ ++&display_subsystem { ++ status = "okay"; ++}; + +From 7134a982d5f5f6995cc06e5ea4c0ee452111bb91 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 28 Jan 2018 15:38:32 +0100 +Subject: [PATCH] arm: dts: rk3288: add cec clock and pinctrl + +--- + arch/arm/boot/dts/rk3288.dtsi | 16 +++++++++++++--- + 1 file changed, 13 insertions(+), 3 deletions(-) + +diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi +index 54b785278956..e3e3a58bb91e 100644 +--- a/arch/arm/boot/dts/rk3288.dtsi ++++ b/arch/arm/boot/dts/rk3288.dtsi +@@ -981,6 +981,8 @@ + <&cru PCLK_MIPI_DSI1>, + <&cru SCLK_EDP_24M>, + <&cru SCLK_EDP>, ++ <&cru SCLK_HDMI_CEC>, ++ <&cru SCLK_HDMI_HDCP>, + <&cru SCLK_ISP_JPE>, + <&cru SCLK_ISP>, + <&cru SCLK_RGA>; +@@ -1579,10 +1581,10 @@ + reg-io-width = <4>; + rockchip,grf = <&grf>; + interrupts = ; +- clocks = <&cru PCLK_HDMI_CTRL>, <&cru SCLK_HDMI_HDCP>; +- clock-names = "iahb", "isfr"; ++ clocks = <&cru PCLK_HDMI_CTRL>, <&cru SCLK_HDMI_HDCP>, <&cru SCLK_HDMI_CEC>; ++ clock-names = "iahb", "isfr", "cec"; + pinctrl-names = "default", "sleep"; +- pinctrl-0 = <&hdmi_ddc>; ++ pinctrl-0 = <&hdmi_ddc>, <&hdmi_cec_c0>; + pinctrl-1 = <&hdmi_gpio>; + power-domains = <&power RK3288_PD_VIO>; + status = "disabled"; +@@ -1966,6 +1968,14 @@ + &pcfg_pull_none>; + }; + ++ hdmi_cec_c0: hdmi-cec-c0 { ++ rockchip,pins = <7 16 RK_FUNC_2 &pcfg_pull_none>; ++ }; ++ ++ hdmi_cec_c7: hdmi-cec-c7 { ++ rockchip,pins = <7 23 RK_FUNC_4 &pcfg_pull_none>; ++ }; ++ + hdmi_ddc: hdmi-ddc { + rockchip,pins = <7 19 RK_FUNC_2 &pcfg_pull_none>, + <7 20 RK_FUNC_2 &pcfg_pull_none>; + +From 967a4f3c204ebd98c2b8d5f4f363629b62fd1870 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Wed, 14 Feb 2018 08:03:12 +0100 +Subject: [PATCH] arm64: dts: rockchip: add rk3399-odroidn1 board + +--- + arch/arm64/boot/dts/rockchip/rk3399-odroidn1.dts | 1005 ++++++++++++++++++++++ + 1 file changed, 1005 insertions(+) + create mode 100644 arch/arm64/boot/dts/rockchip/rk3399-odroidn1.dts + +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-odroidn1.dts b/arch/arm64/boot/dts/rockchip/rk3399-odroidn1.dts +new file mode 100644 +index 000000000000..1bff86c2bf03 +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/rk3399-odroidn1.dts +@@ -0,0 +1,1005 @@ ++/* ++ * Copyright (c) 2017 Hardkernel Co., Ltd ++ * ++ * This file is dual-licensed: you can use it either under the terms ++ * of the GPL or the X11 license, at your option. Note that this dual ++ * licensing only applies to this file, and not this project as a ++ * whole. ++ * ++ * a) This file 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 file is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * Or, alternatively, ++ * ++ * b) Permission is hereby granted, free of charge, to any person ++ * obtaining a copy of this software and associated documentation ++ * files (the "Software"), to deal in the Software without ++ * restriction, including without limitation the rights to use, ++ * copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following ++ * conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES ++ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT ++ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, ++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++/dts-v1/; ++ ++#include "dt-bindings/pwm/pwm.h" ++#include "rk3399.dtsi" ++#include "rk3399-opp.dtsi" ++#include "rk3399-linux.dtsi" ++#include ++ ++/ { ++ model = "Hardkernel ODROID-N1"; ++ compatible = "hardkernel,odroidn1", "rockchip,rk3399"; ++ ++ cpuinfo { ++ compatible = "rockchip,cpuinfo"; ++ nvmem-cells = <&efuse_id>; ++ nvmem-cell-names = "id"; ++ }; ++ ++ clkin_gmac: external-gmac-clock { ++ compatible = "fixed-clock"; ++ clock-frequency = <125000000>; ++ clock-output-names = "clkin_gmac"; ++ #clock-cells = <0>; ++ }; ++ ++ leds: gpio_leds { ++ compatible = "gpio-leds"; ++ pinctrl-names = "led_pins"; ++ pinctrl-0 = <&led_pins>; ++ ++ heartbeat { ++ label = "blue:heartbeat"; ++ gpios = <&gpio4 26 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "heartbeat"; ++ }; ++ }; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ autorepeat; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pwrbtn>; ++ ++ button@0 { ++ gpios = <&gpio0 5 GPIO_ACTIVE_LOW>; ++ linux,code = ; ++ label = "GPIO Key Power"; ++ linux,input-type = <1>; ++ gpio-key,wakeup = <1>; ++ debounce-interval = <100>; ++ }; ++ }; ++ ++ gpio-restart { ++ compatible = "gpio-restart"; ++ gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>; ++ open-source; ++ priority = <255>; /* Highest priority */ ++ }; ++ ++ gpiomem { ++ compatible = "rockchip,rock-gpiomem"; ++ ++ /* gpio mmap area define */ ++ /* GPIO0 64K : 0xff720000 - 0xff72ffff */ ++ /* GPIO1 64K : 0xff730000 - 0xff73ffff */ ++ /* Reserved 64K : 0xff740000 - 0xff74ffff */ ++ /* PMUCRU 64K : 0xff750000 - 0xff75ffff */ ++ /* CRU 64K : 0xff760000 - 0xff76ffff */ ++ /* GRF 64K : 0xff770000 - 0xff77ffff */ ++ /* GPIO2 32K : 0xff780000 - 0xff777fff */ ++ /* GPIO3 32K : 0xff788000 - 0xff78ffff */ ++ /* GPIO4 32K : 0xff790000 - 0xff797fff */ ++ reg = <0 0xff720000 0 0x78000>, ++ ++ /* PMUGRF 64K : 0xff320000 - 0xff32ffff */ ++ <0 0xff320000 0 0x10000>; ++ status = "okay"; ++ }; ++ ++ fan0: pwm-fan { ++ compatible = "pwm-fan"; ++ status = "okay"; ++ pwms = <&pwm0 0 40000 PWM_POLARITY_INVERTED>; /* 25 kHz */ ++ ++ cooling-min-state = <0>; ++ cooling-max-state = <3>; ++ #cooling-cells = <2>; ++ cooling-levels = <255 125 102 51>; /* PWM duty cycle */ ++ }; ++ ++ hdmi-sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,format = "i2s"; ++ simple-audio-card,mclk-fs = <128>; ++ simple-audio-card,name = "HDMI"; ++ ++ simple-audio-card,cpu { ++ sound-dai = <&i2s2>; ++ }; ++ ++ simple-audio-card,codec { ++ sound-dai = <&hdmi>; ++ }; ++ }; ++ ++ vccadc_ref: vccadc-ref { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc1v8_sys"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ }; ++ ++ vcc3v3_sys: vcc3v3-sys { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc3v3_sys"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ }; ++ ++ vcc5v0_host: vcc5v0-host-regulator { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio4 25 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&host_vbus_drv>; ++ regulator-name = "vcc5v0_host"; ++ regulator-always-on; ++ }; ++ ++ vcc5v0_host31: vcc5v0-host31-regulator { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio0 12 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&host31_vbus_drv>; ++ regulator-name = "vcc5v0_host31"; ++ }; ++ ++ vcc5v0_host32: vcc5v0-host32-regulator { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio0 13 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&host32_vbus_drv>; ++ regulator-name = "vcc5v0_host32"; ++ }; ++ ++ vcc5v0_sys: vcc5v0-sys { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc5v0_sys"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ }; ++ ++ vcc_phy: vcc-phy-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc_phy"; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ vdd_log: vdd-log { ++ compatible = "pwm-regulator"; ++ pwms = <&pwm2 0 25000 1>; ++ regulator-name = "vdd_log"; ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <1400000>; ++ regulator-always-on; ++ regulator-boot-on; ++ ++ /* for rockchip boot on */ ++ rockchip,pwm_id= <2>; ++ rockchip,pwm_voltage = <1000000>; ++ }; ++ ++ odroid_sysfs: odroid-sysfs { ++ status = "okay"; ++ compatible = "odroid-sysfs"; ++ }; ++}; ++ ++&cluster0_opp { ++ opp-408000000 { ++ opp-microvolt = <800000>; ++ }; ++ opp-600000000 { ++ opp-microvolt = <800000>; ++ }; ++ opp-816000000 { ++ opp-microvolt = <850000>; ++ }; ++ opp-1008000000 { ++ opp-microvolt = <925000>; ++ }; ++ opp-1200000000 { ++ opp-microvolt = <1000000>; ++ }; ++ opp-1416000000 { ++ opp-microvolt = <1125000>; ++ }; ++ opp-1512000000 { ++ opp-hz = /bits/ 64 <1512000000>; ++ opp-microvolt = <1200000>; ++ opp-microvolt-L0 = <1200000>; ++ opp-microvolt-L1 = <1175000>; ++ opp-microvolt-L2 = <1150000>; ++ opp-microvolt-L3 = <1125000>; ++ clock-latency-ns = <40000>; ++ }; ++}; ++ ++&cluster1_opp { ++ opp-408000000 { ++ opp-microvolt = <800000>; ++ }; ++ opp-600000000 { ++ opp-microvolt = <800000>; ++ }; ++ opp-816000000 { ++ opp-microvolt = <825000>; ++ }; ++ opp-1008000000 { ++ opp-microvolt = <875000>; ++ }; ++ opp-1200000000 { ++ opp-microvolt = <950000>; ++ }; ++ opp-1416000000 { ++ opp-microvolt = <1025000>; ++ }; ++ opp-1608000000 { ++ opp-microvolt = <1100000>; ++ }; ++ opp-1800000000 { ++ opp-microvolt = <1200000>; ++ }; ++ opp-1992000000 { ++ opp-hz = /bits/ 64 <1992000000>; ++ opp-microvolt = <1300000>; ++ opp-microvolt-L0 = <1300000>; ++ opp-microvolt-L1 = <1275000>; ++ opp-microvolt-L2 = <1250000>; ++ opp-microvolt-L3 = <1225000>; ++ clock-latency-ns = <40000>; ++ }; ++}; ++ ++&cpu_l0 { ++ cpu-supply = <&vdd_cpu_l>; ++}; ++ ++&cpu_l1 { ++ cpu-supply = <&vdd_cpu_l>; ++}; ++ ++&cpu_l2 { ++ cpu-supply = <&vdd_cpu_l>; ++}; ++ ++&cpu_l3 { ++ cpu-supply = <&vdd_cpu_l>; ++}; ++ ++&cpu_b0 { ++ cpu-supply = <&vdd_cpu_b>; ++}; ++ ++&cpu_b1 { ++ cpu-supply = <&vdd_cpu_b>; ++}; ++ ++&display_subsystem { ++ status = "okay"; ++}; ++ ++&emmc_phy { ++ status = "okay"; ++}; ++ ++&gmac { ++ phy-supply = <&vcc_phy>; ++ phy-mode = "rgmii"; ++ clock_in_out = "input"; ++ snps,reset-gpio = <&gpio3 15 GPIO_ACTIVE_LOW>; ++ snps,reset-active-low; ++ snps,reset-delays-us = <0 10000 50000>; ++ assigned-clocks = <&cru SCLK_RMII_SRC>; ++ assigned-clock-parents = <&clkin_gmac>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&rgmii_pins>; ++ tx_delay = <0x100>; ++ rx_delay = <0x11>; ++ status = "okay"; ++}; ++ ++&gpu { ++ status = "okay"; ++ mali-supply = <&vdd_gpu>; ++}; ++ ++&hdmi { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ #sound-dai-cells = <0>; ++ status = "okay"; ++}; ++ ++&hdmi_in_vopl { ++ status = "disabled"; ++}; ++ ++&dp_in_vopl { ++ status = "disabled"; ++}; ++ ++&i2c0 { ++ status = "okay"; ++ i2c-scl-rising-time-ns = <168>; ++ i2c-scl-falling-time-ns = <4>; ++ clock-frequency = <400000>; ++ ++ vdd_cpu_b: syr827@40 { ++ compatible = "silergy,syr827"; ++ reg = <0x40>; ++ vin-supply = <&vcc3v3_sys>; ++ regulator-compatible = "fan53555-reg"; ++ regulator-name = "vdd_cpu_b"; ++ regulator-min-microvolt = <712500>; ++ regulator-max-microvolt = <1500000>; ++ regulator-ramp-delay = <1000>; ++ vsel-gpios = <&gpio1 17 GPIO_ACTIVE_HIGH>; ++ fcs,suspend-voltage-selector = <1>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-initial-state = <3>; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_gpu: syr828@41 { ++ compatible = "silergy,syr828"; ++ reg = <0x41>; ++ vin-supply = <&vcc3v3_sys>; ++ regulator-compatible = "fan53555-reg"; ++ regulator-name = "vdd_gpu"; ++ regulator-min-microvolt = <712500>; ++ regulator-max-microvolt = <1500000>; ++ regulator-ramp-delay = <1000>; ++ fcs,suspend-voltage-selector = <1>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-initial-state = <3>; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ rk808: pmic@1b { ++ compatible = "rockchip,rk808"; ++ reg = <0x1b>; ++ interrupt-parent = <&gpio1>; ++ interrupts = <23 IRQ_TYPE_LEVEL_LOW>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pmic_int_l &pmic_dvs2>; ++ rockchip,system-power-controller; ++ wakeup-source; ++ #clock-cells = <1>; ++ clock-output-names = "xin32k", "rk808-clkout2"; ++ ++ vcc1-supply = <&vcc3v3_sys>; ++ vcc2-supply = <&vcc3v3_sys>; ++ vcc3-supply = <&vcc3v3_sys>; ++ vcc4-supply = <&vcc3v3_sys>; ++ vcc6-supply = <&vcc3v3_sys>; ++ vcc7-supply = <&vcc3v3_sys>; ++ vcc8-supply = <&vcc3v3_sys>; ++ vcc9-supply = <&vcc3v3_sys>; ++ vcc10-supply = <&vcc3v3_sys>; ++ vcc11-supply = <&vcc3v3_sys>; ++ vcc12-supply = <&vcc3v3_sys>; ++ vddio-supply = <&vcc1v8_pmu>; ++ ++ regulators { ++ vdd_center: DCDC_REG1 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <1350000>; ++ regulator-ramp-delay = <6001>; ++ regulator-name = "vdd_center"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_cpu_l: DCDC_REG2 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <1350000>; ++ regulator-ramp-delay = <6001>; ++ regulator-name = "vdd_cpu_l"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_ddr: DCDC_REG3 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-name = "vcc_ddr"; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ }; ++ }; ++ ++ vcc_1v8: DCDC_REG4 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-name = "vcc_1v8"; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vcc1v8_dvp: LDO_REG1 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-name = "vcc1v8_dvp"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc3v0_tp: LDO_REG2 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3000000>; ++ regulator-max-microvolt = <3000000>; ++ regulator-name = "vcc3v0_tp"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc1v8_pmu: LDO_REG3 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-name = "vcc1v8_pmu"; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vcc_sd: LDO_REG4 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-name = "vcc_sd"; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3300000>; ++ }; ++ }; ++ ++ vcca3v0_codec: LDO_REG5 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3000000>; ++ regulator-max-microvolt = <3000000>; ++ regulator-name = "vcca3v0_codec"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_1v5: LDO_REG6 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1500000>; ++ regulator-max-microvolt = <1500000>; ++ regulator-name = "vcc_1v5"; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1500000>; ++ }; ++ }; ++ ++ vcca1v8_codec: LDO_REG7 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-name = "vcca1v8_codec"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_3v0: LDO_REG8 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3000000>; ++ regulator-max-microvolt = <3000000>; ++ regulator-name = "vcc_3v0"; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3000000>; ++ }; ++ }; ++ ++ vcc3v3_s3: SWITCH_REG1 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-name = "vcc3v3_s3"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc3v3_s0: SWITCH_REG2 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-name = "vcc3v3_s0"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&i2c1 { ++ status = "okay"; ++ i2c-scl-rising-time-ns = <300>; ++ i2c-scl-falling-time-ns = <15>; ++}; ++ ++&i2c4 { ++ status = "okay"; ++ i2c-scl-rising-time-ns = <600>; ++ i2c-scl-falling-time-ns = <20>; ++}; ++ ++&i2s0 { ++ status = "okay"; ++ rockchip,i2s-broken-burst-len; ++ rockchip,playback-channels = <8>; ++ rockchip,capture-channels = <8>; ++ #sound-dai-cells = <0>; ++}; ++ ++&i2s1 { ++ status = "okay"; ++ rockchip,i2s-broken-burst-len; ++ rockchip,playback-channels = <2>; ++ rockchip,capture-channels = <2>; ++ #sound-dai-cells = <0>; ++}; ++ ++&i2s2 { ++ #sound-dai-cells = <0>; ++ rockchip,bclk-fs = <128>; ++ status = "okay"; ++}; ++ ++&io_domains { ++ status = "okay"; ++ ++ bt656-supply = <&vcc1v8_dvp>; /* bt656_gpio2ab_ms */ ++ audio-supply = <&vcca1v8_codec>; /* audio_gpio3d4a_ms */ ++ sdmmc-supply = <&vcc_sd>; /* sdmmc_gpio4b_ms */ ++ gpio1830-supply = <&vcc_3v0>; /* gpio1833_gpio4cd_ms */ ++}; ++ ++&pcie_phy { ++ status = "okay"; ++}; ++ ++&pcie0 { ++ assigned-clocks = <&cru SCLK_PCIEPHY_REF>; ++ assigned-clock-parents = <&cru SCLK_PCIEPHY_REF100M>; ++ assigned-clock-rates = <100000000>; ++ ep-gpios = <&gpio2 18 GPIO_ACTIVE_HIGH>; ++ num-lanes = <1>; ++ max-link-speed = <2>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pcie_clkreqn>; ++ status = "okay"; ++}; ++ ++&pmu_io_domains { ++ status = "okay"; ++ pmu1830-supply = <&vcc_3v0>; ++}; ++ ++&pinctrl { ++ buttons { ++ pwrbtn: pwrbtn { ++ rockchip,pins = <0 5 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++ ++ pmic { ++ vsel1_gpio: vsel1-gpio { ++ rockchip,pins = ++ <1 17 RK_FUNC_GPIO &pcfg_pull_down>; ++ }; ++ ++ vsel2_gpio: vsel2-gpio { ++ rockchip,pins = ++ <1 14 RK_FUNC_GPIO &pcfg_pull_down>; ++ }; ++ ++ pmic_int_l: pmic-int-l { ++ rockchip,pins = ++ <1 23 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ ++ pmic_dvs2: pmic-dvs2 { ++ rockchip,pins = ++ <1 18 RK_FUNC_GPIO &pcfg_pull_down>; ++ }; ++ }; ++ ++ usb2 { ++ host_vbus_drv: host-vbus-drv { ++ rockchip,pins = ++ <4 25 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ ++ host31_vbus_drv: host31-vbus-drv { ++ rockchip,pins = ++ <0 12 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ ++ host32_vbus_drv: host32-vbus-drv { ++ rockchip,pins = ++ <0 13 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ leds { ++ led_pins: led-pins { ++ rockchip,pins = <4 26 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++}; ++ ++&pwm0 { ++ status = "okay"; ++}; ++ ++&pwm2 { ++ status = "okay"; ++}; ++ ++&rkvdec { ++ status = "okay"; ++}; ++ ++&rockchip_suspend { ++ rockchip,power-ctrl = ++ <&gpio1 18 GPIO_ACTIVE_LOW>, ++ <&gpio1 14 GPIO_ACTIVE_HIGH>; ++}; ++ ++&route_edp { ++ status = "disabled"; ++}; ++ ++&saradc { ++ status = "okay"; ++ vref-supply = <&vccadc_ref>; ++}; ++ ++&sdhci { ++ bus-width = <8>; ++ keep-power-in-suspend; ++ mmc-hs400-1_8v; ++ mmc-hs400-enhanced-strobe; ++ non-removable; ++ status = "okay"; ++ supports-emmc; ++}; ++ ++&sdmmc { ++ max-frequency = <150000000>; ++ supports-sd; ++ bus-width = <4>; ++ cap-mmc-highspeed; ++ cap-sd-highspeed; ++ disable-wp; ++ num-slots = <1>; ++ vqmmc-supply = <&vcc_sd>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd &sdmmc_bus4>; ++ status = "okay"; ++}; ++ ++&tcphy0 { ++ status = "okay"; ++}; ++ ++&tcphy1 { ++ status = "okay"; ++}; ++ ++&soc_thermal { ++ polling-delay-passive = <20>; /* milliseconds */ ++ polling-delay = <1000>; /* milliseconds */ ++ sustainable-power = <1000>; /* milliwatts */ ++ ++ thermal-sensors = <&tsadc 0>; ++ ++ trips { ++ /* fan active thermal point */ ++ cpu_alert0: trip-point@0 { ++ temperature = <50000>; /* millicelsius */ ++ hysteresis = <10000>; /* millicelsius */ ++ type = "active"; ++ }; ++ cpu_alert1: trip-point@1 { ++ temperature = <55000>; /* millicelsius */ ++ hysteresis = <10000>; /* millicelsius */ ++ type = "active"; ++ }; ++ cpu_alert2: trip-point@2 { ++ temperature = <60000>; /* millicelsius */ ++ hysteresis = <10000>; /* millicelsius */ ++ type = "active"; ++ }; ++ ++ /* big cluster thermal point */ ++ cpu_alert3: trip-point@3 { ++ temperature = <80000>; /* millicelsius */ ++ hysteresis = <2000>; /* millicelsius */ ++ type = "passive"; ++ }; ++ cpu_alert4: trip-point@4 { ++ temperature = <82000>; /* millicelsius */ ++ hysteresis = <2000>; /* millicelsius */ ++ type = "passive"; ++ }; ++ cpu_alert5: trip-point@5 { ++ temperature = <85000>; /* millicelsius */ ++ hysteresis = <2000>; /* millicelsius */ ++ type = "passive"; ++ }; ++ cpu_alert6: trip-point@6 { ++ temperature = <88000>; /* millicelsius */ ++ hysteresis = <2000>; /* millicelsius */ ++ type = "passive"; ++ }; ++ ++ /* little cluster thermal point */ ++ cpu_alert7: trip-point@7 { ++ temperature = <90000>; /* millicelsius */ ++ hysteresis = <2000>; /* millicelsius */ ++ type = "passive"; ++ }; ++ cpu_alert8: trip-point@8 { ++ temperature = <92000>; /* millicelsius */ ++ hysteresis = <2000>; /* millicelsius */ ++ type = "passive"; ++ }; ++ cpu_alert9: trip-point@9 { ++ temperature = <95000>; /* millicelsius */ ++ hysteresis = <2000>; /* millicelsius */ ++ type = "passive"; ++ }; ++ soc_crit: soc-crit { ++ temperature = <120000>; /* millicelsius */ ++ hysteresis = <2000>; /* millicelsius */ ++ type = "critical"; ++ }; ++ }; ++ ++ cooling-maps { ++ /* fan cooling map */ ++ map0 { ++ trip = <&cpu_alert0>; ++ cooling-device = ++ <&fan0 0 1>; ++ }; ++ map1 { ++ trip = <&cpu_alert1>; ++ cooling-device = ++ <&fan0 1 2>; ++ }; ++ map2 { ++ trip = <&cpu_alert2>; ++ cooling-device = ++ <&fan0 2 3>; ++ }; ++ ++ /* cpu cooling map */ ++ /* big cluster */ ++ map3 { ++ trip = <&cpu_alert3>; ++ cooling-device = ++ <&cpu_b0 0 2>; ++ contribution = <4096>; ++ }; ++ map4 { ++ trip = <&cpu_alert4>; ++ cooling-device = ++ <&cpu_b0 2 4>; ++ contribution = <4096>; ++ }; ++ map5 { ++ trip = <&cpu_alert5>; ++ cooling-device = ++ <&cpu_b0 4 7>; ++ contribution = <4096>; ++ }; ++ map6 { ++ trip = <&cpu_alert6>; ++ cooling-device = ++ <&cpu_b0 4 7>; ++ contribution = <4096>; ++ }; ++ ++ /* little cluster */ ++ map7 { ++ trip = <&cpu_alert7>; ++ cooling-device = ++ <&cpu_l0 0 2>; ++ contribution = <1024>; ++ }; ++ map8 { ++ trip = <&cpu_alert8>; ++ cooling-device = ++ <&cpu_l0 2 5>; ++ contribution = <1024>; ++ }; ++ ++ map9 { ++ trip = <&cpu_alert9>; ++ cooling-device = ++ <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; ++ contribution = <1024>; ++ }; ++ }; ++}; ++ ++&tsadc { ++ /* tshut mode 0:CRU 1:GPIO */ ++ rockchip,hw-tshut-mode = <1>; ++ /* tshut polarity 0:LOW 1:HIGH */ ++ rockchip,hw-tshut-polarity = <1>; ++ status = "okay"; ++}; ++ ++&u2phy0 { ++ status = "okay"; ++ ++ u2phy0_otg: otg-port { ++ phy-supply = <&vcc5v0_host31>; ++ status = "okay"; ++ }; ++ ++ u2phy0_host: host-port { ++ phy-supply = <&vcc5v0_host>; ++ status = "okay"; ++ }; ++}; ++ ++&u2phy1 { ++ status = "okay"; ++ ++ u2phy1_otg: otg-port { ++ phy-supply = <&vcc5v0_host32>; ++ status = "okay"; ++ }; ++ ++ u2phy1_host: host-port { ++ phy-supply = <&vcc5v0_host>; ++ status = "okay"; ++ }; ++}; ++ ++&sdio0 { ++ status = "disabled"; ++}; ++ ++&uart2 { ++ status = "okay"; ++}; ++ ++&usbdrd3_0 { ++ status = "okay"; ++}; ++ ++&usbdrd3_1 { ++ status = "okay"; ++}; ++ ++&usbdrd_dwc3_0 { ++ status = "okay"; ++ dr_mode = "host"; ++}; ++ ++&usbdrd_dwc3_1 { ++ status = "okay"; ++ dr_mode = "host"; ++}; ++ ++&usb_host0_ehci { ++ status = "okay"; ++}; ++ ++&usb_host0_ohci { ++ status = "okay"; ++}; ++ ++&usb_host1_ehci { ++ status = "okay"; ++}; ++ ++&usb_host1_ohci { ++ status = "okay"; ++}; ++ ++&vopb { ++ status = "okay"; ++}; ++ ++&vopb_mmu { ++ status = "okay"; ++}; ++ ++&vopl { ++ status = "okay"; ++}; ++ ++&vopl_mmu { ++ status = "okay"; ++}; ++ ++&vpu { ++ status = "okay"; ++}; + +From 48e03ae4029beb41ec47af2d5ce71c08e7e01bac Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 4 Mar 2018 09:08:35 +0100 +Subject: [PATCH] arm64: dts: rockchip: add rk3328-box-trn9 board + +--- + arch/arm64/boot/dts/rockchip/rk3328-box-trn9.dts | 667 +++++++++++++++++++++++ + 1 file changed, 667 insertions(+) + create mode 100644 arch/arm64/boot/dts/rockchip/rk3328-box-trn9.dts + +diff --git a/arch/arm64/boot/dts/rockchip/rk3328-box-trn9.dts b/arch/arm64/boot/dts/rockchip/rk3328-box-trn9.dts +new file mode 100644 +index 000000000000..55c4cbf6baff +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/rk3328-box-trn9.dts +@@ -0,0 +1,667 @@ ++/* ++ * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd ++ * ++ * This file is dual-licensed: you can use it either under the terms ++ * of the GPL or the X11 license, at your option. Note that this dual ++ * licensing only applies to this file, and not this project as a ++ * whole. ++ * ++ * a) This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of the ++ * License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * Or, alternatively, ++ * ++ * b) Permission is hereby granted, free of charge, to any person ++ * obtaining a copy of this software and associated documentation ++ * files (the "Software"), to deal in the Software without ++ * restriction, including without limitation the rights to use, ++ * copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following ++ * conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES ++ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT ++ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, ++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++/dts-v1/; ++#include "rk3328.dtsi" ++ ++/ { ++ model = "Rockchip RK3328 TRN9"; ++ compatible = "rockchip,rk3328-box-trn9", "rockchip,rk3328"; ++ ++ chosen { ++ bootargs = ""; ++ }; ++ ++ xin32k: xin32k { ++ compatible = "fixed-clock"; ++ clock-frequency = <32768>; ++ clock-output-names = "xin32k"; ++ #clock-cells = <0>; ++ }; ++ ++ gmac_clkin: external-gmac-clock { ++ compatible = "fixed-clock"; ++ clock-frequency = <125000000>; ++ clock-output-names = "gmac_clkin"; ++ #clock-cells = <0>; ++ }; ++ ++ sdio_pwrseq: sdio-pwrseq { ++ compatible = "mmc-pwrseq-simple"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&wifi_enable_h>; ++ ++ /* ++ * On the module itself this is one of these (depending ++ * on the actual card populated): ++ * - SDIO_RESET_L_WL_REG_ON ++ * - PDN (power down when low) ++ */ ++ reset-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_LOW>; ++ }; ++ ++ vcc_phy: vcc-phy-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc_phy"; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ vcc_sys: vcc-sys { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc_sys"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ }; ++ ++ vcc_sd: sdmmc-regulator { ++ compatible = "regulator-fixed"; ++ gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_LOW>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc0m1_gpio>; ++ regulator-name = "vcc_sd"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ vin-supply = <&vcc_io>; ++ }; ++ ++ vcc_host_5v: vcc-host-5v-regulator { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&usb30_host_drv>; ++ regulator-name = "vcc_host_5v"; ++ regulator-always-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc_sys>; ++ }; ++ ++ vcc_host1_5v: vcc_otg_5v: vcc-host1-5v-regulator { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&usb20_host_drv>; ++ regulator-name = "vcc_host1_5v"; ++ regulator-always-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc_sys>; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led1 { ++ gpios = <&rk805 0 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "heartbeat"; ++ }; ++ ++ led2 { ++ gpios = <&rk805 1 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "mmc0"; ++ }; ++ }; ++ ++ ir-receiver { ++ compatible = "gpio-ir-receiver"; ++ gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>; ++ linux,rc-map-name = "rc-trn9"; ++ pinctrl-0 = <&ir_int>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ }; ++ ++ hdmi-sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,format = "i2s"; ++ simple-audio-card,mclk-fs = <128>; ++ simple-audio-card,name = "HDMI"; ++ simple-audio-card,cpu { ++ sound-dai = <&i2s0>; ++ }; ++ simple-audio-card,codec { ++ sound-dai = <&hdmi>; ++ }; ++ }; ++ ++ sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,format = "i2s"; ++ simple-audio-card,mclk-fs = <256>; ++ simple-audio-card,name = "I2S"; ++ simple-audio-card,cpu { ++ sound-dai = <&i2s1>; ++ }; ++ simple-audio-card,codec { ++ sound-dai = <&codec>; ++ }; ++ }; ++ ++ spdif-sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,name = "SPDIF"; ++ simple-audio-card,cpu { ++ sound-dai = <&spdif>; ++ }; ++ simple-audio-card,codec { ++ sound-dai = <&spdif_out>; ++ }; ++ }; ++ ++ spdif_out: spdif-out { ++ compatible = "linux,spdif-dit"; ++ #sound-dai-cells = <0>; ++ }; ++ ++ wireless-bluetooth { ++ compatible = "bluetooth-platdata"; ++ BT,power_gpio = <&gpio1 RK_PD0 GPIO_ACTIVE_HIGH>; ++ BT,wake_host_irq = <&gpio1 RK_PD2 GPIO_ACTIVE_HIGH>; ++ status = "okay"; ++ }; ++ ++ wireless-wlan { ++ compatible = "wlan-platdata"; ++ rockchip,grf = <&grf>; ++ wifi_chip_type = "rtl8723bs"; ++ WIFI,host_wake_irq = <&gpio3 RK_PA1 GPIO_ACTIVE_HIGH>; ++ status = "okay"; ++ }; ++}; ++ ++&codec { ++ #sound-dai-cells = <0>; ++ status = "okay"; ++}; ++ ++&cpu0 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu1 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu2 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu3 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&dfi { ++ status = "okay"; ++}; ++ ++&dmc { ++ center-supply = <&vdd_logic>; ++ status = "okay"; ++}; ++ ++&display_subsystem { ++ status = "okay"; ++}; ++ ++&emmc { ++ bus-width = <8>; ++ cap-mmc-highspeed; ++ mmc-hs200-1_8v; ++ non-removable; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>; ++ supports-emmc; ++ vmmc-supply = <&vcc_io>; ++ vqmmc-supply = <&vcc18_emmc>; ++ status = "okay"; ++}; ++ ++&gmac2io { ++ assigned-clocks = <&cru SCLK_MAC2IO>, <&cru SCLK_MAC2IO_EXT>; ++ assigned-clock-parents = <&gmac_clkin>, <&gmac_clkin>; ++ clock_in_out = "input"; ++ phy-supply = <&vcc_phy>; ++ phy-mode = "rgmii"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&rgmiim1_pins>; ++ snps,reset-gpio = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; ++ snps,reset-active-low; ++ snps,reset-delays-us = <0 10000 50000>; ++ tx_delay = <0x26>; ++ rx_delay = <0x11>; ++ status = "okay"; ++}; ++ ++&gmac2phy { ++ phy-supply = <&vcc_phy>; ++ assigned-clocks = <&cru SCLK_MAC2PHY_SRC>; ++ assigned-clock-rate = <50000000>; ++ assigned-clocks = <&cru SCLK_MAC2PHY>; ++ assigned-clock-parents = <&cru SCLK_MAC2PHY_SRC>; ++ clock_in_out = "output"; ++ status = "disabled"; ++}; ++ ++&gpu { ++ status = "okay"; ++ mali-supply = <&vdd_logic>; ++}; ++ ++&h265e { ++ status = "okay"; ++}; ++ ++&h265e_mmu { ++ status = "okay"; ++}; ++ ++&hdmi { ++ #sound-dai-cells = <0>; ++ ddc-i2c-scl-high-time-ns = <9625>; ++ ddc-i2c-scl-low-time-ns = <10000>; ++ status = "okay"; ++}; ++ ++&hdmiphy { ++ status = "okay"; ++}; ++ ++&i2c1 { ++ status = "okay"; ++ ++ rk805: rk805@18 { ++ compatible = "rockchip,rk805"; ++ status = "okay"; ++ reg = <0x18>; ++ interrupt-parent = <&gpio2>; ++ interrupts = <6 IRQ_TYPE_LEVEL_LOW>; ++ #clock-cells = <1>; ++ clock-output-names = "rk805-clkout1", "rk805-clkout2"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pmic_int_l>; ++ rockchip,system-power-controller; ++ wakeup-source; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ vcc1-supply = <&vcc_sys>; ++ vcc2-supply = <&vcc_sys>; ++ vcc3-supply = <&vcc_sys>; ++ vcc4-supply = <&vcc_sys>; ++ vcc5-supply = <&vcc_io>; ++ vcc6-supply = <&vcc_sys>; ++ ++ rtc { ++ status = "okay"; ++ }; ++ ++ pwrkey { ++ status = "okay"; ++ }; ++ ++ gpio { ++ status = "okay"; ++ }; ++ ++ regulators { ++ compatible = "rk805-regulator"; ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ vdd_logic: RK805_DCDC1 { ++ regulator-compatible = "RK805_DCDC1"; ++ regulator-name = "vdd_logic"; ++ regulator-min-microvolt = <712500>; ++ regulator-max-microvolt = <1450000>; ++ regulator-initial-mode = <0x1>; ++ regulator-ramp-delay = <12500>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-mode = <0x2>; ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1000000>; ++ }; ++ }; ++ ++ vdd_arm: RK805_DCDC2 { ++ regulator-compatible = "RK805_DCDC2"; ++ regulator-name = "vdd_arm"; ++ regulator-init-microvolt = <1225000>; ++ regulator-min-microvolt = <712500>; ++ regulator-max-microvolt = <1450000>; ++ regulator-initial-mode = <0x1>; ++ regulator-ramp-delay = <12500>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-mode = <0x2>; ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <950000>; ++ }; ++ }; ++ ++ vcc_ddr: RK805_DCDC3 { ++ regulator-compatible = "RK805_DCDC3"; ++ regulator-name = "vcc_ddr"; ++ regulator-initial-mode = <0x1>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-mode = <0x2>; ++ regulator-on-in-suspend; ++ }; ++ }; ++ ++ vcc_io: RK805_DCDC4 { ++ regulator-compatible = "RK805_DCDC4"; ++ regulator-name = "vcc_io"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-initial-mode = <0x1>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-mode = <0x2>; ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3300000>; ++ }; ++ }; ++ ++ vcc_18: RK805_LDO1 { ++ regulator-compatible = "RK805_LDO1"; ++ regulator-name = "vcc_18"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vcc18_emmc: RK805_LDO2 { ++ regulator-compatible = "RK805_LDO2"; ++ regulator-name = "vcc18_emmc"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vdd_10: RK805_LDO3 { ++ regulator-compatible = "RK805_LDO3"; ++ regulator-name = "vdd_10"; ++ regulator-min-microvolt = <1000000>; ++ regulator-max-microvolt = <1000000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1000000>; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&i2s0 { ++ #sound-dai-cells = <0>; ++ rockchip,bclk-fs = <128>; ++ status = "okay"; ++}; ++ ++&i2s1 { ++ #sound-dai-cells = <0>; ++ status = "okay"; ++}; ++ ++&io_domains { ++ status = "okay"; ++ ++ vccio1-supply = <&vcc_io>; ++ vccio2-supply = <&vcc18_emmc>; ++ vccio3-supply = <&vcc_io>; ++ vccio4-supply = <&vcc_18>; ++ vccio5-supply = <&vcc_io>; ++ vccio6-supply = <&vcc_18>; ++ pmuio-supply = <&vcc_io>; ++}; ++ ++&pinctrl { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&clk_32k_out>; ++ ++ clk_32k { ++ clk_32k_out: clk-32k-out { ++ rockchip,pins = <1 RK_PD4 RK_FUNC_1 &pcfg_pull_none>; ++ }; ++ }; ++ ++ ir { ++ ir_int: ir-int { ++ rockchip,pins = <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ pmic { ++ pmic_int_l: pmic-int-l { ++ rockchip,pins = <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++ ++ sdio-pwrseq { ++ wifi_enable_h: wifi-enable-h { ++ rockchip,pins = <3 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ usb2 { ++ usb20_host_drv: usb20-host-drv { ++ rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ usb3 { ++ usb30_host_drv: usb30-host-drv { ++ rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++}; ++ ++&rkvdec { ++ status = "okay"; ++ vcodec-supply = <&vdd_logic>; ++}; ++ ++&rkvdec_mmu { ++ status = "okay"; ++}; ++ ++&sdmmc_ext { ++ bus-width = <4>; ++ cap-sd-highspeed; ++ cap-sdio-irq; ++ disable-wp; ++ keep-power-in-suspend; ++ max-frequency = <150000000>; ++ mmc-pwrseq = <&sdio_pwrseq>; ++ non-removable; ++ num-slots = <1>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc0ext_bus4 &sdmmc0ext_cmd &sdmmc0ext_clk>; ++ sd-uhs-sdr104; ++ supports-sdio; ++ status = "okay"; ++}; ++ ++&sdmmc { ++ bus-width = <4>; ++ cap-mmc-highspeed; ++ cap-sd-highspeed; ++ disable-wp; ++ max-frequency = <150000000>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_dectn &sdmmc0_bus4>; ++ supports-sd; ++ vmmc-supply = <&vcc_sd>; ++ status = "okay"; ++}; ++ ++&spdif { ++ #sound-dai-cells = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spdifm0_tx>; ++ status = "okay"; ++}; ++ ++&threshold { ++ temperature = <80000>; /* millicelsius */ ++}; ++ ++&target { ++ temperature = <95000>; /* millicelsius */ ++}; ++ ++&soc_crit { ++ temperature = <100000>; /* millicelsius */ ++}; ++ ++&tsadc { ++ rockchip,hw-tshut-mode = <0>; ++ rockchip,hw-tshut-polarity = <0>; ++ rockchip,hw-tshut-temp = <110000>; ++ status = "okay"; ++}; ++ ++&uart2 { ++ status = "okay"; ++}; ++ ++&u2phy { ++ status = "okay"; ++ ++}; ++ ++&u2phy_host { ++ phy-supply = <&vcc_host1_5v>; ++ status = "okay"; ++}; ++ ++&u2phy_otg { ++ phy-supply = <&vcc_otg_5v>; ++ status = "okay"; ++}; ++ ++&u3phy { ++ status = "okay"; ++}; ++ ++&u3phy_utmi { ++ phy-supply = <&vcc_host_5v>; ++ status = "okay"; ++}; ++ ++&u3phy_pipe { ++ phy-supply = <&vcc_host_5v>; ++ status = "okay"; ++}; ++ ++&usb20_otg { ++ dr_mode = "host"; ++ status = "okay"; ++}; ++ ++&usb_host0_ehci { ++ status = "okay"; ++}; ++ ++&usb_host0_ohci { ++ status = "okay"; ++}; ++ ++&usbdrd3 { ++ status = "okay"; ++}; ++ ++&usbdrd_dwc3 { ++ status = "okay"; ++}; ++ ++&vop { ++ status = "okay"; ++}; ++ ++&vop_mmu { ++ status = "okay"; ++}; ++ ++&vpu_service { ++ status = "okay"; ++}; ++ ++&vpu_mmu { ++ status = "okay"; ++}; ++ ++&vepu { ++ status = "okay"; ++}; ++ ++&vepu_mmu { ++ status = "okay"; ++}; ++ ++&venc_srv { ++ status = "okay"; ++}; + +From da03fa766cccf5f517e0f043cd5317bdab8a8a09 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 4 Mar 2018 09:08:35 +0100 +Subject: [PATCH] arm64: dts: rockchip: add rk3328-box-z28 board + +--- + arch/arm64/boot/dts/rockchip/rk3328-box-z28.dts | 597 ++++++++++++++++++++++++ + 1 file changed, 597 insertions(+) + create mode 100644 arch/arm64/boot/dts/rockchip/rk3328-box-z28.dts + +diff --git a/arch/arm64/boot/dts/rockchip/rk3328-box-z28.dts b/arch/arm64/boot/dts/rockchip/rk3328-box-z28.dts +new file mode 100644 +index 000000000000..f94526f6f190 +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/rk3328-box-z28.dts +@@ -0,0 +1,597 @@ ++/* ++ * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd ++ * ++ * This file is dual-licensed: you can use it either under the terms ++ * of the GPL or the X11 license, at your option. Note that this dual ++ * licensing only applies to this file, and not this project as a ++ * whole. ++ * ++ * a) This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of the ++ * License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * Or, alternatively, ++ * ++ * b) Permission is hereby granted, free of charge, to any person ++ * obtaining a copy of this software and associated documentation ++ * files (the "Software"), to deal in the Software without ++ * restriction, including without limitation the rights to use, ++ * copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following ++ * conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES ++ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT ++ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, ++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++/dts-v1/; ++#include "rk3328.dtsi" ++ ++/ { ++ model = "Rockchip RK3328 Z28"; ++ compatible = "rockchip,rk3328-box-z28", "rockchip,rk3328"; ++ ++ chosen { ++ bootargs = "earlyprintk=uart8250-32bit,0xff130000"; ++ stdout-path = "serial2:1500000n8"; ++ }; ++ ++ xin32k: xin32k { ++ compatible = "fixed-clock"; ++ clock-frequency = <32768>; ++ clock-output-names = "xin32k"; ++ #clock-cells = <0>; ++ }; ++ ++ vcc_phy: vcc-phy-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc_phy"; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ vcc_sys: vcc-sys { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc_sys"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ }; ++ ++ vcc_sd: sdmmc-regulator { ++ compatible = "regulator-fixed"; ++ gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_LOW>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc0m1_gpio>; ++ regulator-name = "vcc_sd"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ vin-supply = <&vcc_io>; ++ }; ++ ++ vcc_host_5v: vcc-host-5v-regulator { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&usb30_host_drv>; ++ regulator-name = "vcc_host_5v"; ++ regulator-always-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc_sys>; ++ }; ++ ++ vcc_host1_5v: vcc_otg_5v: vcc-host1-5v-regulator { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&usb20_host_drv>; ++ regulator-name = "vcc_host1_5v"; ++ regulator-always-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc_sys>; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led1 { ++ gpios = <&rk805 0 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "heartbeat"; ++ }; ++ ++ led2 { ++ gpios = <&rk805 1 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "mmc0"; ++ }; ++ }; ++ ++ ir-receiver { ++ compatible = "gpio-ir-receiver"; ++ gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>; ++ pinctrl-0 = <&ir_int>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ }; ++ ++ hdmi-sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,format = "i2s"; ++ simple-audio-card,mclk-fs = <128>; ++ simple-audio-card,name = "HDMI"; ++ simple-audio-card,cpu { ++ sound-dai = <&i2s0>; ++ }; ++ simple-audio-card,codec { ++ sound-dai = <&hdmi>; ++ }; ++ }; ++ ++ spdif-sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,name = "SPDIF"; ++ simple-audio-card,cpu { ++ sound-dai = <&spdif>; ++ }; ++ simple-audio-card,codec { ++ sound-dai = <&spdif_out>; ++ }; ++ }; ++ ++ spdif_out: spdif-out { ++ compatible = "linux,spdif-dit"; ++ #sound-dai-cells = <0>; ++ }; ++ ++ wireless-bluetooth { ++ compatible = "bluetooth-platdata"; ++ BT,power_gpio = <&gpio2 RK_PC5 GPIO_ACTIVE_HIGH>; ++ BT,wake_host_irq = <&gpio2 RK_PC0 GPIO_ACTIVE_HIGH>; ++ status = "okay"; ++ }; ++ ++ wireless-wlan { ++ compatible = "wlan-platdata"; ++ rockchip,grf = <&grf>; ++ wifi_chip_type = "rtl8188eu"; ++ WIFI,poweren_gpio = <&gpio2 RK_PC3 GPIO_ACTIVE_HIGH>; ++ WIFI,reset_gpio = <&gpio2 RK_PC4 GPIO_ACTIVE_HIGH>; ++ WIFI,host_wake_irq = <&gpio2 RK_PC6 GPIO_ACTIVE_HIGH>; ++ status = "okay"; ++ }; ++}; ++ ++&codec { ++ #sound-dai-cells = <0>; ++ status = "okay"; ++}; ++ ++&cpu0 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu1 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu2 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu3 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&dfi { ++ status = "okay"; ++}; ++ ++&dmc { ++ center-supply = <&vdd_logic>; ++ status = "okay"; ++}; ++ ++&display_subsystem { ++ status = "okay"; ++}; ++ ++&emmc { ++ bus-width = <8>; ++ cap-mmc-highspeed; ++ mmc-hs200-1_8v; ++ non-removable; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>; ++ supports-emmc; ++ vmmc-supply = <&vcc_io>; ++ vqmmc-supply = <&vcc18_emmc>; ++ status = "okay"; ++}; ++ ++&gmac2phy { ++ phy-supply = <&vcc_phy>; ++ assigned-clocks = <&cru SCLK_MAC2PHY_SRC>; ++ assigned-clock-rate = <50000000>; ++ assigned-clocks = <&cru SCLK_MAC2PHY>; ++ assigned-clock-parents = <&cru SCLK_MAC2PHY_SRC>; ++ clock_in_out = "output"; ++ status = "okay"; ++}; ++ ++&gpu { ++ status = "okay"; ++ mali-supply = <&vdd_logic>; ++}; ++ ++&h265e { ++ status = "okay"; ++}; ++ ++&h265e_mmu { ++ status = "okay"; ++}; ++ ++&hdmi { ++ #sound-dai-cells = <0>; ++ ddc-i2c-scl-high-time-ns = <9625>; ++ ddc-i2c-scl-low-time-ns = <10000>; ++ status = "okay"; ++}; ++ ++&hdmiphy { ++ status = "okay"; ++}; ++ ++&i2c1 { ++ status = "okay"; ++ ++ rk805: rk805@18 { ++ compatible = "rockchip,rk805"; ++ status = "okay"; ++ reg = <0x18>; ++ interrupt-parent = <&gpio2>; ++ interrupts = <6 IRQ_TYPE_LEVEL_LOW>; ++ #clock-cells = <1>; ++ clock-output-names = "rk805-clkout1", "rk805-clkout2"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pmic_int_l>; ++ rockchip,system-power-controller; ++ wakeup-source; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ vcc1-supply = <&vcc_sys>; ++ vcc2-supply = <&vcc_sys>; ++ vcc3-supply = <&vcc_sys>; ++ vcc4-supply = <&vcc_sys>; ++ vcc5-supply = <&vcc_io>; ++ vcc6-supply = <&vcc_sys>; ++ ++ rtc { ++ status = "okay"; ++ }; ++ ++ pwrkey { ++ status = "okay"; ++ }; ++ ++ gpio { ++ status = "okay"; ++ }; ++ ++ regulators { ++ compatible = "rk805-regulator"; ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ vdd_logic: RK805_DCDC1 { ++ regulator-compatible = "RK805_DCDC1"; ++ regulator-name = "vdd_logic"; ++ regulator-min-microvolt = <712500>; ++ regulator-max-microvolt = <1450000>; ++ regulator-initial-mode = <0x1>; ++ regulator-ramp-delay = <12500>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-mode = <0x2>; ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1000000>; ++ }; ++ }; ++ ++ vdd_arm: RK805_DCDC2 { ++ regulator-compatible = "RK805_DCDC2"; ++ regulator-name = "vdd_arm"; ++ regulator-init-microvolt = <1225000>; ++ regulator-min-microvolt = <712500>; ++ regulator-max-microvolt = <1450000>; ++ regulator-initial-mode = <0x1>; ++ regulator-ramp-delay = <12500>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-mode = <0x2>; ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <950000>; ++ }; ++ }; ++ ++ vcc_ddr: RK805_DCDC3 { ++ regulator-compatible = "RK805_DCDC3"; ++ regulator-name = "vcc_ddr"; ++ regulator-initial-mode = <0x1>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-mode = <0x2>; ++ regulator-on-in-suspend; ++ }; ++ }; ++ ++ vcc_io: RK805_DCDC4 { ++ regulator-compatible = "RK805_DCDC4"; ++ regulator-name = "vcc_io"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-initial-mode = <0x1>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-mode = <0x2>; ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3300000>; ++ }; ++ }; ++ ++ vcc_18: RK805_LDO1 { ++ regulator-compatible = "RK805_LDO1"; ++ regulator-name = "vcc_18"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vcc18_emmc: RK805_LDO2 { ++ regulator-compatible = "RK805_LDO2"; ++ regulator-name = "vcc18_emmc"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vdd_10: RK805_LDO3 { ++ regulator-compatible = "RK805_LDO3"; ++ regulator-name = "vdd_10"; ++ regulator-min-microvolt = <1000000>; ++ regulator-max-microvolt = <1000000>; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1000000>; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&i2s0 { ++ #sound-dai-cells = <0>; ++ rockchip,bclk-fs = <128>; ++ status = "okay"; ++}; ++ ++&io_domains { ++ status = "okay"; ++ ++ vccio1-supply = <&vcc_io>; ++ vccio2-supply = <&vcc18_emmc>; ++ vccio3-supply = <&vcc_io>; ++ vccio4-supply = <&vcc_18>; ++ vccio5-supply = <&vcc_io>; ++ vccio6-supply = <&vcc_io>; ++ pmuio-supply = <&vcc_io>; ++}; ++ ++&pinctrl { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&clk_32k_out>; ++ ++ clk_32k { ++ clk_32k_out: clk-32k-out { ++ rockchip,pins = <1 RK_PD4 RK_FUNC_1 &pcfg_pull_none>; ++ }; ++ }; ++ ++ ir { ++ ir_int: ir-int { ++ rockchip,pins = <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ pmic { ++ pmic_int_l: pmic-int-l { ++ rockchip,pins = <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++ ++ usb2 { ++ usb20_host_drv: usb20-host-drv { ++ rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ usb3 { ++ usb30_host_drv: usb30-host-drv { ++ rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++}; ++ ++&rkvdec { ++ status = "okay"; ++ vcodec-supply = <&vdd_logic>; ++}; ++ ++&rkvdec_mmu { ++ status = "okay"; ++}; ++ ++&sdmmc { ++ bus-width = <4>; ++ cap-mmc-highspeed; ++ cap-sd-highspeed; ++ disable-wp; ++ max-frequency = <150000000>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_dectn &sdmmc0_bus4>; ++ supports-sd; ++ vmmc-supply = <&vcc_sd>; ++ status = "okay"; ++}; ++ ++&spdif { ++ #sound-dai-cells = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spdifm0_tx>; ++ status = "okay"; ++}; ++ ++&threshold { ++ temperature = <80000>; /* millicelsius */ ++}; ++ ++&target { ++ temperature = <95000>; /* millicelsius */ ++}; ++ ++&soc_crit { ++ temperature = <100000>; /* millicelsius */ ++}; ++ ++&tsadc { ++ rockchip,hw-tshut-mode = <0>; ++ rockchip,hw-tshut-polarity = <0>; ++ rockchip,hw-tshut-temp = <110000>; ++ status = "okay"; ++}; ++ ++&uart0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart0_xfer &uart0_cts>; ++ status = "okay"; ++}; ++ ++&uart2 { ++ status = "okay"; ++}; ++ ++&u2phy { ++ status = "okay"; ++ ++}; ++ ++&u2phy_host { ++ phy-supply = <&vcc_host1_5v>; ++ status = "okay"; ++}; ++ ++&u2phy_otg { ++ phy-supply = <&vcc_otg_5v>; ++ status = "okay"; ++}; ++ ++&u3phy { ++ status = "okay"; ++}; ++ ++&u3phy_utmi { ++ phy-supply = <&vcc_host_5v>; ++ status = "okay"; ++}; ++ ++&u3phy_pipe { ++ phy-supply = <&vcc_host_5v>; ++ status = "okay"; ++}; ++ ++&usb20_otg { ++ dr_mode = "host"; ++ status = "okay"; ++}; ++ ++&usb_host0_ehci { ++ status = "okay"; ++}; ++ ++&usb_host0_ohci { ++ status = "okay"; ++}; ++ ++&usbdrd3 { ++ status = "okay"; ++}; ++ ++&usbdrd_dwc3 { ++ status = "okay"; ++}; ++ ++&vop { ++ status = "okay"; ++}; ++ ++&vop_mmu { ++ status = "okay"; ++}; ++ ++&vpu_service { ++ status = "okay"; ++}; ++ ++&vpu_mmu { ++ status = "okay"; ++}; ++ ++&vepu { ++ status = "okay"; ++}; ++ ++&vepu_mmu { ++ status = "okay"; ++}; ++ ++&venc_srv { ++ status = "okay"; ++}; + +From 46602937e1dc5b61b2bf1788512a57015dbbb547 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Tue, 10 Apr 2018 22:07:37 +0200 +Subject: [PATCH] arm64: dts: rockchip: rk3328-roc-cc: use 1066MHz ddr + frequency + +--- + .../dts/rockchip/rk3328-dram-box-plus-timing.dtsi | 263 +++++++++++++++++++++ + arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts | 33 ++- + 2 files changed, 295 insertions(+), 1 deletion(-) + create mode 100644 arch/arm64/boot/dts/rockchip/rk3328-dram-box-plus-timing.dtsi + +diff --git a/arch/arm64/boot/dts/rockchip/rk3328-dram-box-plus-timing.dtsi b/arch/arm64/boot/dts/rockchip/rk3328-dram-box-plus-timing.dtsi +new file mode 100644 +index 000000000000..ac34cc7ab1ce +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/rk3328-dram-box-plus-timing.dtsi +@@ -0,0 +1,263 @@ ++/* ++ * Copyright (c) 2016 Fuzhou Rockchip Electronics Co., Ltd ++ * ++ * This file is dual-licensed: you can use it either under the terms ++ * of the GPL or the X11 license, at your option. Note that this dual ++ * licensing only applies to this file, and not this project as a ++ * whole. ++ * ++ * a) This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of the ++ * License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * Or, alternatively, ++ * ++ * b) Permission is hereby granted, free of charge, to any person ++ * obtaining a copy of this software and associated documentation ++ * files (the "Software"), to deal in the Software without ++ * restriction, including without limitation the rights to use, ++ * copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following ++ * conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES ++ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT ++ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, ++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++#include ++#include ++ ++&ddr_timing { ++ ddr4_odt = ; ++ phy_ddr4_ca_drv = ; ++ phy_ddr4_ck_drv = ; ++ phy_ddr4_dq_drv = ; ++ phy_ddr4_odt = ; ++ ++ /* CA de-skew, one step is 47.8ps, range 0-15 */ ++ ddr3a1_ddr4a9_de-skew = <1>; ++ ddr3a0_ddr4a10_de-skew = <1>; ++ ddr3a3_ddr4a6_de-skew = <0>; ++ ddr3a2_ddr4a4_de-skew = <1>; ++ ddr3a5_ddr4a8_de-skew = <0>; ++ ddr3a4_ddr4a5_de-skew = <1>; ++ ddr3a7_ddr4a11_de-skew = <1>; ++ ddr3a6_ddr4a7_de-skew = <0>; ++ ddr3a9_ddr4a0_de-skew = <1>; ++ ddr3a8_ddr4a13_de-skew = <0>; ++ ddr3a11_ddr4a3_de-skew = <2>; ++ ddr3a10_ddr4cs0_de-skew = <3>; ++ ddr3a13_ddr4a2_de-skew = <1>; ++ ddr3a12_ddr4ba1_de-skew = <0>; ++ ddr3a15_ddr4odt0_de-skew = <3>; ++ ddr3a14_ddr4a1_de-skew = <2>; ++ ddr3ba1_ddr4a15_de-skew = <1>; ++ ddr3ba0_ddr4bg0_de-skew = <1>; ++ ddr3ras_ddr4cke_de-skew = <3>; ++ ddr3ba2_ddr4ba0_de-skew = <1>; ++ ddr3we_ddr4bg1_de-skew = <3>; ++ ddr3cas_ddr4a12_de-skew = <1>; ++ ddr3ckn_ddr4ckn_de-skew = <4>; ++ ddr3ckp_ddr4ckp_de-skew = <4>; ++ ddr3cke_ddr4a16_de-skew = <1>; ++ ddr3odt0_ddr4a14_de-skew = <1>; ++ ddr3cs0_ddr4act_de-skew = <2>; ++ ddr3reset_ddr4reset_de-skew = <3>; ++ ddr3cs1_ddr4cs1_de-skew = <2>; ++ ddr3odt1_ddr4odt1_de-skew = <2>; ++ ++ /* DATA de-skew ++ * RX one step is 25.1ps, range 0-15 ++ * TX one step is 47.8ps, range 0-15 ++ */ ++ cs0_dm0_rx_de-skew = <8>; ++ cs0_dm0_tx_de-skew = <9>; ++ cs0_dq0_rx_de-skew = <8>; ++ cs0_dq0_tx_de-skew = <9>; ++ cs0_dq1_rx_de-skew = <8>; ++ cs0_dq1_tx_de-skew = <9>; ++ cs0_dq2_rx_de-skew = <8>; ++ cs0_dq2_tx_de-skew = <9>; ++ cs0_dq3_rx_de-skew = <8>; ++ cs0_dq3_tx_de-skew = <9>; ++ cs0_dq4_rx_de-skew = <8>; ++ cs0_dq4_tx_de-skew = <9>; ++ cs0_dq5_rx_de-skew = <8>; ++ cs0_dq5_tx_de-skew = <9>; ++ cs0_dq6_rx_de-skew = <8>; ++ cs0_dq6_tx_de-skew = <9>; ++ cs0_dq7_rx_de-skew = <8>; ++ cs0_dq7_tx_de-skew = <9>; ++ cs0_dqs0_rx_de-skew = <7>; ++ cs0_dqs0p_tx_de-skew = <10>; ++ cs0_dqs0n_tx_de-skew = <10>; ++ ++ cs0_dm1_rx_de-skew = <8>; ++ cs0_dm1_tx_de-skew = <8>; ++ cs0_dq8_rx_de-skew = <8>; ++ cs0_dq8_tx_de-skew = <9>; ++ cs0_dq9_rx_de-skew = <8>; ++ cs0_dq9_tx_de-skew = <8>; ++ cs0_dq10_rx_de-skew = <8>; ++ cs0_dq10_tx_de-skew = <9>; ++ cs0_dq11_rx_de-skew = <8>; ++ cs0_dq11_tx_de-skew = <8>; ++ cs0_dq12_rx_de-skew = <8>; ++ cs0_dq12_tx_de-skew = <9>; ++ cs0_dq13_rx_de-skew = <8>; ++ cs0_dq13_tx_de-skew = <8>; ++ cs0_dq14_rx_de-skew = <8>; ++ cs0_dq14_tx_de-skew = <9>; ++ cs0_dq15_rx_de-skew = <8>; ++ cs0_dq15_tx_de-skew = <8>; ++ cs0_dqs1_rx_de-skew = <8>; ++ cs0_dqs1p_tx_de-skew = <10>; ++ cs0_dqs1n_tx_de-skew = <10>; ++ ++ cs0_dm2_rx_de-skew = <8>; ++ cs0_dm2_tx_de-skew = <9>; ++ cs0_dq16_rx_de-skew = <8>; ++ cs0_dq16_tx_de-skew = <9>; ++ cs0_dq17_rx_de-skew = <8>; ++ cs0_dq17_tx_de-skew = <9>; ++ cs0_dq18_rx_de-skew = <8>; ++ cs0_dq18_tx_de-skew = <9>; ++ cs0_dq19_rx_de-skew = <8>; ++ cs0_dq19_tx_de-skew = <9>; ++ cs0_dq20_rx_de-skew = <8>; ++ cs0_dq20_tx_de-skew = <9>; ++ cs0_dq21_rx_de-skew = <8>; ++ cs0_dq21_tx_de-skew = <9>; ++ cs0_dq22_rx_de-skew = <8>; ++ cs0_dq22_tx_de-skew = <9>; ++ cs0_dq23_rx_de-skew = <8>; ++ cs0_dq23_tx_de-skew = <9>; ++ cs0_dqs2_rx_de-skew = <7>; ++ cs0_dqs2p_tx_de-skew = <10>; ++ cs0_dqs2n_tx_de-skew = <10>; ++ ++ cs0_dm3_rx_de-skew = <8>; ++ cs0_dm3_tx_de-skew = <8>; ++ cs0_dq24_rx_de-skew = <8>; ++ cs0_dq24_tx_de-skew = <9>; ++ cs0_dq25_rx_de-skew = <8>; ++ cs0_dq25_tx_de-skew = <8>; ++ cs0_dq26_rx_de-skew = <8>; ++ cs0_dq26_tx_de-skew = <8>; ++ cs0_dq27_rx_de-skew = <8>; ++ cs0_dq27_tx_de-skew = <8>; ++ cs0_dq28_rx_de-skew = <8>; ++ cs0_dq28_tx_de-skew = <8>; ++ cs0_dq29_rx_de-skew = <8>; ++ cs0_dq29_tx_de-skew = <8>; ++ cs0_dq30_rx_de-skew = <8>; ++ cs0_dq30_tx_de-skew = <8>; ++ cs0_dq31_rx_de-skew = <8>; ++ cs0_dq31_tx_de-skew = <8>; ++ cs0_dqs3_rx_de-skew = <8>; ++ cs0_dqs3p_tx_de-skew = <10>; ++ cs0_dqs3n_tx_de-skew = <10>; ++ ++ cs1_dm0_rx_de-skew = <8>; ++ cs1_dm0_tx_de-skew = <9>; ++ cs1_dq0_rx_de-skew = <8>; ++ cs1_dq0_tx_de-skew = <9>; ++ cs1_dq1_rx_de-skew = <8>; ++ cs1_dq1_tx_de-skew = <9>; ++ cs1_dq2_rx_de-skew = <8>; ++ cs1_dq2_tx_de-skew = <9>; ++ cs1_dq3_rx_de-skew = <8>; ++ cs1_dq3_tx_de-skew = <9>; ++ cs1_dq4_rx_de-skew = <8>; ++ cs1_dq4_tx_de-skew = <9>; ++ cs1_dq5_rx_de-skew = <8>; ++ cs1_dq5_tx_de-skew = <9>; ++ cs1_dq6_rx_de-skew = <8>; ++ cs1_dq6_tx_de-skew = <9>; ++ cs1_dq7_rx_de-skew = <8>; ++ cs1_dq7_tx_de-skew = <9>; ++ cs1_dqs0_rx_de-skew = <7>; ++ cs1_dqs0p_tx_de-skew = <10>; ++ cs1_dqs0n_tx_de-skew = <10>; ++ ++ cs1_dm1_rx_de-skew = <8>; ++ cs1_dm1_tx_de-skew = <8>; ++ cs1_dq8_rx_de-skew = <8>; ++ cs1_dq8_tx_de-skew = <9>; ++ cs1_dq9_rx_de-skew = <8>; ++ cs1_dq9_tx_de-skew = <8>; ++ cs1_dq10_rx_de-skew = <8>; ++ cs1_dq10_tx_de-skew = <9>; ++ cs1_dq11_rx_de-skew = <8>; ++ cs1_dq11_tx_de-skew = <8>; ++ cs1_dq12_rx_de-skew = <8>; ++ cs1_dq12_tx_de-skew = <9>; ++ cs1_dq13_rx_de-skew = <8>; ++ cs1_dq13_tx_de-skew = <8>; ++ cs1_dq14_rx_de-skew = <8>; ++ cs1_dq14_tx_de-skew = <9>; ++ cs1_dq15_rx_de-skew = <8>; ++ cs1_dq15_tx_de-skew = <8>; ++ cs1_dqs1_rx_de-skew = <8>; ++ cs1_dqs1p_tx_de-skew = <10>; ++ cs1_dqs1n_tx_de-skew = <10>; ++ ++ cs1_dm2_rx_de-skew = <8>; ++ cs1_dm2_tx_de-skew = <9>; ++ cs1_dq16_rx_de-skew = <8>; ++ cs1_dq16_tx_de-skew = <9>; ++ cs1_dq17_rx_de-skew = <8>; ++ cs1_dq17_tx_de-skew = <9>; ++ cs1_dq18_rx_de-skew = <8>; ++ cs1_dq18_tx_de-skew = <9>; ++ cs1_dq19_rx_de-skew = <8>; ++ cs1_dq19_tx_de-skew = <9>; ++ cs1_dq20_rx_de-skew = <8>; ++ cs1_dq20_tx_de-skew = <9>; ++ cs1_dq21_rx_de-skew = <8>; ++ cs1_dq21_tx_de-skew = <9>; ++ cs1_dq22_rx_de-skew = <8>; ++ cs1_dq22_tx_de-skew = <9>; ++ cs1_dq23_rx_de-skew = <8>; ++ cs1_dq23_tx_de-skew = <9>; ++ cs1_dqs2_rx_de-skew = <7>; ++ cs1_dqs2p_tx_de-skew = <10>; ++ cs1_dqs2n_tx_de-skew = <10>; ++ ++ cs1_dm3_rx_de-skew = <8>; ++ cs1_dm3_tx_de-skew = <8>; ++ cs1_dq24_rx_de-skew = <8>; ++ cs1_dq24_tx_de-skew = <9>; ++ cs1_dq25_rx_de-skew = <8>; ++ cs1_dq25_tx_de-skew = <8>; ++ cs1_dq26_rx_de-skew = <8>; ++ cs1_dq26_tx_de-skew = <8>; ++ cs1_dq27_rx_de-skew = <8>; ++ cs1_dq27_tx_de-skew = <8>; ++ cs1_dq28_rx_de-skew = <8>; ++ cs1_dq28_tx_de-skew = <8>; ++ cs1_dq29_rx_de-skew = <8>; ++ cs1_dq29_tx_de-skew = <8>; ++ cs1_dq30_rx_de-skew = <8>; ++ cs1_dq30_tx_de-skew = <8>; ++ cs1_dq31_rx_de-skew = <8>; ++ cs1_dq31_tx_de-skew = <8>; ++ cs1_dqs3_rx_de-skew = <8>; ++ cs1_dqs3p_tx_de-skew = <10>; ++ cs1_dqs3n_tx_de-skew = <10>; ++}; +diff --git a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts +index fadb35d978a9..d0db35366b68 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts +@@ -42,6 +42,7 @@ + + /dts-v1/; + #include "rk3328.dtsi" ++#include "rk3328-dram-box-plus-timing.dtsi" + + / { + model = "Firefly ROC-RK3328-CC Board"; +@@ -194,7 +195,37 @@ + + &dmc { + center-supply = <&vdd_logic>; +- status = "okay"; ++ system-status-freq = < ++ /*system status freq(KHz)*/ ++ SYS_STATUS_NORMAL 1066000 ++ SYS_STATUS_REBOOT 1066000 ++ SYS_STATUS_SUSPEND 1066000 ++ SYS_STATUS_VIDEO_1080P 1066000 ++ SYS_STATUS_VIDEO_4K 1066000 ++ SYS_STATUS_VIDEO_4K_10B 1066000 ++ SYS_STATUS_PERFORMANCE 1066000 ++ SYS_STATUS_BOOST 1066000 ++ >; ++ status = "okay"; ++}; ++ ++&dmc_opp_table { ++ rockchip,leakage-voltage-sel = < ++ 1 8 0 ++ 9 254 0 ++ >; ++ opp-933000000 { ++ opp-hz = /bits/ 64 <933000000>; ++ opp-microvolt = <1150000>; ++ opp-microvolt-L0 = <1150000>; ++ opp-microvolt-L1 = <1100000>; ++ }; ++ opp-1066000000 { ++ opp-hz = /bits/ 64 <1066000000>; ++ opp-microvolt = <1200000>; ++ opp-microvolt-L0 = <1200000>; ++ opp-microvolt-L1 = <1175000>; ++ }; + }; + + &display_subsystem { + +From ecea5988a70f04eecd2694d32416983b5108294d Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sat, 21 Apr 2018 13:21:24 +0200 +Subject: [PATCH] arm64: dts: rockchip: rk3328-box-trn9: use 1066MHz ddr + frequency + +--- + arch/arm64/boot/dts/rockchip/rk3328-box-trn9.dts | 29 +++++++++++++++++++++++- + 1 file changed, 28 insertions(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3328-box-trn9.dts b/arch/arm64/boot/dts/rockchip/rk3328-box-trn9.dts +index 55c4cbf6baff..da823ee47b6a 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3328-box-trn9.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3328-box-trn9.dts +@@ -42,6 +42,7 @@ + + /dts-v1/; + #include "rk3328.dtsi" ++#include "rk3328-dram-box-plus-timing.dtsi" + + / { + model = "Rockchip RK3328 TRN9"; +@@ -240,7 +241,33 @@ + + &dmc { + center-supply = <&vdd_logic>; +- status = "okay"; ++ system-status-freq = < ++ /*system status freq(KHz)*/ ++ SYS_STATUS_NORMAL 1066000 ++ SYS_STATUS_REBOOT 1066000 ++ SYS_STATUS_SUSPEND 1066000 ++ SYS_STATUS_VIDEO_1080P 1066000 ++ SYS_STATUS_VIDEO_4K 1066000 ++ SYS_STATUS_VIDEO_4K_10B 1066000 ++ SYS_STATUS_PERFORMANCE 1066000 ++ SYS_STATUS_BOOST 1066000 ++ >; ++ status = "okay"; ++}; ++ ++&dmc_opp_table { ++ opp-933000000 { ++ opp-hz = /bits/ 64 <933000000>; ++ opp-microvolt = <1150000>; ++ opp-microvolt-L0 = <1150000>; ++ opp-microvolt-L1 = <1100000>; ++ }; ++ opp-1066000000 { ++ opp-hz = /bits/ 64 <1066000000>; ++ opp-microvolt = <1200000>; ++ opp-microvolt-L0 = <1200000>; ++ opp-microvolt-L1 = <1175000>; ++ }; + }; + + &display_subsystem { diff --git a/patch/kernel/rockchip-default/01-linux-0006-rtl8211f.patch b/patch/kernel/rockchip-default/01-linux-0006-rtl8211f.patch new file mode 100644 index 000000000..5d497819a --- /dev/null +++ b/patch/kernel/rockchip-default/01-linux-0006-rtl8211f.patch @@ -0,0 +1,870 @@ +From c5300de0fe982ae8a78e1b95ef7bf30b744e4ca1 Mon Sep 17 00:00:00 2001 +From: Martin Blumenstingl +Date: Fri, 25 Nov 2016 14:12:01 +0100 +Subject: [PATCH] UPSTREAM: net: phy: realtek: fix enabling of the TX-delay for + RTL8211F + +The old logic always enabled the TX-delay when the phy-mode was set to +PHY_INTERFACE_MODE_RGMII. There are dedicated phy-modes which tell the +PHY driver to enable the RX and/or TX delays: +- PHY_INTERFACE_MODE_RGMII should disable the RX and TX delay in the + PHY (if required, the MAC should add the delays in this case) +- PHY_INTERFACE_MODE_RGMII_ID should enable RX and TX delay in the PHY +- PHY_INTERFACE_MODE_RGMII_TXID should enable the TX delay in the PHY +- PHY_INTERFACE_MODE_RGMII_RXID should enable the RX delay in the PHY + (currently not supported by RTL8211F) + +With this patch we enable the TX delay for PHY_INTERFACE_MODE_RGMII_ID +and PHY_INTERFACE_MODE_RGMII_TXID. +Additionally we now explicity disable the TX-delay, which seems to be +enabled automatically after a hard-reset of the PHY (by triggering it's +reset pin) to get a consistent state (as defined by the phy-mode). + +This fixes a compatibility problem with some SoCs where the TX-delay was +also added by the MAC. With the TX-delay being applied twice the TX +clock was off and TX traffic was broken or very slow (<10Mbit/s) on +1000Mbit/s links. + +Signed-off-by: Martin Blumenstingl +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +(cherry picked from commit e3230494b57ece68750e3e32d3e53d6b00917058) +--- + drivers/net/phy/realtek.c | 20 ++++++++++++-------- + 1 file changed, 12 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c +index 43ab691362d4..686f3b259dc0 100644 +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -102,15 +102,19 @@ static int rtl8211f_config_init(struct phy_device *phydev) + if (ret < 0) + return ret; + +- if (phydev->interface == PHY_INTERFACE_MODE_RGMII) { +- /* enable TXDLY */ +- phy_write(phydev, RTL8211F_PAGE_SELECT, 0xd08); +- reg = phy_read(phydev, 0x11); ++ phy_write(phydev, RTL8211F_PAGE_SELECT, 0xd08); ++ reg = phy_read(phydev, 0x11); ++ ++ /* enable TX-delay for rgmii-id and rgmii-txid, otherwise disable it */ ++ if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || ++ phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) + reg |= RTL8211F_TX_DELAY; +- phy_write(phydev, 0x11, reg); +- /* restore to default page 0 */ +- phy_write(phydev, RTL8211F_PAGE_SELECT, 0x0); +- } ++ else ++ reg &= ~RTL8211F_TX_DELAY; ++ ++ phy_write(phydev, 0x11, reg); ++ /* restore to default page 0 */ ++ phy_write(phydev, RTL8211F_PAGE_SELECT, 0x0); + + return 0; + } + +From 647c38d9964680f7fbb24c5a889ef74b23b4cbd4 Mon Sep 17 00:00:00 2001 +From: Kunihiko Hayashi +Date: Tue, 12 Sep 2017 18:54:35 +0900 +Subject: [PATCH] UPSTREAM: net: phy: realtek: rename RTL8211F_PAGE_SELECT to + RTL821x_PAGE_SELECT + +This renames the definition of page select register from +RTL8211F_PAGE_SELECT to RTL821x_PAGE_SELECT to use it across models. + +Signed-off-by: Kunihiko Hayashi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +(cherry picked from commit 013955a6556766a76f9f2cc31e740fc6db6ecff4) +--- + drivers/net/phy/realtek.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c +index 686f3b259dc0..d58cc8f518ac 100644 +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -22,11 +22,11 @@ + #define RTL821x_INER 0x12 + #define RTL821x_INER_INIT 0x6400 + #define RTL821x_INSR 0x13 ++#define RTL821x_PAGE_SELECT 0x1f + #define RTL8211E_INER_LINK_STATUS 0x400 + + #define RTL8211F_INER_LINK_STATUS 0x0010 + #define RTL8211F_INSR 0x1d +-#define RTL8211F_PAGE_SELECT 0x1f + #define RTL8211F_TX_DELAY 0x100 + + MODULE_DESCRIPTION("Realtek PHY driver"); +@@ -46,10 +46,10 @@ static int rtl8211f_ack_interrupt(struct phy_device *phydev) + { + int err; + +- phy_write(phydev, RTL8211F_PAGE_SELECT, 0xa43); ++ phy_write(phydev, RTL821x_PAGE_SELECT, 0xa43); + err = phy_read(phydev, RTL8211F_INSR); + /* restore to default page 0 */ +- phy_write(phydev, RTL8211F_PAGE_SELECT, 0x0); ++ phy_write(phydev, RTL821x_PAGE_SELECT, 0x0); + + return (err < 0) ? err : 0; + } +@@ -102,7 +102,7 @@ static int rtl8211f_config_init(struct phy_device *phydev) + if (ret < 0) + return ret; + +- phy_write(phydev, RTL8211F_PAGE_SELECT, 0xd08); ++ phy_write(phydev, RTL821x_PAGE_SELECT, 0xd08); + reg = phy_read(phydev, 0x11); + + /* enable TX-delay for rgmii-id and rgmii-txid, otherwise disable it */ +@@ -114,7 +114,7 @@ static int rtl8211f_config_init(struct phy_device *phydev) + + phy_write(phydev, 0x11, reg); + /* restore to default page 0 */ +- phy_write(phydev, RTL8211F_PAGE_SELECT, 0x0); ++ phy_write(phydev, RTL821x_PAGE_SELECT, 0x0); + + return 0; + } + +From 724532e7b4ad78722821763c639a73383a0f4418 Mon Sep 17 00:00:00 2001 +From: Jassi Brar +Date: Tue, 12 Sep 2017 18:54:36 +0900 +Subject: [PATCH] UPSTREAM: net: phy: realtek: add RTL8201F phy-id and + functions + +Add RTL8201F phy-id and the related functions to the driver. + +The original patch is as follows: +https://patchwork.kernel.org/patch/2538341/ + +Signed-off-by: Jongsung Kim +Signed-off-by: Jassi Brar +Signed-off-by: Kunihiko Hayashi +Reviewed-by: Andrew Lunn +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +(cherry picked from commit 513588dd44b09bb5fdd5066a4fbc1e7443b86d1c) +--- + drivers/net/phy/realtek.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 44 insertions(+) + +diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c +index d58cc8f518ac..422cf1f6a60c 100644 +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -29,10 +29,22 @@ + #define RTL8211F_INSR 0x1d + #define RTL8211F_TX_DELAY 0x100 + ++#define RTL8201F_ISR 0x1e ++#define RTL8201F_IER 0x13 ++ + MODULE_DESCRIPTION("Realtek PHY driver"); + MODULE_AUTHOR("Johnson Leung"); + MODULE_LICENSE("GPL"); + ++static int rtl8201_ack_interrupt(struct phy_device *phydev) ++{ ++ int err; ++ ++ err = phy_read(phydev, RTL8201F_ISR); ++ ++ return (err < 0) ? err : 0; ++} ++ + static int rtl821x_ack_interrupt(struct phy_device *phydev) + { + int err; +@@ -54,6 +66,25 @@ static int rtl8211f_ack_interrupt(struct phy_device *phydev) + return (err < 0) ? err : 0; + } + ++static int rtl8201_config_intr(struct phy_device *phydev) ++{ ++ int err; ++ ++ /* switch to page 7 */ ++ phy_write(phydev, RTL821x_PAGE_SELECT, 0x7); ++ ++ if (phydev->interrupts == PHY_INTERRUPT_ENABLED) ++ err = phy_write(phydev, RTL8201F_IER, ++ BIT(13) | BIT(12) | BIT(11)); ++ else ++ err = phy_write(phydev, RTL8201F_IER, 0); ++ ++ /* restore to default page 0 */ ++ phy_write(phydev, RTL821x_PAGE_SELECT, 0x0); ++ ++ return err; ++} ++ + static int rtl8211b_config_intr(struct phy_device *phydev) + { + int err; +@@ -129,6 +160,18 @@ static struct phy_driver realtek_drvs[] = { + .config_aneg = &genphy_config_aneg, + .read_status = &genphy_read_status, + .driver = { .owner = THIS_MODULE,}, ++ }, { ++ .phy_id = 0x001cc816, ++ .name = "RTL8201F 10/100Mbps Ethernet", ++ .phy_id_mask = 0x001fffff, ++ .features = PHY_BASIC_FEATURES, ++ .flags = PHY_HAS_INTERRUPT, ++ .config_aneg = &genphy_config_aneg, ++ .read_status = &genphy_read_status, ++ .ack_interrupt = &rtl8201_ack_interrupt, ++ .config_intr = &rtl8201_config_intr, ++ .suspend = genphy_suspend, ++ .resume = genphy_resume, + }, { + .phy_id = 0x001cc912, + .name = "RTL8211B Gigabit Ethernet", +@@ -186,6 +229,7 @@ static struct phy_driver realtek_drvs[] = { + module_phy_driver(realtek_drvs); + + static struct mdio_device_id __maybe_unused realtek_tbl[] = { ++ { 0x001cc816, 0x001fffff }, + { 0x001cc912, 0x001fffff }, + { 0x001cc914, 0x001fffff }, + { 0x001cc915, 0x001fffff }, + +From 933e1e195c40a941b6e5dec0c6a3a4bb7f804cf7 Mon Sep 17 00:00:00 2001 +From: Heiner Kallweit +Date: Sun, 12 Nov 2017 16:16:04 +0100 +Subject: [PATCH] UPSTREAM: net: phy: realtek: fix RTL8211F interrupt mode + +After commit b94d22d94ad22 "ARM64: dts: meson-gx: add external PHY +interrupt on some platforms" ethernet stopped working on my Odroid-C2 +which has a RTL8211F phy. + +It turned out that no interrupts were triggered. Further analysis +showed the register INER can't be altered on page 0. +Because register INSR needs to be accessed via page 0xa43 I assumed +that register INER needs to be accessed via some page too. +Some brute force check resulted in page 0xa42 being the right one. + +With this patch the phy is working properly in interrupt mode. + +Fixes: 3447cf2e9a11 ("net/phy: Add support for Realtek RTL8211F") +Signed-off-by: Heiner Kallweit +Tested-by: Jerome Brunet +Signed-off-by: David S. Miller +(cherry picked from commit 3697d058b08d5b874f0253de173ef72e5d648f9a) +--- + drivers/net/phy/realtek.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c +index 422cf1f6a60c..a30d0c08c63b 100644 +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -115,11 +115,13 @@ static int rtl8211f_config_intr(struct phy_device *phydev) + { + int err; + ++ phy_write(phydev, RTL821x_PAGE_SELECT, 0xa42); + if (phydev->interrupts == PHY_INTERRUPT_ENABLED) + err = phy_write(phydev, RTL821x_INER, + RTL8211F_INER_LINK_STATUS); + else + err = phy_write(phydev, RTL821x_INER, 0); ++ phy_write(phydev, RTL821x_PAGE_SELECT, 0); + + return err; + } + +From 046a2dc318a05236e06b09d8c0ca3f1005cbceca Mon Sep 17 00:00:00 2001 +From: Martin Blumenstingl +Date: Sat, 2 Dec 2017 22:51:24 +0100 +Subject: [PATCH] UPSTREAM: net: phy: realtek: use the BIT and GENMASK macros + +This makes it easier to compare the #defines with the datasheets. +No functional changes. + +Signed-off-by: Martin Blumenstingl +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +(cherry picked from commit 8cc5baefbc0266b6d6c8e99cb8568f59be36a575) +--- + drivers/net/phy/realtek.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c +index a30d0c08c63b..f8dc29a75828 100644 +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -13,21 +13,22 @@ + * option) any later version. + * + */ ++#include + #include + #include + + #define RTL821x_PHYSR 0x11 +-#define RTL821x_PHYSR_DUPLEX 0x2000 +-#define RTL821x_PHYSR_SPEED 0xc000 ++#define RTL821x_PHYSR_DUPLEX BIT(13) ++#define RTL821x_PHYSR_SPEED GENMASK(15, 14) + #define RTL821x_INER 0x12 + #define RTL821x_INER_INIT 0x6400 + #define RTL821x_INSR 0x13 + #define RTL821x_PAGE_SELECT 0x1f +-#define RTL8211E_INER_LINK_STATUS 0x400 ++#define RTL8211E_INER_LINK_STATUS BIT(10) + +-#define RTL8211F_INER_LINK_STATUS 0x0010 ++#define RTL8211F_INER_LINK_STATUS BIT(4) + #define RTL8211F_INSR 0x1d +-#define RTL8211F_TX_DELAY 0x100 ++#define RTL8211F_TX_DELAY BIT(8) + + #define RTL8201F_ISR 0x1e + #define RTL8201F_IER 0x13 + +From 7894b1cae69475242cdb1ca0fb639a5d70ac6316 Mon Sep 17 00:00:00 2001 +From: Martin Blumenstingl +Date: Sat, 2 Dec 2017 22:51:25 +0100 +Subject: [PATCH] UPSTREAM: net: phy: realtek: rename RTL821x_INER_INIT to + RTL8211B_INER_INIT + +This macro is only used by the RTL8211B code. RTL8211E and RTL8211F both +use other bits to initialize the RTL821x_INER register. +No functional changes. + +Signed-off-by: Martin Blumenstingl +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +(cherry picked from commit 69021e32ec3ef02170482f6ed8130febaed27357) +--- + drivers/net/phy/realtek.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c +index f8dc29a75828..89308eac4088 100644 +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -21,7 +21,7 @@ + #define RTL821x_PHYSR_DUPLEX BIT(13) + #define RTL821x_PHYSR_SPEED GENMASK(15, 14) + #define RTL821x_INER 0x12 +-#define RTL821x_INER_INIT 0x6400 ++#define RTL8211B_INER_INIT 0x6400 + #define RTL821x_INSR 0x13 + #define RTL821x_PAGE_SELECT 0x1f + #define RTL8211E_INER_LINK_STATUS BIT(10) +@@ -92,7 +92,7 @@ static int rtl8211b_config_intr(struct phy_device *phydev) + + if (phydev->interrupts == PHY_INTERRUPT_ENABLED) + err = phy_write(phydev, RTL821x_INER, +- RTL821x_INER_INIT); ++ RTL8211B_INER_INIT); + else + err = phy_write(phydev, RTL821x_INER, 0); + + +From f6e8b6c88c6b3d4925607575bc4387a289d49708 Mon Sep 17 00:00:00 2001 +From: Martin Blumenstingl +Date: Sat, 2 Dec 2017 22:51:26 +0100 +Subject: [PATCH] UPSTREAM: net: phy: realtek: group all register bit #defines + for RTL821x_INER + +This simply moves all register bit #defines which describe the (PHY +specific) bits in the RTL821x_INER right below the RTL821x_INER register +definition. This makes it easier to spot which registers and bits belong +together. +No functional changes. + +Signed-off-by: Martin Blumenstingl +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +(cherry picked from commit a82f266d240d87e6111878bbfe287024fb6857c1) +--- + drivers/net/phy/realtek.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c +index 89308eac4088..df97d903d2bf 100644 +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -20,13 +20,16 @@ + #define RTL821x_PHYSR 0x11 + #define RTL821x_PHYSR_DUPLEX BIT(13) + #define RTL821x_PHYSR_SPEED GENMASK(15, 14) ++ + #define RTL821x_INER 0x12 + #define RTL8211B_INER_INIT 0x6400 ++#define RTL8211E_INER_LINK_STATUS BIT(10) ++#define RTL8211F_INER_LINK_STATUS BIT(4) ++ + #define RTL821x_INSR 0x13 ++ + #define RTL821x_PAGE_SELECT 0x1f +-#define RTL8211E_INER_LINK_STATUS BIT(10) + +-#define RTL8211F_INER_LINK_STATUS BIT(4) + #define RTL8211F_INSR 0x1d + #define RTL8211F_TX_DELAY BIT(8) + + +From d5e2b112bb8e5707fc2fb727122ee5a8444ee462 Mon Sep 17 00:00:00 2001 +From: Martin Blumenstingl +Date: Sat, 2 Dec 2017 22:51:27 +0100 +Subject: [PATCH] UPSTREAM: net: phy: realtek: use the same indentation for all + #defines + +This simply makes the code easier to read. No functional changes. + +Signed-off-by: Martin Blumenstingl +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +(cherry picked from commit f609ab0ed8e7bef2cd61d230bf9e83e1ec5b9ddb) +--- + drivers/net/phy/realtek.c | 27 ++++++++++++++------------- + 1 file changed, 14 insertions(+), 13 deletions(-) + +diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c +index df97d903d2bf..701f34ad7d8d 100644 +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -17,24 +17,25 @@ + #include + #include + +-#define RTL821x_PHYSR 0x11 +-#define RTL821x_PHYSR_DUPLEX BIT(13) +-#define RTL821x_PHYSR_SPEED GENMASK(15, 14) ++#define RTL821x_PHYSR 0x11 ++#define RTL821x_PHYSR_DUPLEX BIT(13) ++#define RTL821x_PHYSR_SPEED GENMASK(15, 14) + +-#define RTL821x_INER 0x12 +-#define RTL8211B_INER_INIT 0x6400 +-#define RTL8211E_INER_LINK_STATUS BIT(10) +-#define RTL8211F_INER_LINK_STATUS BIT(4) ++#define RTL821x_INER 0x12 ++#define RTL8211B_INER_INIT 0x6400 ++#define RTL8211E_INER_LINK_STATUS BIT(10) ++#define RTL8211F_INER_LINK_STATUS BIT(4) + +-#define RTL821x_INSR 0x13 ++#define RTL821x_INSR 0x13 + +-#define RTL821x_PAGE_SELECT 0x1f ++#define RTL821x_PAGE_SELECT 0x1f + +-#define RTL8211F_INSR 0x1d +-#define RTL8211F_TX_DELAY BIT(8) ++#define RTL8211F_INSR 0x1d + +-#define RTL8201F_ISR 0x1e +-#define RTL8201F_IER 0x13 ++#define RTL8211F_TX_DELAY BIT(8) ++ ++#define RTL8201F_ISR 0x1e ++#define RTL8201F_IER 0x13 + + MODULE_DESCRIPTION("Realtek PHY driver"); + MODULE_AUTHOR("Johnson Leung"); + +From 8c16425a3c99a1cca4458eb17bd6414d65074027 Mon Sep 17 00:00:00 2001 +From: Martin Blumenstingl +Date: Sat, 2 Dec 2017 22:51:28 +0100 +Subject: [PATCH] UPSTREAM: net: phy: realtek: add utility functions to + read/write page addresses + +Realtek PHYs implement the concept of so-called "extension pages". The +reason for this is probably because these PHYs expose more registers +than available in the standard address range. +After all read/write operations on such a page are done the driver +should switch back to page 0 where the standard MII registers (such as +MII_BMCR) are available. + +When referring to such a register the datasheets of RTL8211E and +RTL8211F always specify: +- the page / "ext. page" which has to be written to RTL821x_PAGE_SELECT +- an address (sometimes also called reg) + +These new utility functions make the existing code easier to read since +it removes some duplication (switching back to page 0 is done within the +new helpers for example). + +No functional changes are intended. + +Signed-off-by: Martin Blumenstingl +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +(cherry picked from commit 136819a6e8df374e6b9b424586ff11c9e241a1cb) +--- + drivers/net/phy/realtek.c | 83 ++++++++++++++++++++++++++++++----------------- + 1 file changed, 53 insertions(+), 30 deletions(-) + +diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c +index 701f34ad7d8d..b1d52e61d91c 100644 +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -41,6 +41,39 @@ MODULE_DESCRIPTION("Realtek PHY driver"); + MODULE_AUTHOR("Johnson Leung"); + MODULE_LICENSE("GPL"); + ++static int rtl8211x_page_read(struct phy_device *phydev, u16 page, u16 address) ++{ ++ int ret; ++ ++ ret = phy_write(phydev, RTL821x_PAGE_SELECT, page); ++ if (ret) ++ return ret; ++ ++ ret = phy_read(phydev, address); ++ ++ /* restore to default page 0 */ ++ phy_write(phydev, RTL821x_PAGE_SELECT, 0x0); ++ ++ return ret; ++} ++ ++static int rtl8211x_page_write(struct phy_device *phydev, u16 page, ++ u16 address, u16 val) ++{ ++ int ret; ++ ++ ret = phy_write(phydev, RTL821x_PAGE_SELECT, page); ++ if (ret) ++ return ret; ++ ++ ret = phy_write(phydev, address, val); ++ ++ /* restore to default page 0 */ ++ phy_write(phydev, RTL821x_PAGE_SELECT, 0x0); ++ ++ return ret; ++} ++ + static int rtl8201_ack_interrupt(struct phy_device *phydev) + { + int err; +@@ -63,31 +96,21 @@ static int rtl8211f_ack_interrupt(struct phy_device *phydev) + { + int err; + +- phy_write(phydev, RTL821x_PAGE_SELECT, 0xa43); +- err = phy_read(phydev, RTL8211F_INSR); +- /* restore to default page 0 */ +- phy_write(phydev, RTL821x_PAGE_SELECT, 0x0); ++ err = rtl8211x_page_read(phydev, 0xa43, RTL8211F_INSR); + + return (err < 0) ? err : 0; + } + + static int rtl8201_config_intr(struct phy_device *phydev) + { +- int err; +- +- /* switch to page 7 */ +- phy_write(phydev, RTL821x_PAGE_SELECT, 0x7); ++ u16 val; + + if (phydev->interrupts == PHY_INTERRUPT_ENABLED) +- err = phy_write(phydev, RTL8201F_IER, +- BIT(13) | BIT(12) | BIT(11)); ++ val = BIT(13) | BIT(12) | BIT(11); + else +- err = phy_write(phydev, RTL8201F_IER, 0); ++ val = 0; + +- /* restore to default page 0 */ +- phy_write(phydev, RTL821x_PAGE_SELECT, 0x0); +- +- return err; ++ return rtl8211x_page_write(phydev, 0x7, RTL8201F_IER, val); + } + + static int rtl8211b_config_intr(struct phy_device *phydev) +@@ -118,41 +141,41 @@ static int rtl8211e_config_intr(struct phy_device *phydev) + + static int rtl8211f_config_intr(struct phy_device *phydev) + { +- int err; ++ u16 val; + +- phy_write(phydev, RTL821x_PAGE_SELECT, 0xa42); + if (phydev->interrupts == PHY_INTERRUPT_ENABLED) +- err = phy_write(phydev, RTL821x_INER, +- RTL8211F_INER_LINK_STATUS); ++ val = RTL8211F_INER_LINK_STATUS; + else +- err = phy_write(phydev, RTL821x_INER, 0); +- phy_write(phydev, RTL821x_PAGE_SELECT, 0); ++ val = 0; + +- return err; ++ return rtl8211x_page_write(phydev, 0xa42, RTL821x_INER, val); + } + + static int rtl8211f_config_init(struct phy_device *phydev) + { + int ret; +- u16 reg; ++ u16 val; + + ret = genphy_config_init(phydev); + if (ret < 0) + return ret; + +- phy_write(phydev, RTL821x_PAGE_SELECT, 0xd08); +- reg = phy_read(phydev, 0x11); ++ ret = rtl8211x_page_read(phydev, 0xd08, 0x11); ++ if (ret < 0) ++ return ret; ++ ++ val = ret & 0xffff; + + /* enable TX-delay for rgmii-id and rgmii-txid, otherwise disable it */ + if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || + phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) +- reg |= RTL8211F_TX_DELAY; ++ val |= RTL8211F_TX_DELAY; + else +- reg &= ~RTL8211F_TX_DELAY; ++ val &= ~RTL8211F_TX_DELAY; + +- phy_write(phydev, 0x11, reg); +- /* restore to default page 0 */ +- phy_write(phydev, RTL821x_PAGE_SELECT, 0x0); ++ ret = rtl8211x_page_write(phydev, 0xd08, 0x11, val); ++ if (ret) ++ return ret; + + return 0; + } + +From 13e556c6d4ece3c890edc414f205cc26381e9826 Mon Sep 17 00:00:00 2001 +From: Martin Blumenstingl +Date: Sat, 2 Dec 2017 23:06:48 +0100 +Subject: [PATCH] FROMLIST: net: phy: realtek: add support for configuring the + RX delay on RTL8211F + +On RTL8211F the RX delay can also be enabled/disabled. +The overall behavior of the RX delay is similar to the behavior of the +TX delay, which was already supported by the driver. + +The RX delay (similar to the TX delay) may be enabled using hardware pin +strapping. If the MAC already configures the RX delay (if required) then +the RX delay generated by the RTL8211F PHY has to be turned off. + +While here, update the comment regarding the TX delay why it has to be +enabled or disabled within the driver. +Also avoid code-duplication by extracting the code to mask/unmask bits +in a paged register into a new rtl8211x_page_mask_bits helper function. + +Signed-off-by: Martin Blumenstingl +--- + drivers/net/phy/realtek.c | 55 ++++++++++++++++++++++++++++++++++++++--------- + 1 file changed, 45 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c +index b1d52e61d91c..890ea9d18d27 100644 +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -32,7 +32,10 @@ + + #define RTL8211F_INSR 0x1d + +-#define RTL8211F_TX_DELAY BIT(8) ++#define RTL8211F_RX_DELAY_REG 0x15 ++#define RTL8211F_RX_DELAY_EN BIT(3) ++#define RTL8211F_TX_DELAY_REG 0x11 ++#define RTL8211F_TX_DELAY_EN BIT(8) + + #define RTL8201F_ISR 0x1e + #define RTL8201F_IER 0x13 +@@ -74,6 +77,23 @@ static int rtl8211x_page_write(struct phy_device *phydev, u16 page, + return ret; + } + ++static int rtl8211x_page_mask_bits(struct phy_device *phydev, u16 page, ++ u16 address, u16 mask, u16 set) ++{ ++ int ret; ++ u16 val; ++ ++ ret = rtl8211x_page_read(phydev, page, address); ++ if (ret < 0) ++ return ret; ++ ++ val = ret & 0xffff; ++ val &= ~mask; ++ val |= (set & mask); ++ ++ return rtl8211x_page_write(phydev, page, address, val); ++} ++ + static int rtl8201_ack_interrupt(struct phy_device *phydev) + { + int err; +@@ -160,20 +180,35 @@ static int rtl8211f_config_init(struct phy_device *phydev) + if (ret < 0) + return ret; + +- ret = rtl8211x_page_read(phydev, 0xd08, 0x11); +- if (ret < 0) +- return ret; ++ /* ++ * enable TX-delay for rgmii-id and rgmii-txid, otherwise disable it. ++ * this is needed because it can be enabled by pin strapping and ++ * conflict with the TX-delay configured by the MAC. ++ */ ++ if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || ++ phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) ++ val = RTL8211F_TX_DELAY_EN; ++ else ++ val = 0; + +- val = ret & 0xffff; ++ ret = rtl8211x_page_mask_bits(phydev, 0xd08, RTL8211F_TX_DELAY_REG, ++ RTL8211F_TX_DELAY_EN, val); ++ if (ret) ++ return ret; + +- /* enable TX-delay for rgmii-id and rgmii-txid, otherwise disable it */ ++ /* ++ * enable RX-delay for rgmii-id and rgmii-rxid, otherwise disable it. ++ * this is needed because it can be enabled by pin strapping and ++ * conflict with the RX-delay configured by the MAC. ++ */ + if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || +- phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) +- val |= RTL8211F_TX_DELAY; ++ phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) ++ val = RTL8211F_RX_DELAY_EN; + else +- val &= ~RTL8211F_TX_DELAY; ++ val = 0; + +- ret = rtl8211x_page_write(phydev, 0xd08, 0x11, val); ++ ret = rtl8211x_page_mask_bits(phydev, 0xd08, RTL8211F_RX_DELAY_REG, ++ RTL8211F_RX_DELAY_EN, val); + if (ret) + return ret; + + +From e8fa4ce26460af84f028b7d215134caa33aa9ecb Mon Sep 17 00:00:00 2001 +From: Martin Blumenstingl +Date: Sat, 2 Dec 2017 23:06:49 +0100 +Subject: [PATCH] FROMLIST: net: phy: realtek: configure the INTB pin on + RTL8211F + +The interrupt pin on the RTL8211F PHY can be used in two different +modes: +INTB +- the default mode of the PHY +- interrupts can be configured through page 0xa42 register RTL821x_INER +- interrupts can be ACK'ed through RTL8211F_INSR +- it acts as a level-interrupt which is active low +- Wake-on-LAN "wakeup" status is available in RTL8211F_INSR bit 7 + +PMEB: +- special mode for Wake-on-LAN +- interrupts configured through page 0xa42 register RTL821x_INER are + disabled +- it supports a "pulse low" waveform for the interrupt + +For now we simply force the pin into INTB mode since the PHY driver does +not support Wake-on-LAN yet. + +Signed-off-by: Martin Blumenstingl +--- + drivers/net/phy/realtek.c | 27 +++++++++++++++++++++++++-- + 1 file changed, 25 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c +index 890ea9d18d27..f307d220b49a 100644 +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -40,6 +40,9 @@ + #define RTL8201F_ISR 0x1e + #define RTL8201F_IER 0x13 + ++#define RTL8211F_INTBCR 0x16 ++#define RTL8211F_INTBCR_INTB_PMEB BIT(5) ++ + MODULE_DESCRIPTION("Realtek PHY driver"); + MODULE_AUTHOR("Johnson Leung"); + MODULE_LICENSE("GPL"); +@@ -161,12 +164,32 @@ static int rtl8211e_config_intr(struct phy_device *phydev) + + static int rtl8211f_config_intr(struct phy_device *phydev) + { ++ int err; + u16 val; + +- if (phydev->interrupts == PHY_INTERRUPT_ENABLED) ++ if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { ++ /* ++ * The interrupt pin has two functions: ++ * 0: INTB: it acts as interrupt pin which can be configured ++ * through RTL821x_INER and the status can be read through ++ * RTL8211F_INSR ++ * 1: PMEB: a special "Power Management Event" mode for ++ * Wake-on-LAN operation (with support for a "pulse low" ++ * wave format). Interrupts configured through RTL821x_INER ++ * will not work in this mode ++ * ++ * select INTB mode in the "INTB pin control" register to ++ * ensure that the interrupt pin is in the correct mode. ++ */ ++ err = rtl8211x_page_mask_bits(phydev, 0xd40, RTL8211F_INTBCR, ++ RTL8211F_INTBCR_INTB_PMEB, 0); ++ if (err) ++ return err; ++ + val = RTL8211F_INER_LINK_STATUS; +- else ++ } else { + val = 0; ++ } + + return rtl8211x_page_write(phydev, 0xa42, RTL821x_INER, val); + } + +From dd026c252cd898bca0b85eb14aa6479b415d2471 Mon Sep 17 00:00:00 2001 +From: Martin Blumenstingl +Date: Sat, 2 Dec 2017 23:06:50 +0100 +Subject: [PATCH] FROMLIST: net: phy: realtek: add more interrupt bits for + RTL8211E and RTL8211F + +This documents a few more bits in the RTL821x_INER register for RTL8211E +and RTL8211F. These are added only to document them (as no public +datasheets are available for these PHYs), they are currently not used. + +Signed-off-by: Martin Blumenstingl +--- + drivers/net/phy/realtek.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c +index f307d220b49a..15d342eefd6d 100644 +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -24,7 +24,14 @@ + #define RTL821x_INER 0x12 + #define RTL8211B_INER_INIT 0x6400 + #define RTL8211E_INER_LINK_STATUS BIT(10) ++#define RTL8211E_INER_ANEG_COMPLETED BIT(11) ++#define RTL8211E_INER_PAGE_RECEIVED BIT(12) ++#define RTL8211E_INER_ANEG_ERROR BIT(15) + #define RTL8211F_INER_LINK_STATUS BIT(4) ++#define RTL8211F_INER_PHY_REGISTER_ACCESSIBLE BIT(5) ++#define RTL8211F_INER_WOL_PME BIT(7) ++#define RTL8211F_INER_ALDPS_STATE_CHANGE BIT(9) ++#define RTL8211F_INER_JABBER BIT(10) + + #define RTL821x_INSR 0x13 + diff --git a/patch/kernel/rockchip-default/01-linux-0007-dtoverlay-configfs.patch b/patch/kernel/rockchip-default/01-linux-0007-dtoverlay-configfs.patch new file mode 100644 index 000000000..ee3b0a125 --- /dev/null +++ b/patch/kernel/rockchip-default/01-linux-0007-dtoverlay-configfs.patch @@ -0,0 +1,1120 @@ +From bb0e3fa6305fe3dead0aa670d7979d6ebcbaf47d Mon Sep 17 00:00:00 2001 +From: Pantelis Antoniou +Date: Thu, 22 Oct 2015 23:30:04 +0300 +Subject: [PATCH] UPSTREAM: configfs: implement binary attributes + +ConfigFS lacked binary attributes up until now. This patch +introduces support for binary attributes in a somewhat similar +manner of sysfs binary attributes albeit with changes that +fit the configfs usage model. + +Problems that configfs binary attributes fix are everything that +requires a binary blob as part of the configuration of a resource, +such as bitstream loading for FPGAs, DTBs for dynamically created +devices etc. + +Look at Documentation/filesystems/configfs/configfs.txt for internals +and howto use them. + +This patch is against linux-next as of today that contains +Christoph's configfs rework. + +Signed-off-by: Pantelis Antoniou +[hch: folded a fix from Geert Uytterhoeven ] +[hch: a few tiny updates based on review feedback] +Signed-off-by: Christoph Hellwig +(cherry picked from commit 03607ace807b414eab46323c794b6fb8fcc2d48c) +--- + Documentation/filesystems/configfs/configfs.txt | 57 +++++- + fs/configfs/configfs_internal.h | 14 +- + fs/configfs/dir.c | 18 +- + fs/configfs/file.c | 255 +++++++++++++++++++++++- + fs/configfs/inode.c | 2 +- + include/linux/configfs.h | 50 +++++ + 6 files changed, 374 insertions(+), 22 deletions(-) + +diff --git a/Documentation/filesystems/configfs/configfs.txt b/Documentation/filesystems/configfs/configfs.txt +index af68efdbbfad..e5fe521eea1d 100644 +--- a/Documentation/filesystems/configfs/configfs.txt ++++ b/Documentation/filesystems/configfs/configfs.txt +@@ -51,15 +51,27 @@ configfs tree is always there, whether mounted on /config or not. + An item is created via mkdir(2). The item's attributes will also + appear at this time. readdir(3) can determine what the attributes are, + read(2) can query their default values, and write(2) can store new +-values. Like sysfs, attributes should be ASCII text files, preferably +-with only one value per file. The same efficiency caveats from sysfs +-apply. Don't mix more than one attribute in one attribute file. +- +-Like sysfs, configfs expects write(2) to store the entire buffer at +-once. When writing to configfs attributes, userspace processes should +-first read the entire file, modify the portions they wish to change, and +-then write the entire buffer back. Attribute files have a maximum size +-of one page (PAGE_SIZE, 4096 on i386). ++values. Don't mix more than one attribute in one attribute file. ++ ++There are two types of configfs attributes: ++ ++* Normal attributes, which similar to sysfs attributes, are small ASCII text ++files, with a maximum size of one page (PAGE_SIZE, 4096 on i386). Preferably ++only one value per file should be used, and the same caveats from sysfs apply. ++Configfs expects write(2) to store the entire buffer at once. When writing to ++normal configfs attributes, userspace processes should first read the entire ++file, modify the portions they wish to change, and then write the entire ++buffer back. ++ ++* Binary attributes, which are somewhat similar to sysfs binary attributes, ++but with a few slight changes to semantics. The PAGE_SIZE limitation does not ++apply, but the whole binary item must fit in single kernel vmalloc'ed buffer. ++The write(2) calls from user space are buffered, and the attributes' ++write_bin_attribute method will be invoked on the final close, therefore it is ++imperative for user-space to check the return code of close(2) in order to ++verify that the operation finished successfully. ++To avoid a malicious user OOMing the kernel, there's a per-binary attribute ++maximum buffer value. + + When an item needs to be destroyed, remove it with rmdir(2). An + item cannot be destroyed if any other item has a link to it (via +@@ -171,6 +183,7 @@ among other things. For that, it needs a type. + struct configfs_item_operations *ct_item_ops; + struct configfs_group_operations *ct_group_ops; + struct configfs_attribute **ct_attrs; ++ struct configfs_bin_attribute **ct_bin_attrs; + }; + + The most basic function of a config_item_type is to define what +@@ -201,6 +214,32 @@ be called whenever userspace asks for a read(2) on the attribute. If an + attribute is writable and provides a ->store method, that method will be + be called whenever userspace asks for a write(2) on the attribute. + ++[struct configfs_bin_attribute] ++ ++ struct configfs_attribute { ++ struct configfs_attribute cb_attr; ++ void *cb_private; ++ size_t cb_max_size; ++ }; ++ ++The binary attribute is used when the one needs to use binary blob to ++appear as the contents of a file in the item's configfs directory. ++To do so add the binary attribute to the NULL-terminated array ++config_item_type->ct_bin_attrs, and the item appears in configfs, the ++attribute file will appear with the configfs_bin_attribute->cb_attr.ca_name ++filename. configfs_bin_attribute->cb_attr.ca_mode specifies the file ++permissions. ++The cb_private member is provided for use by the driver, while the ++cb_max_size member specifies the maximum amount of vmalloc buffer ++to be used. ++ ++If binary attribute is readable and the config_item provides a ++ct_item_ops->read_bin_attribute() method, that method will be called ++whenever userspace asks for a read(2) on the attribute. The converse ++will happen for write(2). The reads/writes are bufferred so only a ++single read/write will occur; the attributes' need not concern itself ++with it. ++ + [struct config_group] + + A config_item cannot live in a vacuum. The only way one can be created +diff --git a/fs/configfs/configfs_internal.h b/fs/configfs/configfs_internal.h +index b65d1ef532d5..ccc31fa6f1a7 100644 +--- a/fs/configfs/configfs_internal.h ++++ b/fs/configfs/configfs_internal.h +@@ -53,13 +53,14 @@ struct configfs_dirent { + #define CONFIGFS_ROOT 0x0001 + #define CONFIGFS_DIR 0x0002 + #define CONFIGFS_ITEM_ATTR 0x0004 ++#define CONFIGFS_ITEM_BIN_ATTR 0x0008 + #define CONFIGFS_ITEM_LINK 0x0020 + #define CONFIGFS_USET_DIR 0x0040 + #define CONFIGFS_USET_DEFAULT 0x0080 + #define CONFIGFS_USET_DROPPING 0x0100 + #define CONFIGFS_USET_IN_MKDIR 0x0200 + #define CONFIGFS_USET_CREATING 0x0400 +-#define CONFIGFS_NOT_PINNED (CONFIGFS_ITEM_ATTR) ++#define CONFIGFS_NOT_PINNED (CONFIGFS_ITEM_ATTR | CONFIGFS_ITEM_BIN_ATTR) + + extern struct mutex configfs_symlink_mutex; + extern spinlock_t configfs_dirent_lock; +@@ -72,6 +73,8 @@ extern struct inode * configfs_new_inode(umode_t mode, struct configfs_dirent *, + extern int configfs_create(struct dentry *, umode_t mode, void (*init)(struct inode *)); + + extern int configfs_create_file(struct config_item *, const struct configfs_attribute *); ++extern int configfs_create_bin_file(struct config_item *, ++ const struct configfs_bin_attribute *); + extern int configfs_make_dirent(struct configfs_dirent *, + struct dentry *, void *, umode_t, int); + extern int configfs_dirent_is_ready(struct configfs_dirent *); +@@ -88,7 +91,7 @@ extern void configfs_release_fs(void); + extern struct rw_semaphore configfs_rename_sem; + extern const struct file_operations configfs_dir_operations; + extern const struct file_operations configfs_file_operations; +-extern const struct file_operations bin_fops; ++extern const struct file_operations configfs_bin_file_operations; + extern const struct inode_operations configfs_dir_inode_operations; + extern const struct inode_operations configfs_root_inode_operations; + extern const struct inode_operations configfs_symlink_inode_operations; +@@ -119,6 +122,13 @@ static inline struct configfs_attribute * to_attr(struct dentry * dentry) + return ((struct configfs_attribute *) sd->s_element); + } + ++static inline struct configfs_bin_attribute *to_bin_attr(struct dentry *dentry) ++{ ++ struct configfs_attribute *attr = to_attr(dentry); ++ ++ return container_of(attr, struct configfs_bin_attribute, cb_attr); ++} ++ + static inline struct config_item *configfs_get_config_item(struct dentry *dentry) + { + struct config_item * item = NULL; +diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c +index a7a1b218f308..7ae97e83f121 100644 +--- a/fs/configfs/dir.c ++++ b/fs/configfs/dir.c +@@ -255,6 +255,12 @@ static void configfs_init_file(struct inode * inode) + inode->i_fop = &configfs_file_operations; + } + ++static void configfs_init_bin_file(struct inode *inode) ++{ ++ inode->i_size = 0; ++ inode->i_fop = &configfs_bin_file_operations; ++} ++ + static void init_symlink(struct inode * inode) + { + inode->i_op = &configfs_symlink_inode_operations; +@@ -423,7 +429,9 @@ static int configfs_attach_attr(struct configfs_dirent * sd, struct dentry * den + spin_unlock(&configfs_dirent_lock); + + error = configfs_create(dentry, (attr->ca_mode & S_IALLUGO) | S_IFREG, +- configfs_init_file); ++ (sd->s_type & CONFIGFS_ITEM_BIN_ATTR) ? ++ configfs_init_bin_file : ++ configfs_init_file); + if (error) { + configfs_put(sd); + return error; +@@ -583,6 +591,7 @@ static int populate_attrs(struct config_item *item) + { + struct config_item_type *t = item->ci_type; + struct configfs_attribute *attr; ++ struct configfs_bin_attribute *bin_attr; + int error = 0; + int i; + +@@ -594,6 +603,13 @@ static int populate_attrs(struct config_item *item) + break; + } + } ++ if (t->ct_bin_attrs) { ++ for (i = 0; (bin_attr = t->ct_bin_attrs[i]) != NULL; i++) { ++ error = configfs_create_bin_file(item, bin_attr); ++ if (error) ++ break; ++ } ++ } + + if (error) + detach_attrs(item); +diff --git a/fs/configfs/file.c b/fs/configfs/file.c +index d39099ea7df7..3687187c8ea5 100644 +--- a/fs/configfs/file.c ++++ b/fs/configfs/file.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + #include + + #include +@@ -48,6 +49,10 @@ struct configfs_buffer { + struct configfs_item_operations * ops; + struct mutex mutex; + int needs_read_fill; ++ bool read_in_progress; ++ bool write_in_progress; ++ char *bin_buffer; ++ int bin_buffer_size; + }; + + +@@ -123,6 +128,87 @@ out: + return retval; + } + ++/** ++ * configfs_read_bin_file - read a binary attribute. ++ * @file: file pointer. ++ * @buf: buffer to fill. ++ * @count: number of bytes to read. ++ * @ppos: starting offset in file. ++ * ++ * Userspace wants to read a binary attribute file. The attribute ++ * descriptor is in the file's ->d_fsdata. The target item is in the ++ * directory's ->d_fsdata. ++ * ++ * We check whether we need to refill the buffer. If so we will ++ * call the attributes' attr->read() twice. The first time we ++ * will pass a NULL as a buffer pointer, which the attributes' method ++ * will use to return the size of the buffer required. If no error ++ * occurs we will allocate the buffer using vmalloc and call ++ * attr->read() again passing that buffer as an argument. ++ * Then we just copy to user-space using simple_read_from_buffer. ++ */ ++ ++static ssize_t ++configfs_read_bin_file(struct file *file, char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct configfs_buffer *buffer = file->private_data; ++ struct dentry *dentry = file->f_path.dentry; ++ struct config_item *item = to_item(dentry->d_parent); ++ struct configfs_bin_attribute *bin_attr = to_bin_attr(dentry); ++ ssize_t retval = 0; ++ ssize_t len = min_t(size_t, count, PAGE_SIZE); ++ ++ mutex_lock(&buffer->mutex); ++ ++ /* we don't support switching read/write modes */ ++ if (buffer->write_in_progress) { ++ retval = -ETXTBSY; ++ goto out; ++ } ++ buffer->read_in_progress = 1; ++ ++ if (buffer->needs_read_fill) { ++ /* perform first read with buf == NULL to get extent */ ++ len = bin_attr->read(item, NULL, 0); ++ if (len <= 0) { ++ retval = len; ++ goto out; ++ } ++ ++ /* do not exceed the maximum value */ ++ if (bin_attr->cb_max_size && len > bin_attr->cb_max_size) { ++ retval = -EFBIG; ++ goto out; ++ } ++ ++ buffer->bin_buffer = vmalloc(len); ++ if (buffer->bin_buffer == NULL) { ++ retval = -ENOMEM; ++ goto out; ++ } ++ buffer->bin_buffer_size = len; ++ ++ /* perform second read to fill buffer */ ++ len = bin_attr->read(item, buffer->bin_buffer, len); ++ if (len < 0) { ++ retval = len; ++ vfree(buffer->bin_buffer); ++ buffer->bin_buffer_size = 0; ++ buffer->bin_buffer = NULL; ++ goto out; ++ } ++ ++ buffer->needs_read_fill = 0; ++ } ++ ++ retval = simple_read_from_buffer(buf, count, ppos, buffer->bin_buffer, ++ buffer->bin_buffer_size); ++out: ++ mutex_unlock(&buffer->mutex); ++ return retval; ++} ++ + + /** + * fill_write_buffer - copy buffer from userspace. +@@ -209,10 +295,80 @@ configfs_write_file(struct file *file, const char __user *buf, size_t count, lof + return len; + } + +-static int check_perm(struct inode * inode, struct file * file) ++/** ++ * configfs_write_bin_file - write a binary attribute. ++ * @file: file pointer ++ * @buf: data to write ++ * @count: number of bytes ++ * @ppos: starting offset ++ * ++ * Writing to a binary attribute file is similar to a normal read. ++ * We buffer the consecutive writes (binary attribute files do not ++ * support lseek) in a continuously growing buffer, but we don't ++ * commit until the close of the file. ++ */ ++ ++static ssize_t ++configfs_write_bin_file(struct file *file, const char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct configfs_buffer *buffer = file->private_data; ++ struct dentry *dentry = file->f_path.dentry; ++ struct configfs_bin_attribute *bin_attr = to_bin_attr(dentry); ++ void *tbuf = NULL; ++ ssize_t len; ++ ++ mutex_lock(&buffer->mutex); ++ ++ /* we don't support switching read/write modes */ ++ if (buffer->read_in_progress) { ++ len = -ETXTBSY; ++ goto out; ++ } ++ buffer->write_in_progress = 1; ++ ++ /* buffer grows? */ ++ if (*ppos + count > buffer->bin_buffer_size) { ++ ++ if (bin_attr->cb_max_size && ++ *ppos + count > bin_attr->cb_max_size) { ++ len = -EFBIG; ++ } ++ ++ tbuf = vmalloc(*ppos + count); ++ if (tbuf == NULL) { ++ len = -ENOMEM; ++ goto out; ++ } ++ ++ /* copy old contents */ ++ if (buffer->bin_buffer) { ++ memcpy(tbuf, buffer->bin_buffer, ++ buffer->bin_buffer_size); ++ vfree(buffer->bin_buffer); ++ } ++ ++ /* clear the new area */ ++ memset(tbuf + buffer->bin_buffer_size, 0, ++ *ppos + count - buffer->bin_buffer_size); ++ buffer->bin_buffer = tbuf; ++ buffer->bin_buffer_size = *ppos + count; ++ } ++ ++ len = simple_write_to_buffer(buffer->bin_buffer, ++ buffer->bin_buffer_size, ppos, buf, count); ++ if (len > 0) ++ *ppos += len; ++out: ++ mutex_unlock(&buffer->mutex); ++ return len; ++} ++ ++static int check_perm(struct inode * inode, struct file * file, int type) + { + struct config_item *item = configfs_get_config_item(file->f_path.dentry->d_parent); + struct configfs_attribute * attr = to_attr(file->f_path.dentry); ++ struct configfs_bin_attribute *bin_attr = NULL; + struct configfs_buffer * buffer; + struct configfs_item_operations * ops = NULL; + int error = 0; +@@ -220,6 +376,9 @@ static int check_perm(struct inode * inode, struct file * file) + if (!item || !attr) + goto Einval; + ++ if (type & CONFIGFS_ITEM_BIN_ATTR) ++ bin_attr = to_bin_attr(file->f_path.dentry); ++ + /* Grab the module reference for this attribute if we have one */ + if (!try_module_get(attr->ca_owner)) { + error = -ENODEV; +@@ -236,9 +395,14 @@ static int check_perm(struct inode * inode, struct file * file) + * and we must have a store method. + */ + if (file->f_mode & FMODE_WRITE) { +- if (!(inode->i_mode & S_IWUGO) || !attr->store) ++ if (!(inode->i_mode & S_IWUGO)) ++ goto Eaccess; ++ ++ if ((type & CONFIGFS_ITEM_ATTR) && !attr->store) + goto Eaccess; + ++ if ((type & CONFIGFS_ITEM_BIN_ATTR) && !bin_attr->write) ++ goto Eaccess; + } + + /* File needs read support. +@@ -246,7 +410,13 @@ static int check_perm(struct inode * inode, struct file * file) + * must be a show method for it. + */ + if (file->f_mode & FMODE_READ) { +- if (!(inode->i_mode & S_IRUGO) || !attr->show) ++ if (!(inode->i_mode & S_IRUGO)) ++ goto Eaccess; ++ ++ if ((type & CONFIGFS_ITEM_ATTR) && !attr->show) ++ goto Eaccess; ++ ++ if ((type & CONFIGFS_ITEM_BIN_ATTR) && !bin_attr->read) + goto Eaccess; + } + +@@ -260,6 +430,8 @@ static int check_perm(struct inode * inode, struct file * file) + } + mutex_init(&buffer->mutex); + buffer->needs_read_fill = 1; ++ buffer->read_in_progress = 0; ++ buffer->write_in_progress = 0; + buffer->ops = ops; + file->private_data = buffer; + goto Done; +@@ -277,12 +449,7 @@ static int check_perm(struct inode * inode, struct file * file) + return error; + } + +-static int configfs_open_file(struct inode * inode, struct file * filp) +-{ +- return check_perm(inode,filp); +-} +- +-static int configfs_release(struct inode * inode, struct file * filp) ++static int configfs_release(struct inode *inode, struct file *filp) + { + struct config_item * item = to_item(filp->f_path.dentry->d_parent); + struct configfs_attribute * attr = to_attr(filp->f_path.dentry); +@@ -303,6 +470,47 @@ static int configfs_release(struct inode * inode, struct file * filp) + return 0; + } + ++static int configfs_open_file(struct inode *inode, struct file *filp) ++{ ++ return check_perm(inode, filp, CONFIGFS_ITEM_ATTR); ++} ++ ++static int configfs_open_bin_file(struct inode *inode, struct file *filp) ++{ ++ return check_perm(inode, filp, CONFIGFS_ITEM_BIN_ATTR); ++} ++ ++static int configfs_release_bin_file(struct inode *inode, struct file *filp) ++{ ++ struct configfs_buffer *buffer = filp->private_data; ++ struct dentry *dentry = filp->f_path.dentry; ++ struct config_item *item = to_item(dentry->d_parent); ++ struct configfs_bin_attribute *bin_attr = to_bin_attr(dentry); ++ ssize_t len = 0; ++ int ret; ++ ++ buffer->read_in_progress = 0; ++ ++ if (buffer->write_in_progress) { ++ buffer->write_in_progress = 0; ++ ++ len = bin_attr->write(item, buffer->bin_buffer, ++ buffer->bin_buffer_size); ++ ++ /* vfree on NULL is safe */ ++ vfree(buffer->bin_buffer); ++ buffer->bin_buffer = NULL; ++ buffer->bin_buffer_size = 0; ++ buffer->needs_read_fill = 1; ++ } ++ ++ ret = configfs_release(inode, filp); ++ if (len < 0) ++ return len; ++ return ret; ++} ++ ++ + const struct file_operations configfs_file_operations = { + .read = configfs_read_file, + .write = configfs_write_file, +@@ -311,6 +519,14 @@ const struct file_operations configfs_file_operations = { + .release = configfs_release, + }; + ++const struct file_operations configfs_bin_file_operations = { ++ .read = configfs_read_bin_file, ++ .write = configfs_write_bin_file, ++ .llseek = NULL, /* bin file is not seekable */ ++ .open = configfs_open_bin_file, ++ .release = configfs_release_bin_file, ++}; ++ + /** + * configfs_create_file - create an attribute file for an item. + * @item: item we're creating for. +@@ -332,3 +548,24 @@ int configfs_create_file(struct config_item * item, const struct configfs_attrib + return error; + } + ++/** ++ * configfs_create_bin_file - create a binary attribute file for an item. ++ * @item: item we're creating for. ++ * @attr: atrribute descriptor. ++ */ ++ ++int configfs_create_bin_file(struct config_item *item, ++ const struct configfs_bin_attribute *bin_attr) ++{ ++ struct dentry *dir = item->ci_dentry; ++ struct configfs_dirent *parent_sd = dir->d_fsdata; ++ umode_t mode = (bin_attr->cb_attr.ca_mode & S_IALLUGO) | S_IFREG; ++ int error = 0; ++ ++ mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_NORMAL); ++ error = configfs_make_dirent(parent_sd, NULL, (void *) bin_attr, mode, ++ CONFIGFS_ITEM_BIN_ATTR); ++ mutex_unlock(&dir->d_inode->i_mutex); ++ ++ return error; ++} +diff --git a/fs/configfs/inode.c b/fs/configfs/inode.c +index eae87575e681..0cc810e9dccc 100644 +--- a/fs/configfs/inode.c ++++ b/fs/configfs/inode.c +@@ -218,7 +218,7 @@ const unsigned char * configfs_get_name(struct configfs_dirent *sd) + if (sd->s_type & (CONFIGFS_DIR | CONFIGFS_ITEM_LINK)) + return sd->s_dentry->d_name.name; + +- if (sd->s_type & CONFIGFS_ITEM_ATTR) { ++ if (sd->s_type & (CONFIGFS_ITEM_ATTR | CONFIGFS_ITEM_BIN_ATTR)) { + attr = sd->s_element; + return attr->ca_name; + } +diff --git a/include/linux/configfs.h b/include/linux/configfs.h +index 758a029011b1..f7300d023dbe 100644 +--- a/include/linux/configfs.h ++++ b/include/linux/configfs.h +@@ -51,6 +51,7 @@ struct module; + struct configfs_item_operations; + struct configfs_group_operations; + struct configfs_attribute; ++struct configfs_bin_attribute; + struct configfs_subsystem; + + struct config_item { +@@ -84,6 +85,7 @@ struct config_item_type { + struct configfs_item_operations *ct_item_ops; + struct configfs_group_operations *ct_group_ops; + struct configfs_attribute **ct_attrs; ++ struct configfs_bin_attribute **ct_bin_attrs; + }; + + /** +@@ -154,6 +156,54 @@ static struct configfs_attribute _pfx##attr_##_name = { \ + .store = _pfx##_name##_store, \ + } + ++struct file; ++struct vm_area_struct; ++ ++struct configfs_bin_attribute { ++ struct configfs_attribute cb_attr; /* std. attribute */ ++ void *cb_private; /* for user */ ++ size_t cb_max_size; /* max core size */ ++ ssize_t (*read)(struct config_item *, void *, size_t); ++ ssize_t (*write)(struct config_item *, const void *, size_t); ++}; ++ ++#define CONFIGFS_BIN_ATTR(_pfx, _name, _priv, _maxsz) \ ++static struct configfs_bin_attribute _pfx##attr_##_name = { \ ++ .cb_attr = { \ ++ .ca_name = __stringify(_name), \ ++ .ca_mode = S_IRUGO | S_IWUSR, \ ++ .ca_owner = THIS_MODULE, \ ++ }, \ ++ .cb_private = _priv, \ ++ .cb_max_size = _maxsz, \ ++ .read = _pfx##_name##_read, \ ++ .write = _pfx##_name##_write, \ ++} ++ ++#define CONFIGFS_BIN_ATTR_RO(_pfx, _name, _priv, _maxsz) \ ++static struct configfs_attribute _pfx##attr_##_name = { \ ++ .cb_attr = { \ ++ .ca_name = __stringify(_name), \ ++ .ca_mode = S_IRUGO, \ ++ .ca_owner = THIS_MODULE, \ ++ }, \ ++ .cb_private = _priv, \ ++ .cb_max_size = _maxsz, \ ++ .read = _pfx##_name##_read, \ ++} ++ ++#define CONFIGFS_BIN_ATTR_WO(_pfx, _name, _priv, _maxsz) \ ++static struct configfs_attribute _pfx##attr_##_name = { \ ++ .cb_attr = { \ ++ .ca_name = __stringify(_name), \ ++ .ca_mode = S_IWUSR, \ ++ .ca_owner = THIS_MODULE, \ ++ }, \ ++ .cb_private = _priv, \ ++ .cb_max_size = _maxsz, \ ++ .write = _pfx##_name##_write, \ ++} ++ + /* + * If allow_link() exists, the item can symlink(2) out to other + * items. If the item is a group, it may support mkdir(2). + +From 5bbcb67edd92f639228cbaf7d597af715442db16 Mon Sep 17 00:00:00 2001 +From: Octavian Purdila +Date: Wed, 23 Mar 2016 14:14:48 +0200 +Subject: [PATCH] UPSTREAM: configfs: fix CONFIGFS_BIN_ATTR_[RW]O definitions + +The type should be struct configfs_bin_attribute and not struct +configfs_attribute. + +Signed-off-by: Octavian Purdila +Signed-off-by: Christoph Hellwig +(cherry picked from commit 96c22a3293512ba684e73a981196430f524689da) +--- + include/linux/configfs.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/include/linux/configfs.h b/include/linux/configfs.h +index f7300d023dbe..658066d63180 100644 +--- a/include/linux/configfs.h ++++ b/include/linux/configfs.h +@@ -181,7 +181,7 @@ static struct configfs_bin_attribute _pfx##attr_##_name = { \ + } + + #define CONFIGFS_BIN_ATTR_RO(_pfx, _name, _priv, _maxsz) \ +-static struct configfs_attribute _pfx##attr_##_name = { \ ++static struct configfs_bin_attribute _pfx##attr_##_name = { \ + .cb_attr = { \ + .ca_name = __stringify(_name), \ + .ca_mode = S_IRUGO, \ +@@ -193,7 +193,7 @@ static struct configfs_attribute _pfx##attr_##_name = { \ + } + + #define CONFIGFS_BIN_ATTR_WO(_pfx, _name, _priv, _maxsz) \ +-static struct configfs_attribute _pfx##attr_##_name = { \ ++static struct configfs_bin_attribute _pfx##attr_##_name = { \ + .cb_attr = { \ + .ca_name = __stringify(_name), \ + .ca_mode = S_IWUSR, \ + +From 34d6438a4d2cedcd1b47f55a3cc63374252c6682 Mon Sep 17 00:00:00 2001 +From: Pantelis Antoniou +Date: Wed, 4 Dec 2013 19:32:00 +0200 +Subject: [PATCH] FROMLIST: OF: DT-Overlay configfs interface (v7) + +Add a runtime interface to using configfs for generic device tree overlay +usage. With it its possible to use device tree overlays without having +to use a per-platform overlay manager. + +Please see Documentation/devicetree/configfs-overlays.txt for more info. + +Changes since v6: +- Default groups properties API changed. + +Changes since v5: +- New style configfs. + +Changes since v4: +- Loading fix for multiple overlays as found out by + Geert Uytterhoeven + +Changes since v3: +- Fixed compilation on SPARC & Xtensa + +Changes since v2: +- Removed ifdef CONFIG_OF_OVERLAY (since for now it's required) +- Created a documentation entry +- Slight rewording in Kconfig + +Changes since v1: +- of_resolve() -> of_resolve_phandles(). + +Signed-off-by: Pantelis Antoniou +[geert: Use %zu to format size_t] +[geert: Let OF_CONFIGFS select OF_FLATTREE to fix sparc all*config] +Signed-off-by: Geert Uytterhoeven +--- + Documentation/devicetree/configfs-overlays.txt | 31 +++ + drivers/of/Kconfig | 8 + + drivers/of/Makefile | 1 + + drivers/of/configfs.c | 314 +++++++++++++++++++++++++ + 4 files changed, 354 insertions(+) + create mode 100644 Documentation/devicetree/configfs-overlays.txt + create mode 100644 drivers/of/configfs.c + +diff --git a/Documentation/devicetree/configfs-overlays.txt b/Documentation/devicetree/configfs-overlays.txt +new file mode 100644 +index 000000000000..5fa43e064307 +--- /dev/null ++++ b/Documentation/devicetree/configfs-overlays.txt +@@ -0,0 +1,31 @@ ++Howto use the configfs overlay interface. ++ ++A device-tree configfs entry is created in /config/device-tree/overlays ++and and it is manipulated using standard file system I/O. ++Note that this is a debug level interface, for use by developers and ++not necessarily something accessed by normal users due to the ++security implications of having direct access to the kernel's device tree. ++ ++* To create an overlay you mkdir the directory: ++ ++ # mkdir /config/device-tree/overlays/foo ++ ++* Either you echo the overlay firmware file to the path property file. ++ ++ # echo foo.dtbo >/config/device-tree/overlays/foo/path ++ ++* Or you cat the contents of the overlay to the dtbo file ++ ++ # cat foo.dtbo >/config/device-tree/overlays/foo/dtbo ++ ++The overlay file will be applied, and devices will be created/destroyed ++as required. ++ ++To remove it simply rmdir the directory. ++ ++ # rmdir /config/device-tree/overlays/foo ++ ++The rationalle of the dual interface (firmware & direct copy) is that each is ++better suited to different use patterns. The firmware interface is what's ++intended to be used by hardware managers in the kernel, while the copy interface ++make sense for developers (since it avoids problems with namespaces). +diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig +index e2a48415d969..c112c9f2ca6b 100644 +--- a/drivers/of/Kconfig ++++ b/drivers/of/Kconfig +@@ -112,4 +112,12 @@ config OF_OVERLAY + While this option is selected automatically when needed, you can + enable it manually to improve device tree unit test coverage. + ++config OF_CONFIGFS ++ bool "Device Tree Overlay ConfigFS interface" ++ select CONFIGFS_FS ++ select OF_FLATTREE ++ depends on OF_OVERLAY ++ help ++ Enable a simple user-space driven DT overlay interface. ++ + endif # OF +diff --git a/drivers/of/Makefile b/drivers/of/Makefile +index 478d4edcd763..732fa66b5263 100644 +--- a/drivers/of/Makefile ++++ b/drivers/of/Makefile +@@ -1,4 +1,5 @@ + obj-y = base.o device.o platform.o property.o ++obj-$(CONFIG_OF_CONFIGFS) += configfs.o + obj-$(CONFIG_OF_DYNAMIC) += dynamic.o + obj-$(CONFIG_OF_FLATTREE) += fdt.o + obj-$(CONFIG_OF_EARLY_FLATTREE) += fdt_address.o +diff --git a/drivers/of/configfs.c b/drivers/of/configfs.c +new file mode 100644 +index 000000000000..908ce4960c30 +--- /dev/null ++++ b/drivers/of/configfs.c +@@ -0,0 +1,314 @@ ++/* ++ * Configfs entries for device-tree ++ * ++ * Copyright (C) 2013 - Pantelis Antoniou ++ * ++ * 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. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "of_private.h" ++ ++struct cfs_overlay_item { ++ struct config_item item; ++ ++ char path[PATH_MAX]; ++ ++ const struct firmware *fw; ++ struct device_node *overlay; ++ int ov_id; ++ ++ void *dtbo; ++ int dtbo_size; ++}; ++ ++static int create_overlay(struct cfs_overlay_item *overlay, void *blob) ++{ ++ int err; ++ ++ /* unflatten the tree */ ++ of_fdt_unflatten_tree(blob, &overlay->overlay); ++ if (overlay->overlay == NULL) { ++ pr_err("%s: failed to unflatten tree\n", __func__); ++ err = -EINVAL; ++ goto out_err; ++ } ++ pr_debug("%s: unflattened OK\n", __func__); ++ ++ /* mark it as detached */ ++ of_node_set_flag(overlay->overlay, OF_DETACHED); ++ ++ /* perform resolution */ ++ err = of_resolve_phandles(overlay->overlay); ++ if (err != 0) { ++ pr_err("%s: Failed to resolve tree\n", __func__); ++ goto out_err; ++ } ++ pr_debug("%s: resolved OK\n", __func__); ++ ++ err = of_overlay_create(overlay->overlay); ++ if (err < 0) { ++ pr_err("%s: Failed to create overlay (err=%d)\n", ++ __func__, err); ++ goto out_err; ++ } ++ overlay->ov_id = err; ++ ++out_err: ++ return err; ++} ++ ++static inline struct cfs_overlay_item *to_cfs_overlay_item( ++ struct config_item *item) ++{ ++ return item ? container_of(item, struct cfs_overlay_item, item) : NULL; ++} ++ ++static ssize_t cfs_overlay_item_path_show(struct config_item *item, ++ char *page) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ return sprintf(page, "%s\n", overlay->path); ++} ++ ++static ssize_t cfs_overlay_item_path_store(struct config_item *item, ++ const char *page, size_t count) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ const char *p = page; ++ char *s; ++ int err; ++ ++ /* if it's set do not allow changes */ ++ if (overlay->path[0] != '\0' || overlay->dtbo_size > 0) ++ return -EPERM; ++ ++ /* copy to path buffer (and make sure it's always zero terminated */ ++ count = snprintf(overlay->path, sizeof(overlay->path) - 1, "%s", p); ++ overlay->path[sizeof(overlay->path) - 1] = '\0'; ++ ++ /* strip trailing newlines */ ++ s = overlay->path + strlen(overlay->path); ++ while (s > overlay->path && *--s == '\n') ++ *s = '\0'; ++ ++ pr_debug("%s: path is '%s'\n", __func__, overlay->path); ++ ++ err = request_firmware(&overlay->fw, overlay->path, NULL); ++ if (err != 0) ++ goto out_err; ++ ++ err = create_overlay(overlay, (void *)overlay->fw->data); ++ if (err < 0) ++ goto out_err; ++ ++ return count; ++ ++out_err: ++ ++ release_firmware(overlay->fw); ++ overlay->fw = NULL; ++ ++ overlay->path[0] = '\0'; ++ return err; ++} ++ ++static ssize_t cfs_overlay_item_status_show(struct config_item *item, ++ char *page) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ ++ return sprintf(page, "%s\n", ++ overlay->ov_id >= 0 ? "applied" : "unapplied"); ++} ++ ++CONFIGFS_ATTR(cfs_overlay_item_, path); ++CONFIGFS_ATTR_RO(cfs_overlay_item_, status); ++ ++static struct configfs_attribute *cfs_overlay_attrs[] = { ++ &cfs_overlay_item_attr_path, ++ &cfs_overlay_item_attr_status, ++ NULL, ++}; ++ ++ssize_t cfs_overlay_item_dtbo_read(struct config_item *item, ++ void *buf, size_t max_count) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ ++ pr_debug("%s: buf=%p max_count=%zu\n", __func__, ++ buf, max_count); ++ ++ if (overlay->dtbo == NULL) ++ return 0; ++ ++ /* copy if buffer provided */ ++ if (buf != NULL) { ++ /* the buffer must be large enough */ ++ if (overlay->dtbo_size > max_count) ++ return -ENOSPC; ++ ++ memcpy(buf, overlay->dtbo, overlay->dtbo_size); ++ } ++ ++ return overlay->dtbo_size; ++} ++ ++ssize_t cfs_overlay_item_dtbo_write(struct config_item *item, ++ const void *buf, size_t count) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ int err; ++ ++ /* if it's set do not allow changes */ ++ if (overlay->path[0] != '\0' || overlay->dtbo_size > 0) ++ return -EPERM; ++ ++ /* copy the contents */ ++ overlay->dtbo = kmemdup(buf, count, GFP_KERNEL); ++ if (overlay->dtbo == NULL) ++ return -ENOMEM; ++ ++ overlay->dtbo_size = count; ++ ++ err = create_overlay(overlay, overlay->dtbo); ++ if (err < 0) ++ goto out_err; ++ ++ return count; ++ ++out_err: ++ kfree(overlay->dtbo); ++ overlay->dtbo = NULL; ++ overlay->dtbo_size = 0; ++ ++ return err; ++} ++ ++CONFIGFS_BIN_ATTR(cfs_overlay_item_, dtbo, NULL, SZ_1M); ++ ++static struct configfs_bin_attribute *cfs_overlay_bin_attrs[] = { ++ &cfs_overlay_item_attr_dtbo, ++ NULL, ++}; ++ ++static void cfs_overlay_release(struct config_item *item) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ ++ if (overlay->ov_id >= 0) ++ of_overlay_destroy(overlay->ov_id); ++ if (overlay->fw) ++ release_firmware(overlay->fw); ++ /* kfree with NULL is safe */ ++ kfree(overlay->dtbo); ++ kfree(overlay); ++} ++ ++static struct configfs_item_operations cfs_overlay_item_ops = { ++ .release = cfs_overlay_release, ++}; ++ ++static struct config_item_type cfs_overlay_type = { ++ .ct_item_ops = &cfs_overlay_item_ops, ++ .ct_attrs = cfs_overlay_attrs, ++ .ct_bin_attrs = cfs_overlay_bin_attrs, ++ .ct_owner = THIS_MODULE, ++}; ++ ++static struct config_item *cfs_overlay_group_make_item( ++ struct config_group *group, const char *name) ++{ ++ struct cfs_overlay_item *overlay; ++ ++ overlay = kzalloc(sizeof(*overlay), GFP_KERNEL); ++ if (!overlay) ++ return ERR_PTR(-ENOMEM); ++ overlay->ov_id = -1; ++ ++ config_item_init_type_name(&overlay->item, name, &cfs_overlay_type); ++ return &overlay->item; ++} ++ ++static void cfs_overlay_group_drop_item(struct config_group *group, ++ struct config_item *item) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ ++ config_item_put(&overlay->item); ++} ++ ++static struct configfs_group_operations overlays_ops = { ++ .make_item = cfs_overlay_group_make_item, ++ .drop_item = cfs_overlay_group_drop_item, ++}; ++ ++static struct config_item_type overlays_type = { ++ .ct_group_ops = &overlays_ops, ++ .ct_owner = THIS_MODULE, ++}; ++ ++static struct configfs_group_operations of_cfs_ops = { ++ /* empty - we don't allow anything to be created */ ++}; ++ ++static struct config_item_type of_cfs_type = { ++ .ct_group_ops = &of_cfs_ops, ++ .ct_owner = THIS_MODULE, ++}; ++ ++struct config_group of_cfs_overlay_group; ++ ++struct config_group *of_cfs_def_groups[] = { ++ &of_cfs_overlay_group, ++ NULL ++}; ++ ++static struct configfs_subsystem of_cfs_subsys = { ++ .su_group = { ++ .cg_item = { ++ .ci_namebuf = "device-tree", ++ .ci_type = &of_cfs_type, ++ }, ++ .default_groups = of_cfs_def_groups, ++ }, ++ .su_mutex = __MUTEX_INITIALIZER(of_cfs_subsys.su_mutex), ++}; ++ ++static int __init of_cfs_init(void) ++{ ++ int ret; ++ ++ pr_info("%s\n", __func__); ++ ++ config_group_init(&of_cfs_subsys.su_group); ++ config_group_init_type_name(&of_cfs_overlay_group, "overlays", ++ &overlays_type); ++ ++ ret = configfs_register_subsystem(&of_cfs_subsys); ++ if (ret != 0) { ++ pr_err("%s: failed to register subsys\n", __func__); ++ goto out; ++ } ++ pr_info("%s: OK\n", __func__); ++out: ++ return ret; ++} ++late_initcall(of_cfs_init); diff --git a/patch/kernel/rockchip-default/01-linux-0008-mmc-pwrseq.patch b/patch/kernel/rockchip-default/01-linux-0008-mmc-pwrseq.patch new file mode 100644 index 000000000..2eb189826 --- /dev/null +++ b/patch/kernel/rockchip-default/01-linux-0008-mmc-pwrseq.patch @@ -0,0 +1,949 @@ +From 75bb99dc815464846a4add357494acf04212271d Mon Sep 17 00:00:00 2001 +From: Julia Lawall +Date: Sat, 14 Nov 2015 18:05:20 +0100 +Subject: [PATCH] UPSTREAM: mmc: pwrseq: constify mmc_pwrseq_ops structures + +The mmc_pwrseq_ops structures are never modified, so declare them as const. + +Done with the help of Coccinelle. + +Signed-off-by: Julia Lawall +Signed-off-by: Ulf Hansson +(cherry picked from commit ffedbd2210f2f4cba490a9205adc11fd1b89a852) +--- + drivers/mmc/core/pwrseq.h | 2 +- + drivers/mmc/core/pwrseq_emmc.c | 2 +- + drivers/mmc/core/pwrseq_simple.c | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/mmc/core/pwrseq.h b/drivers/mmc/core/pwrseq.h +index 096da48c6a7e..133de0426687 100644 +--- a/drivers/mmc/core/pwrseq.h ++++ b/drivers/mmc/core/pwrseq.h +@@ -16,7 +16,7 @@ struct mmc_pwrseq_ops { + }; + + struct mmc_pwrseq { +- struct mmc_pwrseq_ops *ops; ++ const struct mmc_pwrseq_ops *ops; + }; + + #ifdef CONFIG_OF +diff --git a/drivers/mmc/core/pwrseq_emmc.c b/drivers/mmc/core/pwrseq_emmc.c +index ad4f94ec7e8d..4a82bc77fe49 100644 +--- a/drivers/mmc/core/pwrseq_emmc.c ++++ b/drivers/mmc/core/pwrseq_emmc.c +@@ -51,7 +51,7 @@ static void mmc_pwrseq_emmc_free(struct mmc_host *host) + kfree(pwrseq); + } + +-static struct mmc_pwrseq_ops mmc_pwrseq_emmc_ops = { ++static const struct mmc_pwrseq_ops mmc_pwrseq_emmc_ops = { + .post_power_on = mmc_pwrseq_emmc_reset, + .free = mmc_pwrseq_emmc_free, + }; +diff --git a/drivers/mmc/core/pwrseq_simple.c b/drivers/mmc/core/pwrseq_simple.c +index d10538bb5e07..2b16263458af 100644 +--- a/drivers/mmc/core/pwrseq_simple.c ++++ b/drivers/mmc/core/pwrseq_simple.c +@@ -87,7 +87,7 @@ static void mmc_pwrseq_simple_free(struct mmc_host *host) + kfree(pwrseq); + } + +-static struct mmc_pwrseq_ops mmc_pwrseq_simple_ops = { ++static const struct mmc_pwrseq_ops mmc_pwrseq_simple_ops = { + .pre_power_on = mmc_pwrseq_simple_pre_power_on, + .post_power_on = mmc_pwrseq_simple_post_power_on, + .power_off = mmc_pwrseq_simple_power_off, + +From 1977551c6ef29f55b398a02112e3075c9a38649d Mon Sep 17 00:00:00 2001 +From: Martin Fuzzey +Date: Wed, 20 Jan 2016 16:08:03 +0100 +Subject: [PATCH] UPSTREAM: mmc: pwrseq_simple: Make reset-gpios optional to + match doc + +The DT binding doc says reset-gpios is an optional property but the code +currently bails out if it is omitted. + +This is a regression since it breaks previously working device trees. +Fix it by restoring the original documented behaviour. + +Fixes: ce037275861e ("mmc: pwrseq_simple: use GPIO descriptors array API") +Tested-by: Tony Lindgren +Signed-off-by: Martin Fuzzey +Signed-off-by: Ulf Hansson +(cherry picked from commit 64a67d4762ce3ce4c9466eadd152d825fbf84967) +--- + drivers/mmc/core/pwrseq_simple.c | 22 ++++++++++++++-------- + 1 file changed, 14 insertions(+), 8 deletions(-) + +diff --git a/drivers/mmc/core/pwrseq_simple.c b/drivers/mmc/core/pwrseq_simple.c +index 2b16263458af..aba786daebca 100644 +--- a/drivers/mmc/core/pwrseq_simple.c ++++ b/drivers/mmc/core/pwrseq_simple.c +@@ -29,15 +29,18 @@ struct mmc_pwrseq_simple { + static void mmc_pwrseq_simple_set_gpios_value(struct mmc_pwrseq_simple *pwrseq, + int value) + { +- int i; + struct gpio_descs *reset_gpios = pwrseq->reset_gpios; +- int values[reset_gpios->ndescs]; + +- for (i = 0; i < reset_gpios->ndescs; i++) +- values[i] = value; ++ if (!IS_ERR(reset_gpios)) { ++ int i; ++ int values[reset_gpios->ndescs]; + +- gpiod_set_array_value_cansleep(reset_gpios->ndescs, reset_gpios->desc, +- values); ++ for (i = 0; i < reset_gpios->ndescs; i++) ++ values[i] = value; ++ ++ gpiod_set_array_value_cansleep( ++ reset_gpios->ndescs, reset_gpios->desc, values); ++ } + } + + static void mmc_pwrseq_simple_pre_power_on(struct mmc_host *host) +@@ -79,7 +82,8 @@ static void mmc_pwrseq_simple_free(struct mmc_host *host) + struct mmc_pwrseq_simple *pwrseq = container_of(host->pwrseq, + struct mmc_pwrseq_simple, pwrseq); + +- gpiod_put_array(pwrseq->reset_gpios); ++ if (!IS_ERR(pwrseq->reset_gpios)) ++ gpiod_put_array(pwrseq->reset_gpios); + + if (!IS_ERR(pwrseq->ext_clk)) + clk_put(pwrseq->ext_clk); +@@ -112,7 +116,9 @@ struct mmc_pwrseq *mmc_pwrseq_simple_alloc(struct mmc_host *host, + } + + pwrseq->reset_gpios = gpiod_get_array(dev, "reset", GPIOD_OUT_HIGH); +- if (IS_ERR(pwrseq->reset_gpios)) { ++ if (IS_ERR(pwrseq->reset_gpios) && ++ PTR_ERR(pwrseq->reset_gpios) != -ENOENT && ++ PTR_ERR(pwrseq->reset_gpios) != -ENOSYS) { + ret = PTR_ERR(pwrseq->reset_gpios); + goto clk_put; + } + +From e79ed0004dc68dc2f2189256bf00a1f579c78f1a Mon Sep 17 00:00:00 2001 +From: Peter Chen +Date: Wed, 6 Jan 2016 11:34:10 +0800 +Subject: [PATCH] UPSTREAM: mmc: core: pwrseq_simple: remove unused header file + +Signed-off-by: Peter Chen +Signed-off-by: Ulf Hansson +(cherry picked from commit 62c03ca3ffa1ddf55a66411be02f7e4678771fce) +--- + drivers/mmc/core/pwrseq_simple.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/mmc/core/pwrseq_simple.c b/drivers/mmc/core/pwrseq_simple.c +index aba786daebca..bc173e18b71c 100644 +--- a/drivers/mmc/core/pwrseq_simple.c ++++ b/drivers/mmc/core/pwrseq_simple.c +@@ -12,7 +12,6 @@ + #include + #include + #include +-#include + #include + + #include + +From 545d059f7a0a4c470acfdb0fff30397899597f09 Mon Sep 17 00:00:00 2001 +From: Srinivas Kandagatla +Date: Thu, 14 Apr 2016 14:02:14 +0100 +Subject: [PATCH] UPSTREAM: mmc: pwrseq_simple: add to_pwrseq_simple() macro + +This patch adds to_pwrseq_simple() macro to make the code more readable. + +Signed-off-by: Srinivas Kandagatla +Signed-off-by: Ulf Hansson +(cherry picked from commit 5b96fea730ab79bdf6f8071cadf8208296bf5e8d) +--- + drivers/mmc/core/pwrseq_simple.c | 14 ++++++-------- + 1 file changed, 6 insertions(+), 8 deletions(-) + +diff --git a/drivers/mmc/core/pwrseq_simple.c b/drivers/mmc/core/pwrseq_simple.c +index bc173e18b71c..f94271bb1f6b 100644 +--- a/drivers/mmc/core/pwrseq_simple.c ++++ b/drivers/mmc/core/pwrseq_simple.c +@@ -25,6 +25,8 @@ struct mmc_pwrseq_simple { + struct gpio_descs *reset_gpios; + }; + ++#define to_pwrseq_simple(p) container_of(p, struct mmc_pwrseq_simple, pwrseq) ++ + static void mmc_pwrseq_simple_set_gpios_value(struct mmc_pwrseq_simple *pwrseq, + int value) + { +@@ -44,8 +46,7 @@ static void mmc_pwrseq_simple_set_gpios_value(struct mmc_pwrseq_simple *pwrseq, + + static void mmc_pwrseq_simple_pre_power_on(struct mmc_host *host) + { +- struct mmc_pwrseq_simple *pwrseq = container_of(host->pwrseq, +- struct mmc_pwrseq_simple, pwrseq); ++ struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(host->pwrseq); + + if (!IS_ERR(pwrseq->ext_clk) && !pwrseq->clk_enabled) { + clk_prepare_enable(pwrseq->ext_clk); +@@ -57,16 +58,14 @@ static void mmc_pwrseq_simple_pre_power_on(struct mmc_host *host) + + static void mmc_pwrseq_simple_post_power_on(struct mmc_host *host) + { +- struct mmc_pwrseq_simple *pwrseq = container_of(host->pwrseq, +- struct mmc_pwrseq_simple, pwrseq); ++ struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(host->pwrseq); + + mmc_pwrseq_simple_set_gpios_value(pwrseq, 0); + } + + static void mmc_pwrseq_simple_power_off(struct mmc_host *host) + { +- struct mmc_pwrseq_simple *pwrseq = container_of(host->pwrseq, +- struct mmc_pwrseq_simple, pwrseq); ++ struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(host->pwrseq); + + mmc_pwrseq_simple_set_gpios_value(pwrseq, 1); + +@@ -78,8 +77,7 @@ static void mmc_pwrseq_simple_power_off(struct mmc_host *host) + + static void mmc_pwrseq_simple_free(struct mmc_host *host) + { +- struct mmc_pwrseq_simple *pwrseq = container_of(host->pwrseq, +- struct mmc_pwrseq_simple, pwrseq); ++ struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(host->pwrseq); + + if (!IS_ERR(pwrseq->reset_gpios)) + gpiod_put_array(pwrseq->reset_gpios); + +From e8c5f0b9383e6a528c8fc00d61755f8187e4c0b8 Mon Sep 17 00:00:00 2001 +From: Srinivas Kandagatla +Date: Thu, 14 Apr 2016 14:02:15 +0100 +Subject: [PATCH] UPSTREAM: mmc: pwrseq_emmc: add to_pwrseq_emmc() macro + +This patch adds to_pwrseq_emmc() macro to make the code more readable. + +Signed-off-by: Srinivas Kandagatla +Signed-off-by: Ulf Hansson +(cherry picked from commit f01b72d0fd53b61cafd25b16d15e18b1ef8ae065) +--- + drivers/mmc/core/pwrseq_emmc.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/mmc/core/pwrseq_emmc.c b/drivers/mmc/core/pwrseq_emmc.c +index 4a82bc77fe49..c2d732aa464c 100644 +--- a/drivers/mmc/core/pwrseq_emmc.c ++++ b/drivers/mmc/core/pwrseq_emmc.c +@@ -25,6 +25,8 @@ struct mmc_pwrseq_emmc { + struct gpio_desc *reset_gpio; + }; + ++#define to_pwrseq_emmc(p) container_of(p, struct mmc_pwrseq_emmc, pwrseq) ++ + static void __mmc_pwrseq_emmc_reset(struct mmc_pwrseq_emmc *pwrseq) + { + gpiod_set_value(pwrseq->reset_gpio, 1); +@@ -35,16 +37,14 @@ static void __mmc_pwrseq_emmc_reset(struct mmc_pwrseq_emmc *pwrseq) + + static void mmc_pwrseq_emmc_reset(struct mmc_host *host) + { +- struct mmc_pwrseq_emmc *pwrseq = container_of(host->pwrseq, +- struct mmc_pwrseq_emmc, pwrseq); ++ struct mmc_pwrseq_emmc *pwrseq = to_pwrseq_emmc(host->pwrseq); + + __mmc_pwrseq_emmc_reset(pwrseq); + } + + static void mmc_pwrseq_emmc_free(struct mmc_host *host) + { +- struct mmc_pwrseq_emmc *pwrseq = container_of(host->pwrseq, +- struct mmc_pwrseq_emmc, pwrseq); ++ struct mmc_pwrseq_emmc *pwrseq = to_pwrseq_emmc(host->pwrseq); + + unregister_restart_handler(&pwrseq->reset_nb); + gpiod_put(pwrseq->reset_gpio); + +From ef2f3c5b7375b930697a64c85f30f9109e631cb0 Mon Sep 17 00:00:00 2001 +From: Srinivas Kandagatla +Date: Thu, 14 Apr 2016 14:02:16 +0100 +Subject: [PATCH] UPSTREAM: mmc: pwrseq: convert to proper platform device + +simple-pwrseq and emmc-pwrseq drivers rely on platform_device +structure from of_find_device_by_node(), this works mostly. But, as there +is no driver associated with this devices, cases like default/init pinctrl +setup would never be performed by pwrseq. This becomes problem when the +gpios used in pwrseq require pinctrl setup. + +Currently most of the common pinctrl setup is done in +drivers/base/pinctrl.c by pinctrl_bind_pins(). + +There are two ways to solve this issue on either convert pwrseq drivers +to a proper platform drivers or copy the exact code from +pcintrl_bind_pins(). I prefer converting pwrseq to proper drivers so that +other cases like setting up clks/parents from dt would also be possible. + +Signed-off-by: Srinivas Kandagatla +Signed-off-by: Ulf Hansson +(cherry picked from commit d97a1e5d7cd2b5b0edc02a40fe6897b710c9e10f) +--- + drivers/mmc/core/Kconfig | 22 ++++++++ + drivers/mmc/core/Makefile | 4 +- + drivers/mmc/core/pwrseq.c | 108 ++++++++++++++++++--------------------- + drivers/mmc/core/pwrseq.h | 19 ++++--- + drivers/mmc/core/pwrseq_emmc.c | 75 +++++++++++++++++---------- + drivers/mmc/core/pwrseq_simple.c | 79 +++++++++++++++------------- + 6 files changed, 178 insertions(+), 129 deletions(-) + +diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig +index 87cc07dedd9f..00dfaea06003 100644 +--- a/drivers/mmc/core/Kconfig ++++ b/drivers/mmc/core/Kconfig +@@ -16,3 +16,25 @@ config MMC_PARANOID_SD_INIT + about re-trying SD init requests. This can be a useful + work-around for buggy controllers and hardware. Enable + if you are experiencing issues with SD detection. ++ ++config PWRSEQ_EMMC ++ tristate "HW reset support for eMMC" ++ default y ++ depends on OF ++ help ++ This selects Hardware reset support aka pwrseq-emmc for eMMC ++ devices. By default this option is set to y. ++ ++ This driver can also be built as a module. If so, the module ++ will be called pwrseq_emmc. ++ ++config PWRSEQ_SIMPLE ++ tristate "Simple HW reset support for MMC" ++ default y ++ depends on OF ++ help ++ This selects simple hardware reset support aka pwrseq-simple for MMC ++ devices. By default this option is set to y. ++ ++ This driver can also be built as a module. If so, the module ++ will be called pwrseq_simple. +diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile +index 2c25138f28b7..f007151dfdc6 100644 +--- a/drivers/mmc/core/Makefile ++++ b/drivers/mmc/core/Makefile +@@ -8,5 +8,7 @@ mmc_core-y := core.o bus.o host.o \ + sdio.o sdio_ops.o sdio_bus.o \ + sdio_cis.o sdio_io.o sdio_irq.o \ + quirks.o slot-gpio.o +-mmc_core-$(CONFIG_OF) += pwrseq.o pwrseq_simple.o pwrseq_emmc.o ++mmc_core-$(CONFIG_OF) += pwrseq.o ++obj-$(CONFIG_PWRSEQ_SIMPLE) += pwrseq_simple.o ++obj-$(CONFIG_PWRSEQ_EMMC) += pwrseq_emmc.o + mmc_core-$(CONFIG_DEBUG_FS) += debugfs.o +diff --git a/drivers/mmc/core/pwrseq.c b/drivers/mmc/core/pwrseq.c +index 4c1d1757dbf9..9386c4771814 100644 +--- a/drivers/mmc/core/pwrseq.c ++++ b/drivers/mmc/core/pwrseq.c +@@ -8,88 +8,55 @@ + * MMC power sequence management + */ + #include +-#include + #include ++#include + #include +-#include + + #include + + #include "pwrseq.h" + +-struct mmc_pwrseq_match { +- const char *compatible; +- struct mmc_pwrseq *(*alloc)(struct mmc_host *host, struct device *dev); +-}; +- +-static struct mmc_pwrseq_match pwrseq_match[] = { +- { +- .compatible = "mmc-pwrseq-simple", +- .alloc = mmc_pwrseq_simple_alloc, +- }, { +- .compatible = "mmc-pwrseq-emmc", +- .alloc = mmc_pwrseq_emmc_alloc, +- }, +-}; +- +-static struct mmc_pwrseq_match *mmc_pwrseq_find(struct device_node *np) +-{ +- struct mmc_pwrseq_match *match = ERR_PTR(-ENODEV); +- int i; +- +- for (i = 0; i < ARRAY_SIZE(pwrseq_match); i++) { +- if (of_device_is_compatible(np, pwrseq_match[i].compatible)) { +- match = &pwrseq_match[i]; +- break; +- } +- } +- +- return match; +-} ++static DEFINE_MUTEX(pwrseq_list_mutex); ++static LIST_HEAD(pwrseq_list); + + int mmc_pwrseq_alloc(struct mmc_host *host) + { +- struct platform_device *pdev; + struct device_node *np; +- struct mmc_pwrseq_match *match; +- struct mmc_pwrseq *pwrseq; +- int ret = 0; ++ struct mmc_pwrseq *p; + + np = of_parse_phandle(host->parent->of_node, "mmc-pwrseq", 0); + if (!np) + return 0; + +- pdev = of_find_device_by_node(np); +- if (!pdev) { +- ret = -ENODEV; +- goto err; +- } ++ mutex_lock(&pwrseq_list_mutex); ++ list_for_each_entry(p, &pwrseq_list, pwrseq_node) { ++ if (p->dev->of_node == np) { ++ if (!try_module_get(p->owner)) ++ dev_err(host->parent, ++ "increasing module refcount failed\n"); ++ else ++ host->pwrseq = p; + +- match = mmc_pwrseq_find(np); +- if (IS_ERR(match)) { +- ret = PTR_ERR(match); +- goto err; ++ break; ++ } + } + +- pwrseq = match->alloc(host, &pdev->dev); +- if (IS_ERR(pwrseq)) { +- ret = PTR_ERR(pwrseq); +- goto err; +- } ++ of_node_put(np); ++ mutex_unlock(&pwrseq_list_mutex); ++ ++ if (!host->pwrseq) ++ return -EPROBE_DEFER; + +- host->pwrseq = pwrseq; + dev_info(host->parent, "allocated mmc-pwrseq\n"); + +-err: +- of_node_put(np); +- return ret; ++ return 0; + } + + void mmc_pwrseq_pre_power_on(struct mmc_host *host) + { + struct mmc_pwrseq *pwrseq = host->pwrseq; + +- if (pwrseq && pwrseq->ops && pwrseq->ops->pre_power_on) ++ if (pwrseq && pwrseq->ops->pre_power_on) + pwrseq->ops->pre_power_on(host); + } + +@@ -97,7 +64,7 @@ void mmc_pwrseq_post_power_on(struct mmc_host *host) + { + struct mmc_pwrseq *pwrseq = host->pwrseq; + +- if (pwrseq && pwrseq->ops && pwrseq->ops->post_power_on) ++ if (pwrseq && pwrseq->ops->post_power_on) + pwrseq->ops->post_power_on(host); + } + +@@ -105,7 +72,7 @@ void mmc_pwrseq_power_off(struct mmc_host *host) + { + struct mmc_pwrseq *pwrseq = host->pwrseq; + +- if (pwrseq && pwrseq->ops && pwrseq->ops->power_off) ++ if (pwrseq && pwrseq->ops->power_off) + pwrseq->ops->power_off(host); + } + +@@ -113,8 +80,31 @@ void mmc_pwrseq_free(struct mmc_host *host) + { + struct mmc_pwrseq *pwrseq = host->pwrseq; + +- if (pwrseq && pwrseq->ops && pwrseq->ops->free) +- pwrseq->ops->free(host); ++ if (pwrseq) { ++ module_put(pwrseq->owner); ++ host->pwrseq = NULL; ++ } ++} ++ ++int mmc_pwrseq_register(struct mmc_pwrseq *pwrseq) ++{ ++ if (!pwrseq || !pwrseq->ops || !pwrseq->dev) ++ return -EINVAL; + +- host->pwrseq = NULL; ++ mutex_lock(&pwrseq_list_mutex); ++ list_add(&pwrseq->pwrseq_node, &pwrseq_list); ++ mutex_unlock(&pwrseq_list_mutex); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(mmc_pwrseq_register); ++ ++void mmc_pwrseq_unregister(struct mmc_pwrseq *pwrseq) ++{ ++ if (pwrseq) { ++ mutex_lock(&pwrseq_list_mutex); ++ list_del(&pwrseq->pwrseq_node); ++ mutex_unlock(&pwrseq_list_mutex); ++ } + } ++EXPORT_SYMBOL_GPL(mmc_pwrseq_unregister); +diff --git a/drivers/mmc/core/pwrseq.h b/drivers/mmc/core/pwrseq.h +index 133de0426687..d69e751f148b 100644 +--- a/drivers/mmc/core/pwrseq.h ++++ b/drivers/mmc/core/pwrseq.h +@@ -8,32 +8,39 @@ + #ifndef _MMC_CORE_PWRSEQ_H + #define _MMC_CORE_PWRSEQ_H + ++#include ++ + struct mmc_pwrseq_ops { + void (*pre_power_on)(struct mmc_host *host); + void (*post_power_on)(struct mmc_host *host); + void (*power_off)(struct mmc_host *host); +- void (*free)(struct mmc_host *host); + }; + + struct mmc_pwrseq { + const struct mmc_pwrseq_ops *ops; ++ struct device *dev; ++ struct list_head pwrseq_node; ++ struct module *owner; + }; + + #ifdef CONFIG_OF + ++int mmc_pwrseq_register(struct mmc_pwrseq *pwrseq); ++void mmc_pwrseq_unregister(struct mmc_pwrseq *pwrseq); ++ + int mmc_pwrseq_alloc(struct mmc_host *host); + void mmc_pwrseq_pre_power_on(struct mmc_host *host); + void mmc_pwrseq_post_power_on(struct mmc_host *host); + void mmc_pwrseq_power_off(struct mmc_host *host); + void mmc_pwrseq_free(struct mmc_host *host); + +-struct mmc_pwrseq *mmc_pwrseq_simple_alloc(struct mmc_host *host, +- struct device *dev); +-struct mmc_pwrseq *mmc_pwrseq_emmc_alloc(struct mmc_host *host, +- struct device *dev); +- + #else + ++static inline int mmc_pwrseq_register(struct mmc_pwrseq *pwrseq) ++{ ++ return -ENOSYS; ++} ++static inline void mmc_pwrseq_unregister(struct mmc_pwrseq *pwrseq) {} + static inline int mmc_pwrseq_alloc(struct mmc_host *host) { return 0; } + static inline void mmc_pwrseq_pre_power_on(struct mmc_host *host) {} + static inline void mmc_pwrseq_post_power_on(struct mmc_host *host) {} +diff --git a/drivers/mmc/core/pwrseq_emmc.c b/drivers/mmc/core/pwrseq_emmc.c +index c2d732aa464c..adc9c0c614fb 100644 +--- a/drivers/mmc/core/pwrseq_emmc.c ++++ b/drivers/mmc/core/pwrseq_emmc.c +@@ -9,6 +9,9 @@ + */ + #include + #include ++#include ++#include ++#include + #include + #include + #include +@@ -42,20 +45,6 @@ static void mmc_pwrseq_emmc_reset(struct mmc_host *host) + __mmc_pwrseq_emmc_reset(pwrseq); + } + +-static void mmc_pwrseq_emmc_free(struct mmc_host *host) +-{ +- struct mmc_pwrseq_emmc *pwrseq = to_pwrseq_emmc(host->pwrseq); +- +- unregister_restart_handler(&pwrseq->reset_nb); +- gpiod_put(pwrseq->reset_gpio); +- kfree(pwrseq); +-} +- +-static const struct mmc_pwrseq_ops mmc_pwrseq_emmc_ops = { +- .post_power_on = mmc_pwrseq_emmc_reset, +- .free = mmc_pwrseq_emmc_free, +-}; +- + static int mmc_pwrseq_emmc_reset_nb(struct notifier_block *this, + unsigned long mode, void *cmd) + { +@@ -66,21 +55,22 @@ static int mmc_pwrseq_emmc_reset_nb(struct notifier_block *this, + return NOTIFY_DONE; + } + +-struct mmc_pwrseq *mmc_pwrseq_emmc_alloc(struct mmc_host *host, +- struct device *dev) ++static const struct mmc_pwrseq_ops mmc_pwrseq_emmc_ops = { ++ .post_power_on = mmc_pwrseq_emmc_reset, ++}; ++ ++static int mmc_pwrseq_emmc_probe(struct platform_device *pdev) + { + struct mmc_pwrseq_emmc *pwrseq; +- int ret = 0; ++ struct device *dev = &pdev->dev; + +- pwrseq = kzalloc(sizeof(struct mmc_pwrseq_emmc), GFP_KERNEL); ++ pwrseq = devm_kzalloc(dev, sizeof(*pwrseq), GFP_KERNEL); + if (!pwrseq) +- return ERR_PTR(-ENOMEM); ++ return -ENOMEM; + +- pwrseq->reset_gpio = gpiod_get(dev, "reset", GPIOD_OUT_LOW); +- if (IS_ERR(pwrseq->reset_gpio)) { +- ret = PTR_ERR(pwrseq->reset_gpio); +- goto free; +- } ++ pwrseq->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); ++ if (IS_ERR(pwrseq->reset_gpio)) ++ return PTR_ERR(pwrseq->reset_gpio); + + /* + * register reset handler to ensure emmc reset also from +@@ -92,9 +82,38 @@ struct mmc_pwrseq *mmc_pwrseq_emmc_alloc(struct mmc_host *host, + register_restart_handler(&pwrseq->reset_nb); + + pwrseq->pwrseq.ops = &mmc_pwrseq_emmc_ops; ++ pwrseq->pwrseq.dev = dev; ++ pwrseq->pwrseq.owner = THIS_MODULE; ++ platform_set_drvdata(pdev, pwrseq); ++ ++ return mmc_pwrseq_register(&pwrseq->pwrseq); ++} ++ ++static int mmc_pwrseq_emmc_remove(struct platform_device *pdev) ++{ ++ struct mmc_pwrseq_emmc *pwrseq = platform_get_drvdata(pdev); ++ ++ unregister_restart_handler(&pwrseq->reset_nb); ++ mmc_pwrseq_unregister(&pwrseq->pwrseq); + +- return &pwrseq->pwrseq; +-free: +- kfree(pwrseq); +- return ERR_PTR(ret); ++ return 0; + } ++ ++static const struct of_device_id mmc_pwrseq_emmc_of_match[] = { ++ { .compatible = "mmc-pwrseq-emmc",}, ++ {/* sentinel */}, ++}; ++ ++MODULE_DEVICE_TABLE(of, mmc_pwrseq_emmc_of_match); ++ ++static struct platform_driver mmc_pwrseq_emmc_driver = { ++ .probe = mmc_pwrseq_emmc_probe, ++ .remove = mmc_pwrseq_emmc_remove, ++ .driver = { ++ .name = "pwrseq_emmc", ++ .of_match_table = mmc_pwrseq_emmc_of_match, ++ }, ++}; ++ ++module_platform_driver(mmc_pwrseq_emmc_driver); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/mmc/core/pwrseq_simple.c b/drivers/mmc/core/pwrseq_simple.c +index f94271bb1f6b..450d907c6e6c 100644 +--- a/drivers/mmc/core/pwrseq_simple.c ++++ b/drivers/mmc/core/pwrseq_simple.c +@@ -8,7 +8,10 @@ + * Simple MMC power sequence management + */ + #include ++#include + #include ++#include ++#include + #include + #include + #include +@@ -75,58 +78,64 @@ static void mmc_pwrseq_simple_power_off(struct mmc_host *host) + } + } + +-static void mmc_pwrseq_simple_free(struct mmc_host *host) +-{ +- struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(host->pwrseq); +- +- if (!IS_ERR(pwrseq->reset_gpios)) +- gpiod_put_array(pwrseq->reset_gpios); +- +- if (!IS_ERR(pwrseq->ext_clk)) +- clk_put(pwrseq->ext_clk); +- +- kfree(pwrseq); +-} +- + static const struct mmc_pwrseq_ops mmc_pwrseq_simple_ops = { + .pre_power_on = mmc_pwrseq_simple_pre_power_on, + .post_power_on = mmc_pwrseq_simple_post_power_on, + .power_off = mmc_pwrseq_simple_power_off, +- .free = mmc_pwrseq_simple_free, + }; + +-struct mmc_pwrseq *mmc_pwrseq_simple_alloc(struct mmc_host *host, +- struct device *dev) ++static const struct of_device_id mmc_pwrseq_simple_of_match[] = { ++ { .compatible = "mmc-pwrseq-simple",}, ++ {/* sentinel */}, ++}; ++MODULE_DEVICE_TABLE(of, mmc_pwrseq_simple_of_match); ++ ++static int mmc_pwrseq_simple_probe(struct platform_device *pdev) + { + struct mmc_pwrseq_simple *pwrseq; +- int ret = 0; ++ struct device *dev = &pdev->dev; + +- pwrseq = kzalloc(sizeof(*pwrseq), GFP_KERNEL); ++ pwrseq = devm_kzalloc(dev, sizeof(*pwrseq), GFP_KERNEL); + if (!pwrseq) +- return ERR_PTR(-ENOMEM); ++ return -ENOMEM; + +- pwrseq->ext_clk = clk_get(dev, "ext_clock"); +- if (IS_ERR(pwrseq->ext_clk) && +- PTR_ERR(pwrseq->ext_clk) != -ENOENT) { +- ret = PTR_ERR(pwrseq->ext_clk); +- goto free; +- } ++ pwrseq->ext_clk = devm_clk_get(dev, "ext_clock"); ++ if (IS_ERR(pwrseq->ext_clk) && PTR_ERR(pwrseq->ext_clk) != -ENOENT) ++ return PTR_ERR(pwrseq->ext_clk); + +- pwrseq->reset_gpios = gpiod_get_array(dev, "reset", GPIOD_OUT_HIGH); ++ pwrseq->reset_gpios = devm_gpiod_get_array(dev, "reset", ++ GPIOD_OUT_HIGH); + if (IS_ERR(pwrseq->reset_gpios) && + PTR_ERR(pwrseq->reset_gpios) != -ENOENT && + PTR_ERR(pwrseq->reset_gpios) != -ENOSYS) { +- ret = PTR_ERR(pwrseq->reset_gpios); +- goto clk_put; ++ return PTR_ERR(pwrseq->reset_gpios); + } + ++ pwrseq->pwrseq.dev = dev; + pwrseq->pwrseq.ops = &mmc_pwrseq_simple_ops; ++ pwrseq->pwrseq.owner = THIS_MODULE; ++ platform_set_drvdata(pdev, pwrseq); + +- return &pwrseq->pwrseq; +-clk_put: +- if (!IS_ERR(pwrseq->ext_clk)) +- clk_put(pwrseq->ext_clk); +-free: +- kfree(pwrseq); +- return ERR_PTR(ret); ++ return mmc_pwrseq_register(&pwrseq->pwrseq); + } ++ ++static int mmc_pwrseq_simple_remove(struct platform_device *pdev) ++{ ++ struct mmc_pwrseq_simple *pwrseq = platform_get_drvdata(pdev); ++ ++ mmc_pwrseq_unregister(&pwrseq->pwrseq); ++ ++ return 0; ++} ++ ++static struct platform_driver mmc_pwrseq_simple_driver = { ++ .probe = mmc_pwrseq_simple_probe, ++ .remove = mmc_pwrseq_simple_remove, ++ .driver = { ++ .name = "pwrseq_simple", ++ .of_match_table = mmc_pwrseq_simple_of_match, ++ }, ++}; ++ ++module_platform_driver(mmc_pwrseq_simple_driver); ++MODULE_LICENSE("GPL v2"); + +From 42eb02ddb70002e4f72fa627037b6acbdd4cb7a1 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sun, 7 Aug 2016 21:02:38 +0200 +Subject: [PATCH] UPSTREAM: mmc: pwrseq-simple: Add an optional + post-power-on-delay + +Some devices need a while to boot their firmware after providing clks / +de-asserting resets before they are ready to receive sdio commands. + +This commits adds a post-power-on-delay-ms devicetree property to +mmc-pwrseq-simple for use with such devices. + +Signed-off-by: Hans de Goede +Acked-by: Rob Herring +Signed-off-by: Ulf Hansson +(cherry picked from commit 721e0497172f0fa661eed2d63367cddf479f35e8) +--- + Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt | 2 ++ + drivers/mmc/core/pwrseq_simple.c | 9 +++++++++ + 2 files changed, 11 insertions(+) + +diff --git a/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt b/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt +index ce0e76749671..e25436861867 100644 +--- a/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt ++++ b/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt +@@ -16,6 +16,8 @@ Optional properties: + See ../clocks/clock-bindings.txt for details. + - clock-names : Must include the following entry: + "ext_clock" (External clock provided to the card). ++- post-power-on-delay-ms : Delay in ms after powering the card and ++ de-asserting the reset-gpios (if any) + + Example: + +diff --git a/drivers/mmc/core/pwrseq_simple.c b/drivers/mmc/core/pwrseq_simple.c +index 450d907c6e6c..1304160de168 100644 +--- a/drivers/mmc/core/pwrseq_simple.c ++++ b/drivers/mmc/core/pwrseq_simple.c +@@ -16,6 +16,8 @@ + #include + #include + #include ++#include ++#include + + #include + +@@ -24,6 +26,7 @@ + struct mmc_pwrseq_simple { + struct mmc_pwrseq pwrseq; + bool clk_enabled; ++ u32 post_power_on_delay_ms; + struct clk *ext_clk; + struct gpio_descs *reset_gpios; + }; +@@ -64,6 +67,9 @@ static void mmc_pwrseq_simple_post_power_on(struct mmc_host *host) + struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(host->pwrseq); + + mmc_pwrseq_simple_set_gpios_value(pwrseq, 0); ++ ++ if (pwrseq->post_power_on_delay_ms) ++ msleep(pwrseq->post_power_on_delay_ms); + } + + static void mmc_pwrseq_simple_power_off(struct mmc_host *host) +@@ -111,6 +117,9 @@ static int mmc_pwrseq_simple_probe(struct platform_device *pdev) + return PTR_ERR(pwrseq->reset_gpios); + } + ++ device_property_read_u32(dev, "post-power-on-delay-ms", ++ &pwrseq->post_power_on_delay_ms); ++ + pwrseq->pwrseq.dev = dev; + pwrseq->pwrseq.ops = &mmc_pwrseq_simple_ops; + pwrseq->pwrseq.owner = THIS_MODULE; + +From bf90ebd56d6f327f77bd7add55b3593679cd5c67 Mon Sep 17 00:00:00 2001 +From: Ulf Hansson +Date: Sat, 6 May 2017 11:41:30 +0200 +Subject: [PATCH] UPSTREAM: mmc: dt: pwrseq-simple: Invent power-off-delay-us + +During power off, after the GPIO pin has been asserted, some devices like +the Wifi chip from TI, Wl18xx, needs a delay before the host continues with +clock gating and turning off regulators as to follow a graceful shutdown +sequence. + +Therefore invent an optional power-off-delay-us DT binding for +mmc-pwrseq-simple, to allow us to support this constraint. + +Cc: devicetree@vger.kernel.org +Cc: Rob Herring +Cc: linux-mmc@vger.kernel.org +Signed-off-by: Ulf Hansson +Acked-by: Arnd Bergmann +--- + Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt b/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt +index e25436861867..9029b45b8a22 100644 +--- a/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt ++++ b/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt +@@ -18,6 +18,8 @@ Optional properties: + "ext_clock" (External clock provided to the card). + - post-power-on-delay-ms : Delay in ms after powering the card and + de-asserting the reset-gpios (if any) ++- power-off-delay-us : Delay in us after asserting the reset-gpios (if any) ++ during power off of the card. + + Example: + + +From bc79b1f8ca4d16d45b93c2888474bb3f11b10226 Mon Sep 17 00:00:00 2001 +From: Ulf Hansson +Date: Sat, 6 May 2017 11:43:05 +0200 +Subject: [PATCH] UPSTREAM: mmc: pwrseq_simple: Parse DTS for the + power-off-delay-us property + +If the optional power-off-delay-us property is found, insert the +corresponding delay after asserting the GPIO during power off. This enables +a graceful shutdown sequence for some devices. + +Cc: linux-mmc@vger.kernel.org +Signed-off-by: Ulf Hansson +Acked-by: Arnd Bergmann +(cherry picked from commit e9256e142f597edf90c68cec22db4c4aebaa27de) +--- + drivers/mmc/core/pwrseq_simple.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/mmc/core/pwrseq_simple.c b/drivers/mmc/core/pwrseq_simple.c +index 1304160de168..13ef162cf066 100644 +--- a/drivers/mmc/core/pwrseq_simple.c ++++ b/drivers/mmc/core/pwrseq_simple.c +@@ -27,6 +27,7 @@ struct mmc_pwrseq_simple { + struct mmc_pwrseq pwrseq; + bool clk_enabled; + u32 post_power_on_delay_ms; ++ u32 power_off_delay_us; + struct clk *ext_clk; + struct gpio_descs *reset_gpios; + }; +@@ -78,6 +79,10 @@ static void mmc_pwrseq_simple_power_off(struct mmc_host *host) + + mmc_pwrseq_simple_set_gpios_value(pwrseq, 1); + ++ if (pwrseq->power_off_delay_us) ++ usleep_range(pwrseq->power_off_delay_us, ++ 2 * pwrseq->power_off_delay_us); ++ + if (!IS_ERR(pwrseq->ext_clk) && pwrseq->clk_enabled) { + clk_disable_unprepare(pwrseq->ext_clk); + pwrseq->clk_enabled = false; +@@ -119,6 +124,8 @@ static int mmc_pwrseq_simple_probe(struct platform_device *pdev) + + device_property_read_u32(dev, "post-power-on-delay-ms", + &pwrseq->post_power_on_delay_ms); ++ device_property_read_u32(dev, "power-off-delay-us", ++ &pwrseq->power_off_delay_us); + + pwrseq->pwrseq.dev = dev; + pwrseq->pwrseq.ops = &mmc_pwrseq_simple_ops; diff --git a/patch/kernel/rockchip-default/01-linux-0009-mmc.patch b/patch/kernel/rockchip-default/01-linux-0009-mmc.patch new file mode 100644 index 000000000..d3a8ed9a1 --- /dev/null +++ b/patch/kernel/rockchip-default/01-linux-0009-mmc.patch @@ -0,0 +1,633 @@ +From 38396ba52ab85ea1eabea3c92fd7532f8732f92e Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Tue, 24 Jul 2018 15:49:29 +0200 +Subject: [PATCH] mmc: core: use hs400es voltage flags + +--- + drivers/mmc/core/mmc.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c +index a814eb6882aa..1d950f0b3aa6 100644 +--- a/drivers/mmc/core/mmc.c ++++ b/drivers/mmc/core/mmc.c +@@ -1259,10 +1259,10 @@ static int mmc_select_hs400es(struct mmc_card *card) + goto out_err; + } + +- if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_2V) ++ if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400_1_2V) + err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120); + +- if (err && card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_8V) ++ if (err && card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400_1_8V) + err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180); + + /* If fails try again during next card power cycle */ + +From 92a57737adc14e15e80b6913932bb5d2d3478068 Mon Sep 17 00:00:00 2001 +From: Haibo Chen +Date: Tue, 8 Aug 2017 18:54:01 +0800 +Subject: [PATCH] UPSTREAM: mmc: mmc: correct the logic for setting HS400ES + signal voltage + +Change the default err value to -EINVAL, make sure the card only +has type EXT_CSD_CARD_TYPE_HS400_1_8V also do the signal voltage +setting when select hs400es mode. + +Fixes: commit 1720d3545b77 ("mmc: core: switch to 1V8 or 1V2 for hs400es mode") +Cc: +Signed-off-by: Haibo Chen +Reviewed-by: Shawn Lin +Signed-off-by: Ulf Hansson +(cherry picked from commit 92ddd95919466de5d34f3cb43635da9a7f9ab814) +--- + drivers/mmc/core/mmc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c +index 1d950f0b3aa6..70de514dd061 100644 +--- a/drivers/mmc/core/mmc.c ++++ b/drivers/mmc/core/mmc.c +@@ -1251,7 +1251,7 @@ out_err: + static int mmc_select_hs400es(struct mmc_card *card) + { + struct mmc_host *host = card->host; +- int err = 0; ++ int err = -EINVAL; + u8 val; + + if (!(host->caps & MMC_CAP_8_BIT_DATA)) { + +From 108a045df9dc1cee2127aec0bdd327ba7f2fdb81 Mon Sep 17 00:00:00 2001 +From: Ulf Hansson +Date: Wed, 25 Jan 2017 10:12:10 +0100 +Subject: [PATCH] UPSTREAM: mmc: core: Remove redundant code in + mmc_set_signal_voltage() + +The mmc_set_signal_voltage() function is used for SD/SDIO when switching to +1.8V for UHS mode. Therefore let's remove the redundant code dealing with +MMC_SIGNAL_VOLTAGE_330. + +Signed-off-by: Ulf Hansson +Reviewed-by: Shawn Lin +Tested-by: Jan Glauber +Tested-by: Stefan Wahren +(cherry picked from commit a44efa4796249c6d4341935e90e9105d6e1a5f15) +--- + drivers/mmc/core/core.c | 7 ------- + 1 file changed, 7 deletions(-) + +diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c +index 3e3c79feb07b..b69c96ad9486 100644 +--- a/drivers/mmc/core/core.c ++++ b/drivers/mmc/core/core.c +@@ -1598,13 +1598,6 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, u32 ocr) + + BUG_ON(!host); + +- /* +- * Send CMD11 only if the request is to switch the card to +- * 1.8V signalling. +- */ +- if (signal_voltage == MMC_SIGNAL_VOLTAGE_330) +- return __mmc_set_signal_voltage(host, signal_voltage); +- + /* + * If we cannot switch voltages, return failure so the caller + * can continue without UHS mode + +From d28c1bfff6556db2c4ce1093091293cf20542202 Mon Sep 17 00:00:00 2001 +From: Ulf Hansson +Date: Wed, 25 Jan 2017 10:25:01 +0100 +Subject: [PATCH] UPSTREAM: mmc: core: Clarify usage of + mmc_set_signal_voltage() + +The mmc_set_signal_voltage() function is used for SD/SDIO when switching to +1.8V for UHS mode. To clarify this let's do the following changes. + +- We are always providing MMC_SIGNAL_VOLTAGE_180 as the signal_voltage + parameter to the function. Then, let's just remove the parameter as it + serves no purpose. +- Rename the function to mmc_set_uhs_voltage(). + +Signed-off-by: Ulf Hansson +Reviewed-by: Shawn Lin +Tested-by: Jan Glauber +Tested-by: Stefan Wahren +(cherry picked from commit 2ed573b603f78289dd1435c94597aa25a97e2b76) +--- + drivers/mmc/core/core.c | 4 ++-- + drivers/mmc/core/core.h | 2 +- + drivers/mmc/core/sd.c | 3 +-- + drivers/mmc/core/sdio.c | 3 +-- + 4 files changed, 5 insertions(+), 7 deletions(-) + +diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c +index b69c96ad9486..35d19d57d2c5 100644 +--- a/drivers/mmc/core/core.c ++++ b/drivers/mmc/core/core.c +@@ -1590,7 +1590,7 @@ int __mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage) + + } + +-int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, u32 ocr) ++int mmc_set_uhs_voltage(struct mmc_host *host, u32 ocr) + { + struct mmc_command cmd = {0}; + int err = 0; +@@ -1636,7 +1636,7 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, u32 ocr) + host->ios.clock = 0; + mmc_set_ios(host); + +- if (__mmc_set_signal_voltage(host, signal_voltage)) { ++ if (__mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180)) { + /* + * Voltages may not have been switched, but we've already + * sent CMD11, so a power cycle is required anyway +diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h +index ed7c3167763a..88ef50b2e0be 100644 +--- a/drivers/mmc/core/core.h ++++ b/drivers/mmc/core/core.h +@@ -43,7 +43,7 @@ void mmc_set_clock(struct mmc_host *host, unsigned int hz); + void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode); + void mmc_set_bus_width(struct mmc_host *host, unsigned int width); + u32 mmc_select_voltage(struct mmc_host *host, u32 ocr); +-int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, u32 ocr); ++int mmc_set_uhs_voltage(struct mmc_host *host, u32 ocr); + int __mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage); + void mmc_set_timing(struct mmc_host *host, unsigned int timing); + void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type); +diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c +index cd437d6b1843..d9943d82db95 100644 +--- a/drivers/mmc/core/sd.c ++++ b/drivers/mmc/core/sd.c +@@ -742,8 +742,7 @@ try_again: + */ + if (!mmc_host_is_spi(host) && rocr && + ((*rocr & 0x41000000) == 0x41000000)) { +- err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180, +- pocr); ++ err = mmc_set_uhs_voltage(host, pocr); + if (err == -EAGAIN) { + retries--; + goto try_again; +diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c +index c586b11a40b5..f221418542e2 100644 +--- a/drivers/mmc/core/sdio.c ++++ b/drivers/mmc/core/sdio.c +@@ -648,8 +648,7 @@ try_again: + * to make sure which speed mode should work. + */ + if (!powered_resume && (rocr & ocr & R4_18V_PRESENT)) { +- err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180, +- ocr_card); ++ err = mmc_set_uhs_voltage(host, ocr_card); + if (err == -EAGAIN) { + mmc_sdio_resend_if_cond(host, card); + retries--; + +From 0f61c64862ed54163c5f88389170c95055a74f68 Mon Sep 17 00:00:00 2001 +From: Ulf Hansson +Date: Wed, 25 Jan 2017 11:12:34 +0100 +Subject: [PATCH] UPSTREAM: mmc: core: Rename __mmc_set_signal_voltage() to + mmc_set_signal_voltage() + +Earlier the mmc_set_signal_voltage() existed, but since it has been renamed +to mmc_set_uhs_voltage(), we can now use that name instead. + +Signed-off-by: Ulf Hansson +Reviewed-by: Shawn Lin +Tested-by: Jan Glauber +Tested-by: Stefan Wahren +(cherry picked from commit 4e74b6b3c6e9adfe6a8fdebfc56a6416a996d905) +--- + drivers/mmc/core/core.c | 10 +++++----- + drivers/mmc/core/core.h | 2 +- + drivers/mmc/core/mmc.c | 16 ++++++++-------- + 3 files changed, 14 insertions(+), 14 deletions(-) + +diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c +index 35d19d57d2c5..ba285431c2d0 100644 +--- a/drivers/mmc/core/core.c ++++ b/drivers/mmc/core/core.c +@@ -1574,7 +1574,7 @@ u32 mmc_select_voltage(struct mmc_host *host, u32 ocr) + return ocr; + } + +-int __mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage) ++int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage) + { + int err = 0; + int old_signal_voltage = host->ios.signal_voltage; +@@ -1636,7 +1636,7 @@ int mmc_set_uhs_voltage(struct mmc_host *host, u32 ocr) + host->ios.clock = 0; + mmc_set_ios(host); + +- if (__mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180)) { ++ if (mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180)) { + /* + * Voltages may not have been switched, but we've already + * sent CMD11, so a power cycle is required anyway +@@ -1745,11 +1745,11 @@ void mmc_power_up(struct mmc_host *host, u32 ocr) + mmc_set_initial_state(host); + + /* Try to set signal voltage to 3.3V but fall back to 1.8v or 1.2v */ +- if (__mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330) == 0) ++ if (!mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330)) + dev_dbg(mmc_dev(host), "Initial signal voltage of 3.3v\n"); +- else if (__mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180) == 0) ++ else if (!mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180)) + dev_dbg(mmc_dev(host), "Initial signal voltage of 1.8v\n"); +- else if (__mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120) == 0) ++ else if (!mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120)) + dev_dbg(mmc_dev(host), "Initial signal voltage of 1.2v\n"); + + /* +diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h +index 88ef50b2e0be..0e4bc1c7a773 100644 +--- a/drivers/mmc/core/core.h ++++ b/drivers/mmc/core/core.h +@@ -44,7 +44,7 @@ void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode); + void mmc_set_bus_width(struct mmc_host *host, unsigned int width); + u32 mmc_select_voltage(struct mmc_host *host, u32 ocr); + int mmc_set_uhs_voltage(struct mmc_host *host, u32 ocr); +-int __mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage); ++int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage); + void mmc_set_timing(struct mmc_host *host, unsigned int timing); + void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type); + int mmc_select_drive_strength(struct mmc_card *card, unsigned int max_dtr, +diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c +index 70de514dd061..dd0040a10c0b 100644 +--- a/drivers/mmc/core/mmc.c ++++ b/drivers/mmc/core/mmc.c +@@ -1088,14 +1088,14 @@ static int mmc_select_hs_ddr(struct mmc_card *card) + */ + err = -EINVAL; + if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_DDR_1_2V) +- err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120); ++ err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120); + + if (err && (card->mmc_avail_type & EXT_CSD_CARD_TYPE_DDR_1_8V)) +- err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180); ++ err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180); + + /* make sure vccq is 3.3v after switching disaster */ + if (err) +- err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330); ++ err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330); + + if (!err) + mmc_set_timing(host, MMC_TIMING_MMC_DDR52); +@@ -1260,10 +1260,10 @@ static int mmc_select_hs400es(struct mmc_card *card) + } + + if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400_1_2V) +- err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120); ++ err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120); + + if (err && card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400_1_8V) +- err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180); ++ err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180); + + /* If fails try again during next card power cycle */ + if (err) +@@ -1362,10 +1362,10 @@ static int mmc_select_hs200(struct mmc_card *card) + + old_signal_voltage = host->ios.signal_voltage; + if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_2V) +- err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120); ++ err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120); + + if (err && card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_8V) +- err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180); ++ err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180); + + /* If fails try again during next card power cycle */ + if (err) +@@ -1393,7 +1393,7 @@ static int mmc_select_hs200(struct mmc_card *card) + err: + if (err) { + /* fall back to the old signal voltage, if fails report error */ +- if (__mmc_set_signal_voltage(host, old_signal_voltage)) ++ if (mmc_set_signal_voltage(host, old_signal_voltage)) + err = -EIO; + + pr_err("%s: %s failed, error %d\n", mmc_hostname(card->host), + +From db9fd591980256d95de5675ebd84759b9cc9831c Mon Sep 17 00:00:00 2001 +From: Adrian Hunter +Date: Mon, 25 Sep 2017 11:29:03 +0300 +Subject: [PATCH] UPSTREAM: mmc: core: Factor out mmc_host_set_uhs_voltage() + +Factor out mmc_host_set_uhs_voltage() so it can be reused. + +Signed-off-by: Adrian Hunter +Signed-off-by: Ulf Hansson +(cherry picked from commit 3f496afb6fb361b282f37968ff7d3d80b0f1b5cb) +--- + drivers/mmc/core/core.c | 38 ++++++++++++++++++++++++-------------- + drivers/mmc/core/core.h | 1 + + 2 files changed, 25 insertions(+), 14 deletions(-) + +diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c +index ba285431c2d0..dae82afcbc99 100644 +--- a/drivers/mmc/core/core.c ++++ b/drivers/mmc/core/core.c +@@ -1590,11 +1590,33 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage) + + } + ++int mmc_host_set_uhs_voltage(struct mmc_host *host) ++{ ++ u32 clock; ++ ++ /* ++ * During a signal voltage level switch, the clock must be gated ++ * for 5 ms according to the SD spec ++ */ ++ clock = host->ios.clock; ++ host->ios.clock = 0; ++ mmc_set_ios(host); ++ ++ if (mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180)) ++ return -EAGAIN; ++ ++ /* Keep clock gated for at least 10 ms, though spec only says 5 ms */ ++ mmc_delay(10); ++ host->ios.clock = clock; ++ mmc_set_ios(host); ++ ++ return 0; ++} ++ + int mmc_set_uhs_voltage(struct mmc_host *host, u32 ocr) + { + struct mmc_command cmd = {0}; + int err = 0; +- u32 clock; + + BUG_ON(!host); + +@@ -1628,15 +1650,8 @@ int mmc_set_uhs_voltage(struct mmc_host *host, u32 ocr) + err = -EAGAIN; + goto power_cycle; + } +- /* +- * During a signal voltage level switch, the clock must be gated +- * for 5 ms according to the SD spec +- */ +- clock = host->ios.clock; +- host->ios.clock = 0; +- mmc_set_ios(host); + +- if (mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180)) { ++ if (mmc_host_set_uhs_voltage(host)) { + /* + * Voltages may not have been switched, but we've already + * sent CMD11, so a power cycle is required anyway +@@ -1645,11 +1660,6 @@ int mmc_set_uhs_voltage(struct mmc_host *host, u32 ocr) + goto power_cycle; + } + +- /* Keep clock gated for at least 10 ms, though spec only says 5 ms */ +- mmc_delay(10); +- host->ios.clock = clock; +- mmc_set_ios(host); +- + /* Wait for at least 1 ms according to spec */ + mmc_delay(1); + +diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h +index 0e4bc1c7a773..11f3d2c22ecb 100644 +--- a/drivers/mmc/core/core.h ++++ b/drivers/mmc/core/core.h +@@ -44,6 +44,7 @@ void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode); + void mmc_set_bus_width(struct mmc_host *host, unsigned int width); + u32 mmc_select_voltage(struct mmc_host *host, u32 ocr); + int mmc_set_uhs_voltage(struct mmc_host *host, u32 ocr); ++int mmc_host_set_uhs_voltage(struct mmc_host *host); + int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage); + void mmc_set_timing(struct mmc_host *host, unsigned int timing); + void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type); + +From 9c2d593200bd835b8e55eb6e0ba188e4dd9c744e Mon Sep 17 00:00:00 2001 +From: Adrian Hunter +Date: Mon, 25 Sep 2017 11:29:04 +0300 +Subject: [PATCH] UPSTREAM: mmc: sd: Fix signal voltage when there is no power + cycle + +Some boards have SD card connectors where the power rail cannot be switched +off by the driver. However there are various circumstances when a card +might be re-initialized, such as after system resume, warm re-boot, or +error handling. However, a UHS card will continue to use 1.8V signaling +unless it is power cycled. + +If the card has not been power cycled, it may still be using 1.8V +signaling. According to the SD spec., the Bus Speed Mode (function group 1) +bits 2 to 4 are zero if the card is initialized at 3.3V signal level. Thus +they can be used to determine if the card has already switched to 1.8V +signaling. Detect that situation and try to initialize a UHS-I (1.8V) +transfer mode. + +Tested with the following cards: + Transcend 4GB High Speed + Kingston 64GB SDR104 + Lexar by Micron HIGH-PERFORMANCE 300x 16GB DDR50 + SanDisk Ultra 8GB DDR50 + Transcend Ultimate 600x 16GB SDR104 + Transcend Premium 300x 64GB SDR104 + Lexar by Micron Professional 1000x 32GB UHS-II SDR104 + SanDisk Extreme Pro 16GB SDR104 + +Signed-off-by: Adrian Hunter +Tested-by: Zhoujie Wu +Reviewed-by: Shawn Lin +Signed-off-by: Ulf Hansson +(cherry picked from commit 6a11fc47f175c8d87018e89cb58e2d36c66534cb) +--- + drivers/mmc/core/sd.c | 47 +++++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 45 insertions(+), 2 deletions(-) + +diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c +index d9943d82db95..2808a281d094 100644 +--- a/drivers/mmc/core/sd.c ++++ b/drivers/mmc/core/sd.c +@@ -898,6 +898,18 @@ unsigned mmc_sd_get_max_clock(struct mmc_card *card) + return max_dtr; + } + ++static bool mmc_sd_card_using_v18(struct mmc_card *card) ++{ ++ /* ++ * According to the SD spec., the Bus Speed Mode (function group 1) bits ++ * 2 to 4 are zero if the card is initialized at 3.3V signal level. Thus ++ * they can be used to determine if the card has already switched to ++ * 1.8V signaling. ++ */ ++ return card->sw_caps.sd3_bus_mode & ++ (SD_MODE_UHS_SDR50 | SD_MODE_UHS_SDR104 | SD_MODE_UHS_DDR50); ++} ++ + /* + * Handle the detection and initialisation of a card. + * +@@ -911,10 +923,11 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, + int err; + u32 cid[4]; + u32 rocr = 0; ++ bool v18_fixup_failed = false; + + BUG_ON(!host); + WARN_ON(!host->claimed); +- ++retry: + err = mmc_sd_get_cid(host, ocr, cid, &rocr); + if (err) + return err; +@@ -980,6 +993,36 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, + if (err) + goto free_card; + ++ /* ++ * If the card has not been power cycled, it may still be using 1.8V ++ * signaling. Detect that situation and try to initialize a UHS-I (1.8V) ++ * transfer mode. ++ */ ++ if (!v18_fixup_failed && !mmc_host_is_spi(host) && mmc_host_uhs(host) && ++ mmc_sd_card_using_v18(card) && ++ host->ios.signal_voltage != MMC_SIGNAL_VOLTAGE_180) { ++ /* ++ * Re-read switch information in case it has changed since ++ * oldcard was initialized. ++ */ ++ if (oldcard) { ++ err = mmc_read_switch(card); ++ if (err) ++ goto free_card; ++ } ++ if (mmc_sd_card_using_v18(card)) { ++ if (mmc_host_set_uhs_voltage(host) || ++ mmc_sd_init_uhs_card(card)) { ++ v18_fixup_failed = true; ++ mmc_power_cycle(host, ocr); ++ if (!oldcard) ++ mmc_remove_card(card); ++ goto retry; ++ } ++ goto done; ++ } ++ } ++ + /* Initialization sequence for UHS-I cards */ + if (rocr & SD_ROCR_S18A && mmc_host_uhs(host)) { + err = mmc_sd_init_uhs_card(card); +@@ -1012,7 +1055,7 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, + mmc_set_bus_width(host, MMC_BUS_WIDTH_4); + } + } +- ++done: + host->card = card; + return 0; + + +From 6ee3035196c307a77f95b1c1f3cc537e467fb838 Mon Sep 17 00:00:00 2001 +From: Ulf Hansson +Date: Thu, 5 Apr 2018 21:24:15 +0200 +Subject: [PATCH] UPSTREAM: mmc: core: Share internal function to set initial + signal voltage + +Move the corresponding code for setting the initial signal voltage, from +mmc_power_up() into a new function, mmc_set_initial_signal_voltage(). + +Make the function internally available to the mmc core, as to allow the +following changes to make use of it. + +Signed-off-by: Ulf Hansson +Tested-by: Quentin Schulz +Reviewed-by: Shawn Lin +(cherry picked from commit 508c9864ccede5dd4b8a7220b3fe6998763e4407) +--- + drivers/mmc/core/core.c | 19 ++++++++++++------- + drivers/mmc/core/core.h | 1 + + 2 files changed, 13 insertions(+), 7 deletions(-) + +diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c +index dae82afcbc99..7aa83beea957 100644 +--- a/drivers/mmc/core/core.c ++++ b/drivers/mmc/core/core.c +@@ -1590,6 +1590,17 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage) + + } + ++void mmc_set_initial_signal_voltage(struct mmc_host *host) ++{ ++ /* Try to set signal voltage to 3.3V but fall back to 1.8v or 1.2v */ ++ if (!mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330)) ++ dev_dbg(mmc_dev(host), "Initial signal voltage of 3.3v\n"); ++ else if (!mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180)) ++ dev_dbg(mmc_dev(host), "Initial signal voltage of 1.8v\n"); ++ else if (!mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120)) ++ dev_dbg(mmc_dev(host), "Initial signal voltage of 1.2v\n"); ++} ++ + int mmc_host_set_uhs_voltage(struct mmc_host *host) + { + u32 clock; +@@ -1754,13 +1765,7 @@ void mmc_power_up(struct mmc_host *host, u32 ocr) + /* Set initial state and call mmc_set_ios */ + mmc_set_initial_state(host); + +- /* Try to set signal voltage to 3.3V but fall back to 1.8v or 1.2v */ +- if (!mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330)) +- dev_dbg(mmc_dev(host), "Initial signal voltage of 3.3v\n"); +- else if (!mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180)) +- dev_dbg(mmc_dev(host), "Initial signal voltage of 1.8v\n"); +- else if (!mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120)) +- dev_dbg(mmc_dev(host), "Initial signal voltage of 1.2v\n"); ++ mmc_set_initial_signal_voltage(host); + + /* + * This delay should be sufficient to allow the power supply +diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h +index 11f3d2c22ecb..2634722265ad 100644 +--- a/drivers/mmc/core/core.h ++++ b/drivers/mmc/core/core.h +@@ -46,6 +46,7 @@ u32 mmc_select_voltage(struct mmc_host *host, u32 ocr); + int mmc_set_uhs_voltage(struct mmc_host *host, u32 ocr); + int mmc_host_set_uhs_voltage(struct mmc_host *host); + int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage); ++void mmc_set_initial_signal_voltage(struct mmc_host *host); + void mmc_set_timing(struct mmc_host *host, unsigned int timing); + void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type); + int mmc_select_drive_strength(struct mmc_card *card, unsigned int max_dtr, + +From adadab9687a3e07be7557e4272fdf5a007b4c604 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Tue, 24 Jul 2018 15:50:06 +0200 +Subject: [PATCH] mmc: core: set initial signal voltage on power off + +--- + drivers/mmc/core/core.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c +index 7aa83beea957..d2c59b5e04ab 100644 +--- a/drivers/mmc/core/core.c ++++ b/drivers/mmc/core/core.c +@@ -1792,6 +1792,14 @@ void mmc_power_off(struct mmc_host *host) + if (host->ios.power_mode == MMC_POWER_OFF) + return; + ++ mmc_set_initial_signal_voltage(host); ++ ++ /* ++ * This delay should be sufficient to allow the power supply ++ * to reach the minimum voltage. ++ */ ++ mmc_delay(10); ++ + mmc_pwrseq_power_off(host); + + host->ios.clock = 0; diff --git a/patch/kernel/rockchip-default/01-linux-0010-dvb.patch b/patch/kernel/rockchip-default/01-linux-0010-dvb.patch new file mode 100644 index 000000000..d871851a6 --- /dev/null +++ b/patch/kernel/rockchip-default/01-linux-0010-dvb.patch @@ -0,0 +1,376 @@ +From ae39146426642d51de99ba3bdef54912c579991b Mon Sep 17 00:00:00 2001 +From: Jakub Kicinski +Date: Wed, 31 Aug 2016 12:46:44 +0100 +Subject: [PATCH] UPSTREAM: add basic register-field manipulation macros + +Common approach to accessing register fields is to define +structures or sets of macros containing mask and shift pair. +Operations on the register are then performed as follows: + + field = (reg >> shift) & mask; + + reg &= ~(mask << shift); + reg |= (field & mask) << shift; + +Defining shift and mask separately is tedious. Ivo van Doorn +came up with an idea of computing them at compilation time +based on a single shifted mask (later refined by Felix) which +can be used like this: + + #define REG_FIELD 0x000ff000 + + field = FIELD_GET(REG_FIELD, reg); + + reg &= ~REG_FIELD; + reg |= FIELD_PREP(REG_FIELD, field); + +FIELD_{GET,PREP} macros take care of finding out what the +appropriate shift is based on compilation time ffs operation. + +GENMASK can be used to define registers (which is usually +less error-prone and easier to match with datasheets). + +This approach is the most convenient I've seen so to limit code +multiplication let's move the macros to a global header file. +Attempts to use static inlines instead of macros failed due +to false positive triggering of BUILD_BUG_ON()s, especially with +GCC < 6.0. + +Signed-off-by: Jakub Kicinski +Reviewed-by: Dinan Gunawardena +Signed-off-by: Kalle Valo +(cherry picked from commit 3e9b3112ec74f192eaab976c3889e34255cae940) +--- + include/linux/bitfield.h | 93 ++++++++++++++++++++++++++++++++++++++++++++++++ + include/linux/bug.h | 3 ++ + 2 files changed, 96 insertions(+) + create mode 100644 include/linux/bitfield.h + +diff --git a/include/linux/bitfield.h b/include/linux/bitfield.h +new file mode 100644 +index 000000000000..f6505d83069d +--- /dev/null ++++ b/include/linux/bitfield.h +@@ -0,0 +1,93 @@ ++/* ++ * Copyright (C) 2014 Felix Fietkau ++ * Copyright (C) 2004 - 2009 Ivo van Doorn ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 ++ * as published by the Free Software Foundation ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef _LINUX_BITFIELD_H ++#define _LINUX_BITFIELD_H ++ ++#include ++ ++/* ++ * Bitfield access macros ++ * ++ * FIELD_{GET,PREP} macros take as first parameter shifted mask ++ * from which they extract the base mask and shift amount. ++ * Mask must be a compilation time constant. ++ * ++ * Example: ++ * ++ * #define REG_FIELD_A GENMASK(6, 0) ++ * #define REG_FIELD_B BIT(7) ++ * #define REG_FIELD_C GENMASK(15, 8) ++ * #define REG_FIELD_D GENMASK(31, 16) ++ * ++ * Get: ++ * a = FIELD_GET(REG_FIELD_A, reg); ++ * b = FIELD_GET(REG_FIELD_B, reg); ++ * ++ * Set: ++ * reg = FIELD_PREP(REG_FIELD_A, 1) | ++ * FIELD_PREP(REG_FIELD_B, 0) | ++ * FIELD_PREP(REG_FIELD_C, c) | ++ * FIELD_PREP(REG_FIELD_D, 0x40); ++ * ++ * Modify: ++ * reg &= ~REG_FIELD_C; ++ * reg |= FIELD_PREP(REG_FIELD_C, c); ++ */ ++ ++#define __bf_shf(x) (__builtin_ffsll(x) - 1) ++ ++#define __BF_FIELD_CHECK(_mask, _reg, _val, _pfx) \ ++ ({ \ ++ BUILD_BUG_ON_MSG(!__builtin_constant_p(_mask), \ ++ _pfx "mask is not constant"); \ ++ BUILD_BUG_ON_MSG(!(_mask), _pfx "mask is zero"); \ ++ BUILD_BUG_ON_MSG(__builtin_constant_p(_val) ? \ ++ ~((_mask) >> __bf_shf(_mask)) & (_val) : 0, \ ++ _pfx "value too large for the field"); \ ++ BUILD_BUG_ON_MSG((_mask) > (typeof(_reg))~0ull, \ ++ _pfx "type of reg too small for mask"); \ ++ __BUILD_BUG_ON_NOT_POWER_OF_2((_mask) + \ ++ (1ULL << __bf_shf(_mask))); \ ++ }) ++ ++/** ++ * FIELD_PREP() - prepare a bitfield element ++ * @_mask: shifted mask defining the field's length and position ++ * @_val: value to put in the field ++ * ++ * FIELD_PREP() masks and shifts up the value. The result should ++ * be combined with other fields of the bitfield using logical OR. ++ */ ++#define FIELD_PREP(_mask, _val) \ ++ ({ \ ++ __BF_FIELD_CHECK(_mask, 0ULL, _val, "FIELD_PREP: "); \ ++ ((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask); \ ++ }) ++ ++/** ++ * FIELD_GET() - extract a bitfield element ++ * @_mask: shifted mask defining the field's length and position ++ * @_reg: 32bit value of entire bitfield ++ * ++ * FIELD_GET() extracts the field specified by @_mask from the ++ * bitfield passed in as @_reg by masking and shifting it down. ++ */ ++#define FIELD_GET(_mask, _reg) \ ++ ({ \ ++ __BF_FIELD_CHECK(_mask, _reg, 0U, "FIELD_GET: "); \ ++ (typeof(_mask))(((_reg) & (_mask)) >> __bf_shf(_mask)); \ ++ }) ++ ++#endif +diff --git a/include/linux/bug.h b/include/linux/bug.h +index 7f4818673c41..edd3d8d3cd90 100644 +--- a/include/linux/bug.h ++++ b/include/linux/bug.h +@@ -13,6 +13,7 @@ enum bug_trap_type { + struct pt_regs; + + #ifdef __CHECKER__ ++#define __BUILD_BUG_ON_NOT_POWER_OF_2(n) (0) + #define BUILD_BUG_ON_NOT_POWER_OF_2(n) (0) + #define BUILD_BUG_ON_ZERO(e) (0) + #define BUILD_BUG_ON_NULL(e) ((void*)0) +@@ -23,6 +24,8 @@ struct pt_regs; + #else /* __CHECKER__ */ + + /* Force a compilation error if a constant expression is not a power of 2 */ ++#define __BUILD_BUG_ON_NOT_POWER_OF_2(n) \ ++ BUILD_BUG_ON(((n) & ((n) - 1)) != 0) + #define BUILD_BUG_ON_NOT_POWER_OF_2(n) \ + BUILD_BUG_ON((n) == 0 || (((n) & ((n) - 1)) != 0)) + + +From 8c11cf13e9f5c633bc2d1f3414d3b95c9cc82e4c Mon Sep 17 00:00:00 2001 +From: Jakub Kicinski +Date: Thu, 9 Feb 2017 09:17:27 -0800 +Subject: [PATCH] UPSTREAM: bitfield.h: add FIELD_FIT() helper + +Add a helper for checking at runtime that a value will fit inside +a specified field/mask. + +Signed-off-by: Jakub Kicinski +Signed-off-by: David S. Miller +(cherry picked from commit 1697599ee301a52cded6499a09bd609f7f63fd06) +--- + include/linux/bitfield.h | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/include/linux/bitfield.h b/include/linux/bitfield.h +index f6505d83069d..8b9d6fff002d 100644 +--- a/include/linux/bitfield.h ++++ b/include/linux/bitfield.h +@@ -62,6 +62,19 @@ + (1ULL << __bf_shf(_mask))); \ + }) + ++/** ++ * FIELD_FIT() - check if value fits in the field ++ * @_mask: shifted mask defining the field's length and position ++ * @_val: value to test against the field ++ * ++ * Return: true if @_val can fit inside @_mask, false if @_val is too big. ++ */ ++#define FIELD_FIT(_mask, _val) \ ++ ({ \ ++ __BF_FIELD_CHECK(_mask, 0ULL, _val, "FIELD_FIT: "); \ ++ !((((typeof(_mask))_val) << __bf_shf(_mask)) & ~(_mask)); \ ++ }) ++ + /** + * FIELD_PREP() - prepare a bitfield element + * @_mask: shifted mask defining the field's length and position + +From 9b03f083c3ba2b3ca6dbcfdc76bf24edfe8b2947 Mon Sep 17 00:00:00 2001 +From: Laurent Defert +Date: Wed, 11 Oct 2017 08:46:52 +0200 +Subject: [PATCH] FROMLIST: compat_ioctl: add compat handler for + FE_SET_PROPERTY and FE_GET_PROPERTY + +https://patchwork.linuxtv.org/patch/8209/ +--- + fs/compat_ioctl.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 138 insertions(+) + +diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c +index a52ca5cba015..438ce0c6851e 100644 +--- a/fs/compat_ioctl.c ++++ b/fs/compat_ioctl.c +@@ -223,6 +223,140 @@ static int do_video_set_spu_palette(unsigned int fd, unsigned int cmd, + return err; + } + ++struct compat_dtv_property { ++ __u32 cmd; ++ __u32 reserved[3]; ++ union { ++ __u32 data; ++ struct { ++ __u8 data[32]; ++ __u32 len; ++ __u32 reserved1[3]; ++ compat_uptr_t reserved2; ++ } buffer; ++ } u; ++ int result; ++}; ++ ++struct compat_dtv_properties { ++ __u32 num; ++ compat_uptr_t props; ++}; ++ ++#define FE_SET_PROPERTY32 _IOW('o', 82, struct compat_dtv_properties) ++#define FE_GET_PROPERTY32 _IOR('o', 83, struct compat_dtv_properties) ++ ++static int do_fe_set_property(unsigned int fd, unsigned int cmd, ++ struct compat_dtv_properties __user *dtv32) ++{ ++ struct dtv_properties __user *dtv; ++ struct dtv_property __user *properties; ++ struct compat_dtv_property __user *properties32; ++ compat_uptr_t data; ++ ++ int err; ++ int i; ++ __u32 num; ++ ++ err = get_user(num, &dtv32->num); ++ err |= get_user(data, &dtv32->props); ++ ++ if(err) ++ return -EFAULT; ++ ++ dtv = compat_alloc_user_space(sizeof(struct dtv_properties) + ++ sizeof(struct dtv_property) * num); ++ properties = (struct dtv_property*)((char*)dtv + ++ sizeof(struct dtv_properties)); ++ ++ err = put_user(properties, &dtv->props); ++ err |= put_user(num, &dtv->num); ++ ++ properties32 = compat_ptr(data); ++ ++ if(err) ++ return -EFAULT; ++ ++ for(i = 0; i < num; i++) { ++ compat_uptr_t reserved2; ++ ++ err |= copy_in_user(&properties[i], &properties32[i], ++ (8 * sizeof(__u32)) + (32 * sizeof(__u8))); ++ err |= get_user(reserved2, &properties32[i].u.buffer.reserved2); ++ err |= put_user(compat_ptr(reserved2), ++ &properties[i].u.buffer.reserved2); ++ } ++ ++ if(err) ++ return -EFAULT; ++ ++ err = sys_ioctl(fd, FE_SET_PROPERTY, (unsigned long) dtv); ++ ++ for(i = 0; i < num; i++) { ++ if(copy_in_user(&properties32[i].result, &properties[i].result, ++ sizeof(int))) ++ return -EFAULT; ++ } ++ ++ return err; ++} ++ ++static int do_fe_get_property(unsigned int fd, unsigned int cmd, ++ struct compat_dtv_properties __user *dtv32) ++{ ++ struct dtv_properties __user *dtv; ++ struct dtv_property __user *properties; ++ struct compat_dtv_property __user *properties32; ++ compat_uptr_t data; ++ ++ int err; ++ int i; ++ __u32 num; ++ ++ err = get_user(num, &dtv32->num); ++ err |= get_user(data, &dtv32->props); ++ ++ if(err) ++ return -EFAULT; ++ ++ dtv = compat_alloc_user_space(sizeof(struct dtv_properties) + ++ sizeof(struct dtv_property) * num); ++ properties = (struct dtv_property*)((char*)dtv + ++ sizeof(struct dtv_properties)); ++ ++ err = put_user(properties, &dtv->props); ++ err |= put_user(num, &dtv->num); ++ ++ properties32 = compat_ptr(data); ++ ++ if(err) ++ return -EFAULT; ++ ++ for(i = 0; i < num; i++) { ++ compat_uptr_t reserved2; ++ ++ err |= copy_in_user(&properties[i], &properties32[i], ++ (8 * sizeof(__u32)) + (32 * sizeof(__u8))); ++ err |= get_user(reserved2, &properties32[i].u.buffer.reserved2); ++ err |= put_user(compat_ptr(reserved2), ++ &properties[i].u.buffer.reserved2); ++ } ++ ++ if(err) ++ return -EFAULT; ++ ++ err = sys_ioctl(fd, FE_GET_PROPERTY, (unsigned long) dtv); ++ ++ for(i = 0; i < num; i++) { ++ ++ if(copy_in_user(&properties32[i], &properties[i], ++ sizeof(properties32[i]))) ++ return -EFAULT; ++ } ++ ++ return err; ++} ++ + #ifdef CONFIG_BLOCK + typedef struct sg_io_hdr32 { + compat_int_t interface_id; /* [i] 'S' for SCSI generic (required) */ +@@ -1483,6 +1617,10 @@ static long do_ioctl_trans(int fd, unsigned int cmd, + return do_video_stillpicture(fd, cmd, argp); + case VIDEO_SET_SPU_PALETTE: + return do_video_set_spu_palette(fd, cmd, argp); ++ case FE_SET_PROPERTY32: ++ return do_fe_set_property(fd, cmd, argp); ++ case FE_GET_PROPERTY32: ++ return do_fe_get_property(fd, cmd, argp); + } + + /* diff --git a/patch/kernel/rockchip-default/01-linux-1000-pl330.patch b/patch/kernel/rockchip-default/01-linux-1000-pl330.patch new file mode 100644 index 000000000..f3f1590f2 --- /dev/null +++ b/patch/kernel/rockchip-default/01-linux-1000-pl330.patch @@ -0,0 +1,2419 @@ +From 0a3affb0d28223e6ffbdb3ccceeaae1ed7a35b21 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 3 Jun 2018 07:36:35 +0200 +Subject: [PATCH] Revert "dmaengine: pl330: add support for interlace cyclic + xfer" + +This reverts commit 191583d95bae59c82b50f7437f2b738fcc5f8015. +--- + drivers/dma/pl330.c | 21 ++++++++++++--------- + 1 file changed, 12 insertions(+), 9 deletions(-) + +diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c +index 5893c11dd858..b4a0d48bafa4 100644 +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -1398,9 +1398,7 @@ static inline int _loop_cyclic(struct pl330_dmac *pl330, unsigned dry_run, + off += _emit_LPEND(dry_run, &buf[off], &lpend); + } + +- if (pxs->desc->src_interlace_size == 0 && +- pxs->desc->dst_interlace_size == 0 && +- pl330->peripherals_req_type == BURST) { ++ if (pl330->peripherals_req_type == BURST) { + unsigned int ccr = pxs->ccr; + unsigned long c = 0; + +@@ -1501,12 +1499,6 @@ static inline int _setup_xfer_cyclic(struct pl330_dmac *pl330, unsigned dry_run, + unsigned long bursts = BYTE_TO_BURST(x->bytes, ccr); + int off = 0; + +- if (pxs->desc->rqtype == DMA_DEV_TO_MEM) +- bursts = x->bytes / (BRST_SIZE(ccr) * BRST_LEN(ccr) +- + pxs->desc->dst_interlace_size); +- else if (pxs->desc->rqtype == DMA_MEM_TO_DEV) +- bursts = x->bytes / (BRST_SIZE(ccr) * BRST_LEN(ccr) +- + pxs->desc->src_interlace_size); + /* Setup Loop(s) */ + off += _loop_cyclic(pl330, dry_run, &buf[off], bursts, pxs, ev); + +@@ -2729,6 +2721,7 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic( + struct dma_pl330_desc *desc = NULL; + struct dma_pl330_chan *pch = to_pchan(chan); + struct pl330_dmac *pl330 = pch->dmac; ++ unsigned int size = 0; + dma_addr_t dst; + dma_addr_t src; + +@@ -2754,12 +2747,14 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic( + desc->rqcfg.dst_inc = 0; + src = dma_addr; + dst = pch->fifo_addr; ++ size = pch->src_interlace_size; + break; + case DMA_DEV_TO_MEM: + desc->rqcfg.src_inc = 0; + desc->rqcfg.dst_inc = 1; + src = pch->fifo_addr; + dst = dma_addr; ++ size = pch->dst_interlace_size; + break; + default: + break; +@@ -2779,8 +2774,16 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic( + desc->cyclic = true; + desc->num_periods = len / period_len; + desc->txd.flags = flags; ++ + desc->src_interlace_size = pch->src_interlace_size; + desc->dst_interlace_size = pch->dst_interlace_size; ++ /* refine bytes_requested if interlace_size set */ ++ if (size) { ++ size += (pch->burst_len * (1 << pch->burst_sz)); ++ size *= desc->bytes_requested; ++ size /= (pch->burst_len * (1 << pch->burst_sz)); ++ desc->bytes_requested = size; ++ } + return &desc->txd; + } + + +From 16aaccef2d6178e8ce9bdb676526301fd071c3d6 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 3 Jun 2018 07:36:53 +0200 +Subject: [PATCH] Revert "dmaengine: pl330: add support for interlace size + config" + +This reverts commit ddd2e87ad41e2c9e95322a1fb7d8ca65e578aa65. +--- + drivers/dma/pl330.c | 32 -------------------------------- + include/linux/dmaengine.h | 2 -- + 2 files changed, 34 deletions(-) + +diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c +index b4a0d48bafa4..babaeace0a8a 100644 +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -447,10 +447,6 @@ struct dma_pl330_chan { + int burst_len; /* the number of burst */ + dma_addr_t fifo_addr; + +- /* interlace size */ +- unsigned int src_interlace_size; +- unsigned int dst_interlace_size; +- + /* for runtime pm tracking */ + bool active; + }; +@@ -540,9 +536,6 @@ struct dma_pl330_desc { + /* For cyclic capability */ + bool cyclic; + size_t num_periods; +- /* interlace size */ +- unsigned int src_interlace_size; +- unsigned int dst_interlace_size; + }; + + struct _xfer_spec { +@@ -1194,10 +1187,6 @@ static inline int _ldst_devtomem(struct pl330_dmac *pl330, unsigned dry_run, + if (!(pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP)) + off += _emit_FLUSHP(dry_run, &buf[off], + pxs->desc->peri); +- if (pxs->desc->dst_interlace_size) { +- off += _emit_ADDH(dry_run, &buf[off], DST, +- pxs->desc->dst_interlace_size); +- } + } + + return off; +@@ -1228,9 +1217,6 @@ static inline int _ldst_memtodev(struct pl330_dmac *pl330, + if (!(pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP)) + off += _emit_FLUSHP(dry_run, &buf[off], + pxs->desc->peri); +- if (pxs->desc->src_interlace_size) +- off += _emit_ADDH(dry_run, &buf[off], SRC, +- pxs->desc->src_interlace_size); + } + + return off; +@@ -2318,8 +2304,6 @@ static int pl330_config(struct dma_chan *chan, + pch->burst_sz = __ffs(slave_config->dst_addr_width); + if (slave_config->dst_maxburst) + pch->burst_len = slave_config->dst_maxburst; +- if (slave_config->src_interlace_size) +- pch->src_interlace_size = slave_config->src_interlace_size; + } else if (slave_config->direction == DMA_DEV_TO_MEM) { + if (slave_config->src_addr) + pch->fifo_addr = slave_config->src_addr; +@@ -2327,8 +2311,6 @@ static int pl330_config(struct dma_chan *chan, + pch->burst_sz = __ffs(slave_config->src_addr_width); + if (slave_config->src_maxburst) + pch->burst_len = slave_config->src_maxburst; +- if (slave_config->dst_interlace_size) +- pch->dst_interlace_size = slave_config->dst_interlace_size; + } + + return 0; +@@ -2721,7 +2703,6 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic( + struct dma_pl330_desc *desc = NULL; + struct dma_pl330_chan *pch = to_pchan(chan); + struct pl330_dmac *pl330 = pch->dmac; +- unsigned int size = 0; + dma_addr_t dst; + dma_addr_t src; + +@@ -2747,14 +2728,12 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic( + desc->rqcfg.dst_inc = 0; + src = dma_addr; + dst = pch->fifo_addr; +- size = pch->src_interlace_size; + break; + case DMA_DEV_TO_MEM: + desc->rqcfg.src_inc = 0; + desc->rqcfg.dst_inc = 1; + src = pch->fifo_addr; + dst = dma_addr; +- size = pch->dst_interlace_size; + break; + default: + break; +@@ -2775,15 +2754,6 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic( + desc->num_periods = len / period_len; + desc->txd.flags = flags; + +- desc->src_interlace_size = pch->src_interlace_size; +- desc->dst_interlace_size = pch->dst_interlace_size; +- /* refine bytes_requested if interlace_size set */ +- if (size) { +- size += (pch->burst_len * (1 << pch->burst_sz)); +- size *= desc->bytes_requested; +- size /= (pch->burst_len * (1 << pch->burst_sz)); +- desc->bytes_requested = size; +- } + return &desc->txd; + } + +@@ -2920,8 +2890,6 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, + + desc->rqtype = direction; + desc->bytes_requested = sg_dma_len(sg); +- desc->src_interlace_size = pch->src_interlace_size; +- desc->dst_interlace_size = pch->dst_interlace_size; + } + + /* Return the last desc in the chain */ +diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h +index 3050f88daf9e..948c17e409e9 100644 +--- a/include/linux/dmaengine.h ++++ b/include/linux/dmaengine.h +@@ -365,8 +365,6 @@ struct dma_slave_config { + u32 dst_maxburst; + bool device_fc; + unsigned int slave_id; +- unsigned int src_interlace_size; +- unsigned int dst_interlace_size; + }; + + /** + +From ef7bddfb9e1490a323aa322b3f1719f071720f3b Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 4 Feb 2018 10:47:28 +0100 +Subject: [PATCH] Revert "dmaengine: pl330: fix bug that chan descdone is null" + +This reverts commit 636c30b38ae6ec499735ce7621ba474944b4e9b7. +--- + drivers/dma/pl330.c | 17 ++++++++--------- + 1 file changed, 8 insertions(+), 9 deletions(-) + +diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c +index babaeace0a8a..6e375d7ec09c 100644 +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -1789,17 +1789,16 @@ static int pl330_update(struct pl330_dmac *pl330) + + /* Detach the req */ + descdone = thrd->req[active].desc; +- if (descdone) { +- if (!descdone->cyclic) { +- thrd->req[active].desc = NULL; +- thrd->req_running = -1; +- /* Get going again ASAP */ +- _start(thrd); +- } + +- /* For now, just make a list of callbacks to be done */ +- list_add_tail(&descdone->rqd, &pl330->req_done); ++ if (!descdone->cyclic) { ++ thrd->req[active].desc = NULL; ++ thrd->req_running = -1; ++ /* Get going again ASAP */ ++ _start(thrd); + } ++ ++ /* For now, just make a list of callbacks to be done */ ++ list_add_tail(&descdone->rqd, &pl330->req_done); + } + } + + +From 0e87104dd4138e358202bc6bad1f6ca2701fb711 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 4 Feb 2018 10:47:38 +0100 +Subject: [PATCH] Revert "dmaengine: pl330: flush before first loop" + +This reverts commit 34be2cf4679cadbf910de9651d54b46930166446. +--- + drivers/dma/pl330.c | 12 ++---------- + 1 file changed, 2 insertions(+), 10 deletions(-) + +diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c +index 6e375d7ec09c..9664f71dbab2 100644 +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -1351,11 +1351,7 @@ static inline int _loop_cyclic(struct pl330_dmac *pl330, unsigned dry_run, + /* forever loop */ + off += _emit_MOV(dry_run, &buf[off], SAR, x->src_addr); + off += _emit_MOV(dry_run, &buf[off], DAR, x->dst_addr); +-#ifdef CONFIG_ARCH_ROCKCHIP +- if (!(pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP)) +- off += _emit_FLUSHP(dry_run, &buf[off], +- pxs->desc->peri); +-#endif ++ + /* loop0 */ + off += _emit_LP(dry_run, &buf[off], 0, lcnt0); + ljmp0 = off; +@@ -1431,11 +1427,7 @@ static inline int _setup_loops(struct pl330_dmac *pl330, + u32 ccr = pxs->ccr; + unsigned long c, bursts = BYTE_TO_BURST(x->bytes, ccr); + int off = 0; +-#ifdef CONFIG_ARCH_ROCKCHIP +- if (!(pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP)) +- off += _emit_FLUSHP(dry_run, &buf[off], +- pxs->desc->peri); +-#endif ++ + while (bursts) { + c = bursts; + off += _loop(pl330, dry_run, &buf[off], &c, pxs); + +From 31a66caa86b6ed3bde555f70d7d6cb351ff60156 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 4 Feb 2018 10:47:51 +0100 +Subject: [PATCH] Revert "dmaengine: pl330: fix 2 bursts transfer when dma + flushes" + +This reverts commit 98753e172dc1d06cf4d61c48f5c3487df0247472. +--- + drivers/dma/pl330.c | 20 -------------------- + 1 file changed, 20 deletions(-) + +diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c +index 9664f71dbab2..9c3699ad2245 100644 +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -1173,16 +1173,6 @@ static inline int _ldst_devtomem(struct pl330_dmac *pl330, unsigned dry_run, + off += _emit_WFP(dry_run, &buf[off], cond, pxs->desc->peri); + off += _emit_LDP(dry_run, &buf[off], cond, pxs->desc->peri); + off += _emit_ST(dry_run, &buf[off], ALWAYS); +-#ifdef CONFIG_ARCH_ROCKCHIP +- /* +- * Make suree dma has finish transmission, or later flush may +- * cause dma second transmission,and fifo is overrun. +- */ +- off += _emit_WMB(dry_run, &buf[off]); +- off += _emit_NOP(dry_run, &buf[off]); +- off += _emit_WMB(dry_run, &buf[off]); +- off += _emit_NOP(dry_run, &buf[off]); +-#endif + + if (!(pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP)) + off += _emit_FLUSHP(dry_run, &buf[off], +@@ -1203,16 +1193,6 @@ static inline int _ldst_memtodev(struct pl330_dmac *pl330, + off += _emit_WFP(dry_run, &buf[off], cond, pxs->desc->peri); + off += _emit_LD(dry_run, &buf[off], ALWAYS); + off += _emit_STP(dry_run, &buf[off], cond, pxs->desc->peri); +-#ifdef CONFIG_ARCH_ROCKCHIP +- /* +- * Make suree dma has finish transmission, or later flush may +- * cause dma second transmission,and fifo is overrun. +- */ +- off += _emit_WMB(dry_run, &buf[off]); +- off += _emit_NOP(dry_run, &buf[off]); +- off += _emit_WMB(dry_run, &buf[off]); +- off += _emit_NOP(dry_run, &buf[off]); +-#endif + + if (!(pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP)) + off += _emit_FLUSHP(dry_run, &buf[off], + +From 4429392f7f65d46bac1dd0dda3d8611663acce63 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sat, 21 Oct 2017 19:49:27 +0200 +Subject: [PATCH] Revert "dmaengine: pl330: _loop_cyclic fix cycles of last + loop" + +This reverts commit d7155171cbc65e45b5b0c8db03fd16fa57a181f2. +--- + drivers/dma/pl330.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c +index 9c3699ad2245..be4ea6e089ae 100644 +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -1370,7 +1370,7 @@ static inline int _loop_cyclic(struct pl330_dmac *pl330, unsigned dry_run, + ccr &= ~(0xf << CC_SRCBRSTLEN_SHFT); + ccr &= ~(0xf << CC_DSTBRSTLEN_SHFT); + off += _emit_MOV(dry_run, &buf[off], CCR, ccr); +- off += _emit_LP(dry_run, &buf[off], 1, c); ++ off += _emit_LP(dry_run, &buf[off], 1, c - 1); + ljmp1 = off; + off += _bursts(pl330, dry_run, &buf[off], pxs, 1); + lpend.cond = ALWAYS; + +From 4bd0efa160df1d9cdfd2fd213b96587cb7961c76 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 4 Feb 2018 11:05:44 +0100 +Subject: [PATCH] Revert "dmaengine: pl330: pl330_tasklet init power_down by + pch->active" + +This reverts commit 796b13f24a158f14d540bcf7316d843f72242c0d. +--- + drivers/dma/pl330.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c +index be4ea6e089ae..2ba795d599fb 100644 +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -2169,7 +2169,7 @@ static void pl330_tasklet(unsigned long data) + spin_lock(&pch->thread->dmac->lock); + _stop(pch->thread); + spin_unlock(&pch->thread->dmac->lock); +- power_down = pch->active; ++ power_down = true; + pch->active = false; + } else { + /* Make sure the PL330 Channel thread is active */ + +From 2550b832a5aec4d0a2b584bed27a789cb76c2d35 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Fri, 16 Jun 2017 23:14:54 +0200 +Subject: [PATCH] Revert "dmaengine: pl330: _loop_cyclic supports unaligned + size" + +This reverts commit 13dbe2cccd5851540af8158b12499c33801b6ef6. +--- + drivers/dma/pl330.c | 38 ++++++++++---------------------------- + 1 file changed, 10 insertions(+), 28 deletions(-) + +diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c +index 2ba795d599fb..e5b3893d441e 100644 +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -1360,28 +1360,6 @@ static inline int _loop_cyclic(struct pl330_dmac *pl330, unsigned dry_run, + off += _emit_LPEND(dry_run, &buf[off], &lpend); + } + +- if (pl330->peripherals_req_type == BURST) { +- unsigned int ccr = pxs->ccr; +- unsigned long c = 0; +- +- c = BYTE_MOD_BURST_LEN(x->bytes, pxs->ccr); +- +- if (c) { +- ccr &= ~(0xf << CC_SRCBRSTLEN_SHFT); +- ccr &= ~(0xf << CC_DSTBRSTLEN_SHFT); +- off += _emit_MOV(dry_run, &buf[off], CCR, ccr); +- off += _emit_LP(dry_run, &buf[off], 1, c - 1); +- ljmp1 = off; +- off += _bursts(pl330, dry_run, &buf[off], pxs, 1); +- lpend.cond = ALWAYS; +- lpend.forever = false; +- lpend.loop = 1; +- lpend.bjump = off - ljmp1; +- off += _emit_LPEND(dry_run, &buf[off], &lpend); +- off += _emit_MOV(dry_run, &buf[off], CCR, pxs->ccr); +- } +- } +- + off += _emit_SEV(dry_run, &buf[off], ev); + + lpend.cond = ALWAYS; +@@ -1483,13 +1461,13 @@ static int _setup_req(struct pl330_dmac *pl330, unsigned dry_run, + + x = &pxs->desc->px; + +- if (pl330->peripherals_req_type != BURST) { +- /* Error if xfer length is not aligned at burst size */ +- if (x->bytes % (BRST_SIZE(pxs->ccr) * BRST_LEN(pxs->ccr))) +- return -EINVAL; +- } +- + if (!pxs->desc->cyclic) { ++ if (pl330->peripherals_req_type != BURST) { ++ /* Error if xfer length is not aligned at burst size */ ++ if (x->bytes % (BRST_SIZE(pxs->ccr) * BRST_LEN(pxs->ccr))) ++ return -EINVAL; ++ } ++ + off += _setup_xfer(pl330, dry_run, &buf[off], pxs); + + /* DMASEV peripheral/event */ +@@ -1497,6 +1475,10 @@ static int _setup_req(struct pl330_dmac *pl330, unsigned dry_run, + /* DMAEND */ + off += _emit_END(dry_run, &buf[off]); + } else { ++ /* Error if xfer length is not aligned at burst size */ ++ if (x->bytes % (BRST_SIZE(pxs->ccr) * BRST_LEN(pxs->ccr))) ++ return -EINVAL; ++ + off += _setup_xfer_cyclic(pl330, dry_run, &buf[off], + pxs, thrd->ev); + } + +From ce768db94e3fb2c33d68ccf90001f725c0c7feb5 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Fri, 16 Jun 2017 23:14:54 +0200 +Subject: [PATCH] Revert "dmaengine: pl330: redefine the cyclic transfer" + +This reverts commit 5f638786e66089344c9cf594b81fbf02cd794f15. +--- + drivers/dma/pl330.c | 137 +++++++++++----------------------------------------- + 1 file changed, 29 insertions(+), 108 deletions(-) + +diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c +index e5b3893d441e..38c46f4e0408 100644 +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -1307,76 +1307,6 @@ static inline int _loop(struct pl330_dmac *pl330, unsigned dry_run, u8 buf[], + return off; + } + +-/* Returns bytes consumed */ +-static inline int _loop_cyclic(struct pl330_dmac *pl330, unsigned dry_run, +- u8 buf[], unsigned long bursts, const struct _xfer_spec *pxs, int ev) +-{ +- int cyc, off; +- unsigned lcnt0, lcnt1, ljmp0, ljmp1, ljmpfe; +- struct _arg_LPEND lpend; +- struct pl330_xfer *x = &pxs->desc->px; +- +- off = 0; +- ljmpfe = off; +- lcnt0 = pxs->desc->num_periods; +- +- if (bursts > 256) { +- lcnt1 = 256; +- cyc = bursts / 256; +- } else { +- lcnt1 = bursts; +- cyc = 1; +- } +- +- /* forever loop */ +- off += _emit_MOV(dry_run, &buf[off], SAR, x->src_addr); +- off += _emit_MOV(dry_run, &buf[off], DAR, x->dst_addr); +- +- /* loop0 */ +- off += _emit_LP(dry_run, &buf[off], 0, lcnt0); +- ljmp0 = off; +- +- /* loop1 */ +- off += _emit_LP(dry_run, &buf[off], 1, lcnt1); +- ljmp1 = off; +- off += _bursts(pl330, dry_run, &buf[off], pxs, cyc); +- lpend.cond = ALWAYS; +- lpend.forever = false; +- lpend.loop = 1; +- lpend.bjump = off - ljmp1; +- off += _emit_LPEND(dry_run, &buf[off], &lpend); +- +- /* remainder */ +- lcnt1 = bursts - (lcnt1 * cyc); +- +- if (lcnt1) { +- off += _emit_LP(dry_run, &buf[off], 1, lcnt1); +- ljmp1 = off; +- off += _bursts(pl330, dry_run, &buf[off], pxs, 1); +- lpend.cond = ALWAYS; +- lpend.forever = false; +- lpend.loop = 1; +- lpend.bjump = off - ljmp1; +- off += _emit_LPEND(dry_run, &buf[off], &lpend); +- } +- +- off += _emit_SEV(dry_run, &buf[off], ev); +- +- lpend.cond = ALWAYS; +- lpend.forever = false; +- lpend.loop = 0; +- lpend.bjump = off - ljmp0; +- off += _emit_LPEND(dry_run, &buf[off], &lpend); +- +- lpend.cond = ALWAYS; +- lpend.forever = true; +- lpend.loop = 1; +- lpend.bjump = off - ljmpfe; +- off += _emit_LPEND(dry_run, &buf[off], &lpend); +- +- return off; +-} +- + static inline int _setup_loops(struct pl330_dmac *pl330, + unsigned dry_run, u8 buf[], + const struct _xfer_spec *pxs) +@@ -1396,16 +1326,19 @@ static inline int _setup_loops(struct pl330_dmac *pl330, + } + + static inline int _setup_xfer(struct pl330_dmac *pl330, +- unsigned dry_run, u8 buf[], ++ unsigned dry_run, u8 buf[], u32 period, + const struct _xfer_spec *pxs) + { + struct pl330_xfer *x = &pxs->desc->px; ++ struct pl330_reqcfg *rqcfg = &pxs->desc->rqcfg; + int off = 0; + + /* DMAMOV SAR, x->src_addr */ +- off += _emit_MOV(dry_run, &buf[off], SAR, x->src_addr); ++ off += _emit_MOV(dry_run, &buf[off], SAR, ++ x->src_addr + rqcfg->src_inc * period * x->bytes); + /* DMAMOV DAR, x->dst_addr */ +- off += _emit_MOV(dry_run, &buf[off], DAR, x->dst_addr); ++ off += _emit_MOV(dry_run, &buf[off], DAR, ++ x->dst_addr + rqcfg->dst_inc * period * x->bytes); + + /* Setup Loop(s) */ + off += _setup_loops(pl330, dry_run, &buf[off], pxs); +@@ -1427,20 +1360,6 @@ static inline int _setup_xfer(struct pl330_dmac *pl330, + return off; + } + +-static inline int _setup_xfer_cyclic(struct pl330_dmac *pl330, unsigned dry_run, +- u8 buf[], const struct _xfer_spec *pxs, int ev) +-{ +- struct pl330_xfer *x = &pxs->desc->px; +- u32 ccr = pxs->ccr; +- unsigned long bursts = BYTE_TO_BURST(x->bytes, ccr); +- int off = 0; +- +- /* Setup Loop(s) */ +- off += _loop_cyclic(pl330, dry_run, &buf[off], bursts, pxs, ev); +- +- return off; +-} +- + /* + * A req is a sequence of one or more xfer units. + * Returns the number of bytes taken to setup the MC for the req. +@@ -1453,34 +1372,42 @@ static int _setup_req(struct pl330_dmac *pl330, unsigned dry_run, + struct pl330_xfer *x; + u8 *buf = req->mc_cpu; + int off = 0; ++ int period; ++ int again_off; + + PL330_DBGMC_START(req->mc_bus); + + /* DMAMOV CCR, ccr */ + off += _emit_MOV(dry_run, &buf[off], CCR, pxs->ccr); ++ again_off = off; + + x = &pxs->desc->px; ++ if (pl330->peripherals_req_type != BURST) { ++ /* Error if xfer length is not aligned at burst size */ ++ if (x->bytes % (BRST_SIZE(pxs->ccr) * BRST_LEN(pxs->ccr))) ++ return -EINVAL; ++ } + +- if (!pxs->desc->cyclic) { +- if (pl330->peripherals_req_type != BURST) { +- /* Error if xfer length is not aligned at burst size */ +- if (x->bytes % (BRST_SIZE(pxs->ccr) * BRST_LEN(pxs->ccr))) +- return -EINVAL; +- } +- +- off += _setup_xfer(pl330, dry_run, &buf[off], pxs); ++ for (period = 0; period < pxs->desc->num_periods; period++) { ++ off += _setup_xfer(pl330, dry_run, &buf[off], period, pxs); + + /* DMASEV peripheral/event */ + off += _emit_SEV(dry_run, &buf[off], thrd->ev); ++ } ++ ++ if (!pxs->desc->cyclic) { + /* DMAEND */ + off += _emit_END(dry_run, &buf[off]); + } else { +- /* Error if xfer length is not aligned at burst size */ +- if (x->bytes % (BRST_SIZE(pxs->ccr) * BRST_LEN(pxs->ccr))) +- return -EINVAL; +- +- off += _setup_xfer_cyclic(pl330, dry_run, &buf[off], +- pxs, thrd->ev); ++ struct _arg_LPEND lpend; ++ /* LP */ ++ off += _emit_LP(dry_run, &buf[off], 0, 255); ++ /* LPEND */ ++ lpend.cond = ALWAYS; ++ lpend.forever = false; ++ lpend.loop = 0; ++ lpend.bjump = off - again_off; ++ off += _emit_LPEND(dry_run, &buf[off], &lpend); + } + + return off; +@@ -2655,7 +2582,6 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic( + { + struct dma_pl330_desc *desc = NULL; + struct dma_pl330_chan *pch = to_pchan(chan); +- struct pl330_dmac *pl330 = pch->dmac; + dma_addr_t dst; + dma_addr_t src; + +@@ -2694,12 +2620,7 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic( + + desc->rqtype = direction; + desc->rqcfg.brst_size = pch->burst_sz; +- +- if (pl330->peripherals_req_type == BURST) +- desc->rqcfg.brst_len = pch->burst_len; +- else +- desc->rqcfg.brst_len = 1; +- ++ desc->rqcfg.brst_len = pch->burst_len; + desc->bytes_requested = len; + fill_px(&desc->px, dst, src, period_len); + + +From 8ad1819a2e61483c3840d09b9a27f669c7fcb8bc Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Fri, 16 Jun 2017 23:14:54 +0200 +Subject: [PATCH] Revert "dmaengine: pl330: make transfer run infinitely + without CPU intervention" + +This reverts commit e8a6e5086cb82d59cae6ae029b1eb4432cc62288. +--- + drivers/dma/pl330.c | 199 +++++++++++++++++++++++++++------------------------- + 1 file changed, 105 insertions(+), 94 deletions(-) + +diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c +index 38c46f4e0408..ad9d616551f8 100644 +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -447,6 +447,9 @@ struct dma_pl330_chan { + int burst_len; /* the number of burst */ + dma_addr_t fifo_addr; + ++ /* for cyclic capability */ ++ bool cyclic; ++ + /* for runtime pm tracking */ + bool active; + }; +@@ -532,10 +535,6 @@ struct dma_pl330_desc { + unsigned peri:5; + /* Hook to attach to DMAC's list of reqs with due callback */ + struct list_head rqd; +- +- /* For cyclic capability */ +- bool cyclic; +- size_t num_periods; + }; + + struct _xfer_spec { +@@ -1326,19 +1325,16 @@ static inline int _setup_loops(struct pl330_dmac *pl330, + } + + static inline int _setup_xfer(struct pl330_dmac *pl330, +- unsigned dry_run, u8 buf[], u32 period, ++ unsigned dry_run, u8 buf[], + const struct _xfer_spec *pxs) + { + struct pl330_xfer *x = &pxs->desc->px; +- struct pl330_reqcfg *rqcfg = &pxs->desc->rqcfg; + int off = 0; + + /* DMAMOV SAR, x->src_addr */ +- off += _emit_MOV(dry_run, &buf[off], SAR, +- x->src_addr + rqcfg->src_inc * period * x->bytes); ++ off += _emit_MOV(dry_run, &buf[off], SAR, x->src_addr); + /* DMAMOV DAR, x->dst_addr */ +- off += _emit_MOV(dry_run, &buf[off], DAR, +- x->dst_addr + rqcfg->dst_inc * period * x->bytes); ++ off += _emit_MOV(dry_run, &buf[off], DAR, x->dst_addr); + + /* Setup Loop(s) */ + off += _setup_loops(pl330, dry_run, &buf[off], pxs); +@@ -1372,14 +1368,11 @@ static int _setup_req(struct pl330_dmac *pl330, unsigned dry_run, + struct pl330_xfer *x; + u8 *buf = req->mc_cpu; + int off = 0; +- int period; +- int again_off; + + PL330_DBGMC_START(req->mc_bus); + + /* DMAMOV CCR, ccr */ + off += _emit_MOV(dry_run, &buf[off], CCR, pxs->ccr); +- again_off = off; + + x = &pxs->desc->px; + if (pl330->peripherals_req_type != BURST) { +@@ -1388,27 +1381,12 @@ static int _setup_req(struct pl330_dmac *pl330, unsigned dry_run, + return -EINVAL; + } + +- for (period = 0; period < pxs->desc->num_periods; period++) { +- off += _setup_xfer(pl330, dry_run, &buf[off], period, pxs); +- +- /* DMASEV peripheral/event */ +- off += _emit_SEV(dry_run, &buf[off], thrd->ev); +- } ++ off += _setup_xfer(pl330, dry_run, &buf[off], pxs); + +- if (!pxs->desc->cyclic) { +- /* DMAEND */ +- off += _emit_END(dry_run, &buf[off]); +- } else { +- struct _arg_LPEND lpend; +- /* LP */ +- off += _emit_LP(dry_run, &buf[off], 0, 255); +- /* LPEND */ +- lpend.cond = ALWAYS; +- lpend.forever = false; +- lpend.loop = 0; +- lpend.bjump = off - again_off; +- off += _emit_LPEND(dry_run, &buf[off], &lpend); +- } ++ /* DMASEV peripheral/event */ ++ off += _emit_SEV(dry_run, &buf[off], thrd->ev); ++ /* DMAEND */ ++ off += _emit_END(dry_run, &buf[off]); + + return off; + } +@@ -1670,13 +1648,12 @@ static int pl330_update(struct pl330_dmac *pl330) + + /* Detach the req */ + descdone = thrd->req[active].desc; ++ thrd->req[active].desc = NULL; + +- if (!descdone->cyclic) { +- thrd->req[active].desc = NULL; +- thrd->req_running = -1; +- /* Get going again ASAP */ +- _start(thrd); +- } ++ thrd->req_running = -1; ++ ++ /* Get going again ASAP */ ++ _start(thrd); + + /* For now, just make a list of callbacks to be done */ + list_add_tail(&descdone->rqd, &pl330->req_done); +@@ -2049,27 +2026,12 @@ static void pl330_tasklet(unsigned long data) + spin_lock_irqsave(&pch->lock, flags); + + /* Pick up ripe tomatoes */ +- list_for_each_entry_safe(desc, _dt, &pch->work_list, node) { ++ list_for_each_entry_safe(desc, _dt, &pch->work_list, node) + if (desc->status == DONE) { +- if (!desc->cyclic) { ++ if (!pch->cyclic) + dma_cookie_complete(&desc->txd); +- list_move_tail(&desc->node, &pch->completed_list); +- } else { +- dma_async_tx_callback callback; +- void *callback_param; +- +- desc->status = BUSY; +- callback = desc->txd.callback; +- callback_param = desc->txd.callback_param; +- +- if (callback) { +- spin_unlock_irqrestore(&pch->lock, flags); +- callback(callback_param); +- spin_lock_irqsave(&pch->lock, flags); +- } +- } ++ list_move_tail(&desc->node, &pch->completed_list); + } +- } + + /* Try to submit a req imm. next to the last completed cookie */ + fill_queue(pch); +@@ -2097,8 +2059,20 @@ static void pl330_tasklet(unsigned long data) + callback = desc->txd.callback; + callback_param = desc->txd.callback_param; + +- desc->status = FREE; +- list_move_tail(&desc->node, &pch->dmac->desc_pool); ++ if (pch->cyclic) { ++ desc->status = PREP; ++ list_move_tail(&desc->node, &pch->work_list); ++ if (power_down) { ++ pch->active = true; ++ spin_lock(&pch->thread->dmac->lock); ++ _start(pch->thread); ++ spin_unlock(&pch->thread->dmac->lock); ++ power_down = false; ++ } ++ } else { ++ desc->status = FREE; ++ list_move_tail(&desc->node, &pch->dmac->desc_pool); ++ } + + dma_descriptor_unmap(&desc->txd); + +@@ -2158,6 +2132,7 @@ static int pl330_alloc_chan_resources(struct dma_chan *chan) + spin_lock_irqsave(&pl330->lock, flags); + + dma_cookie_init(chan); ++ pch->cyclic = false; + + pch->thread = pl330_request_channel(pl330); + if (!pch->thread) { +@@ -2281,7 +2256,8 @@ static void pl330_free_chan_resources(struct dma_chan *chan) + pl330_release_channel(pch->thread); + pch->thread = NULL; + +- list_splice_tail_init(&pch->work_list, &pch->dmac->desc_pool); ++ if (pch->cyclic) ++ list_splice_tail_init(&pch->work_list, &pch->dmac->desc_pool); + + spin_unlock_irqrestore(&pl330->lock, flags); + pm_runtime_mark_last_busy(pch->dmac->ddma.dev); +@@ -2335,7 +2311,7 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie, + + /* Check in pending list */ + list_for_each_entry(desc, &pch->work_list, node) { +- if (desc->status == DONE && !desc->cyclic) ++ if (desc->status == DONE) + transferred = desc->bytes_requested; + else if (running && desc == running) + transferred = +@@ -2407,8 +2383,12 @@ static dma_cookie_t pl330_tx_submit(struct dma_async_tx_descriptor *tx) + /* Assign cookies to all nodes */ + while (!list_empty(&last->node)) { + desc = list_entry(last->node.next, struct dma_pl330_desc, node); +- ++ if (pch->cyclic) { ++ desc->txd.callback = last->txd.callback; ++ desc->txd.callback_param = last->txd.callback_param; ++ } + desc->last = false; ++ + dma_cookie_assign(&desc->txd); + + list_move_tail(&desc->node, &pch->submitted_list); +@@ -2508,9 +2488,6 @@ static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch) + desc->peri = peri_id ? pch->chan.chan_id : 0; + desc->rqcfg.pcfg = &pch->dmac->pcfg; + +- desc->cyclic = false; +- desc->num_periods = 1; +- + dma_async_tx_descriptor_init(&desc->txd, &pch->chan); + + return desc; +@@ -2580,8 +2557,10 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic( + size_t period_len, enum dma_transfer_direction direction, + unsigned long flags) + { +- struct dma_pl330_desc *desc = NULL; ++ struct dma_pl330_desc *desc = NULL, *first = NULL; + struct dma_pl330_chan *pch = to_pchan(chan); ++ struct pl330_dmac *pl330 = pch->dmac; ++ unsigned int i; + dma_addr_t dst; + dma_addr_t src; + +@@ -2594,38 +2573,70 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic( + return NULL; + } + +- desc = pl330_get_desc(pch); +- if (!desc) { +- dev_err(pch->dmac->ddma.dev, "%s:%d Unable to fetch desc\n", +- __func__, __LINE__); +- return NULL; +- } ++ for (i = 0; i < len / period_len; i++) { ++ desc = pl330_get_desc(pch); ++ if (!desc) { ++ dev_err(pch->dmac->ddma.dev, "%s:%d Unable to fetch desc\n", ++ __func__, __LINE__); + +- switch (direction) { +- case DMA_MEM_TO_DEV: +- desc->rqcfg.src_inc = 1; +- desc->rqcfg.dst_inc = 0; +- src = dma_addr; +- dst = pch->fifo_addr; +- break; +- case DMA_DEV_TO_MEM: +- desc->rqcfg.src_inc = 0; +- desc->rqcfg.dst_inc = 1; +- src = pch->fifo_addr; +- dst = dma_addr; +- break; +- default: +- break; ++ if (!first) ++ return NULL; ++ ++ spin_lock_irqsave(&pl330->pool_lock, flags); ++ ++ while (!list_empty(&first->node)) { ++ desc = list_entry(first->node.next, ++ struct dma_pl330_desc, node); ++ list_move_tail(&desc->node, &pl330->desc_pool); ++ } ++ ++ list_move_tail(&first->node, &pl330->desc_pool); ++ ++ spin_unlock_irqrestore(&pl330->pool_lock, flags); ++ ++ return NULL; ++ } ++ ++ switch (direction) { ++ case DMA_MEM_TO_DEV: ++ desc->rqcfg.src_inc = 1; ++ desc->rqcfg.dst_inc = 0; ++ src = dma_addr; ++ dst = pch->fifo_addr; ++ break; ++ case DMA_DEV_TO_MEM: ++ desc->rqcfg.src_inc = 0; ++ desc->rqcfg.dst_inc = 1; ++ src = pch->fifo_addr; ++ dst = dma_addr; ++ break; ++ default: ++ break; ++ } ++ ++ desc->rqtype = direction; ++ desc->rqcfg.brst_size = pch->burst_sz; ++ ++ if (pl330->peripherals_req_type == BURST) ++ desc->rqcfg.brst_len = pch->burst_len; ++ else ++ desc->rqcfg.brst_len = 1; ++ ++ desc->bytes_requested = period_len; ++ fill_px(&desc->px, dst, src, period_len); ++ ++ if (!first) ++ first = desc; ++ else ++ list_add_tail(&desc->node, &first->node); ++ ++ dma_addr += period_len; + } + +- desc->rqtype = direction; +- desc->rqcfg.brst_size = pch->burst_sz; +- desc->rqcfg.brst_len = pch->burst_len; +- desc->bytes_requested = len; +- fill_px(&desc->px, dst, src, period_len); ++ if (!desc) ++ return NULL; + +- desc->cyclic = true; +- desc->num_periods = len / period_len; ++ pch->cyclic = true; + desc->txd.flags = flags; + + return &desc->txd; + +From ef009783e673113536eb2c9809f3787f5aeef87a Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sun, 22 Jul 2018 16:07:46 +0200 +Subject: [PATCH] Revert "dmaengine: pl330: fix error message to + dev_err_ratelimited" + +This reverts commit e25503f147cf665b6fc910983859d9f94eaf0d00. +--- + drivers/dma/pl330.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c +index ad9d616551f8..3d5d91084605 100644 +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -1620,8 +1620,8 @@ static int pl330_update(struct pl330_dmac *pl330) + if (pl330->pcfg.num_events < 32 + && val & ~((1 << pl330->pcfg.num_events) - 1)) { + pl330->dmac_tbd.reset_dmac = true; +- dev_err_ratelimited(pl330->ddma.dev, "%s:%d Unexpected!\n", +- __func__, __LINE__); ++ dev_err(pl330->ddma.dev, "%s:%d Unexpected!\n", __func__, ++ __LINE__); + ret = 1; + goto updt_exit; + } + +From 45c38c611da7df545138bf436f43e78481a6fa1a Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Fri, 16 Jun 2017 23:14:55 +0200 +Subject: [PATCH] Revert "dmaengine: pl330: support transfer that doesn't align + with (burst len * burst size)" + +This reverts commit c66ecf19b98ffac86177c29859e683de39f44e73. +--- + drivers/dma/pl330.c | 23 +++-------------------- + 1 file changed, 3 insertions(+), 20 deletions(-) + +diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c +index 3d5d91084605..2f5f8d40147c 100644 +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -240,7 +240,6 @@ enum pl330_byteswap { + + #define BYTE_TO_BURST(b, ccr) ((b) / BRST_SIZE(ccr) / BRST_LEN(ccr)) + #define BURST_TO_BYTE(c, ccr) ((c) * BRST_SIZE(ccr) * BRST_LEN(ccr)) +-#define BYTE_MOD_BURST_LEN(b, ccr) (((b) / BRST_SIZE(ccr)) % BRST_LEN(ccr)) + + /* + * With 256 bytes, we can do more than 2.5MB and 5MB xfers per req +@@ -1339,20 +1338,6 @@ static inline int _setup_xfer(struct pl330_dmac *pl330, + /* Setup Loop(s) */ + off += _setup_loops(pl330, dry_run, &buf[off], pxs); + +- if (pl330->peripherals_req_type == BURST) { +- unsigned int ccr = pxs->ccr; +- unsigned long c = 0; +- +- c = BYTE_MOD_BURST_LEN(x->bytes, pxs->ccr); +- +- if (c) { +- ccr &= ~(0xf << CC_SRCBRSTLEN_SHFT); +- ccr &= ~(0xf << CC_DSTBRSTLEN_SHFT); +- off += _emit_MOV(dry_run, &buf[off], CCR, ccr); +- off += _loop(pl330, dry_run, &buf[off], &c, pxs); +- } +- } +- + return off; + } + +@@ -1375,11 +1360,9 @@ static int _setup_req(struct pl330_dmac *pl330, unsigned dry_run, + off += _emit_MOV(dry_run, &buf[off], CCR, pxs->ccr); + + x = &pxs->desc->px; +- if (pl330->peripherals_req_type != BURST) { +- /* Error if xfer length is not aligned at burst size */ +- if (x->bytes % (BRST_SIZE(pxs->ccr) * BRST_LEN(pxs->ccr))) +- return -EINVAL; +- } ++ /* Error if xfer length is not aligned at burst size */ ++ if (x->bytes % (BRST_SIZE(pxs->ccr) * BRST_LEN(pxs->ccr))) ++ return -EINVAL; + + off += _setup_xfer(pl330, dry_run, &buf[off], pxs); + + +From 0be5f99a27515b375304a2dc85226a2fd3d560cd Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Fri, 16 Jun 2017 23:14:55 +0200 +Subject: [PATCH] Revert "dmaengine: pl330: add burst mode according to dts + config" + +This reverts commit 8e770f371cc27f8828cb9ceb0516adc23fe75995. +--- + drivers/dma/pl330.c | 36 ++++++++++++++---------------------- + 1 file changed, 14 insertions(+), 22 deletions(-) + +diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c +index 2f5f8d40147c..f7977979cbf5 100644 +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -494,8 +494,6 @@ struct pl330_dmac { + /* Peripheral channels connected to this DMAC */ + unsigned int num_peripherals; + struct dma_pl330_chan *peripherals; /* keep at end */ +- /* set peripherals request type according to soc config*/ +- enum pl330_cond peripherals_req_type; + int quirks; + }; + +@@ -1165,7 +1163,12 @@ static inline int _ldst_devtomem(struct pl330_dmac *pl330, unsigned dry_run, + int cyc) + { + int off = 0; +- enum pl330_cond cond = pl330->peripherals_req_type; ++ enum pl330_cond cond; ++ ++ if (pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP) ++ cond = BURST; ++ else ++ cond = SINGLE; + + while (cyc--) { + off += _emit_WFP(dry_run, &buf[off], cond, pxs->desc->peri); +@@ -1185,7 +1188,12 @@ static inline int _ldst_memtodev(struct pl330_dmac *pl330, + const struct _xfer_spec *pxs, int cyc) + { + int off = 0; +- enum pl330_cond cond = pl330->peripherals_req_type; ++ enum pl330_cond cond; ++ ++ if (pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP) ++ cond = BURST; ++ else ++ cond = SINGLE; + + while (cyc--) { + off += _emit_WFP(dry_run, &buf[off], cond, pxs->desc->peri); +@@ -2599,12 +2607,7 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic( + + desc->rqtype = direction; + desc->rqcfg.brst_size = pch->burst_sz; +- +- if (pl330->peripherals_req_type == BURST) +- desc->rqcfg.brst_len = pch->burst_len; +- else +- desc->rqcfg.brst_len = 1; +- ++ desc->rqcfg.brst_len = 1; + desc->bytes_requested = period_len; + fill_px(&desc->px, dst, src, period_len); + +@@ -2706,7 +2709,6 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, + { + struct dma_pl330_desc *first, *desc = NULL; + struct dma_pl330_chan *pch = to_pchan(chan); +- struct pl330_dmac *pl330 = pch->dmac; + struct scatterlist *sg; + int i; + dma_addr_t addr; +@@ -2750,12 +2752,7 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, + } + + desc->rqcfg.brst_size = pch->burst_sz; +- +- if (pl330->peripherals_req_type == BURST) +- desc->rqcfg.brst_len = pch->burst_len; +- else +- desc->rqcfg.brst_len = 1; +- ++ desc->rqcfg.brst_len = 1; + desc->rqtype = direction; + desc->bytes_requested = sg_dma_len(sg); + } +@@ -2851,11 +2848,6 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) + + pl330->mcbufsz = pdat ? pdat->mcbuf_sz : 0; + +- if (of_find_property(np, "peripherals-req-type-burst", NULL)) +- pl330->peripherals_req_type = BURST; +- else +- pl330->peripherals_req_type = SINGLE; +- + /* get quirk */ + for (i = 0; i < ARRAY_SIZE(of_quirks); i++) + if (of_property_read_bool(np, of_quirks[i].quirk)) + +From a3456e55253a88214f07c72127744eee7e81ede1 Mon Sep 17 00:00:00 2001 +From: Vinod Koul +Date: Tue, 5 Jul 2016 10:02:16 +0530 +Subject: [PATCH] UPSTREAM: dmaengine: pl330: explicitly freeup irq + +dmaengine device should explicitly call devm_free_irq() when using +devm_request_irq(). + +The irq is still ON when devices remove is executed and irq should be +quiesced before remove is completed. + +Signed-off-by: Vinod Koul +Cc: Jassi Brar +Cc: Linus Walleij +(cherry picked from commit 46cf94d6ab38420690d890d9922bfc61a7b3e2c5) +--- + drivers/dma/pl330.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c +index f7977979cbf5..b6793b0d53c9 100644 +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -3015,12 +3015,18 @@ static int pl330_remove(struct amba_device *adev) + { + struct pl330_dmac *pl330 = amba_get_drvdata(adev); + struct dma_pl330_chan *pch, *_p; ++ int i, irq; + + pm_runtime_get_noresume(pl330->ddma.dev); + + if (adev->dev.of_node) + of_dma_controller_free(adev->dev.of_node); + ++ for (i = 0; i < AMBA_NR_IRQS; i++) { ++ irq = adev->irq[i]; ++ devm_free_irq(&adev->dev, irq, pl330); ++ } ++ + dma_async_device_unregister(&pl330->ddma); + + /* Idle the DMAC */ + +From f1fd696d39b9ded57b30f79bbe23317262481a80 Mon Sep 17 00:00:00 2001 +From: Stephen Barber +Date: Thu, 18 Aug 2016 17:59:59 -0700 +Subject: [PATCH] UPSTREAM: dmaengine: pl330: fix residual for non-running BUSY + descriptors + +Only one descriptor in the work list should be running at +any given time, but it's possible to have an enqueued BUSY +descriptor that has not yet transferred any data, or for +a BUSY descriptor to linger briefly before transitioning +to DONE. These cases should be handled to keep residual +calculations consistent even with the non-running BUSY +descriptors in the work list. + +Signed-off-by: Stephen Barber +Signed-off-by: Vinod Koul +(cherry picked from commit d64e9a2c750930272492952c16f3f2c95311a6c9) +--- + drivers/dma/pl330.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c +index b6793b0d53c9..7e05ef5ba37f 100644 +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -2283,7 +2283,7 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie, + { + enum dma_status ret; + unsigned long flags; +- struct dma_pl330_desc *desc, *running = NULL; ++ struct dma_pl330_desc *desc, *running = NULL, *last_enq = NULL; + struct dma_pl330_chan *pch = to_pchan(chan); + unsigned int transferred, residual = 0; + +@@ -2300,6 +2300,8 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie, + if (pch->thread->req_running != -1) + running = pch->thread->req[pch->thread->req_running].desc; + ++ last_enq = pch->thread->req[pch->thread->lstenq].desc; ++ + /* Check in pending list */ + list_for_each_entry(desc, &pch->work_list, node) { + if (desc->status == DONE) +@@ -2307,6 +2309,15 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie, + else if (running && desc == running) + transferred = + pl330_get_current_xferred_count(pch, desc); ++ else if (desc->status == BUSY) ++ /* ++ * Busy but not running means either just enqueued, ++ * or finished and not yet marked done ++ */ ++ if (desc == last_enq) ++ transferred = 0; ++ else ++ transferred = desc->bytes_requested; + else + transferred = 0; + residual += desc->bytes_requested - transferred; + +From 5cb6529514e53ca8db016137788675be769a75b7 Mon Sep 17 00:00:00 2001 +From: Hsin-Yu Chao +Date: Tue, 23 Aug 2016 17:16:55 +0800 +Subject: [PATCH] UPSTREAM: dmaengine: pl330: Acquire dmac's spinlock in + pl330_tx_status + +There is a racing when accessing dmac thread in pl330_tx_status that +the pl330_update is handling active request at the same time and +changing the status of descriptors. This could cause an invalid +transferred count from BUSY descriptor added up to the residual number. +Fix the bug by using the dmac's spinlock in pl330_tx_status to protect +thread resources from changing. +Note that the nested order of holding dmac's and dma_chan's spinlock is +consistent with the rest of the driver: dma_chan first and then dmac, +so it is safe from deadlock scenario. + +Signed-off-by: Hsin-Yu Chao +Reviewed-by: Guenter Roeck +Signed-off-by: Vinod Koul +(cherry picked from commit a40235a2278a315261ee007fc433ec1cfb31666f) +--- + drivers/dma/pl330.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c +index 7e05ef5ba37f..93efdcc54f19 100644 +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -2296,6 +2296,7 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie, + goto out; + + spin_lock_irqsave(&pch->lock, flags); ++ spin_lock(&pch->thread->dmac->lock); + + if (pch->thread->req_running != -1) + running = pch->thread->req[pch->thread->req_running].desc; +@@ -2338,6 +2339,7 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie, + if (desc->last) + residual = 0; + } ++ spin_unlock(&pch->thread->dmac->lock); + spin_unlock_irqrestore(&pch->lock, flags); + + out: + +From cd1b3fa8ef7ec0a775321d44d2f5469ffbab7431 Mon Sep 17 00:00:00 2001 +From: Stephen Barber +Date: Tue, 1 Nov 2016 16:44:27 -0700 +Subject: [PATCH] UPSTREAM: dmaengine: pl330: Handle xferred count if DMAMOV + hasn't finished + +After executing DMAGO it's possible that a request can come in for the +current xferred count, but if that happens too soon then DMAMOV SAR/DAR +may not have yet completed. If that happens, we should explicitly return 0 +since nothing has been transferred yet. + +Signed-off-by: Stephen Barber +Signed-off-by: Vinod Koul +(cherry picked from commit c44da03dd517c11c2b3525937b0a241fc1c69399) +--- + drivers/dma/pl330.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c +index 93efdcc54f19..497cc048feaa 100644 +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -2274,6 +2274,11 @@ static int pl330_get_current_xferred_count(struct dma_pl330_chan *pch, + } + pm_runtime_mark_last_busy(pch->dmac->ddma.dev); + pm_runtime_put_autosuspend(pl330->ddma.dev); ++ ++ /* If DMAMOV hasn't finished yet, SAR/DAR can be zero */ ++ if (!val) ++ return 0; ++ + return val - addr; + } + + +From 5f387aa530599beb607885a28a5bbf8f50d1dbb6 Mon Sep 17 00:00:00 2001 +From: Vladimir Murzin +Date: Wed, 7 Dec 2016 13:17:40 +0000 +Subject: [PATCH] UPSTREAM: dmaengine: pl330: do not generate unaligned access + +When PL330 is used with !MMU the following fault is seen: + +Unhandled fault: alignment exception (0x801) at 0x8f26a002 +Internal error: : 801 [#1] ARM +Modules linked in: +CPU: 0 PID: 640 Comm: dma0chan0-copy0 Not tainted 4.8.0-6a82063-clean+ #1600 +Hardware name: ARM-Versatile Express +task: 8f1baa80 task.stack: 8e6fe000 +PC is at _setup_req+0x4c/0x350 +LR is at 0x8f2cbc00 +pc : [<801ea538>] lr : [<8f2cbc00>] psr: 60000093 +sp : 8e6ffdc0 ip : 00000000 fp : 00000000 +r10: 00000000 r9 : 8f2cba10 r8 : 8f2cbc00 +r7 : 80000013 r6 : 8f21a050 r5 : 8f21a000 r4 : 8f2ac800 +r3 : 8e6ffe18 r2 : 00944251 r1 : ffffffbc r0 : 8f26a000 +Flags: nZCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment none +Control: 00c5387c +Process dma0chan0-copy0 (pid: 640, stack limit = 0x8e6fe210) +Stack: (0x8e6ffdc0 to 0x8e700000) +fdc0: 00000001 60000093 00000000 8f2cba10 8f26a000 00000004 8f0ae000 8f2cbc00 +fde0: 8f0ae000 8f2ac800 8f21a000 8f21a050 80000013 8f2cbc00 8f2cba10 00000000 +fe00: 60000093 801ebca0 8e6ffe18 000013ff 40000093 00000000 00944251 8f2ac800 +fe20: a0000013 8f2b1320 00001986 00000000 00000001 000013ff 8f1e4f00 8f2cba10 +fe40: 8e6fff6c 801e9044 00000003 00000000 fef98c80 002faf07 8e6ffe7c 00000000 +fe60: 00000002 00000000 00001986 8f1f158d 8f1e4f00 80568de4 00000002 00000000 +fe80: 00001986 8f1f53ff 40000001 80580500 8f1f158d 8001e00c 00000000 cfdfdfdf +fea0: fdae2a25 00000001 00000004 8e6fe000 00000008 00000010 00000000 00000005 +fec0: 8f2b1330 8f2b1334 8e6ffe80 8e6ffe8c 00001986 00000000 8f21a014 00000001 +fee0: 8e6ffe60 8e6ffe78 00000002 00000000 000013ff 00000001 80568de4 8f1e8018 +ff00: 0000158d 8055ec30 00000001 803f6b00 00001986 8f2cba10 fdae2a25 00000001 +ff20: 8f1baca8 8e6fff24 8e6fff24 00000000 8e6fff24 ac6f3037 00000000 00000000 +ff40: 00000000 8e6fe000 8f1e4f40 00000000 8f1e4f40 8f1e4f00 801e84ec 00000000 +ff60: 00000000 00000000 00000000 80031714 dfdfdfcf 00000000 dfdfdfcf 8f1e4f00 +ff80: 00000000 8e6fff84 8e6fff84 00000000 8e6fff90 8e6fff90 8e6fffac 8f1e4f40 +ffa0: 80031640 00000000 00000000 8000f548 00000000 00000000 00000000 00000000 +ffc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 +ffe0: 00000000 00000000 00000000 00000000 00000013 00000000 dfdfdfcf cfdfdfdf +[<801ea538>] (_setup_req) from [<801ebca0>] (pl330_tasklet+0x41c/0x490) +[<801ebca0>] (pl330_tasklet) from [<801e9044>] (dmatest_func+0xb58/0x149c) +[<801e9044>] (dmatest_func) from [<80031714>] (kthread+0xd4/0xec) +[<80031714>] (kthread) from [<8000f548>] (ret_from_fork+0x14/0x2c) +Code: e3a03001 e3e01043 e5c03001 e59d3048 (e5802002) + +This happens because _emit_{ADDH,MOV,GO) accessing to unaligned data +while writing to buffer. Fix it with writing to buffer byte by byte. + +Reviewed-by: Robin Murphy +Tested-by: Robin Murphy +Signed-off-by: Vladimir Murzin +Signed-off-by: Vinod Koul +(cherry picked from commit d07c9e1e212c9687f9198bfeba582e86cae3f6f9) +--- + drivers/dma/pl330.c | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c +index 497cc048feaa..eb274eeda0aa 100644 +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -573,7 +573,8 @@ static inline u32 _emit_ADDH(unsigned dry_run, u8 buf[], + + buf[0] = CMD_DMAADDH; + buf[0] |= (da << 1); +- *((__le16 *)&buf[1]) = cpu_to_le16(val); ++ buf[1] = val; ++ buf[2] = val >> 8; + + PL330_DBGCMD_DUMP(SZ_DMAADDH, "\tDMAADDH %s %u\n", + da == 1 ? "DA" : "SA", val); +@@ -727,7 +728,10 @@ static inline u32 _emit_MOV(unsigned dry_run, u8 buf[], + + buf[0] = CMD_DMAMOV; + buf[1] = dst; +- *((__le32 *)&buf[2]) = cpu_to_le32(val); ++ buf[2] = val; ++ buf[3] = val >> 8; ++ buf[4] = val >> 16; ++ buf[5] = val >> 24; + + PL330_DBGCMD_DUMP(SZ_DMAMOV, "\tDMAMOV %s 0x%x\n", + dst == SAR ? "SAR" : (dst == DAR ? "DAR" : "CCR"), val); +@@ -902,10 +906,11 @@ static inline u32 _emit_GO(unsigned dry_run, u8 buf[], + + buf[0] = CMD_DMAGO; + buf[0] |= (ns << 1); +- + buf[1] = chan & 0x7; +- +- *((__le32 *)&buf[2]) = cpu_to_le32(addr); ++ buf[2] = addr; ++ buf[3] = addr >> 8; ++ buf[4] = addr >> 16; ++ buf[5] = addr >> 24; + + return SZ_DMAGO; + } + +From 90b0d473241a84db9a284123c7357231a0ffd7d2 Mon Sep 17 00:00:00 2001 +From: Vinod Koul +Date: Fri, 9 Dec 2016 15:24:12 +0530 +Subject: [PATCH] =?UTF-8?q?UPSTREAM:=20dmaengine:=20pl330:=20remove=20unus?= + =?UTF-8?q?ed=20=E2=80=98regs=E2=80=99?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In pl330_add(), variable ‘regs’ is initialized but never used, which +leads to warning with W=1. + +drivers/dma/pl330.c: In function 'pl330_add': +drivers/dma/pl330.c:1891:16: warning: variable 'regs' set but not used [-Wunused-but-set-variable] + +So remove it. + +Cc: Linus Walleij +Signed-off-by: Vinod Koul +(cherry picked from commit 920e00d62ef9a818a4af7b2f9e1dbca23f846fc1) +--- + drivers/dma/pl330.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c +index eb274eeda0aa..14efb0e4a6a8 100644 +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -1889,11 +1889,8 @@ static int dmac_alloc_resources(struct pl330_dmac *pl330) + + static int pl330_add(struct pl330_dmac *pl330) + { +- void __iomem *regs; + int i, ret; + +- regs = pl330->base; +- + /* Check if we can handle this DMAC */ + if ((pl330->pcfg.periph_id & 0xfffff) != PERIPH_ID_VAL) { + dev_err(pl330->ddma.dev, "PERIPH_ID 0x%x !\n", + +From 10abe915578c8bbd0e2621a255718beecc6a3425 Mon Sep 17 00:00:00 2001 +From: Marek Szyprowski +Date: Mon, 27 Mar 2017 07:31:03 +0200 +Subject: [PATCH] UPSTREAM: dmaengine: pl330: remove pdata based initialization + +This driver is now used only on platforms which support device tree, so +it is safe to remove legacy platform data based initialization code. + +Signed-off-by: Marek Szyprowski +Reviewed-by: Ulf Hansson +Acked-by: Arnd Bergmann +For plat-samsung: +Acked-by: Krzysztof Kozlowski +Signed-off-by: Vinod Koul +(cherry picked from commit e8bb4673596ea28fab287dbc417e8100d798cd40) +--- + arch/arm/plat-samsung/devs.c | 1 - + drivers/dma/pl330.c | 42 ++++++++---------------------------------- + include/linux/amba/pl330.h | 35 ----------------------------------- + 3 files changed, 8 insertions(+), 70 deletions(-) + delete mode 100644 include/linux/amba/pl330.h + +diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c +index e212f9d804bd..2ef19ad5cb62 100644 +--- a/arch/arm/plat-samsung/devs.c ++++ b/arch/arm/plat-samsung/devs.c +@@ -10,7 +10,6 @@ + * published by the Free Software Foundation. + */ + +-#include + #include + #include + #include +diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c +index 14efb0e4a6a8..8d6c483663dc 100644 +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -22,7 +22,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -2084,18 +2083,6 @@ static void pl330_tasklet(unsigned long data) + } + } + +-bool pl330_filter(struct dma_chan *chan, void *param) +-{ +- u8 *peri_id; +- +- if (chan->device->dev->driver != &pl330_driver.drv) +- return false; +- +- peri_id = chan->private; +- return *peri_id == (unsigned long)param; +-} +-EXPORT_SYMBOL(pl330_filter); +- + static struct dma_chan *of_dma_pl330_xlate(struct of_phandle_args *dma_spec, + struct of_dma *ofdma) + { +@@ -2840,7 +2827,6 @@ static SIMPLE_DEV_PM_OPS(pl330_pm, pl330_suspend, pl330_resume); + static int + pl330_probe(struct amba_device *adev, const struct amba_id *id) + { +- struct dma_pl330_platdata *pdat; + struct pl330_config *pcfg; + struct pl330_dmac *pl330; + struct dma_pl330_chan *pch, *_p; +@@ -2850,8 +2836,6 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) + int num_chan; + struct device_node *np = adev->dev.of_node; + +- pdat = dev_get_platdata(&adev->dev); +- + ret = dma_set_mask_and_coherent(&adev->dev, DMA_BIT_MASK(32)); + if (ret) + return ret; +@@ -2866,7 +2850,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) + pd = &pl330->ddma; + pd->dev = &adev->dev; + +- pl330->mcbufsz = pdat ? pdat->mcbuf_sz : 0; ++ pl330->mcbufsz = 0; + + /* get quirk */ + for (i = 0; i < ARRAY_SIZE(of_quirks); i++) +@@ -2910,10 +2894,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) + INIT_LIST_HEAD(&pd->channels); + + /* Initialize channel parameters */ +- if (pdat) +- num_chan = max_t(int, pdat->nr_valid_peri, pcfg->num_chan); +- else +- num_chan = max_t(int, pcfg->num_peri, pcfg->num_chan); ++ num_chan = max_t(int, pcfg->num_peri, pcfg->num_chan); + + pl330->num_peripherals = num_chan; + +@@ -2926,11 +2907,8 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) + + for (i = 0; i < num_chan; i++) { + pch = &pl330->peripherals[i]; +- if (!adev->dev.of_node) +- pch->chan.private = pdat ? &pdat->peri_id[i] : NULL; +- else +- pch->chan.private = adev->dev.of_node; + ++ pch->chan.private = adev->dev.of_node; + INIT_LIST_HEAD(&pch->submitted_list); + INIT_LIST_HEAD(&pch->work_list); + INIT_LIST_HEAD(&pch->completed_list); +@@ -2943,15 +2921,11 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) + list_add_tail(&pch->chan.device_node, &pd->channels); + } + +- if (pdat) { +- pd->cap_mask = pdat->cap_mask; +- } else { +- dma_cap_set(DMA_MEMCPY, pd->cap_mask); +- if (pcfg->num_peri) { +- dma_cap_set(DMA_SLAVE, pd->cap_mask); +- dma_cap_set(DMA_CYCLIC, pd->cap_mask); +- dma_cap_set(DMA_PRIVATE, pd->cap_mask); +- } ++ dma_cap_set(DMA_MEMCPY, pd->cap_mask); ++ if (pcfg->num_peri) { ++ dma_cap_set(DMA_SLAVE, pd->cap_mask); ++ dma_cap_set(DMA_CYCLIC, pd->cap_mask); ++ dma_cap_set(DMA_PRIVATE, pd->cap_mask); + } + + pd->device_alloc_chan_resources = pl330_alloc_chan_resources; +diff --git a/include/linux/amba/pl330.h b/include/linux/amba/pl330.h +deleted file mode 100644 +index fe93758e8403..000000000000 +--- a/include/linux/amba/pl330.h ++++ /dev/null +@@ -1,35 +0,0 @@ +-/* linux/include/linux/amba/pl330.h +- * +- * Copyright (C) 2010 Samsung Electronics Co. Ltd. +- * Jaswinder Singh +- * +- * 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. +- */ +- +-#ifndef __AMBA_PL330_H_ +-#define __AMBA_PL330_H_ +- +-#include +- +-struct dma_pl330_platdata { +- /* +- * Number of valid peripherals connected to DMAC. +- * This may be different from the value read from +- * CR0, as the PL330 implementation might have 'holes' +- * in the peri list or the peri could also be reached +- * from another DMAC which the platform prefers. +- */ +- u8 nr_valid_peri; +- /* Array of valid peripherals */ +- u8 *peri_id; +- /* Operational capabilities */ +- dma_cap_mask_t cap_mask; +- /* Bytes to allocate for MC buffer */ +- unsigned mcbuf_sz; +-}; +- +-extern bool pl330_filter(struct dma_chan *chan, void *param); +-#endif /* __AMBA_PL330_H_ */ + +From 1ecb8e7abb5ba82380d83c7951621faeba06389e Mon Sep 17 00:00:00 2001 +From: Jean-Philippe Brucker +Date: Thu, 1 Jun 2017 19:22:01 +0100 +Subject: [PATCH] UPSTREAM: dmaengine: pl330: fix warning in pl330_remove + +When removing a device with less than 9 IRQs (AMBA_NR_IRQS), we'll get a +big WARN_ON from devres.c because pl330_remove calls devm_free_irqs for +unallocated irqs. Similarly to pl330_probe, check that IRQ number is +present before calling devm_free_irq. + +Signed-off-by: Jean-Philippe Brucker +Signed-off-by: Vinod Koul +(cherry picked from commit ebcdaee4cebb3a8d0d702ab5e9392373672ec1de) +--- + drivers/dma/pl330.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c +index 8d6c483663dc..f6a4a89ae8aa 100644 +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -3018,7 +3018,8 @@ static int pl330_remove(struct amba_device *adev) + + for (i = 0; i < AMBA_NR_IRQS; i++) { + irq = adev->irq[i]; +- devm_free_irq(&adev->dev, irq, pl330); ++ if (irq) ++ devm_free_irq(&adev->dev, irq, pl330); + } + + dma_async_device_unregister(&pl330->ddma); + +From 7d8694893a9e8d32c82b52fa589fe1e5660ec590 Mon Sep 17 00:00:00 2001 +From: Matthias Kaehlcke +Date: Thu, 15 Jun 2017 16:55:57 -0700 +Subject: [PATCH] UPSTREAM: dmaengine: pl330: Delete unused functions + +The functions _queue_empty(), _emit_ADDH(), _emit_NOP(), _emit_STZ() +and _emit_WFE() are not used. Delete them. + +Signed-off-by: Matthias Kaehlcke +Signed-off-by: Vinod Koul +(cherry picked from commit d43674ecc002b49926f216cb414cff2d230ca3fb) +--- + drivers/dma/pl330.c | 67 ----------------------------------------------------- + 1 file changed, 67 deletions(-) + +diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c +index f6a4a89ae8aa..bd4a0c3deaf6 100644 +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -538,11 +538,6 @@ struct _xfer_spec { + struct dma_pl330_desc *desc; + }; + +-static inline bool _queue_empty(struct pl330_thread *thrd) +-{ +- return thrd->req[0].desc == NULL && thrd->req[1].desc == NULL; +-} +- + static inline bool _queue_full(struct pl330_thread *thrd) + { + return thrd->req[0].desc != NULL && thrd->req[1].desc != NULL; +@@ -564,23 +559,6 @@ static inline u32 get_revision(u32 periph_id) + return (periph_id >> PERIPH_REV_SHIFT) & PERIPH_REV_MASK; + } + +-static inline u32 _emit_ADDH(unsigned dry_run, u8 buf[], +- enum pl330_dst da, u16 val) +-{ +- if (dry_run) +- return SZ_DMAADDH; +- +- buf[0] = CMD_DMAADDH; +- buf[0] |= (da << 1); +- buf[1] = val; +- buf[2] = val >> 8; +- +- PL330_DBGCMD_DUMP(SZ_DMAADDH, "\tDMAADDH %s %u\n", +- da == 1 ? "DA" : "SA", val); +- +- return SZ_DMAADDH; +-} +- + static inline u32 _emit_END(unsigned dry_run, u8 buf[]) + { + if (dry_run) +@@ -738,18 +716,6 @@ static inline u32 _emit_MOV(unsigned dry_run, u8 buf[], + return SZ_DMAMOV; + } + +-static inline u32 _emit_NOP(unsigned dry_run, u8 buf[]) +-{ +- if (dry_run) +- return SZ_DMANOP; +- +- buf[0] = CMD_DMANOP; +- +- PL330_DBGCMD_DUMP(SZ_DMANOP, "\tDMANOP\n"); +- +- return SZ_DMANOP; +-} +- + static inline u32 _emit_RMB(unsigned dry_run, u8 buf[]) + { + if (dry_run) +@@ -817,39 +783,6 @@ static inline u32 _emit_STP(unsigned dry_run, u8 buf[], + return SZ_DMASTP; + } + +-static inline u32 _emit_STZ(unsigned dry_run, u8 buf[]) +-{ +- if (dry_run) +- return SZ_DMASTZ; +- +- buf[0] = CMD_DMASTZ; +- +- PL330_DBGCMD_DUMP(SZ_DMASTZ, "\tDMASTZ\n"); +- +- return SZ_DMASTZ; +-} +- +-static inline u32 _emit_WFE(unsigned dry_run, u8 buf[], u8 ev, +- unsigned invalidate) +-{ +- if (dry_run) +- return SZ_DMAWFE; +- +- buf[0] = CMD_DMAWFE; +- +- ev &= 0x1f; +- ev <<= 3; +- buf[1] = ev; +- +- if (invalidate) +- buf[1] |= (1 << 1); +- +- PL330_DBGCMD_DUMP(SZ_DMAWFE, "\tDMAWFE %u%s\n", +- ev >> 3, invalidate ? ", I" : ""); +- +- return SZ_DMAWFE; +-} +- + static inline u32 _emit_WFP(unsigned dry_run, u8 buf[], + enum pl330_cond cond, u8 peri) + { + +From 66625effb6e47117c803249fc0d843eff367f32b Mon Sep 17 00:00:00 2001 +From: Arvind Yadav +Date: Wed, 23 Aug 2017 21:57:31 +0530 +Subject: [PATCH] UPSTREAM: dmaengine: pl330: constify amba_id + +amba_id are not supposed to change at runtime. All functions +working with const amba_id. So mark the non-const structs as const. + +Signed-off-by: Arvind Yadav +Signed-off-by: Vinod Koul +(cherry picked from commit b753351ec8f4c6a25c6d9b5c4eccce62e448a571) +--- + drivers/dma/pl330.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c +index bd4a0c3deaf6..63ffb8d1f885 100644 +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -2976,7 +2976,7 @@ static int pl330_remove(struct amba_device *adev) + return 0; + } + +-static struct amba_id pl330_ids[] = { ++static const struct amba_id pl330_ids[] = { + { + .id = 0x00041330, + .mask = 0x000fffff, + +From 32b006c4a5e5af627e8daa773a49da36a5deeced Mon Sep 17 00:00:00 2001 +From: Alexander Kochetkov +Date: Wed, 4 Oct 2017 14:37:23 +0300 +Subject: [PATCH] UPSTREAM: dmaengine: pl330: fix descriptor allocation fail + +If two concurrent threads call pl330_get_desc() when DMAC descriptor +pool is empty it is possible that allocation for one of threads will fail +with message: + +kernel: dma-pl330 20078000.dma-controller: pl330_get_desc:2469 ALERT! + +Here how that can happen. Thread A calls pl330_get_desc() to get +descriptor. If DMAC descriptor pool is empty pl330_get_desc() allocates +new descriptor on shared pool using add_desc() and then get newly +allocated descriptor using pluck_desc(). At the same time thread B calls +pluck_desc() and take newly allocated descriptor. In that case descriptor +allocation for thread A will fail. + +Using on-stack pool for new descriptor allow avoid the issue described. +The patch modify pl330_get_desc() to use on-stack pool for allocation +new descriptors. + +Signed-off-by: Alexander Kochetkov +Tested-by: Marek Szyprowski +Signed-off-by: Vinod Koul +(cherry picked from commit e588710311ee5bece284871d613418831d56f2bd) +--- + drivers/dma/pl330.c | 39 ++++++++++++++++++++------------------- + 1 file changed, 20 insertions(+), 19 deletions(-) + +diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c +index 63ffb8d1f885..257492238cea 100644 +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -2344,7 +2344,8 @@ static inline void _init_desc(struct dma_pl330_desc *desc) + } + + /* Returns the number of descriptors added to the DMAC pool */ +-static int add_desc(struct pl330_dmac *pl330, gfp_t flg, int count) ++static int add_desc(struct list_head *pool, spinlock_t *lock, ++ gfp_t flg, int count) + { + struct dma_pl330_desc *desc; + unsigned long flags; +@@ -2354,27 +2355,28 @@ static int add_desc(struct pl330_dmac *pl330, gfp_t flg, int count) + if (!desc) + return 0; + +- spin_lock_irqsave(&pl330->pool_lock, flags); ++ spin_lock_irqsave(lock, flags); + + for (i = 0; i < count; i++) { + _init_desc(&desc[i]); +- list_add_tail(&desc[i].node, &pl330->desc_pool); ++ list_add_tail(&desc[i].node, pool); + } + +- spin_unlock_irqrestore(&pl330->pool_lock, flags); ++ spin_unlock_irqrestore(lock, flags); + + return count; + } + +-static struct dma_pl330_desc *pluck_desc(struct pl330_dmac *pl330) ++static struct dma_pl330_desc *pluck_desc(struct list_head *pool, ++ spinlock_t *lock) + { + struct dma_pl330_desc *desc = NULL; + unsigned long flags; + +- spin_lock_irqsave(&pl330->pool_lock, flags); ++ spin_lock_irqsave(lock, flags); + +- if (!list_empty(&pl330->desc_pool)) { +- desc = list_entry(pl330->desc_pool.next, ++ if (!list_empty(pool)) { ++ desc = list_entry(pool->next, + struct dma_pl330_desc, node); + + list_del_init(&desc->node); +@@ -2383,7 +2385,7 @@ static struct dma_pl330_desc *pluck_desc(struct pl330_dmac *pl330) + desc->txd.callback = NULL; + } + +- spin_unlock_irqrestore(&pl330->pool_lock, flags); ++ spin_unlock_irqrestore(lock, flags); + + return desc; + } +@@ -2395,20 +2397,18 @@ static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch) + struct dma_pl330_desc *desc; + + /* Pluck one desc from the pool of DMAC */ +- desc = pluck_desc(pl330); ++ desc = pluck_desc(&pl330->desc_pool, &pl330->pool_lock); + + /* If the DMAC pool is empty, alloc new */ + if (!desc) { +- if (!add_desc(pl330, GFP_ATOMIC, 1)) +- return NULL; ++ DEFINE_SPINLOCK(lock); ++ LIST_HEAD(pool); + +- /* Try again */ +- desc = pluck_desc(pl330); +- if (!desc) { +- dev_err(pch->dmac->ddma.dev, +- "%s:%d ALERT!\n", __func__, __LINE__); ++ if (!add_desc(&pool, &lock, GFP_ATOMIC, 1)) + return NULL; +- } ++ ++ desc = pluck_desc(&pool, &lock); ++ WARN_ON(!desc || !list_empty(&pool)); + } + + /* Initialize the descriptor */ +@@ -2821,7 +2821,8 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) + spin_lock_init(&pl330->pool_lock); + + /* Create a descriptor pool of default size */ +- if (!add_desc(pl330, GFP_KERNEL, NR_DEFAULT_DESC)) ++ if (!add_desc(&pl330->desc_pool, &pl330->pool_lock, ++ GFP_KERNEL, NR_DEFAULT_DESC)) + dev_warn(&adev->dev, "unable to allocate desc\n"); + + INIT_LIST_HEAD(&pd->channels); + +From 60af02189c1e3cc3d8e957754ac0f97dc20655f5 Mon Sep 17 00:00:00 2001 +From: Frank Mori Hess +Date: Wed, 18 Apr 2018 20:31:06 -0400 +Subject: [PATCH] UPSTREAM: dmaengine: pl330: flush before wait, and add dev + burst support. + +Do DMAFLUSHP _before_ the first DMAWFP to ensure controller +and peripheral are in agreement about dma request state before first +transfer. Add support for burst transfers to/from peripherals. In the new +scheme, the controller does as many burst transfers as it can then +transfers the remaining dregs with either single transfers for +peripherals, or with a reduced size burst for memory-to-memory transfers. + +Signed-off-by: Frank Mori Hess +Tested-by: Frank Mori Hess +Signed-off-by: Vinod Koul +(cherry picked from commit 1d48745b192a7a45bbdd3557b4c039609569ca41) +--- + drivers/dma/pl330.c | 209 +++++++++++++++++++++++++++++++++++++++------------- + 1 file changed, 159 insertions(+), 50 deletions(-) + +diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c +index 257492238cea..fd48c031ead8 100644 +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + + #include "dmaengine.h" + #define PL330_MAX_CHAN 8 +@@ -1095,51 +1096,96 @@ static inline int _ldst_memtomem(unsigned dry_run, u8 buf[], + return off; + } + +-static inline int _ldst_devtomem(struct pl330_dmac *pl330, unsigned dry_run, +- u8 buf[], const struct _xfer_spec *pxs, +- int cyc) ++static u32 _emit_load(unsigned int dry_run, u8 buf[], ++ enum pl330_cond cond, enum dma_transfer_direction direction, ++ u8 peri) + { + int off = 0; +- enum pl330_cond cond; + +- if (pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP) +- cond = BURST; +- else +- cond = SINGLE; ++ switch (direction) { ++ case DMA_MEM_TO_MEM: ++ /* fall through */ ++ case DMA_MEM_TO_DEV: ++ off += _emit_LD(dry_run, &buf[off], cond); ++ break; + +- while (cyc--) { +- off += _emit_WFP(dry_run, &buf[off], cond, pxs->desc->peri); +- off += _emit_LDP(dry_run, &buf[off], cond, pxs->desc->peri); +- off += _emit_ST(dry_run, &buf[off], ALWAYS); ++ case DMA_DEV_TO_MEM: ++ if (cond == ALWAYS) { ++ off += _emit_LDP(dry_run, &buf[off], SINGLE, ++ peri); ++ off += _emit_LDP(dry_run, &buf[off], BURST, ++ peri); ++ } else { ++ off += _emit_LDP(dry_run, &buf[off], cond, ++ peri); ++ } ++ break; + +- if (!(pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP)) +- off += _emit_FLUSHP(dry_run, &buf[off], +- pxs->desc->peri); ++ default: ++ /* this code should be unreachable */ ++ WARN_ON(1); ++ break; + } + + return off; + } + +-static inline int _ldst_memtodev(struct pl330_dmac *pl330, ++static inline u32 _emit_store(unsigned int dry_run, u8 buf[], ++ enum pl330_cond cond, enum dma_transfer_direction direction, ++ u8 peri) ++{ ++ int off = 0; ++ ++ switch (direction) { ++ case DMA_MEM_TO_MEM: ++ /* fall through */ ++ case DMA_DEV_TO_MEM: ++ off += _emit_ST(dry_run, &buf[off], cond); ++ break; ++ ++ case DMA_MEM_TO_DEV: ++ if (cond == ALWAYS) { ++ off += _emit_STP(dry_run, &buf[off], SINGLE, ++ peri); ++ off += _emit_STP(dry_run, &buf[off], BURST, ++ peri); ++ } else { ++ off += _emit_STP(dry_run, &buf[off], cond, ++ peri); ++ } ++ break; ++ ++ default: ++ /* this code should be unreachable */ ++ WARN_ON(1); ++ break; ++ } ++ ++ return off; ++} ++ ++static inline int _ldst_peripheral(struct pl330_dmac *pl330, + unsigned dry_run, u8 buf[], +- const struct _xfer_spec *pxs, int cyc) ++ const struct _xfer_spec *pxs, int cyc, ++ enum pl330_cond cond) + { + int off = 0; +- enum pl330_cond cond; + + if (pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP) + cond = BURST; +- else +- cond = SINGLE; + ++ /* ++ * do FLUSHP at beginning to clear any stale dma requests before the ++ * first WFP. ++ */ ++ if (!(pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP)) ++ off += _emit_FLUSHP(dry_run, &buf[off], pxs->desc->peri); + while (cyc--) { + off += _emit_WFP(dry_run, &buf[off], cond, pxs->desc->peri); +- off += _emit_LD(dry_run, &buf[off], ALWAYS); +- off += _emit_STP(dry_run, &buf[off], cond, pxs->desc->peri); +- +- if (!(pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP)) +- off += _emit_FLUSHP(dry_run, &buf[off], +- pxs->desc->peri); ++ off += _emit_load(dry_run, &buf[off], cond, pxs->desc->rqtype, ++ pxs->desc->peri); ++ off += _emit_store(dry_run, &buf[off], cond, pxs->desc->rqtype, ++ pxs->desc->peri); + } + + return off; +@@ -1149,19 +1195,65 @@ static int _bursts(struct pl330_dmac *pl330, unsigned dry_run, u8 buf[], + const struct _xfer_spec *pxs, int cyc) + { + int off = 0; ++ enum pl330_cond cond = BRST_LEN(pxs->ccr) > 1 ? BURST : SINGLE; + + switch (pxs->desc->rqtype) { + case DMA_MEM_TO_DEV: +- off += _ldst_memtodev(pl330, dry_run, &buf[off], pxs, cyc); +- break; ++ /* fall through */ + case DMA_DEV_TO_MEM: +- off += _ldst_devtomem(pl330, dry_run, &buf[off], pxs, cyc); ++ off += _ldst_peripheral(pl330, dry_run, &buf[off], pxs, cyc, ++ cond); + break; ++ + case DMA_MEM_TO_MEM: + off += _ldst_memtomem(dry_run, &buf[off], pxs, cyc); + break; ++ ++ default: ++ /* this code should be unreachable */ ++ WARN_ON(1); ++ break; ++ } ++ ++ return off; ++} ++ ++/* ++ * transfer dregs with single transfers to peripheral, or a reduced size burst ++ * for mem-to-mem. ++ */ ++static int _dregs(struct pl330_dmac *pl330, unsigned int dry_run, u8 buf[], ++ const struct _xfer_spec *pxs, int transfer_length) ++{ ++ int off = 0; ++ int dregs_ccr; ++ ++ if (transfer_length == 0) ++ return off; ++ ++ switch (pxs->desc->rqtype) { ++ case DMA_MEM_TO_DEV: ++ /* fall through */ ++ case DMA_DEV_TO_MEM: ++ off += _ldst_peripheral(pl330, dry_run, &buf[off], pxs, ++ transfer_length, SINGLE); ++ break; ++ ++ case DMA_MEM_TO_MEM: ++ dregs_ccr = pxs->ccr; ++ dregs_ccr &= ~((0xf << CC_SRCBRSTLEN_SHFT) | ++ (0xf << CC_DSTBRSTLEN_SHFT)); ++ dregs_ccr |= (((transfer_length - 1) & 0xf) << ++ CC_SRCBRSTLEN_SHFT); ++ dregs_ccr |= (((transfer_length - 1) & 0xf) << ++ CC_DSTBRSTLEN_SHFT); ++ off += _emit_MOV(dry_run, &buf[off], CCR, dregs_ccr); ++ off += _ldst_memtomem(dry_run, &buf[off], pxs, 1); ++ break; ++ + default: +- off += 0x40000000; /* Scare off the Client */ ++ /* this code should be unreachable */ ++ WARN_ON(1); + break; + } + +@@ -1257,6 +1349,8 @@ static inline int _setup_loops(struct pl330_dmac *pl330, + struct pl330_xfer *x = &pxs->desc->px; + u32 ccr = pxs->ccr; + unsigned long c, bursts = BYTE_TO_BURST(x->bytes, ccr); ++ int num_dregs = (x->bytes - BURST_TO_BYTE(bursts, ccr)) / ++ BRST_SIZE(ccr); + int off = 0; + + while (bursts) { +@@ -1264,6 +1358,7 @@ static inline int _setup_loops(struct pl330_dmac *pl330, + off += _loop(pl330, dry_run, &buf[off], &c, pxs); + bursts -= c; + } ++ off += _dregs(pl330, dry_run, &buf[off], pxs, num_dregs); + + return off; + } +@@ -1295,7 +1390,6 @@ static int _setup_req(struct pl330_dmac *pl330, unsigned dry_run, + struct _xfer_spec *pxs) + { + struct _pl330_req *req = &thrd->req[index]; +- struct pl330_xfer *x; + u8 *buf = req->mc_cpu; + int off = 0; + +@@ -1304,11 +1398,6 @@ static int _setup_req(struct pl330_dmac *pl330, unsigned dry_run, + /* DMAMOV CCR, ccr */ + off += _emit_MOV(dry_run, &buf[off], CCR, pxs->ccr); + +- x = &pxs->desc->px; +- /* Error if xfer length is not aligned at burst size */ +- if (x->bytes % (BRST_SIZE(pxs->ccr) * BRST_LEN(pxs->ccr))) +- return -EINVAL; +- + off += _setup_xfer(pl330, dry_run, &buf[off], pxs); + + /* DMASEV peripheral/event */ +@@ -1366,6 +1455,20 @@ static int pl330_submit_req(struct pl330_thread *thrd, + u32 ccr; + int ret = 0; + ++ switch (desc->rqtype) { ++ case DMA_MEM_TO_DEV: ++ break; ++ ++ case DMA_DEV_TO_MEM: ++ break; ++ ++ case DMA_MEM_TO_MEM: ++ break; ++ ++ default: ++ return -ENOTSUPP; ++ } ++ + if (pl330->state == DYING + || pl330->dmac_tbd.reset_chan & (1 << thrd->id)) { + dev_info(thrd->dmac->ddma.dev, "%s:%d\n", +@@ -2060,6 +2163,18 @@ static int pl330_alloc_chan_resources(struct dma_chan *chan) + return 1; + } + ++static int fixup_burst_len(int max_burst_len, int quirks) ++{ ++ if (quirks & PL330_QUIRK_BROKEN_NO_FLUSHP) ++ return 1; ++ else if (max_burst_len > PL330_MAX_BURST) ++ return PL330_MAX_BURST; ++ else if (max_burst_len < 1) ++ return 1; ++ else ++ return max_burst_len; ++} ++ + static int pl330_config(struct dma_chan *chan, + struct dma_slave_config *slave_config) + { +@@ -2070,15 +2185,15 @@ static int pl330_config(struct dma_chan *chan, + pch->fifo_addr = slave_config->dst_addr; + if (slave_config->dst_addr_width) + pch->burst_sz = __ffs(slave_config->dst_addr_width); +- if (slave_config->dst_maxburst) +- pch->burst_len = slave_config->dst_maxburst; ++ pch->burst_len = fixup_burst_len(slave_config->dst_maxburst, ++ pch->dmac->quirks); + } else if (slave_config->direction == DMA_DEV_TO_MEM) { + if (slave_config->src_addr) + pch->fifo_addr = slave_config->src_addr; + if (slave_config->src_addr_width) + pch->burst_sz = __ffs(slave_config->src_addr_width); +- if (slave_config->src_maxburst) +- pch->burst_len = slave_config->src_maxburst; ++ pch->burst_len = fixup_burst_len(slave_config->src_maxburst, ++ pch->dmac->quirks); + } + + return 0; +@@ -2471,14 +2586,8 @@ static inline int get_burst_len(struct dma_pl330_desc *desc, size_t len) + burst_len >>= desc->rqcfg.brst_size; + + /* src/dst_burst_len can't be more than 16 */ +- if (burst_len > 16) +- burst_len = 16; +- +- while (burst_len > 1) { +- if (!(len % (burst_len << desc->rqcfg.brst_size))) +- break; +- burst_len--; +- } ++ if (burst_len > PL330_MAX_BURST) ++ burst_len = PL330_MAX_BURST; + + return burst_len; + } +@@ -2547,7 +2656,7 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic( + + desc->rqtype = direction; + desc->rqcfg.brst_size = pch->burst_sz; +- desc->rqcfg.brst_len = 1; ++ desc->rqcfg.brst_len = pch->burst_len; + desc->bytes_requested = period_len; + fill_px(&desc->px, dst, src, period_len); + +@@ -2692,7 +2801,7 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, + } + + desc->rqcfg.brst_size = pch->burst_sz; +- desc->rqcfg.brst_len = 1; ++ desc->rqcfg.brst_len = pch->burst_len; + desc->rqtype = direction; + desc->bytes_requested = sg_dma_len(sg); + } + +From b970d8fda69d56f0c9b59e436493bbbc6448ef10 Mon Sep 17 00:00:00 2001 +From: Marek Szyprowski +Date: Tue, 19 Jun 2018 15:20:50 +0200 +Subject: [PATCH] UPSTREAM: dmaengine: pl330: report BURST residue granularity + +The reported residue is already calculated in BURST unit granularity, so +advertise this capability properly to other devices in the system. + +Fixes: aee4d1fac887 ("dmaengine: pl330: improve pl330_tx_status() function") +Signed-off-by: Marek Szyprowski +Signed-off-by: Vinod Koul +(cherry picked from commit e3f329c600033f011a978a8bc4ddb1e2e94c4f4d) +--- + drivers/dma/pl330.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c +index fd48c031ead8..029bd0444137 100644 +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -2984,7 +2984,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) + pd->src_addr_widths = PL330_DMA_BUSWIDTHS; + pd->dst_addr_widths = PL330_DMA_BUSWIDTHS; + pd->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); +- pd->residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT; ++ pd->residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; + pd->max_burst = ((pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP) ? + 1 : PL330_MAX_BURST); + diff --git a/patch/kernel/rockchip-default/01-linux-1000-vcodec.patch b/patch/kernel/rockchip-default/01-linux-1000-vcodec.patch new file mode 100644 index 000000000..2de4f79a0 --- /dev/null +++ b/patch/kernel/rockchip-default/01-linux-1000-vcodec.patch @@ -0,0 +1,945 @@ +From 499f15c3237602cca9ccebe902d31bd7404fb2db Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Thu, 5 Jul 2018 00:14:14 +0200 +Subject: [PATCH] Revert "drm/drm-prime: cache dma_buf import context" + +This reverts commit 5a90381e5acc2cf32be03099a14d05d4362b3348. +--- + drivers/gpu/drm/drm_prime.c | 46 ++--------------------------- + drivers/gpu/drm/rockchip/rockchip_drm_gem.c | 1 + + 2 files changed, 3 insertions(+), 44 deletions(-) + +diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c +index 6f207d5946dc..6b7417a194a3 100644 +--- a/drivers/gpu/drm/drm_prime.c ++++ b/drivers/gpu/drm/drm_prime.c +@@ -71,11 +71,6 @@ struct drm_prime_attachment { + enum dma_data_direction dir; + }; + +-struct drm_prime_callback_data { +- struct drm_gem_object *obj; +- struct sg_table *sgt; +-}; +- + static int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv, + struct dma_buf *dma_buf, uint32_t handle) + { +@@ -524,23 +519,6 @@ out_unlock: + } + EXPORT_SYMBOL(drm_gem_prime_handle_to_fd); + +-static void drm_gem_prime_dmabuf_release_callback(void *data) +-{ +- struct drm_prime_callback_data *cb_data = data; +- +- if (cb_data && cb_data->obj && cb_data->obj->import_attach) { +- struct dma_buf_attachment *attach = cb_data->obj->import_attach; +- struct sg_table *sgt = cb_data->sgt; +- +- if (sgt) +- dma_buf_unmap_attachment(attach, sgt, +- DMA_BIDIRECTIONAL); +- dma_buf_detach(attach->dmabuf, attach); +- drm_gem_object_unreference_unlocked(cb_data->obj); +- kfree(cb_data); +- } +-} +- + /** + * drm_gem_prime_import - helper library implementation of the import callback + * @dev: drm_device to import into +@@ -555,7 +533,6 @@ struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev, + struct dma_buf_attachment *attach; + struct sg_table *sgt; + struct drm_gem_object *obj; +- struct drm_prime_callback_data *cb_data; + int ret; + + if (dma_buf->ops == &drm_gem_prime_dmabuf_ops) { +@@ -570,13 +547,6 @@ struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev, + } + } + +- cb_data = dma_buf_get_release_callback_data(dma_buf, +- drm_gem_prime_dmabuf_release_callback); +- if (cb_data && cb_data->obj && cb_data->obj->dev == dev) { +- drm_gem_object_reference(cb_data->obj); +- return cb_data->obj; +- } +- + if (!dev->driver->gem_prime_import_sg_table) + return ERR_PTR(-EINVAL); + +@@ -585,16 +555,11 @@ struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev, + return ERR_CAST(attach); + + get_dma_buf(dma_buf); +- cb_data = kmalloc(sizeof(*cb_data), GFP_KERNEL); +- if (!cb_data) { +- ret = -ENOMEM; +- goto fail_detach; +- } + + sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL); + if (IS_ERR(sgt)) { + ret = PTR_ERR(sgt); +- goto fail_free; ++ goto fail_detach; + } + + obj = dev->driver->gem_prime_import_sg_table(dev, attach, sgt); +@@ -602,20 +567,13 @@ struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev, + ret = PTR_ERR(obj); + goto fail_unmap; + } ++ + obj->import_attach = attach; +- cb_data->obj = obj; +- cb_data->sgt = sgt; +- dma_buf_set_release_callback(dma_buf, +- drm_gem_prime_dmabuf_release_callback, cb_data); +- dma_buf_put(dma_buf); +- drm_gem_object_reference(obj); + + return obj; + + fail_unmap: + dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL); +-fail_free: +- kfree(cb_data); + fail_detach: + dma_buf_detach(dma_buf, attach); + dma_buf_put(dma_buf); +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c +index 273a52b5eb66..85bbd19c87b0 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c +@@ -649,6 +649,7 @@ void rockchip_gem_free_object(struct drm_gem_object *obj) + dma_unmap_sg(drm->dev, rk_obj->sgt->sgl, + rk_obj->sgt->nents, DMA_BIDIRECTIONAL); + } ++ drm_prime_gem_destroy(obj, rk_obj->sgt); + } else { + rockchip_gem_free_buf(rk_obj); + } + +From 3dd29985f5f1cec249c833b1b2ca33e131f79825 Mon Sep 17 00:00:00 2001 +From: Rob Clark +Date: Thu, 9 Jun 2016 15:29:19 -0400 +Subject: [PATCH] UPSTREAM: drm/prime: fix error path deadlock fail + +There were a couple messed up things about this fail path. +(1) it would drop object_name_lock twice +(2) drm_gem_handle_delete() (in drm_gem_remove_prime_handles()) + needs to grab prime_lock + +Reported-by: Alex Deucher +Signed-off-by: Rob Clark +Reviewed-by: Alex Deucher +Signed-off-by: Daniel Vetter +Link: http://patchwork.freedesktop.org/patch/msgid/1465500559-17873-1-git-send-email-robdclark@gmail.com +(cherry picked from commit bd6e2732f0e2894ce792f344c41fc32591436fe3) +--- + drivers/gpu/drm/drm_prime.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c +index 6b7417a194a3..d8d85286764d 100644 +--- a/drivers/gpu/drm/drm_prime.c ++++ b/drivers/gpu/drm/drm_prime.c +@@ -628,7 +628,7 @@ int drm_gem_prime_fd_to_handle(struct drm_device *dev, + get_dma_buf(dma_buf); + } + +- /* drm_gem_handle_create_tail unlocks dev->object_name_lock. */ ++ /* _handle_create_tail unconditionally unlocks dev->object_name_lock. */ + ret = drm_gem_handle_create_tail(file_priv, obj, handle); + drm_gem_object_unreference_unlocked(obj); + if (ret) +@@ -636,11 +636,10 @@ int drm_gem_prime_fd_to_handle(struct drm_device *dev, + + ret = drm_prime_add_buf_handle(&file_priv->prime, + dma_buf, *handle); ++ mutex_unlock(&file_priv->prime.lock); + if (ret) + goto fail; + +- mutex_unlock(&file_priv->prime.lock); +- + dma_buf_put(dma_buf); + + return 0; +@@ -650,11 +649,14 @@ fail: + * to detach.. which seems ok.. + */ + drm_gem_handle_delete(file_priv, *handle); ++ dma_buf_put(dma_buf); ++ return ret; ++ + out_unlock: + mutex_unlock(&dev->object_name_lock); + out_put: +- dma_buf_put(dma_buf); + mutex_unlock(&file_priv->prime.lock); ++ dma_buf_put(dma_buf); + return ret; + } + EXPORT_SYMBOL(drm_gem_prime_fd_to_handle); + +From a689159fac372a8210d2c63ba63da3a097388b97 Mon Sep 17 00:00:00 2001 +From: Chris Wilson +Date: Mon, 26 Sep 2016 21:44:14 +0100 +Subject: [PATCH] UPSTREAM: drm: Convert prime dma-buf <-> handle to rbtree + +Currently we use a linear walk to lookup a handle and return a dma-buf, +and vice versa. A long overdue TODO task is to convert that to a +hashtable. Since the initial implementation of dma-buf/prime, we now +have resizeable hashtables we can use (and now a future task is to RCU +enable the lookup!). However, this patch opts to use an rbtree instead +to provide O(lgN) lookups (and insertion, deletion). rbtrees were chosen +over using the RCU backed resizable hashtable to firstly avoid the +reallocations (rbtrees can be embedded entirely within the parent +struct) and to favour simpler code with predictable worst case +behaviour. In simple testing, the difference between using the constant +lookup and insertion of the rhashtable and the rbtree was less than 10% +of the wall time (igt/benchmarks/prime_lookup) - both are dramatic +improvements over the existing linear lists. + +v2: Favour rbtree over rhashtable + +Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=94631 +Signed-off-by: Chris Wilson +Cc: Sean Paul +Cc: David Herrmann +Reviewed-by: David Herrmann +Reviewed-by: Sean Paul +Signed-off-by: Daniel Vetter +Link: http://patchwork.freedesktop.org/patch/msgid/20160926204414.23222-1-chris@chris-wilson.co.uk +(cherry picked from commit 077675c1e8a193a6355d4a7c8c7bf63be310b472) +--- + drivers/gpu/drm/drm_prime.c | 85 +++++++++++++++++++++++++++++++++++++++------ + include/drm/drmP.h | 5 +-- + 2 files changed, 77 insertions(+), 13 deletions(-) + +diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c +index d8d85286764d..4c49e736bc9c 100644 +--- a/drivers/gpu/drm/drm_prime.c ++++ b/drivers/gpu/drm/drm_prime.c +@@ -28,6 +28,7 @@ + + #include + #include ++#include + #include + #include + +@@ -61,9 +62,11 @@ + */ + + struct drm_prime_member { +- struct list_head entry; + struct dma_buf *dma_buf; + uint32_t handle; ++ ++ struct rb_node dmabuf_rb; ++ struct rb_node handle_rb; + }; + + struct drm_prime_attachment { +@@ -75,6 +78,7 @@ static int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv, + struct dma_buf *dma_buf, uint32_t handle) + { + struct drm_prime_member *member; ++ struct rb_node **p, *rb; + + member = kmalloc(sizeof(*member), GFP_KERNEL); + if (!member) +@@ -83,18 +87,56 @@ static int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv, + get_dma_buf(dma_buf); + member->dma_buf = dma_buf; + member->handle = handle; +- list_add(&member->entry, &prime_fpriv->head); ++ ++ rb = NULL; ++ p = &prime_fpriv->dmabufs.rb_node; ++ while (*p) { ++ struct drm_prime_member *pos; ++ ++ rb = *p; ++ pos = rb_entry(rb, struct drm_prime_member, dmabuf_rb); ++ if (dma_buf > pos->dma_buf) ++ p = &rb->rb_right; ++ else ++ p = &rb->rb_left; ++ } ++ rb_link_node(&member->dmabuf_rb, rb, p); ++ rb_insert_color(&member->dmabuf_rb, &prime_fpriv->dmabufs); ++ ++ rb = NULL; ++ p = &prime_fpriv->handles.rb_node; ++ while (*p) { ++ struct drm_prime_member *pos; ++ ++ rb = *p; ++ pos = rb_entry(rb, struct drm_prime_member, handle_rb); ++ if (handle > pos->handle) ++ p = &rb->rb_right; ++ else ++ p = &rb->rb_left; ++ } ++ rb_link_node(&member->handle_rb, rb, p); ++ rb_insert_color(&member->handle_rb, &prime_fpriv->handles); ++ + return 0; + } + + static struct dma_buf *drm_prime_lookup_buf_by_handle(struct drm_prime_file_private *prime_fpriv, + uint32_t handle) + { +- struct drm_prime_member *member; ++ struct rb_node *rb; ++ ++ rb = prime_fpriv->handles.rb_node; ++ while (rb) { ++ struct drm_prime_member *member; + +- list_for_each_entry(member, &prime_fpriv->head, entry) { ++ member = rb_entry(rb, struct drm_prime_member, handle_rb); + if (member->handle == handle) + return member->dma_buf; ++ else if (member->handle < handle) ++ rb = rb->rb_right; ++ else ++ rb = rb->rb_left; + } + + return NULL; +@@ -104,14 +146,23 @@ static int drm_prime_lookup_buf_handle(struct drm_prime_file_private *prime_fpri + struct dma_buf *dma_buf, + uint32_t *handle) + { +- struct drm_prime_member *member; ++ struct rb_node *rb; ++ ++ rb = prime_fpriv->dmabufs.rb_node; ++ while (rb) { ++ struct drm_prime_member *member; + +- list_for_each_entry(member, &prime_fpriv->head, entry) { ++ member = rb_entry(rb, struct drm_prime_member, dmabuf_rb); + if (member->dma_buf == dma_buf) { + *handle = member->handle; + return 0; ++ } else if (member->dma_buf < dma_buf) { ++ rb = rb->rb_right; ++ } else { ++ rb = rb->rb_left; + } + } ++ + return -ENOENT; + } + +@@ -166,13 +217,24 @@ static void drm_gem_map_detach(struct dma_buf *dma_buf, + void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private *prime_fpriv, + struct dma_buf *dma_buf) + { +- struct drm_prime_member *member, *safe; ++ struct rb_node *rb; + +- list_for_each_entry_safe(member, safe, &prime_fpriv->head, entry) { ++ rb = prime_fpriv->dmabufs.rb_node; ++ while (rb) { ++ struct drm_prime_member *member; ++ ++ member = rb_entry(rb, struct drm_prime_member, dmabuf_rb); + if (member->dma_buf == dma_buf) { ++ rb_erase(&member->handle_rb, &prime_fpriv->handles); ++ rb_erase(&member->dmabuf_rb, &prime_fpriv->dmabufs); ++ + dma_buf_put(dma_buf); +- list_del(&member->entry); + kfree(member); ++ return; ++ } else if (member->dma_buf < dma_buf) { ++ rb = rb->rb_right; ++ } else { ++ rb = rb->rb_left; + } + } + } +@@ -794,12 +856,13 @@ EXPORT_SYMBOL(drm_prime_gem_destroy); + + void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv) + { +- INIT_LIST_HEAD(&prime_fpriv->head); + mutex_init(&prime_fpriv->lock); ++ prime_fpriv->dmabufs = RB_ROOT; ++ prime_fpriv->handles = RB_ROOT; + } + + void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv) + { + /* by now drm_gem_release should've made sure the list is empty */ +- WARN_ON(!list_empty(&prime_fpriv->head)); ++ WARN_ON(!RB_EMPTY_ROOT(&prime_fpriv->dmabufs)); + } +diff --git a/include/drm/drmP.h b/include/drm/drmP.h +index 04edcd32b409..93da65df2e7e 100644 +--- a/include/drm/drmP.h ++++ b/include/drm/drmP.h +@@ -51,6 +51,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -365,10 +366,10 @@ struct drm_pending_event { + void (*destroy)(struct drm_pending_event *event); + }; + +-/* initial implementaton using a linked list - todo hashtab */ + struct drm_prime_file_private { +- struct list_head head; + struct mutex lock; ++ struct rb_root dmabufs; ++ struct rb_root handles; + }; + + /** File private data */ + +From f977098a9a02ac2df267eafe860370cb4c407d69 Mon Sep 17 00:00:00 2001 +From: Chris Wilson +Date: Wed, 5 Oct 2016 13:21:44 +0100 +Subject: [PATCH] UPSTREAM: drm/prime: Take a ref on the drm_dev when exporting + a dma_buf +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +dma_buf may live a long time, longer than the last direct user of the +driver. We already hold a reference to the owner module (that prevents +the object code from disappearing), but there is no reference to the +drm_dev - so the pointers to the driver backend themselves may vanish. + +v2: Resist temptation to fix the bug in armada_gem.c not setting the +correct flags on the exported dma-buf (it should pass the flags through +and not be arbitrarily setting O_RDWR). + +Use a common wrapper for exporting the dmabuf and acquiring the +reference to the drm_device. + +Testcase: igt/vgem_basic/unload +Suggested-by: Daniel Vetter +Signed-off-by: Chris Wilson +Cc: Petri Latvala +Cc: Daniel Vetter +Cc: stable@vger.kernel.org +Tested-by: Petri Latvala +Reviewed-by: Christian König +Signed-off-by: Daniel Vetter +Link: http://patchwork.freedesktop.org/patch/msgid/20161005122145.1507-2-chris@chris-wilson.co.uk +(cherry picked from commit a4fce9cb782ad340ee5576a38e934e5e75832dc6) +--- + drivers/gpu/drm/armada/armada_gem.c | 2 +- + drivers/gpu/drm/drm_prime.c | 30 +++++++++++++++++++++++++++++- + drivers/gpu/drm/i915/i915_gem_dmabuf.c | 2 +- + drivers/gpu/drm/tegra/gem.c | 2 +- + drivers/gpu/drm/udl/udl_dmabuf.c | 2 +- + include/drm/drmP.h | 4 ++++ + 6 files changed, 37 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpu/drm/armada/armada_gem.c b/drivers/gpu/drm/armada/armada_gem.c +index 60a688ef81c7..cd5bb991f49a 100644 +--- a/drivers/gpu/drm/armada/armada_gem.c ++++ b/drivers/gpu/drm/armada/armada_gem.c +@@ -546,7 +546,7 @@ armada_gem_prime_export(struct drm_device *dev, struct drm_gem_object *obj, + exp_info.flags = O_RDWR; + exp_info.priv = obj; + +- return dma_buf_export(&exp_info); ++ return drm_gem_dmabuf_export(dev, &exp_info); + } + + struct drm_gem_object * +diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c +index 4c49e736bc9c..94b4872255c8 100644 +--- a/drivers/gpu/drm/drm_prime.c ++++ b/drivers/gpu/drm/drm_prime.c +@@ -283,19 +283,47 @@ static void drm_gem_unmap_dma_buf(struct dma_buf_attachment *attach, + /* nothing to be done here */ + } + ++/** ++ * drm_gem_dmabuf_export - dma_buf export implementation for GEM ++ * @dma_buf: buffer to be exported ++ * ++ * This wraps dma_buf_export() for use by generic GEM drivers that are using ++ * drm_gem_dmabuf_release(). In addition to calling dma_buf_export(), we take ++ * a reference to the drm_device which is released by drm_gem_dmabuf_release(). ++ * ++ * Returns the new dmabuf. ++ */ ++struct dma_buf *drm_gem_dmabuf_export(struct drm_device *dev, ++ struct dma_buf_export_info *exp_info) ++{ ++ struct dma_buf *dma_buf; ++ ++ dma_buf = dma_buf_export(exp_info); ++ if (!IS_ERR(dma_buf)) ++ drm_dev_ref(dev); ++ ++ return dma_buf; ++} ++EXPORT_SYMBOL(drm_gem_dmabuf_export); ++ + /** + * drm_gem_dmabuf_release - dma_buf release implementation for GEM + * @dma_buf: buffer to be released + * + * Generic release function for dma_bufs exported as PRIME buffers. GEM drivers + * must use this in their dma_buf ops structure as the release callback. ++ * drm_gem_dmabuf_release() should be used in conjunction with ++ * drm_gem_dmabuf_export(). + */ + void drm_gem_dmabuf_release(struct dma_buf *dma_buf) + { + struct drm_gem_object *obj = dma_buf->priv; ++ struct drm_device *dev = obj->dev; + + /* drop the reference on the export fd holds */ + drm_gem_object_unreference_unlocked(obj); ++ ++ drm_dev_unref(dev); + } + EXPORT_SYMBOL(drm_gem_dmabuf_release); + +@@ -444,7 +472,7 @@ struct dma_buf *drm_gem_prime_export(struct drm_device *dev, + if (dev->driver->gem_prime_res_obj) + exp_info.resv = dev->driver->gem_prime_res_obj(obj); + +- return dma_buf_export(&exp_info); ++ return drm_gem_dmabuf_export(dev, &exp_info); + } + EXPORT_SYMBOL(drm_gem_prime_export); + +diff --git a/drivers/gpu/drm/i915/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/i915_gem_dmabuf.c +index e9c2bfd85b52..d4a021629bd6 100644 +--- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c ++++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c +@@ -244,7 +244,7 @@ struct dma_buf *i915_gem_prime_export(struct drm_device *dev, + return ERR_PTR(ret); + } + +- return dma_buf_export(&exp_info); ++ return drm_gem_dmabuf_export(dev, &exp_info); + } + + static int i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj) +diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c +index 01e16e146bfe..da06f1c1ee0f 100644 +--- a/drivers/gpu/drm/tegra/gem.c ++++ b/drivers/gpu/drm/tegra/gem.c +@@ -625,7 +625,7 @@ struct dma_buf *tegra_gem_prime_export(struct drm_device *drm, + exp_info.flags = flags; + exp_info.priv = gem; + +- return dma_buf_export(&exp_info); ++ return drm_gem_dmabuf_export(drm, &exp_info); + } + + struct drm_gem_object *tegra_gem_prime_import(struct drm_device *drm, +diff --git a/drivers/gpu/drm/udl/udl_dmabuf.c b/drivers/gpu/drm/udl/udl_dmabuf.c +index e2243edd1ce3..ac90ffdb5912 100644 +--- a/drivers/gpu/drm/udl/udl_dmabuf.c ++++ b/drivers/gpu/drm/udl/udl_dmabuf.c +@@ -209,7 +209,7 @@ struct dma_buf *udl_gem_prime_export(struct drm_device *dev, + exp_info.flags = flags; + exp_info.priv = obj; + +- return dma_buf_export(&exp_info); ++ return drm_gem_dmabuf_export(dev, &exp_info); + } + + static int udl_prime_create(struct drm_device *dev, +diff --git a/include/drm/drmP.h b/include/drm/drmP.h +index 93da65df2e7e..4aba6478d718 100644 +--- a/include/drm/drmP.h ++++ b/include/drm/drmP.h +@@ -1124,6 +1124,8 @@ static inline int drm_debugfs_remove_files(const struct drm_info_list *files, + } + #endif + ++struct dma_buf_export_info; ++ + extern struct dma_buf *drm_gem_prime_export(struct drm_device *dev, + struct drm_gem_object *obj, + int flags); +@@ -1134,6 +1136,8 @@ extern struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev, + struct dma_buf *dma_buf); + extern int drm_gem_prime_fd_to_handle(struct drm_device *dev, + struct drm_file *file_priv, int prime_fd, uint32_t *handle); ++struct dma_buf *drm_gem_dmabuf_export(struct drm_device *dev, ++ struct dma_buf_export_info *exp_info); + extern void drm_gem_dmabuf_release(struct dma_buf *dma_buf); + + extern int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages, + +From f30ee0d19425a6c21a9959513e482282ba08dd6a Mon Sep 17 00:00:00 2001 +From: Chris Wilson +Date: Wed, 7 Dec 2016 21:45:27 +0000 +Subject: [PATCH] UPSTREAM: drm: Take ownership of the dmabuf->obj when + exporting + +Currently the reference for the dmabuf->obj is incremented for the +dmabuf in drm_gem_prime_handle_to_fd() (at the high level userspace +interface), but is released in drm_gem_dmabuf_release() (the lowlevel +handler). Improve the symmetry of the dmabuf->obj ownership by acquiring +the reference in drm_gem_dmabuf_export(). This makes it easier to use +the prime functions directly. + +Signed-off-by: Chris Wilson +[danvet: Update kerneldoc.] +Signed-off-by: Daniel Vetter +Link: http://patchwork.freedesktop.org/patch/msgid/20161207214527.22533-1-chris@chris-wilson.co.uk +(cherry picked from commit 72a93e8dd52c9feea42f1258d555e6070680a347) +--- + drivers/gpu/drm/drm_prime.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c +index 94b4872255c8..dbd34fa7f71c 100644 +--- a/drivers/gpu/drm/drm_prime.c ++++ b/drivers/gpu/drm/drm_prime.c +@@ -289,7 +289,8 @@ static void drm_gem_unmap_dma_buf(struct dma_buf_attachment *attach, + * + * This wraps dma_buf_export() for use by generic GEM drivers that are using + * drm_gem_dmabuf_release(). In addition to calling dma_buf_export(), we take +- * a reference to the drm_device which is released by drm_gem_dmabuf_release(). ++ * a reference to the &drm_device and the exported &drm_gem_object (stored in ++ * exp_info->priv) which is released by drm_gem_dmabuf_release(). + * + * Returns the new dmabuf. + */ +@@ -299,8 +300,11 @@ struct dma_buf *drm_gem_dmabuf_export(struct drm_device *dev, + struct dma_buf *dma_buf; + + dma_buf = dma_buf_export(exp_info); +- if (!IS_ERR(dma_buf)) +- drm_dev_ref(dev); ++ if (IS_ERR(dma_buf)) ++ return dma_buf; ++ ++ drm_dev_ref(dev); ++ drm_gem_object_reference(exp_info->priv); + + return dma_buf; + } +@@ -503,8 +507,6 @@ static struct dma_buf *export_and_register_object(struct drm_device *dev, + */ + obj->dma_buf = dmabuf; + get_dma_buf(obj->dma_buf); +- /* Grab a new ref since the callers is now used by the dma-buf */ +- drm_gem_object_reference(obj); + + return dmabuf; + } + +From a1fe1ad6076ec27f60555a9393f40959cea94bff Mon Sep 17 00:00:00 2001 +From: Lucas Stach +Date: Thu, 30 Nov 2017 18:34:28 +0100 +Subject: [PATCH] UPSTREAM: drm/prime: skip CPU sync in map/unmap dma_buf + +Dma-bufs should already be device coherent, as they are only pulled in the +CPU domain via the begin/end cpu_access calls. As we cache the mapping set +up by dma_map_sg a CPU sync at this point will not actually guarantee proper +coherency on non-coherent architectures, so we can as well stop pretending. + +This is an important performance fix for architectures which need explicit +cache synchronization and userspace doing lots of dma-buf imports. +Improves Weston on Etnaviv performance 5x, where before this patch > 90% +of Weston CPU time was spent synchronizing caches for buffers which are +already device coherent. + +Signed-off-by: Lucas Stach +Reviewed-by: Chris Wilson +Signed-off-by: Daniel Vetter +Link: https://patchwork.freedesktop.org/patch/msgid/20171130173428.8666-1-l.stach@pengutronix.de +(cherry picked from commit ca0e68e21aae10220eff71a297e7d794425add77) +--- + drivers/gpu/drm/drm_prime.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c +index dbd34fa7f71c..133362279591 100644 +--- a/drivers/gpu/drm/drm_prime.c ++++ b/drivers/gpu/drm/drm_prime.c +@@ -203,9 +203,12 @@ static void drm_gem_map_detach(struct dma_buf *dma_buf, + + sgt = prime_attach->sgt; + if (sgt) { ++ DEFINE_DMA_ATTRS(attrs); ++ dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs); + if (prime_attach->dir != DMA_NONE) +- dma_unmap_sg(attach->dev, sgt->sgl, sgt->nents, +- prime_attach->dir); ++ dma_unmap_sg_attrs(attach->dev, sgt->sgl, sgt->nents, ++ prime_attach->dir, ++ &attrs); + sg_free_table(sgt); + } + +@@ -263,7 +266,9 @@ static struct sg_table *drm_gem_map_dma_buf(struct dma_buf_attachment *attach, + sgt = obj->dev->driver->gem_prime_get_sg_table(obj); + + if (!IS_ERR(sgt)) { +- if (!dma_map_sg(attach->dev, sgt->sgl, sgt->nents, dir)) { ++ DEFINE_DMA_ATTRS(attrs); ++ dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs); ++ if (!dma_map_sg_attrs(attach->dev, sgt->sgl, sgt->nents, dir, &attrs)) { + sg_free_table(sgt); + kfree(sgt); + sgt = ERR_PTR(-ENOMEM); + +From bdfc956545f8292cf462a7feee96d811f5d34414 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20K=C3=B6nig?= +Date: Tue, 27 Feb 2018 12:49:56 +0100 +Subject: [PATCH] UPSTREAM: drm/prime: fix potential race in drm_gem_map_detach +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Unpin the GEM object only after freeing the sg table. + +Signed-off-by: Christian König +Reviewed-by: Daniel Vetter +Acked-by: Roger He +Signed-off-by: Alex Deucher +Link: https://patchwork.freedesktop.org/patch/msgid/20180227115000.4105-1-christian.koenig@amd.com +(cherry picked from commit 681066ec1d41e4b299146bada52cef846b323c04) +--- + drivers/gpu/drm/drm_prime.c | 36 ++++++++++++++++++------------------ + 1 file changed, 18 insertions(+), 18 deletions(-) + +diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c +index 133362279591..95ecc69d03a0 100644 +--- a/drivers/gpu/drm/drm_prime.c ++++ b/drivers/gpu/drm/drm_prime.c +@@ -193,28 +193,28 @@ static void drm_gem_map_detach(struct dma_buf *dma_buf, + struct drm_prime_attachment *prime_attach = attach->priv; + struct drm_gem_object *obj = dma_buf->priv; + struct drm_device *dev = obj->dev; +- struct sg_table *sgt; +- +- if (dev->driver->gem_prime_unpin) +- dev->driver->gem_prime_unpin(obj); + +- if (!prime_attach) +- return; ++ if (prime_attach) { ++ struct sg_table *sgt = prime_attach->sgt; ++ ++ if (sgt) { ++ DEFINE_DMA_ATTRS(attrs); ++ dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs); ++ if (prime_attach->dir != DMA_NONE) ++ dma_unmap_sg_attrs(attach->dev, sgt->sgl, ++ sgt->nents, ++ prime_attach->dir, ++ &attrs); ++ sg_free_table(sgt); ++ } + +- sgt = prime_attach->sgt; +- if (sgt) { +- DEFINE_DMA_ATTRS(attrs); +- dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs); +- if (prime_attach->dir != DMA_NONE) +- dma_unmap_sg_attrs(attach->dev, sgt->sgl, sgt->nents, +- prime_attach->dir, +- &attrs); +- sg_free_table(sgt); ++ kfree(sgt); ++ kfree(prime_attach); ++ attach->priv = NULL; + } + +- kfree(sgt); +- kfree(prime_attach); +- attach->priv = NULL; ++ if (dev->driver->gem_prime_unpin) ++ dev->driver->gem_prime_unpin(obj); + } + + void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private *prime_fpriv, + +From 54f13f6370c654d59a9a5938e5953888a65c1980 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20K=C3=B6nig?= +Date: Tue, 27 Feb 2018 12:49:57 +0100 +Subject: [PATCH] UPSTREAM: drm/prime: make the pages array optional for + drm_prime_sg_to_page_addr_arrays +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Most of the time we only need the dma addresses. + +Signed-off-by: Christian König +Reviewed-by: Roger He +Signed-off-by: Alex Deucher +Link: https://patchwork.freedesktop.org/patch/msgid/20180227115000.4105-2-christian.koenig@amd.com +Link: https://patchwork.freedesktop.org/patch/msgid/20180227115000.4105-3-christian.koenig@amd.com +Link: https://patchwork.freedesktop.org/patch/msgid/20180227115000.4105-4-christian.koenig@amd.com +Link: https://patchwork.freedesktop.org/patch/msgid/20180227115000.4105-5-christian.koenig@amd.com +Link: https://patchwork.freedesktop.org/patch/msgid/BN6PR12MB18262C0DE9B5F07B9A42EAE7F2C60@BN6PR12MB1826.namprd12.prod.outlook.com +(cherry picked from commit 186ca446aea19e49d2e1433dd170c6e1c211a52a) +--- + drivers/gpu/drm/drm_prime.c | 20 ++++++++++---------- + 1 file changed, 10 insertions(+), 10 deletions(-) + +diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c +index 95ecc69d03a0..7ea65c4105c1 100644 +--- a/drivers/gpu/drm/drm_prime.c ++++ b/drivers/gpu/drm/drm_prime.c +@@ -827,40 +827,40 @@ EXPORT_SYMBOL(drm_prime_pages_to_sg); + /** + * drm_prime_sg_to_page_addr_arrays - convert an sg table into a page array + * @sgt: scatter-gather table to convert +- * @pages: array of page pointers to store the page array in ++ * @pages: optional array of page pointers to store the page array in + * @addrs: optional array to store the dma bus address of each page +- * @max_pages: size of both the passed-in arrays ++ * @max_entries: size of both the passed-in arrays + * + * Exports an sg table into an array of pages and addresses. This is currently + * required by the TTM driver in order to do correct fault handling. + */ + int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages, +- dma_addr_t *addrs, int max_pages) ++ dma_addr_t *addrs, int max_entries) + { + unsigned count; + struct scatterlist *sg; + struct page *page; +- u32 len; +- int pg_index; ++ u32 len, index; + dma_addr_t addr; + +- pg_index = 0; ++ index = 0; + for_each_sg(sgt->sgl, sg, sgt->nents, count) { + len = sg->length; + page = sg_page(sg); + addr = sg_dma_address(sg); + + while (len > 0) { +- if (WARN_ON(pg_index >= max_pages)) ++ if (WARN_ON(index >= max_entries)) + return -1; +- pages[pg_index] = page; ++ if (pages) ++ pages[index] = page; + if (addrs) +- addrs[pg_index] = addr; ++ addrs[index] = addr; + + page++; + addr += PAGE_SIZE; + len -= PAGE_SIZE; +- pg_index++; ++ index++; + } + } + return 0; + +From c5e39a7e46511dffadabea97e3d74310561d1ba0 Mon Sep 17 00:00:00 2001 +From: Chris Wilson +Date: Sat, 19 Aug 2017 13:05:58 +0100 +Subject: [PATCH] UPSTREAM: drm: Release driver tracking before making the + object available again +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This is the same bug as we fixed in commit f6cd7daecff5 ("drm: Release +driver references to handle before making it available again"), but now +the exposure is via the PRIME lookup tables. If we remove the +object/handle from the PRIME lut, then a new request for the same +object/fd will generate a new handle, thus for a short window that +object is known to userspace by two different handles. Fix this by +releasing the driver tracking before PRIME. + +Fixes: 0ff926c7d4f0 ("drm/prime: add exported buffers to current fprivs +imported buffer list (v2)") +Signed-off-by: Chris Wilson +Cc: David Airlie +Cc: Daniel Vetter +Cc: Rob Clark +Cc: Ville Syrjälä +Cc: Thierry Reding +Cc: stable@vger.kernel.org +Reviewed-by: Daniel Vetter +Signed-off-by: Joonas Lahtinen +Link: https://patchwork.freedesktop.org/patch/msgid/20170819120558.6465-1-chris@chris-wilson.co.uk +(cherry picked from commit d0a133f7f5bc3583e460ba6bb54474a50ada5201) +--- + drivers/gpu/drm/drm_gem.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c +index d7f39a03c2c9..966ea63581b1 100644 +--- a/drivers/gpu/drm/drm_gem.c ++++ b/drivers/gpu/drm/drm_gem.c +@@ -255,13 +255,13 @@ drm_gem_object_release_handle(int id, void *ptr, void *data) + struct drm_gem_object *obj = ptr; + struct drm_device *dev = obj->dev; + ++ if (dev->driver->gem_close_object) ++ dev->driver->gem_close_object(obj, file_priv); ++ + if (drm_core_check_feature(dev, DRIVER_PRIME)) + drm_gem_remove_prime_handles(obj, file_priv); + drm_vma_node_revoke(&obj->vma_node, file_priv->filp); + +- if (dev->driver->gem_close_object) +- dev->driver->gem_close_object(obj, file_priv); +- + drm_gem_object_handle_unreference_unlocked(obj); + + return 0; + +From 42f26aa9c8d429886b0af174b740f72741e571e2 Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Sat, 17 Feb 2018 05:30:36 +0100 +Subject: [PATCH] vcodec: skip reduce freq + +--- + drivers/video/rockchip/vcodec/vcodec_service.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/drivers/video/rockchip/vcodec/vcodec_service.c b/drivers/video/rockchip/vcodec/vcodec_service.c +index 0f177d9ab4c2..903ea8554649 100644 +--- a/drivers/video/rockchip/vcodec/vcodec_service.c ++++ b/drivers/video/rockchip/vcodec/vcodec_service.c +@@ -1602,9 +1602,6 @@ static void try_set_reg(struct vpu_subdev_data *data) + reg_from_wait_to_run(pservice, reg); + reg_copy_to_hw(reg->data, reg); + } +- } else { +- if (pservice->hw_ops->reduce_freq) +- pservice->hw_ops->reduce_freq(pservice); + } + + mutex_unlock(&pservice->shutdown_lock); +@@ -2353,6 +2350,7 @@ static void vcodec_set_freq_rk3328(struct vpu_service_info *pservice, + if (curr == reg->freq) + return; + ++ atomic_set(&pservice->freq_status, reg->freq); + if (pservice->dev_id == VCODEC_DEVICE_ID_RKVDEC) { + if (reg->reg[1] & 0x00800000) { + if (rkv_dec_get_fmt(reg->reg) == FMT_H264D) diff --git a/patch/kernel/rockchip-default/100_DTS_opp.patch b/patch/kernel/rockchip-default/100_DTS_opp.patch deleted file mode 100644 index 7ebe92857..000000000 --- a/patch/kernel/rockchip-default/100_DTS_opp.patch +++ /dev/null @@ -1,26 +0,0 @@ -diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi -index 4a428bf..6708434 100644 ---- a/arch/arm/boot/dts/rk3288.dtsi -+++ b/arch/arm/boot/dts/rk3288.dtsi -@@ -597,7 +615,7 @@ - type = "passive"; - }; - target: trip-point@1 { -- temperature = <85000>; /* millicelsius */ -+ temperature = <80000>; /* millicelsius */ - hysteresis = <2000>; /* millicelsius */ - type = "passive"; - }; -diff --git a/arch/arm/boot/dts/rk3288-miniarm.dts b/arch/arm/boot/dts/rk3288-miniarm.dts -index de6c4a6..30f0c46 100644 ---- a/arch/arm/boot/dts/rk3288-miniarm.dts -+++ b/arch/arm/boot/dts/rk3288-miniarm.dts -@@ -42,7 +42,7 @@ - #include - #include "rk3288.dtsi" - #include "rk3288-rkisp1.dtsi" --#include "rk3288-linux.dtsi" -+#include "rk3288cg-opp.dtsi" - - / { - compatible = "rockchip,rk3288-miniarm", "rockchip,rk3288"; diff --git a/patch/kernel/rockchip-default/110_DTS_8723bs.patch b/patch/kernel/rockchip-default/110_DTS_8723bs.patch deleted file mode 100644 index fb83d5d69..000000000 --- a/patch/kernel/rockchip-default/110_DTS_8723bs.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/arch/arm/boot/dts/rk3288-miniarm.dts b/arch/arm/boot/dts/rk3288-miniarm.dts -index 16995ca..553f091 100644 ---- a/arch/arm/boot/dts/rk3288-miniarm.dts -+++ b/arch/arm/boot/dts/rk3288-miniarm.dts -@@ -70,7 +70,7 @@ - wireless-wlan { - compatible = "wlan-platdata"; - rockchip,grf = <&grf>; -- wifi_chip_type = "ap6212"; -+ wifi_chip_type = "8723bs"; - sdio_vref = <1800>; - WIFI,host_wake_irq = <&gpio4 30 GPIO_ACTIVE_HIGH>; - status = "okay"; diff --git a/patch/kernel/rockchip-default/120_DTS_led1_heartbeat.patch b/patch/kernel/rockchip-default/120_DTS_led1_heartbeat.patch deleted file mode 100644 index 7ebe84dfe..000000000 --- a/patch/kernel/rockchip-default/120_DTS_led1_heartbeat.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/arch/arm/boot/dts/rk3288-miniarm.dts b/arch/arm/boot/dts/rk3288-miniarm.dts -index 553f091..de6c4a6 100644 ---- a/arch/arm/boot/dts/rk3288-miniarm.dts -+++ b/arch/arm/boot/dts/rk3288-miniarm.dts -@@ -134,7 +134,7 @@ - - led1-led { - gpios=<&gpio1 25 GPIO_ACTIVE_HIGH>; -- linux,default-trigger="default-off"; -+ linux,default-trigger="heartbeat"; - }; - }; - diff --git a/patch/kernel/rockchip-default/130_workaround_tinker_board_reboot.patch b/patch/kernel/rockchip-default/130_workaround_tinker_board_reboot.patch.disabled similarity index 100% rename from patch/kernel/rockchip-default/130_workaround_tinker_board_reboot.patch rename to patch/kernel/rockchip-default/130_workaround_tinker_board_reboot.patch.disabled diff --git a/patch/kernel/rockchip-default/135_tinker_boot_fix.patch b/patch/kernel/rockchip-default/135_tinker_boot_fix.patch.disabled similarity index 100% rename from patch/kernel/rockchip-default/135_tinker_boot_fix.patch rename to patch/kernel/rockchip-default/135_tinker_boot_fix.patch.disabled diff --git a/patch/kernel/rockchip-default/180_simple_dtoverlay.patch b/patch/kernel/rockchip-default/180_simple_dtoverlay.patch deleted file mode 100644 index 88a5e4389..000000000 --- a/patch/kernel/rockchip-default/180_simple_dtoverlay.patch +++ /dev/null @@ -1,426 +0,0 @@ -From f875ad99fe6d44c7683954b3023209d3d84dbf2d Mon Sep 17 00:00:00 2001 -From: andy_chi -Date: Wed, 21 Jun 2017 15:52:19 +0800 -Subject: [PATCH] Enable a simple user-space driven DT overlay interface - -Change-Id: I6e9f71d8b46df65abd698378b8994988c7fa5651 ---- - drivers/of/Kconfig | 7 + - drivers/of/Makefile | 1 + - drivers/of/dtbocfg.c | 381 +++++++++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 389 insertions(+) - create mode 100644 drivers/of/dtbocfg.c - -diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig -index e2a48415d969..7e5e6c4e77e0 100644 ---- a/drivers/of/Kconfig -+++ b/drivers/of/Kconfig -@@ -112,4 +112,11 @@ config OF_OVERLAY - While this option is selected automatically when needed, you can - enable it manually to improve device tree unit test coverage. - -+config OF_CONFIGFS -+ bool "Device Tree Overlay ConfigFS interface" -+ select CONFIGFS_FS -+ select OF_OVERLAY -+ help -+ Enable a simple user-space driven DT overlay interface. -+ - endif # OF -diff --git a/drivers/of/Makefile b/drivers/of/Makefile -index 156c072b3117..413b0fe675c4 100644 ---- a/drivers/of/Makefile -+++ b/drivers/of/Makefile -@@ -1,4 +1,5 @@ - obj-y = base.o device.o platform.o property.o -+obj-$(CONFIG_OF_CONFIGFS) += dtbocfg.o - obj-$(CONFIG_OF_DYNAMIC) += dynamic.o - obj-$(CONFIG_OF_FLATTREE) += fdt.o - obj-$(CONFIG_OF_EARLY_FLATTREE) += fdt_address.o -diff --git a/drivers/of/dtbocfg.c b/drivers/of/dtbocfg.c -new file mode 100644 -index 000000000000..1f715ea3895c ---- /dev/null -+++ b/drivers/of/dtbocfg.c -@@ -0,0 +1,381 @@ -+/********************************************************************************* -+ * -+ * Copyright (C) 2016-2017 Ichiro Kawazome -+ * All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in -+ * the documentation and/or other materials provided with the -+ * distribution. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ ********************************************************************************/ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/** -+ * Device Tree Overlay Item Structure -+ */ -+struct dtbocfg_overlay_item { -+ struct config_item item; -+ struct device_node* node; -+ int id; -+ void* dtbo; -+ int dtbo_size; -+}; -+ -+/** -+ * dtbocfg_overlay_create() - Create Device Tree Overlay -+ * @overlay: Pointer to Device Tree Overlay Item -+ * return Success(0) or Error Status. -+ */ -+static int dtbocfg_overlay_item_create(struct dtbocfg_overlay_item *overlay) -+{ -+ int ret_val; -+ -+#if (LINUX_VERSION_CODE >= 0x040700) -+ of_fdt_unflatten_tree(overlay->dtbo, NULL, &overlay->node); -+#else -+ of_fdt_unflatten_tree(overlay->dtbo, &overlay->node); -+#endif -+ if (overlay->node == NULL) { -+ pr_err("%s: failed to unflatten tree\n", __func__); -+ ret_val = -EINVAL; -+ goto failed; -+ } -+ pr_debug("%s: unflattened OK\n", __func__); -+ -+ of_node_set_flag(overlay->node, OF_DETACHED); -+ -+ ret_val = of_resolve_phandles(overlay->node); -+ if (ret_val != 0) { -+ pr_err("%s: Failed to resolve tree\n", __func__); -+ goto failed; -+ } -+ pr_debug("%s: resolved OK\n", __func__); -+ -+ ret_val = of_overlay_create(overlay->node); -+ if (ret_val < 0) { -+ pr_err("%s: Failed to create overlay (ret_val=%d)\n", __func__, ret_val); -+ goto failed; -+ } -+ overlay->id = ret_val; -+ pr_debug("%s: create OK\n", __func__); -+ return 0; -+ -+ failed: -+ return ret_val; -+} -+ -+/** -+ * dtbocfg_overlay_item_release() - Relase Device Tree Overlay -+ * @overlay: Pointer to Device Tree Overlay Item -+ * return none -+ */ -+static void dtbocfg_overlay_item_release(struct dtbocfg_overlay_item *overlay) -+{ -+ if (overlay->id >= 0) { -+ of_overlay_destroy(overlay->id); -+ overlay->id = -1; -+ } -+} -+ -+/** -+ * container_of_dtbocfg_overlay_item() - Get Device Tree Overlay Item Pointer from Configuration Item -+ * @item: Pointer to Configuration Item -+ * return Pointer to Device Tree Overlay Item -+ */ -+static inline struct dtbocfg_overlay_item* container_of_dtbocfg_overlay_item(struct config_item *item) -+{ -+ return item ? container_of(item, struct dtbocfg_overlay_item, item) : NULL; -+} -+ -+/** -+ * dtbocfg_overlay_item_status_store() - Set Status Attibute -+ * @item: Pointer to Configuration Item -+ * @page: Pointer to Value Buffer -+ * @count: Size of Value Buffer Size -+ * return Stored Size or Error Status. -+ */ -+static ssize_t dtbocfg_overlay_item_status_store(struct config_item *item, const char *buf, size_t count) -+{ -+ struct dtbocfg_overlay_item *overlay = container_of_dtbocfg_overlay_item(item); -+ ssize_t status; -+ unsigned long value; -+ if (0 != (status = kstrtoul(buf, 10, &value))) { -+ goto failed; -+ } -+ if (value == 0) { -+ if (overlay->id >= 0) { -+ dtbocfg_overlay_item_release(overlay); -+ } -+ } else { -+ if (overlay->id < 0) { -+ dtbocfg_overlay_item_create(overlay); -+ } -+ } -+ return count; -+ failed: -+ return -EPERM; -+} -+ -+/** -+ * dtbocfg_overlay_item_status_show() - Show Status Attibute -+ * @item : Pointer to Configuration Item -+ * @page : Pointer to Value for Store -+ * return String Size or Error Status. -+ */ -+static ssize_t dtbocfg_overlay_item_status_show(struct config_item *item, char *page) -+{ -+ struct dtbocfg_overlay_item *overlay = container_of_dtbocfg_overlay_item(item); -+ return sprintf(page, "%d\n", overlay->id >= 0 ? 1 : 0); -+} -+ -+/** -+ * dtbocfg_overlay_item_dtbo_store() - Store Device Tree Blob to Configuration Item -+ * @item : Pointer to Configuration Item -+ * @page : Pointer to Value Buffer -+ * @count: Size of Value Buffer -+ * return Stored Size or Error Status. -+ */ -+static ssize_t dtbocfg_overlay_item_dtbo_store(struct config_item *item, const char *buf, size_t count) -+{ -+ struct dtbocfg_overlay_item *overlay = container_of_dtbocfg_overlay_item(item); -+ -+ if (overlay->dtbo_size > 0) { -+ if (overlay->id >= 0) { -+ return -EPERM; -+ } -+ kfree(overlay->dtbo); -+ overlay->dtbo = NULL; -+ overlay->dtbo_size = 0; -+ } -+ -+ overlay->dtbo = kmemdup(buf, count, GFP_KERNEL); -+ if (overlay->dtbo == NULL) { -+ overlay->dtbo_size = 0; -+ return -ENOMEM; -+ } else { -+ overlay->dtbo_size = count; -+ return count; -+ } -+} -+ -+/** -+ * dtbocfg_overlay_item_dtbo_show() - Read Device Tree Blob from Configuration Item -+ * @item : Pointer to Configuration Item -+ * @page : Pointer to Value for Store -+ * return Read Size -+ */ -+static ssize_t dtbocfg_overlay_item_dtbo_show(struct config_item *item, char *buf) -+{ -+ struct dtbocfg_overlay_item *overlay = container_of_dtbocfg_overlay_item(item); -+ -+ if (overlay->dtbo == NULL) -+ return 0; -+ -+ if (overlay->dtbo_size > PAGE_SIZE) -+ return -EINVAL; -+ -+ if (buf != NULL) -+ memcpy(buf, overlay->dtbo, overlay->dtbo_size); -+ -+ return overlay->dtbo_size; -+} -+ -+/** -+ * Device Tree Blob Overlay Attribute Structure -+ */ -+CONFIGFS_ATTR(dtbocfg_overlay_item_, dtbo ); -+CONFIGFS_ATTR(dtbocfg_overlay_item_, status); -+ -+static struct configfs_attribute *dtbocfg_overlay_attrs[] = { -+ &dtbocfg_overlay_item_attr_status, -+ &dtbocfg_overlay_item_attr_dtbo, -+ NULL, -+}; -+ -+/** -+ * dtbocfg_overlay_release() - Release Device Tree Overlay Item -+ * @item : Pointer to Configuration Item -+ * Return None -+ */ -+static void dtbocfg_overlay_release(struct config_item *item) -+{ -+ struct dtbocfg_overlay_item *overlay = container_of_dtbocfg_overlay_item(item); -+ -+ pr_debug("%s\n", __func__); -+ -+ dtbocfg_overlay_item_release(overlay); -+ -+ if (overlay->dtbo) { -+ kfree(overlay->dtbo); -+ overlay->dtbo = NULL; -+ overlay->dtbo_size = 0; -+ } -+ -+ kfree(overlay); -+} -+ -+/** -+ * Device Tree Blob Overlay Item Structure -+ */ -+static struct configfs_item_operations dtbocfg_overlay_item_ops = { -+ .release = dtbocfg_overlay_release, -+}; -+ -+static struct config_item_type dtbocfg_overlay_item_type = { -+ .ct_item_ops = &dtbocfg_overlay_item_ops, -+ .ct_attrs = dtbocfg_overlay_attrs, -+ .ct_owner = THIS_MODULE, -+}; -+ -+/** -+ * dtbocfg_overlay_group_make_item() - Make Device Tree Overlay Group Item -+ * @group: Pointer to Configuration Group -+ * @name : Pointer to Group Name -+ * Return Pointer to Device Tree Overlay Group Item -+ */ -+static struct config_item *dtbocfg_overlay_group_make_item(struct config_group *group, const char *name) -+{ -+ struct dtbocfg_overlay_item *overlay; -+ -+ pr_debug("%s\n", __func__); -+ -+ overlay = kzalloc(sizeof(*overlay), GFP_KERNEL); -+ -+ if (!overlay) -+ return ERR_PTR(-ENOMEM); -+ overlay->id = -1; -+ overlay->dtbo = NULL; -+ overlay->dtbo_size = 0; -+ -+ config_item_init_type_name(&overlay->item, name, &dtbocfg_overlay_item_type); -+ return &overlay->item; -+} -+ -+/** -+ * dtbocfg_overlay_group_drop_item() - Drop Device Tree Overlay Group Item -+ * @group: Pointer to Configuration Group -+ * @item : Pointer to Device Tree Overlay Group Item -+ */ -+static void dtbocfg_overlay_group_drop_item(struct config_group *group, struct config_item *item) -+{ -+ struct dtbocfg_overlay_item *overlay = container_of_dtbocfg_overlay_item(item); -+ -+ pr_debug("%s\n", __func__); -+ -+ config_item_put(&overlay->item); -+} -+ -+/** -+ * Device Tree Blob Overlay Sub Group Structures -+ */ -+static struct configfs_group_operations dtbocfg_overlays_ops = { -+ .make_item = dtbocfg_overlay_group_make_item, -+ .drop_item = dtbocfg_overlay_group_drop_item, -+}; -+ -+static struct config_item_type dtbocfg_overlays_type = { -+ .ct_group_ops = &dtbocfg_overlays_ops, -+ .ct_owner = THIS_MODULE, -+}; -+ -+static struct config_group dtbocfg_overlay_group; -+ -+/** -+ * Device Tree Blob Overlay Root Sub System Structures -+ */ -+static struct configfs_group_operations dtbocfg_root_ops = { -+ /* empty - we don't allow anything to be created */ -+}; -+ -+static struct config_item_type dtbocfg_root_type = { -+ .ct_group_ops = &dtbocfg_root_ops, -+ .ct_owner = THIS_MODULE, -+}; -+ -+static struct configfs_subsystem dtbocfg_root_subsys = { -+ .su_group = { -+ .cg_item = { -+ .ci_namebuf = "device-tree", -+ .ci_type = &dtbocfg_root_type, -+ }, -+ }, -+ .su_mutex = __MUTEX_INITIALIZER(dtbocfg_root_subsys.su_mutex), -+}; -+ -+/** -+ * dtbocfg_module_init() -+ */ -+static int __init dtbocfg_module_init(void) -+{ -+ int retval = 0; -+ -+ pr_info("%s\n", __func__); -+ -+ config_group_init(&dtbocfg_root_subsys.su_group); -+ config_group_init_type_name(&dtbocfg_overlay_group, "overlays", &dtbocfg_overlays_type); -+ -+ retval = configfs_register_subsystem(&dtbocfg_root_subsys); -+ if (retval != 0) { -+ pr_err( "%s: couldn't register subsys\n", __func__); -+ goto register_subsystem_failed; -+ } -+ -+ retval = configfs_register_group(&dtbocfg_root_subsys.su_group, &dtbocfg_overlay_group); -+ if (retval != 0) { -+ pr_err( "%s: couldn't register group\n", __func__); -+ goto register_group_failed; -+ } -+ -+ pr_info("%s: OK\n", __func__); -+ return 0; -+ -+ register_group_failed: -+ configfs_unregister_subsystem(&dtbocfg_root_subsys); -+ register_subsystem_failed: -+ return retval; -+} -+ -+/** -+ * dtbocfg_module_exit() -+ */ -+static void __exit dtbocfg_module_exit(void) -+{ -+ configfs_unregister_group(&dtbocfg_overlay_group); -+ configfs_unregister_subsystem(&dtbocfg_root_subsys); -+} -+ -+module_init(dtbocfg_module_init); -+module_exit(dtbocfg_module_exit); -+ -+MODULE_AUTHOR("ikwzm"); -+MODULE_DESCRIPTION("Device Tree Overlay Configuration File System"); -+MODULE_LICENSE("Dual BSD/GPL"); diff --git a/patch/kernel/rockchip-default/increasing_DMA_block_memory_allocation_to_2048.patch b/patch/kernel/rockchip-default/increasing_DMA_block_memory_allocation_to_2048.patch deleted file mode 100644 index 1c4d60250..000000000 --- a/patch/kernel/rockchip-default/increasing_DMA_block_memory_allocation_to_2048.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c -index bd83c53..af7cfe3 ---- a/arch/arm/mm/dma-mapping.c -+++ b/arch/arm/mm/dma-mapping.c -@@ -374,7 +374,7 @@ static void __dma_free_remap(void *cpu_addr, size_t size) - VM_ARM_DMA_CONSISTENT | VM_USERMAP); - } - --#define DEFAULT_DMA_COHERENT_POOL_SIZE SZ_256K -+#define DEFAULT_DMA_COHERENT_POOL_SIZE SZ_2M - static struct gen_pool *atomic_pool; - - static size_t atomic_pool_size = DEFAULT_DMA_COHERENT_POOL_SIZE;