summaryrefslogtreecommitdiff |
diff options
author | Jiri Kosina <jkosina@suse.cz> | 2017-11-19 22:04:49 +0100 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2017-11-19 22:04:49 +0100 |
commit | 0cd8d2469cd889adc3842734c8cb84ebb9db2dee (patch) | |
tree | a53712f2d8263ff9d6a85d0042e71633a44e9439 | |
parent | 5ea7a5fbb37fedb55aa94f6f232f31473112ce80 (diff) | |
parent | e7201a259e950979f5da17ba1302381e7e869304 (diff) |
Merge remote-tracking branch 'origin/users/ykaukab/SLE15/for-next' into SLE15rpm-4.12.14-4--SLE-15-Packages-Beta3rpm-4.12.14-4--SLE-12-SP4-RT-RC1rpm-4.12.14-4
suse-commit: 349e50cfae788dccfab9b141e4d3c28757e6b4a5
127 files changed, 4290 insertions, 1646 deletions
diff --git a/Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt b/Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt index 046076c6b277..fad8b7619647 100644 --- a/Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt +++ b/Documentation/devicetree/bindings/display/rockchip/dw_hdmi-rockchip.txt @@ -11,7 +11,9 @@ following device-specific properties. Required properties: -- compatible: Shall contain "rockchip,rk3288-dw-hdmi". +- compatible: should be one of the following: + "rockchip,rk3288-dw-hdmi" + "rockchip,rk3399-dw-hdmi" - reg: See dw_hdmi.txt. - reg-io-width: See dw_hdmi.txt. Shall be 4. - interrupts: HDMI interrupt number @@ -30,7 +32,8 @@ Optional properties I2C master controller. - clock-names: See dw_hdmi.txt. The "cec" clock is optional. - clock-names: May contain "cec" as defined in dw_hdmi.txt. - +- clock-names: May contain "grf", power for grf io. +- clock-names: May contain "vpll", external clock for some hdmi phy. Example: diff --git a/Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb2.txt b/Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb2.txt index e71a8d23f4a8..90cf87b3af50 100644 --- a/Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb2.txt +++ b/Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb2.txt @@ -2,9 +2,11 @@ ROCKCHIP USB2.0 PHY WITH INNO IP BLOCK Required properties (phy (parent) node): - compatible : should be one of the listed compatibles: + * "rockchip,rk3228-usb2phy" * "rockchip,rk3328-usb2phy" * "rockchip,rk3366-usb2phy" * "rockchip,rk3399-usb2phy" + * "rockchip,rv1108-usb2phy" - reg : the address offset of grf for usb-phy configuration. - #clock-cells : should be 0. - clock-output-names : specify the 480m output clock name. diff --git a/Documentation/devicetree/bindings/pwm/pwm-rockchip.txt b/Documentation/devicetree/bindings/pwm/pwm-rockchip.txt index b8be3d09ee26..2350ef918bef 100644 --- a/Documentation/devicetree/bindings/pwm/pwm-rockchip.txt +++ b/Documentation/devicetree/bindings/pwm/pwm-rockchip.txt @@ -6,7 +6,13 @@ Required properties: "rockchip,rk3288-pwm": found on RK3288 SoC "rockchip,vop-pwm": found integrated in VOP on RK3288 SoC - reg: physical base address and length of the controller's registers - - clocks: phandle and clock specifier of the PWM reference clock + - clocks: See ../clock/clock-bindings.txt + - For older hardware (rk2928, rk3066, rk3188, rk3228, rk3288, rk3399): + - There is one clock that's used both to derive the functional clock + for the device and as the bus clock. + - For newer hardware (rk3328 and future socs): specified by name + - "pwm": This is used to derive the functional clock. + - "pclk": This is the APB bus clock. - #pwm-cells: must be 2 (rk2928) or 3 (rk3288). See pwm.txt in this directory for a description of the cell format. diff --git a/MAINTAINERS b/MAINTAINERS index 336eec0f140e..521fe1f094b1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1843,8 +1843,8 @@ F: drivers/i2c/busses/i2c-st.c F: drivers/media/rc/st_rc.c F: drivers/media/platform/sti/c8sectpfe/ F: drivers/mmc/host/sdhci-st.c -F: drivers/phy/phy-miphy28lp.c -F: drivers/phy/phy-stih407-usb.c +F: drivers/phy/st/phy-miphy28lp.c +F: drivers/phy/st/phy-stih407-usb.c F: drivers/pinctrl/pinctrl-st.c F: drivers/remoteproc/st_remoteproc.c F: drivers/remoteproc/st_slim_rproc.c @@ -10855,7 +10855,7 @@ RENESAS USB2 PHY DRIVER M: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> L: linux-renesas-soc@vger.kernel.org S: Maintained -F: drivers/phy/phy-rcar-gen3-usb2.c +F: drivers/phy/renesas/phy-rcar-gen3-usb2.c RESET CONTROLLER FRAMEWORK M: Philipp Zabel <p.zabel@pengutronix.de> @@ -11257,12 +11257,12 @@ L: linux-kernel@vger.kernel.org S: Supported F: Documentation/devicetree/bindings/phy/samsung-phy.txt F: Documentation/phy/samsung-usb2.txt -F: drivers/phy/phy-exynos4210-usb2.c -F: drivers/phy/phy-exynos4x12-usb2.c -F: drivers/phy/phy-exynos5250-usb2.c -F: drivers/phy/phy-s5pv210-usb2.c -F: drivers/phy/phy-samsung-usb2.c -F: drivers/phy/phy-samsung-usb2.h +F: drivers/phy/samsung/phy-exynos4210-usb2.c +F: drivers/phy/samsung/phy-exynos4x12-usb2.c +F: drivers/phy/samsung/phy-exynos5250-usb2.c +F: drivers/phy/samsung/phy-s5pv210-usb2.c +F: drivers/phy/samsung/phy-samsung-usb2.c +F: drivers/phy/samsung/phy-samsung-usb2.h SERIAL DRIVERS M: Greg Kroah-Hartman <gregkh@linuxfoundation.org> diff --git a/drivers/clk/clk-fractional-divider.c b/drivers/clk/clk-fractional-divider.c index aab904618eb6..fdf625fb10fa 100644 --- a/drivers/clk/clk-fractional-divider.c +++ b/drivers/clk/clk-fractional-divider.c @@ -49,16 +49,12 @@ static unsigned long clk_fd_recalc_rate(struct clk_hw *hw, return ret; } -static long clk_fd_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) +static void clk_fd_general_approximation(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate, + unsigned long *m, unsigned long *n) { struct clk_fractional_divider *fd = to_clk_fd(hw); unsigned long scale; - unsigned long m, n; - u64 ret; - - if (!rate || rate >= *parent_rate) - return *parent_rate; /* * Get rate closer to *parent_rate to guarantee there is no overflow @@ -71,7 +67,23 @@ static long clk_fd_round_rate(struct clk_hw *hw, unsigned long rate, rational_best_approximation(rate, *parent_rate, GENMASK(fd->mwidth - 1, 0), GENMASK(fd->nwidth - 1, 0), - &m, &n); + m, n); +} + +static long clk_fd_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + struct clk_fractional_divider *fd = to_clk_fd(hw); + unsigned long m, n; + u64 ret; + + if (!rate || rate >= *parent_rate) + return *parent_rate; + + if (fd->approximation) + fd->approximation(hw, rate, parent_rate, &m, &n); + else + clk_fd_general_approximation(hw, rate, parent_rate, &m, &n); ret = (u64)*parent_rate * m; do_div(ret, n); diff --git a/drivers/clk/rockchip/clk-cpu.c b/drivers/clk/rockchip/clk-cpu.c index 0e09684d43a5..32c19c0f1e14 100644 --- a/drivers/clk/rockchip/clk-cpu.c +++ b/drivers/clk/rockchip/clk-cpu.c @@ -322,8 +322,6 @@ struct clk *rockchip_clk_register_cpuclk(const char *name, sizeof(*rates) * nrates, GFP_KERNEL); if (!cpuclk->rate_table) { - pr_err("%s: could not allocate memory for cpuclk rates\n", - __func__); ret = -ENOMEM; goto unregister_notifier; } diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c index fa3cbef08776..6847120b61cd 100644 --- a/drivers/clk/rockchip/clk-rk3399.c +++ b/drivers/clk/rockchip/clk-rk3399.c @@ -1066,13 +1066,13 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { /* cif_testout */ MUX(0, "clk_testout1_pll_src", mux_pll_src_cpll_gpll_npll_p, 0, RK3399_CLKSEL_CON(38), 6, 2, MFLAGS), - COMPOSITE(0, "clk_testout1", mux_clk_testout1_p, 0, + COMPOSITE(SCLK_TESTCLKOUT1, "clk_testout1", mux_clk_testout1_p, 0, RK3399_CLKSEL_CON(38), 5, 1, MFLAGS, 0, 5, DFLAGS, RK3399_CLKGATE_CON(13), 14, GFLAGS), MUX(0, "clk_testout2_pll_src", mux_pll_src_cpll_gpll_npll_p, 0, RK3399_CLKSEL_CON(38), 14, 2, MFLAGS), - COMPOSITE(0, "clk_testout2", mux_clk_testout2_p, 0, + COMPOSITE(SCLK_TESTCLKOUT2, "clk_testout2", mux_clk_testout2_p, 0, RK3399_CLKSEL_CON(38), 13, 1, MFLAGS, 8, 5, DFLAGS, RK3399_CLKGATE_CON(13), 15, GFLAGS), diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c index fe1d393cf678..35dbd63c2f49 100644 --- a/drivers/clk/rockchip/clk.c +++ b/drivers/clk/rockchip/clk.c @@ -29,6 +29,7 @@ #include <linux/mfd/syscon.h> #include <linux/regmap.h> #include <linux/reboot.h> +#include <linux/rational.h> #include "clk.h" /** @@ -164,6 +165,40 @@ static int rockchip_clk_frac_notifier_cb(struct notifier_block *nb, return notifier_from_errno(ret); } +/** + * fractional divider must set that denominator is 20 times larger than + * numerator to generate precise clock frequency. + */ +static void rockchip_fractional_approximation(struct clk_hw *hw, + unsigned long rate, unsigned long *parent_rate, + unsigned long *m, unsigned long *n) +{ + struct clk_fractional_divider *fd = to_clk_fd(hw); + unsigned long p_rate, p_parent_rate; + struct clk_hw *p_parent; + unsigned long scale; + + p_rate = clk_hw_get_rate(clk_hw_get_parent(hw)); + if ((rate * 20 > p_rate) && (p_rate % rate != 0)) { + p_parent = clk_hw_get_parent(clk_hw_get_parent(hw)); + p_parent_rate = clk_hw_get_rate(p_parent); + *parent_rate = p_parent_rate; + } + + /* + * Get rate closer to *parent_rate to guarantee there is no overflow + * for m and n. In the result it will be the nearest rate left shifted + * by (scale - fd->nwidth) bits. + */ + scale = fls_long(*parent_rate / rate - 1); + if (scale > fd->nwidth) + rate <<= scale - fd->nwidth; + + rational_best_approximation(rate, *parent_rate, + GENMASK(fd->mwidth - 1, 0), GENMASK(fd->nwidth - 1, 0), + m, n); +} + static struct clk *rockchip_clk_register_frac_branch( struct rockchip_clk_provider *ctx, const char *name, const char *const *parent_names, u8 num_parents, @@ -210,6 +245,7 @@ static struct clk *rockchip_clk_register_frac_branch( div->nwidth = 16; div->nmask = GENMASK(div->nwidth - 1, 0) << div->nshift; div->lock = lock; + div->approximation = rockchip_fractional_approximation; div_ops = &clk_fractional_divider_ops; clk = clk_register_composite(NULL, name, parent_names, num_parents, diff --git a/drivers/clocksource/rockchip_timer.c b/drivers/clocksource/rockchip_timer.c index 49c02be50eca..54884ba39aba 100644 --- a/drivers/clocksource/rockchip_timer.c +++ b/drivers/clocksource/rockchip_timer.c @@ -274,7 +274,7 @@ static int __init rk_clksrc_init(struct device_node *np) TIMER_NAME, rk_clksrc->freq, 250, 32, clocksource_mmio_readl_down); if (ret) { - pr_err("Failed to register clocksource"); + pr_err("Failed to register clocksource\n"); goto out_clocksource; } diff --git a/drivers/devfreq/rk3399_dmc.c b/drivers/devfreq/rk3399_dmc.c index 40a2499730fc..1b89ebbad02c 100644 --- a/drivers/devfreq/rk3399_dmc.c +++ b/drivers/devfreq/rk3399_dmc.c @@ -336,8 +336,9 @@ static int rk3399_dmcfreq_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(&pdev->dev, "Cannot get the dmc interrupt resource\n"); - return -EINVAL; + dev_err(&pdev->dev, + "Cannot get the dmc interrupt resource: %d\n", irq); + return irq; } data = devm_kzalloc(dev, sizeof(struct rk3399_dmcfreq), GFP_KERNEL); if (!data) diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig index dcc539ba85d6..0ccc76217ee4 100644 --- a/drivers/gpu/drm/rockchip/Kconfig +++ b/drivers/gpu/drm/rockchip/Kconfig @@ -57,4 +57,13 @@ config ROCKCHIP_INNO_HDMI for the Innosilicon HDMI driver. If you want to enable HDMI on RK3036 based SoC, you should select this option. +config ROCKCHIP_LVDS + bool "Rockchip LVDS support" + depends on DRM_ROCKCHIP + depends on PINCTRL && OF + help + Choose this option to enable support for Rockchip LVDS controllers. + Rockchip rk3288 SoC has LVDS TX Controller can be used, and it + support LVDS, rgb, dual LVDS output mode. say Y to enable its + driver. endif diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile index fa8dc9d9aac2..a881d2cc4f25 100644 --- a/drivers/gpu/drm/rockchip/Makefile +++ b/drivers/gpu/drm/rockchip/Makefile @@ -12,5 +12,6 @@ rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o rockchipdrm-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi.o rockchipdrm-$(CONFIG_ROCKCHIP_INNO_HDMI) += inno_hdmi.o +rockchipdrm-$(CONFIG_ROCKCHIP_LVDS) += rockchip_lvds.o obj-$(CONFIG_DRM_ROCKCHIP) += rockchipdrm.o diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index ce5f2d1f9994..4d3f6ad0abdd 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -88,7 +88,7 @@ static void analogix_dp_psr_set(struct drm_encoder *encoder, bool enabled) if (!analogix_dp_psr_supported(dp->dev)) return; - dev_dbg(dp->dev, "%s PSR...\n", enabled ? "Entry" : "Exit"); + DRM_DEV_DEBUG(dp->dev, "%s PSR...\n", enabled ? "Entry" : "Exit"); spin_lock_irqsave(&dp->psr_lock, flags); if (enabled) @@ -104,26 +104,18 @@ static void analogix_dp_psr_work(struct work_struct *work) { struct rockchip_dp_device *dp = container_of(work, typeof(*dp), psr_work); - struct drm_crtc *crtc = dp->encoder.crtc; - int psr_state = dp->psr_state; - int vact_end; int ret; unsigned long flags; - if (!crtc) - return; - - vact_end = crtc->mode.vtotal - crtc->mode.vsync_start + crtc->mode.vdisplay; - - ret = rockchip_drm_wait_line_flag(dp->encoder.crtc, vact_end, - PSR_WAIT_LINE_FLAG_TIMEOUT_MS); + ret = rockchip_drm_wait_vact_end(dp->encoder.crtc, + PSR_WAIT_LINE_FLAG_TIMEOUT_MS); if (ret) { - dev_err(dp->dev, "line flag interrupt did not arrive\n"); + DRM_DEV_ERROR(dp->dev, "line flag interrupt did not arrive\n"); return; } spin_lock_irqsave(&dp->psr_lock, flags); - if (psr_state == EDP_VSC_PSR_STATE_ACTIVE) + if (dp->psr_state == EDP_VSC_PSR_STATE_ACTIVE) analogix_dp_enable_psr(dp->dev); else analogix_dp_disable_psr(dp->dev); @@ -148,13 +140,13 @@ static int rockchip_dp_poweron(struct analogix_dp_plat_data *plat_data) ret = clk_prepare_enable(dp->pclk); if (ret < 0) { - dev_err(dp->dev, "failed to enable pclk %d\n", ret); + DRM_DEV_ERROR(dp->dev, "failed to enable pclk %d\n", ret); return ret; } ret = rockchip_dp_pre_init(dp); if (ret < 0) { - dev_err(dp->dev, "failed to dp pre init %d\n", ret); + DRM_DEV_ERROR(dp->dev, "failed to dp pre init %d\n", ret); clk_disable_unprepare(dp->pclk); return ret; } @@ -219,17 +211,17 @@ static void rockchip_dp_drm_encoder_enable(struct drm_encoder *encoder) else val = dp->data->lcdsel_big; - dev_dbg(dp->dev, "vop %s output to dp\n", (ret) ? "LIT" : "BIG"); + DRM_DEV_DEBUG(dp->dev, "vop %s output to dp\n", (ret) ? "LIT" : "BIG"); ret = clk_prepare_enable(dp->grfclk); if (ret < 0) { - dev_err(dp->dev, "failed to enable grfclk %d\n", ret); + DRM_DEV_ERROR(dp->dev, "failed to enable grfclk %d\n", ret); return; } ret = regmap_write(dp->grf, dp->data->lcdsel_grf_reg, val); if (ret != 0) - dev_err(dp->dev, "Could not write to GRF: %d\n", ret); + DRM_DEV_ERROR(dp->dev, "Could not write to GRF: %d\n", ret); clk_disable_unprepare(dp->grfclk); } @@ -285,7 +277,7 @@ static int rockchip_dp_init(struct rockchip_dp_device *dp) dp->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); if (IS_ERR(dp->grf)) { - dev_err(dev, "failed to get rockchip,grf property\n"); + DRM_DEV_ERROR(dev, "failed to get rockchip,grf property\n"); return PTR_ERR(dp->grf); } @@ -295,31 +287,31 @@ static int rockchip_dp_init(struct rockchip_dp_device *dp) } else if (PTR_ERR(dp->grfclk) == -EPROBE_DEFER) { return -EPROBE_DEFER; } else if (IS_ERR(dp->grfclk)) { - dev_err(dev, "failed to get grf clock\n"); + DRM_DEV_ERROR(dev, "failed to get grf clock\n"); return PTR_ERR(dp->grfclk); } dp->pclk = devm_clk_get(dev, "pclk"); if (IS_ERR(dp->pclk)) { - dev_err(dev, "failed to get pclk property\n"); + DRM_DEV_ERROR(dev, "failed to get pclk property\n"); return PTR_ERR(dp->pclk); } dp->rst = devm_reset_control_get(dev, "dp"); if (IS_ERR(dp->rst)) { - dev_err(dev, "failed to get dp reset control\n"); + DRM_DEV_ERROR(dev, "failed to get dp reset control\n"); return PTR_ERR(dp->rst); } ret = clk_prepare_enable(dp->pclk); if (ret < 0) { - dev_err(dp->dev, "failed to enable pclk %d\n", ret); + DRM_DEV_ERROR(dp->dev, "failed to enable pclk %d\n", ret); return ret; } ret = rockchip_dp_pre_init(dp); if (ret < 0) { - dev_err(dp->dev, "failed to pre init %d\n", ret); + DRM_DEV_ERROR(dp->dev, "failed to pre init %d\n", ret); clk_disable_unprepare(dp->pclk); return ret; } diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c index 14fa1f8351e8..4588b9e107d2 100644 --- a/drivers/gpu/drm/rockchip/cdn-dp-core.c +++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c @@ -288,14 +288,6 @@ static int cdn_dp_connector_get_modes(struct drm_connector *connector) return ret; } -static struct drm_encoder * -cdn_dp_connector_best_encoder(struct drm_connector *connector) -{ - struct cdn_dp_device *dp = connector_to_dp(connector); - - return &dp->encoder; -} - static int cdn_dp_connector_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { @@ -347,7 +339,6 @@ static int cdn_dp_connector_mode_valid(struct drm_connector *connector, static struct drm_connector_helper_funcs cdn_dp_connector_helper_funcs = { .get_modes = cdn_dp_connector_get_modes, - .best_encoder = cdn_dp_connector_best_encoder, .mode_valid = cdn_dp_connector_mode_valid, }; @@ -1195,7 +1186,7 @@ static int cdn_dp_probe(struct platform_device *pdev) continue; port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL); - if (!dp) + if (!port) return -ENOMEM; port->extcon = extcon; diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.c b/drivers/gpu/drm/rockchip/cdn-dp-reg.c index b14d211f6c21..eb3042c6d1b2 100644 --- a/drivers/gpu/drm/rockchip/cdn-dp-reg.c +++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.c @@ -323,7 +323,7 @@ int cdn_dp_load_firmware(struct cdn_dp_device *dp, const u32 *i_mem, reg = readl(dp->regs + VER_LIB_H_ADDR) & 0xff; dp->fw_version |= reg << 24; - dev_dbg(dp->dev, "firmware version: %x\n", dp->fw_version); + DRM_DEV_DEBUG(dp->dev, "firmware version: %x\n", dp->fw_version); return 0; } diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c index 21b9737662ae..d074d260109a 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c @@ -430,9 +430,9 @@ static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi) testdin = max_mbps_to_testdin(dsi->lane_mbps); if (testdin < 0) { - dev_err(dsi->dev, - "failed to get testdin for %dmbps lane clock\n", - dsi->lane_mbps); + DRM_DEV_ERROR(dsi->dev, + "failed to get testdin for %dmbps lane clock\n", + dsi->lane_mbps); return testdin; } @@ -443,7 +443,7 @@ static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi) ret = clk_prepare_enable(dsi->phy_cfg_clk); if (ret) { - dev_err(dsi->dev, "Failed to enable phy_cfg_clk\n"); + DRM_DEV_ERROR(dsi->dev, "Failed to enable phy_cfg_clk\n"); return ret; } @@ -501,7 +501,7 @@ static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi) ret = readl_poll_timeout(dsi->base + DSI_PHY_STATUS, val, val & LOCK, 1000, PHY_STATUS_TIMEOUT_US); if (ret < 0) { - dev_err(dsi->dev, "failed to wait for phy lock state\n"); + DRM_DEV_ERROR(dsi->dev, "failed to wait for phy lock state\n"); goto phy_init_end; } @@ -509,8 +509,8 @@ static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi) val, val & STOP_STATE_CLK_LANE, 1000, PHY_STATUS_TIMEOUT_US); if (ret < 0) - dev_err(dsi->dev, - "failed to wait for phy clk lane stop state\n"); + DRM_DEV_ERROR(dsi->dev, + "failed to wait for phy clk lane stop state\n"); phy_init_end: clk_disable_unprepare(dsi->phy_cfg_clk); @@ -529,8 +529,9 @@ static int dw_mipi_dsi_get_lane_bps(struct dw_mipi_dsi *dsi, bpp = mipi_dsi_pixel_format_to_bpp(dsi->format); if (bpp < 0) { - dev_err(dsi->dev, "failed to get bpp for pixel format %d\n", - dsi->format); + DRM_DEV_ERROR(dsi->dev, + "failed to get bpp for pixel format %d\n", + dsi->format); return bpp; } @@ -541,7 +542,8 @@ static int dw_mipi_dsi_get_lane_bps(struct dw_mipi_dsi *dsi, if (tmp < max_mbps) target_mbps = tmp; else - dev_err(dsi->dev, "DPHY clock frequency is out of range\n"); + DRM_DEV_ERROR(dsi->dev, + "DPHY clock frequency is out of range\n"); } pllref = DIV_ROUND_UP(clk_get_rate(dsi->pllref_clk), USEC_PER_SEC); @@ -582,8 +584,9 @@ static int dw_mipi_dsi_host_attach(struct mipi_dsi_host *host, struct dw_mipi_dsi *dsi = host_to_dsi(host); if (device->lanes > dsi->pdata->max_data_lanes) { - dev_err(dsi->dev, "the number of data lanes(%u) is too many\n", - device->lanes); + DRM_DEV_ERROR(dsi->dev, + "the number of data lanes(%u) is too many\n", + device->lanes); return -EINVAL; } @@ -632,7 +635,8 @@ static int dw_mipi_dsi_gen_pkt_hdr_write(struct dw_mipi_dsi *dsi, u32 hdr_val) val, !(val & GEN_CMD_FULL), 1000, CMD_PKT_STATUS_TIMEOUT_US); if (ret < 0) { - dev_err(dsi->dev, "failed to get available command FIFO\n"); + DRM_DEV_ERROR(dsi->dev, + "failed to get available command FIFO\n"); return ret; } @@ -643,7 +647,7 @@ static int dw_mipi_dsi_gen_pkt_hdr_write(struct dw_mipi_dsi *dsi, u32 hdr_val) val, (val & mask) == mask, 1000, CMD_PKT_STATUS_TIMEOUT_US); if (ret < 0) { - dev_err(dsi->dev, "failed to write command FIFO\n"); + DRM_DEV_ERROR(dsi->dev, "failed to write command FIFO\n"); return ret; } @@ -663,8 +667,9 @@ static int dw_mipi_dsi_dcs_short_write(struct dw_mipi_dsi *dsi, data |= tx_buf[1] << 8; if (msg->tx_len > 2) { - dev_err(dsi->dev, "too long tx buf length %zu for short write\n", - msg->tx_len); + DRM_DEV_ERROR(dsi->dev, + "too long tx buf length %zu for short write\n", + msg->tx_len); return -EINVAL; } @@ -682,8 +687,9 @@ static int dw_mipi_dsi_dcs_long_write(struct dw_mipi_dsi *dsi, u32 val; if (msg->tx_len < 3) { - dev_err(dsi->dev, "wrong tx buf length %zu for long write\n", - msg->tx_len); + DRM_DEV_ERROR(dsi->dev, + "wrong tx buf length %zu for long write\n", + msg->tx_len); return -EINVAL; } @@ -704,8 +710,8 @@ static int dw_mipi_dsi_dcs_long_write(struct dw_mipi_dsi *dsi, val, !(val & GEN_PLD_W_FULL), 1000, CMD_PKT_STATUS_TIMEOUT_US); if (ret < 0) { - dev_err(dsi->dev, - "failed to get available write payload FIFO\n"); + DRM_DEV_ERROR(dsi->dev, + "failed to get available write payload FIFO\n"); return ret; } } @@ -731,8 +737,8 @@ static ssize_t dw_mipi_dsi_host_transfer(struct mipi_dsi_host *host, ret = dw_mipi_dsi_dcs_long_write(dsi, msg); break; default: - dev_err(dsi->dev, "unsupported message type 0x%02x\n", - msg->type); + DRM_DEV_ERROR(dsi->dev, "unsupported message type 0x%02x\n", + msg->type); ret = -EINVAL; } @@ -935,7 +941,7 @@ static void dw_mipi_dsi_encoder_disable(struct drm_encoder *encoder) return; if (clk_prepare_enable(dsi->pclk)) { - dev_err(dsi->dev, "%s: Failed to enable pclk\n", __func__); + DRM_DEV_ERROR(dsi->dev, "Failed to enable pclk\n"); return; } @@ -967,7 +973,7 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder *encoder) return; if (clk_prepare_enable(dsi->pclk)) { - dev_err(dsi->dev, "%s: Failed to enable pclk\n", __func__); + DRM_DEV_ERROR(dsi->dev, "Failed to enable pclk\n"); return; } @@ -991,7 +997,7 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder *encoder) */ ret = clk_prepare_enable(dsi->grf_clk); if (ret) { - dev_err(dsi->dev, "Failed to enable grf_clk: %d\n", ret); + DRM_DEV_ERROR(dsi->dev, "Failed to enable grf_clk: %d\n", ret); return; } @@ -1004,7 +1010,7 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder *encoder) dw_mipi_dsi_set_mode(dsi, DW_MIPI_DSI_CMD_MODE); if (drm_panel_prepare(dsi->panel)) - dev_err(dsi->dev, "failed to prepare panel\n"); + DRM_DEV_ERROR(dsi->dev, "failed to prepare panel\n"); dw_mipi_dsi_set_mode(dsi, DW_MIPI_DSI_VID_MODE); drm_panel_enable(dsi->panel); @@ -1017,7 +1023,8 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder *encoder) val = pdata->dsi0_en_bit << 16; regmap_write(dsi->grf_regmap, pdata->grf_switch_reg, val); - dev_dbg(dsi->dev, "vop %s output to dsi0\n", (mux) ? "LIT" : "BIG"); + DRM_DEV_DEBUG(dsi->dev, + "vop %s output to dsi0\n", (mux) ? "LIT" : "BIG"); dsi->dpms_mode = DRM_MODE_DPMS_ON; clk_disable_unprepare(dsi->grf_clk); @@ -1112,7 +1119,7 @@ static int dw_mipi_dsi_register(struct drm_device *drm, ret = drm_encoder_init(drm, &dsi->encoder, &dw_mipi_dsi_encoder_funcs, DRM_MODE_ENCODER_DSI, NULL); if (ret) { - dev_err(dev, "Failed to initialize encoder with drm\n"); + DRM_DEV_ERROR(dev, "Failed to initialize encoder with drm\n"); return ret; } @@ -1134,7 +1141,7 @@ static int rockchip_mipi_parse_dt(struct dw_mipi_dsi *dsi) dsi->grf_regmap = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); if (IS_ERR(dsi->grf_regmap)) { - dev_err(dsi->dev, "Unable to get rockchip,grf\n"); + DRM_DEV_ERROR(dsi->dev, "Unable to get rockchip,grf\n"); return PTR_ERR(dsi->grf_regmap); } @@ -1206,14 +1213,15 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master, dsi->pllref_clk = devm_clk_get(dev, "ref"); if (IS_ERR(dsi->pllref_clk)) { ret = PTR_ERR(dsi->pllref_clk); - dev_err(dev, "Unable to get pll reference clock: %d\n", ret); + DRM_DEV_ERROR(dev, + "Unable to get pll reference clock: %d\n", ret); return ret; } dsi->pclk = devm_clk_get(dev, "pclk"); if (IS_ERR(dsi->pclk)) { ret = PTR_ERR(dsi->pclk); - dev_err(dev, "Unable to get pclk: %d\n", ret); + DRM_DEV_ERROR(dev, "Unable to get pclk: %d\n", ret); return ret; } @@ -1227,7 +1235,8 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master, if (ret == -ENOENT) { apb_rst = NULL; } else { - dev_err(dev, "Unable to get reset control: %d\n", ret); + DRM_DEV_ERROR(dev, + "Unable to get reset control: %d\n", ret); return ret; } } @@ -1235,7 +1244,7 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master, if (apb_rst) { ret = clk_prepare_enable(dsi->pclk); if (ret) { - dev_err(dev, "%s: Failed to enable pclk\n", __func__); + DRM_DEV_ERROR(dev, "Failed to enable pclk\n"); return ret; } @@ -1250,7 +1259,8 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master, dsi->phy_cfg_clk = devm_clk_get(dev, "phy_cfg"); if (IS_ERR(dsi->phy_cfg_clk)) { ret = PTR_ERR(dsi->phy_cfg_clk); - dev_err(dev, "Unable to get phy_cfg_clk: %d\n", ret); + DRM_DEV_ERROR(dev, + "Unable to get phy_cfg_clk: %d\n", ret); return ret; } } @@ -1259,20 +1269,20 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master, dsi->grf_clk = devm_clk_get(dev, "grf"); if (IS_ERR(dsi->grf_clk)) { ret = PTR_ERR(dsi->grf_clk); - dev_err(dev, "Unable to get grf_clk: %d\n", ret); + DRM_DEV_ERROR(dev, "Unable to get grf_clk: %d\n", ret); return ret; } } ret = clk_prepare_enable(dsi->pllref_clk); if (ret) { - dev_err(dev, "%s: Failed to enable pllref_clk\n", __func__); + DRM_DEV_ERROR(dev, "Failed to enable pllref_clk\n"); return ret; } ret = dw_mipi_dsi_register(drm, dsi); if (ret) { - dev_err(dev, "Failed to register mipi_dsi: %d\n", ret); + DRM_DEV_ERROR(dev, "Failed to register mipi_dsi: %d\n", ret); goto err_pllref; } @@ -1282,7 +1292,7 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master, dsi->dsi_host.dev = dev; ret = mipi_dsi_host_register(&dsi->dsi_host); if (ret) { - dev_err(dev, "Failed to register MIPI host: %d\n", ret); + DRM_DEV_ERROR(dev, "Failed to register MIPI host: %d\n", ret); goto err_cleanup; } diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index 63dab6f1b191..0eea9fce35ac 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c @@ -7,10 +7,12 @@ * (at your option) any later version. */ +#include <linux/clk.h> +#include <linux/mfd/syscon.h> #include <linux/module.h> #include <linux/platform_device.h> -#include <linux/mfd/syscon.h> #include <linux/regmap.h> + #include <drm/drm_of.h> #include <drm/drmP.h> #include <drm/drm_crtc_helper.h> @@ -20,13 +22,32 @@ #include "rockchip_drm_drv.h" #include "rockchip_drm_vop.h" -#define GRF_SOC_CON6 0x025c -#define HDMI_SEL_VOP_LIT (1 << 4) +#define RK3288_GRF_SOC_CON6 0x025C +#define RK3288_HDMI_LCDC_SEL BIT(4) +#define RK3399_GRF_SOC_CON20 0x6250 +#define RK3399_HDMI_LCDC_SEL BIT(6) + +#define HIWORD_UPDATE(val, mask) (val | (mask) << 16) + +/** + * struct rockchip_hdmi_chip_data - splite the grf setting of kind of chips + * @lcdsel_grf_reg: grf register offset of lcdc select + * @lcdsel_big: reg value of selecting vop big for HDMI + * @lcdsel_lit: reg value of selecting vop little for HDMI + */ +struct rockchip_hdmi_chip_data { + u32 lcdsel_grf_reg; + u32 lcdsel_big; + u32 lcdsel_lit; +}; struct rockchip_hdmi { struct device *dev; struct regmap *regmap; struct drm_encoder encoder; + const struct rockchip_hdmi_chip_data *chip_data; + struct clk *vpll_clk; + struct clk *grf_clk; }; #define to_rockchip_hdmi(x) container_of(x, struct rockchip_hdmi, x) @@ -143,13 +164,41 @@ static const struct dw_hdmi_phy_config rockchip_phy_config[] = { static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi) { struct device_node *np = hdmi->dev->of_node; + int ret; hdmi->regmap = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); if (IS_ERR(hdmi->regmap)) { - dev_err(hdmi->dev, "Unable to get rockchip,grf\n"); + DRM_DEV_ERROR(hdmi->dev, "Unable to get rockchip,grf\n"); return PTR_ERR(hdmi->regmap); } + hdmi->vpll_clk = devm_clk_get(hdmi->dev, "vpll"); + if (PTR_ERR(hdmi->vpll_clk) == -ENOENT) { + hdmi->vpll_clk = NULL; + } else if (PTR_ERR(hdmi->vpll_clk) == -EPROBE_DEFER) { + return -EPROBE_DEFER; + } else if (IS_ERR(hdmi->vpll_clk)) { + DRM_DEV_ERROR(hdmi->dev, "failed to get grf clock\n"); + return PTR_ERR(hdmi->vpll_clk); + } + + hdmi->grf_clk = devm_clk_get(hdmi->dev, "grf"); + if (PTR_ERR(hdmi->grf_clk) == -ENOENT) { + hdmi->grf_clk = NULL; + } else if (PTR_ERR(hdmi->grf_clk) == -EPROBE_DEFER) { + return -EPROBE_DEFER; + } else if (IS_ERR(hdmi->grf_clk)) { + DRM_DEV_ERROR(hdmi->dev, "failed to get grf clock\n"); + return PTR_ERR(hdmi->grf_clk); + } + + ret = clk_prepare_enable(hdmi->vpll_clk); + if (ret) { + DRM_DEV_ERROR(hdmi->dev, + "Failed to enable HDMI vpll: %d\n", ret); + return ret; + } + return 0; } @@ -192,23 +241,36 @@ static void dw_hdmi_rockchip_encoder_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adj_mode) { + struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder); + + clk_set_rate(hdmi->vpll_clk, adj_mode->clock * 1000); } static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder) { struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder); u32 val; - int mux; + int ret; - mux = drm_of_encoder_active_endpoint_id(hdmi->dev->of_node, encoder); - if (mux) - val = HDMI_SEL_VOP_LIT | (HDMI_SEL_VOP_LIT << 16); + ret = drm_of_encoder_active_endpoint_id(hdmi->dev->of_node, encoder); + if (ret) + val = hdmi->chip_data->lcdsel_lit; else - val = HDMI_SEL_VOP_LIT << 16; + val = hdmi->chip_data->lcdsel_big; - regmap_write(hdmi->regmap, GRF_SOC_CON6, val); - dev_dbg(hdmi->dev, "vop %s output to hdmi\n", - (mux) ? "LIT" : "BIG"); + ret = clk_prepare_enable(hdmi->grf_clk); + if (ret < 0) { + DRM_DEV_ERROR(hdmi->dev, "failed to enable grfclk %d\n", ret); + return; + } + + ret = regmap_write(hdmi->regmap, hdmi->chip_data->lcdsel_grf_reg, val); + if (ret != 0) + DRM_DEV_ERROR(hdmi->dev, "Could not write to GRF: %d\n", ret); + + clk_disable_unprepare(hdmi->grf_clk); + DRM_DEV_DEBUG(hdmi->dev, "vop %s output to hdmi\n", + ret ? "LIT" : "BIG"); } static int @@ -232,16 +294,40 @@ static const struct drm_encoder_helper_funcs dw_hdmi_rockchip_encoder_helper_fun .atomic_check = dw_hdmi_rockchip_encoder_atomic_check, }; -static const struct dw_hdmi_plat_data rockchip_hdmi_drv_data = { +static struct rockchip_hdmi_chip_data rk3288_chip_data = { + .lcdsel_grf_reg = RK3288_GRF_SOC_CON6, + .lcdsel_big = HIWORD_UPDATE(0, RK3288_HDMI_LCDC_SEL), + .lcdsel_lit = HIWORD_UPDATE(RK3288_HDMI_LCDC_SEL, RK3288_HDMI_LCDC_SEL), +}; + +static const struct dw_hdmi_plat_data rk3288_hdmi_drv_data = { .mode_valid = dw_hdmi_rockchip_mode_valid, .mpll_cfg = rockchip_mpll_cfg, .cur_ctr = rockchip_cur_ctr, .phy_config = rockchip_phy_config, + .phy_data = &rk3288_chip_data, +}; + +static struct rockchip_hdmi_chip_data rk3399_chip_data = { + .lcdsel_grf_reg = RK3399_GRF_SOC_CON20, + .lcdsel_big = HIWORD_UPDATE(0, RK3399_HDMI_LCDC_SEL), + .lcdsel_lit = HIWORD_UPDATE(RK3399_HDMI_LCDC_SEL, RK3399_HDMI_LCDC_SEL), +}; + +static const struct dw_hdmi_plat_data rk3399_hdmi_drv_data = { + .mode_valid = dw_hdmi_rockchip_mode_valid, + .mpll_cfg = rockchip_mpll_cfg, + .cur_ctr = rockchip_cur_ctr, + .phy_config = rockchip_phy_config, + .phy_data = &rk3399_chip_data, }; static const struct of_device_id dw_hdmi_rockchip_dt_ids[] = { { .compatible = "rockchip,rk3288-dw-hdmi", - .data = &rockchip_hdmi_drv_data + .data = &rk3288_hdmi_drv_data + }, + { .compatible = "rockchip,rk3399-dw-hdmi", + .data = &rk3399_hdmi_drv_data }, {}, }; @@ -268,6 +354,7 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, match = of_match_node(dw_hdmi_rockchip_dt_ids, pdev->dev.of_node); plat_data = match->data; hdmi->dev = &pdev->dev; + hdmi->chip_data = plat_data->phy_data; encoder = &hdmi->encoder; encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node); @@ -282,7 +369,7 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, ret = rockchip_hdmi_parse_dt(hdmi); if (ret) { - dev_err(hdmi->dev, "Unable to parse OF data\n"); + DRM_DEV_ERROR(hdmi->dev, "Unable to parse OF data\n"); return ret; } diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c index 7d9b75eb6c44..e55312cf1b50 100644 --- a/drivers/gpu/drm/rockchip/inno_hdmi.c +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c @@ -224,7 +224,7 @@ static void inno_hdmi_set_pwr_mode(struct inno_hdmi *hdmi, int mode) break; default: - dev_err(hdmi->dev, "Unknown power mode %d\n", mode); + DRM_DEV_ERROR(hdmi->dev, "Unknown power mode %d\n", mode); } } @@ -592,7 +592,7 @@ static void inno_hdmi_connector_destroy(struct drm_connector *connector) drm_connector_cleanup(connector); } -static struct drm_connector_funcs inno_hdmi_connector_funcs = { +static const struct drm_connector_funcs inno_hdmi_connector_funcs = { .dpms = drm_atomic_helper_connector_dpms, .fill_modes = inno_hdmi_probe_single_connector_modes, .detect = inno_hdmi_connector_detect, @@ -743,8 +743,9 @@ static int inno_hdmi_i2c_xfer(struct i2c_adapter *adap, hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY); for (i = 0; i < num; i++) { - dev_dbg(hdmi->dev, "xfer: num: %d/%d, len: %d, flags: %#x\n", - i + 1, num, msgs[i].len, msgs[i].flags); + DRM_DEV_DEBUG(hdmi->dev, + "xfer: num: %d/%d, len: %d, flags: %#x\n", + i + 1, num, msgs[i].len, msgs[i].flags); if (msgs[i].flags & I2C_M_RD) ret = inno_hdmi_i2c_read(hdmi, &msgs[i]); @@ -807,7 +808,7 @@ static struct i2c_adapter *inno_hdmi_i2c_adapter(struct inno_hdmi *hdmi) hdmi->i2c = i2c; - dev_info(hdmi->dev, "registered %s I2C bus driver\n", adap->name); + DRM_DEV_INFO(hdmi->dev, "registered %s I2C bus driver\n", adap->name); return adap; } @@ -839,13 +840,14 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, hdmi->pclk = devm_clk_get(hdmi->dev, "pclk"); if (IS_ERR(hdmi->pclk)) { - dev_err(hdmi->dev, "Unable to get HDMI pclk clk\n"); + DRM_DEV_ERROR(hdmi->dev, "Unable to get HDMI pclk clk\n"); return PTR_ERR(hdmi->pclk); } ret = clk_prepare_enable(hdmi->pclk); if (ret) { - dev_err(hdmi->dev, "Cannot enable HDMI pclk clock: %d\n", ret); + DRM_DEV_ERROR(hdmi->dev, + "Cannot enable HDMI pclk clock: %d\n", ret); return ret; } diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index c6b1b7f3a2a3..76d63de5921d 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -58,7 +58,7 @@ int rockchip_drm_dma_attach_device(struct drm_device *drm_dev, ret = iommu_attach_device(private->domain, dev); if (ret) { - dev_err(dev, "Failed to attach iommu device\n"); + DRM_DEV_ERROR(dev, "Failed to attach iommu device\n"); return ret; } @@ -161,23 +161,21 @@ static int rockchip_drm_bind(struct device *dev) */ drm_dev->irq_enabled = true; - /* init kms poll for handling hpd */ - drm_kms_helper_poll_init(drm_dev); - ret = rockchip_drm_fbdev_init(drm_dev); if (ret) - goto err_kms_helper_poll_fini; + goto err_unbind_all; + + /* init kms poll for handling hpd */ + drm_kms_helper_poll_init(drm_dev); ret = drm_dev_register(drm_dev, 0); if (ret) - goto err_fbdev_fini; + goto err_kms_helper_poll_fini; return 0; -err_fbdev_fini: - rockchip_drm_fbdev_fini(drm_dev); err_kms_helper_poll_fini: drm_kms_helper_poll_fini(drm_dev); - drm_vblank_cleanup(drm_dev); + rockchip_drm_fbdev_fini(drm_dev); err_unbind_all: component_unbind_all(dev, drm_dev); err_mode_config_cleanup: @@ -200,7 +198,6 @@ static void rockchip_drm_unbind(struct device *dev) drm_kms_helper_poll_fini(drm_dev); drm_atomic_helper_shutdown(drm_dev); - drm_vblank_cleanup(drm_dev); component_unbind_all(dev, drm_dev); drm_mode_config_cleanup(drm_dev); rockchip_iommu_cleanup(drm_dev); @@ -235,8 +232,6 @@ static struct drm_driver rockchip_drm_driver = { .gem_vm_ops = &drm_gem_cma_vm_ops, .gem_free_object_unlocked = rockchip_gem_free_object, .dumb_create = rockchip_gem_dumb_create, - .dumb_map_offset = rockchip_gem_dumb_map_offset, - .dumb_destroy = drm_gem_dumb_destroy, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, .gem_prime_import = drm_gem_prime_import, @@ -275,11 +270,15 @@ static void rockchip_drm_fb_resume(struct drm_device *drm) static int rockchip_drm_sys_suspend(struct device *dev) { struct drm_device *drm = dev_get_drvdata(dev); - struct rockchip_drm_private *priv = drm->dev_private; + struct rockchip_drm_private *priv; + + if (!drm) + return 0; drm_kms_helper_poll_disable(drm); rockchip_drm_fb_suspend(drm); + priv = drm->dev_private; priv->state = drm_atomic_helper_suspend(drm); if (IS_ERR(priv->state)) { rockchip_drm_fb_resume(drm); @@ -293,8 +292,12 @@ static int rockchip_drm_sys_suspend(struct device *dev) static int rockchip_drm_sys_resume(struct device *dev) { struct drm_device *drm = dev_get_drvdata(dev); - struct rockchip_drm_private *priv = drm->dev_private; + struct rockchip_drm_private *priv; + + if (!drm) + return 0; + priv = drm->dev_private; drm_atomic_helper_resume(drm, priv->state); rockchip_drm_fb_resume(drm); drm_kms_helper_poll_enable(drm); @@ -370,8 +373,9 @@ static int rockchip_drm_platform_of_probe(struct device *dev) iommu = of_parse_phandle(port->parent, "iommus", 0); if (!iommu || !of_device_is_available(iommu->parent)) { - dev_dbg(dev, "no iommu attached for %s, using non-iommu buffers\n", - port->parent->full_name); + DRM_DEV_DEBUG(dev, + "no iommu attached for %pOF, using non-iommu buffers\n", + port->parent); /* * if there is a crtc not support iommu, force set all * crtc use non-iommu buffer. @@ -386,12 +390,13 @@ static int rockchip_drm_platform_of_probe(struct device *dev) } if (i == 0) { - dev_err(dev, "missing 'ports' property\n"); + DRM_DEV_ERROR(dev, "missing 'ports' property\n"); return -ENODEV; } if (!found) { - dev_err(dev, "No available vop found for display-subsystem.\n"); + DRM_DEV_ERROR(dev, + "No available vop found for display-subsystem.\n"); return -ENODEV; } @@ -450,6 +455,8 @@ static int __init rockchip_drm_init(void) num_rockchip_sub_drivers = 0; ADD_ROCKCHIP_SUB_DRIVER(vop_platform_driver, CONFIG_DRM_ROCKCHIP); + ADD_ROCKCHIP_SUB_DRIVER(rockchip_lvds_driver, + CONFIG_ROCKCHIP_LVDS); ADD_ROCKCHIP_SUB_DRIVER(rockchip_dp_driver, CONFIG_ROCKCHIP_ANALOGIX_DP); ADD_ROCKCHIP_SUB_DRIVER(cdn_dp_driver, CONFIG_ROCKCHIP_CDN_DP); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h index a48fcce3f5f6..498dfbc52cec 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h @@ -45,13 +45,13 @@ struct rockchip_crtc_state { * * @crtc: array of enabled CRTCs, used to map from "pipe" to drm_crtc. * @num_pipe: number of pipes for this device. + * @mm_lock: protect drm_mm on multi-threads. */ struct rockchip_drm_private { struct drm_fb_helper fbdev_helper; struct drm_gem_object *fbdev_bo; struct drm_atomic_state *state; struct iommu_domain *domain; - /* protect drm_mm on multi-threads */ struct mutex mm_lock; struct drm_mm mm; struct list_head psr_list; @@ -62,13 +62,13 @@ int rockchip_drm_dma_attach_device(struct drm_device *drm_dev, struct device *dev); void rockchip_drm_dma_detach_device(struct drm_device *drm_dev, struct device *dev); -int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int line_num, - unsigned int mstimeout); +int rockchip_drm_wait_vact_end(struct drm_crtc *crtc, unsigned int mstimeout); extern struct platform_driver cdn_dp_driver; extern struct platform_driver dw_hdmi_rockchip_pltfm_driver; extern struct platform_driver dw_mipi_dsi_driver; extern struct platform_driver inno_hdmi_driver; extern struct platform_driver rockchip_dp_driver; +extern struct platform_driver rockchip_lvds_driver; extern struct platform_driver vop_platform_driver; #endif /* _ROCKCHIP_DRM_DRV_H_ */ diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c index 81f9548672b0..69904c1abe9f 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c @@ -48,7 +48,7 @@ static void rockchip_drm_fb_destroy(struct drm_framebuffer *fb) int i; for (i = 0; i < ROCKCHIP_MAX_FB_BUFFER; i++) - drm_gem_object_unreference_unlocked(rockchip_fb->obj[i]); + drm_gem_object_put_unlocked(rockchip_fb->obj[i]); drm_framebuffer_cleanup(fb); kfree(rockchip_fb); @@ -100,8 +100,9 @@ rockchip_fb_alloc(struct drm_device *dev, const struct drm_mode_fb_cmd2 *mode_cm ret = drm_framebuffer_init(dev, &rockchip_fb->fb, &rockchip_drm_fb_funcs); if (ret) { - dev_err(dev->dev, "Failed to initialize framebuffer: %d\n", - ret); + DRM_DEV_ERROR(dev->dev, + "Failed to initialize framebuffer: %d\n", + ret); kfree(rockchip_fb); return ERR_PTR(ret); } @@ -134,7 +135,8 @@ rockchip_user_fb_create(struct drm_device *dev, struct drm_file *file_priv, obj = drm_gem_object_lookup(file_priv, mode_cmd->handles[i]); if (!obj) { - dev_err(dev->dev, "Failed to lookup GEM object\n"); + DRM_DEV_ERROR(dev->dev, + "Failed to lookup GEM object\n"); ret = -ENXIO; goto err_gem_object_unreference; } @@ -144,7 +146,7 @@ rockchip_user_fb_create(struct drm_device *dev, struct drm_file *file_priv, width * drm_format_plane_cpp(mode_cmd->pixel_format, i); if (obj->size < min_size) { - drm_gem_object_unreference_unlocked(obj); + drm_gem_object_put_unlocked(obj); ret = -EINVAL; goto err_gem_object_unreference; } @@ -161,17 +163,15 @@ rockchip_user_fb_create(struct drm_device *dev, struct drm_file *file_priv, err_gem_object_unreference: for (i--; i >= 0; i--) - drm_gem_object_unreference_unlocked(objs[i]); + drm_gem_object_put_unlocked(objs[i]); return ERR_PTR(ret); } static void rockchip_drm_output_poll_changed(struct drm_device *dev) { struct rockchip_drm_private *private = dev->dev_private; - struct drm_fb_helper *fb_helper = &private->fbdev_helper; - if (fb_helper) - drm_fb_helper_hotplug_event(fb_helper); + drm_fb_helper_hotplug_event(&private->fbdev_helper); } static void diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c b/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c index ce946b9c57a9..e6650553f5d6 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c @@ -76,7 +76,7 @@ static int rockchip_drm_fbdev_create(struct drm_fb_helper *helper, fbi = drm_fb_helper_alloc_fbi(helper); if (IS_ERR(fbi)) { - dev_err(dev->dev, "Failed to create framebuffer info.\n"); + DRM_DEV_ERROR(dev->dev, "Failed to create framebuffer info.\n"); ret = PTR_ERR(fbi); goto out; } @@ -84,7 +84,8 @@ static int rockchip_drm_fbdev_create(struct drm_fb_helper *helper, helper->fb = rockchip_drm_framebuffer_init(dev, &mode_cmd, private->fbdev_bo); if (IS_ERR(helper->fb)) { - dev_err(dev->dev, "Failed to allocate DRM framebuffer.\n"); + DRM_DEV_ERROR(dev->dev, + "Failed to allocate DRM framebuffer.\n"); ret = PTR_ERR(helper->fb); goto out; } @@ -138,21 +139,24 @@ int rockchip_drm_fbdev_init(struct drm_device *dev) ret = drm_fb_helper_init(dev, helper, ROCKCHIP_MAX_CONNECTOR); if (ret < 0) { - dev_err(dev->dev, "Failed to initialize drm fb helper - %d.\n", - ret); + DRM_DEV_ERROR(dev->dev, + "Failed to initialize drm fb helper - %d.\n", + ret); return ret; } ret = drm_fb_helper_single_add_all_connectors(helper); if (ret < 0) { - dev_err(dev->dev, "Failed to add connectors - %d.\n", ret); + DRM_DEV_ERROR(dev->dev, + "Failed to add connectors - %d.\n", ret); goto err_drm_fb_helper_fini; } ret = drm_fb_helper_initial_config(helper, PREFERRED_BPP); if (ret < 0) { - dev_err(dev->dev, "Failed to set initial hw config - %d.\n", - ret); + DRM_DEV_ERROR(dev->dev, + "Failed to set initial hw config - %d.\n", + ret); goto err_drm_fb_helper_fini; } @@ -173,7 +177,7 @@ void rockchip_drm_fbdev_fini(struct drm_device *dev) drm_fb_helper_unregister_fbi(helper); if (helper->fb) - drm_framebuffer_unreference(helper->fb); + drm_framebuffer_put(helper->fb); drm_fb_helper_fini(helper); } diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c index df9e57064f19..1d9655576b6e 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c @@ -29,12 +29,11 @@ static int rockchip_gem_iommu_map(struct rockchip_gem_object *rk_obj) ssize_t ret; mutex_lock(&private->mm_lock); - ret = drm_mm_insert_node_generic(&private->mm, &rk_obj->mm, rk_obj->base.size, PAGE_SIZE, 0, 0); - mutex_unlock(&private->mm_lock); + if (ret < 0) { DRM_ERROR("out of I/O virtual memory: %zd\n", ret); return ret; @@ -56,7 +55,9 @@ static int rockchip_gem_iommu_map(struct rockchip_gem_object *rk_obj) return 0; err_remove_node: + mutex_lock(&private->mm_lock); drm_mm_remove_node(&rk_obj->mm); + mutex_unlock(&private->mm_lock); return ret; } @@ -219,7 +220,7 @@ static int rockchip_drm_gem_object_mmap_iommu(struct drm_gem_object *obj, { struct rockchip_gem_object *rk_obj = to_rockchip_obj(obj); unsigned int i, count = obj->size >> PAGE_SHIFT; - unsigned long user_count = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; + unsigned long user_count = vma_pages(vma); unsigned long uaddr = vma->vm_start; unsigned long offset = vma->vm_pgoff; unsigned long end = user_count + offset; @@ -382,7 +383,7 @@ rockchip_gem_create_with_handle(struct drm_file *file_priv, goto err_handle_create; /* drop reference from allocate - handle holds it now. */ - drm_gem_object_unreference_unlocked(obj); + drm_gem_object_put_unlocked(obj); return rk_obj; @@ -392,32 +393,6 @@ err_handle_create: return ERR_PTR(ret); } -int rockchip_gem_dumb_map_offset(struct drm_file *file_priv, - struct drm_device *dev, uint32_t handle, - uint64_t *offset) -{ - struct drm_gem_object *obj; - int ret; - - obj = drm_gem_object_lookup(file_priv, handle); - if (!obj) { - DRM_ERROR("failed to lookup gem object.\n"); - return -EINVAL; - } - - ret = drm_gem_create_mmap_offset(obj); - if (ret) - goto out; - - *offset = drm_vma_node_offset_addr(&obj->vma_node); - DRM_DEBUG_KMS("offset = 0x%llx\n", *offset); - -out: - drm_gem_object_unreference_unlocked(obj); - - return 0; -} - /* * rockchip_gem_dumb_create - (struct drm_driver)->dumb_create callback * function diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.h b/drivers/gpu/drm/rockchip/rockchip_drm_gem.h index 3f6ea4d18a5c..f237375582fb 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.h @@ -57,7 +57,4 @@ void rockchip_gem_free_object(struct drm_gem_object *obj); int rockchip_gem_dumb_create(struct drm_file *file_priv, struct drm_device *dev, struct drm_mode_create_dumb *args); -int rockchip_gem_dumb_map_offset(struct drm_file *file_priv, - struct drm_device *dev, uint32_t handle, - uint64_t *offset); #endif /* _ROCKCHIP_DRM_GEM_H */ diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 45589d6ce65e..ba164295578f 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -42,33 +42,20 @@ #include "rockchip_drm_psr.h" #include "rockchip_drm_vop.h" -#define __REG_SET_RELAXED(x, off, mask, shift, v, write_mask) \ - vop_mask_write(x, off, mask, shift, v, write_mask, true) - -#define __REG_SET_NORMAL(x, off, mask, shift, v, write_mask) \ - vop_mask_write(x, off, mask, shift, v, write_mask, false) - -#define REG_SET(x, base, reg, v, mode) \ - __REG_SET_##mode(x, base + reg.offset, \ - reg.mask, reg.shift, v, reg.write_mask) -#define REG_SET_MASK(x, base, reg, mask, v, mode) \ - __REG_SET_##mode(x, base + reg.offset, \ - mask, reg.shift, v, reg.write_mask) - #define VOP_WIN_SET(x, win, name, v) \ - REG_SET(x, win->base, win->phy->name, v, RELAXED) + vop_reg_set(vop, &win->phy->name, win->base, ~0, v, #name) #define VOP_SCL_SET(x, win, name, v) \ - REG_SET(x, win->base, win->phy->scl->name, v, RELAXED) + vop_reg_set(vop, &win->phy->scl->name, win->base, ~0, v, #name) #define VOP_SCL_SET_EXT(x, win, name, v) \ - REG_SET(x, win->base, win->phy->scl->ext->name, v, RELAXED) -#define VOP_CTRL_SET(x, name, v) \ - REG_SET(x, 0, (x)->data->ctrl->name, v, NORMAL) + vop_reg_set(vop, &win->phy->scl->ext->name, \ + win->base, ~0, v, #name) + +#define VOP_INTR_SET_MASK(vop, name, mask, v) \ + vop_reg_set(vop, &vop->data->intr->name, 0, mask, v, #name) -#define VOP_INTR_GET(vop, name) \ - vop_read_reg(vop, 0, &vop->data->ctrl->name) +#define VOP_REG_SET(vop, group, name, v) \ + vop_reg_set(vop, &vop->data->group->name, 0, ~0, v, #name) -#define VOP_INTR_SET(vop, name, mask, v) \ - REG_SET_MASK(vop, 0, vop->data->intr->name, mask, v, NORMAL) #define VOP_INTR_SET_TYPE(vop, name, type, v) \ do { \ int i, reg = 0, mask = 0; \ @@ -78,13 +65,13 @@ mask |= 1 << i; \ } \ } \ - VOP_INTR_SET(vop, name, mask, reg); \ + VOP_INTR_SET_MASK(vop, name, mask, reg); \ } while (0) #define VOP_INTR_GET_TYPE(vop, name, type) \ vop_get_intr_type(vop, &vop->data->intr->name, type) #define VOP_WIN_GET(x, win, name) \ - vop_read_reg(x, win->base, &win->phy->name) + vop_read_reg(x, win->offset, win->phy->name) #define VOP_WIN_GET_YRGBADDR(vop, win) \ vop_readl(vop, win->base + win->phy->yrgb_mst.offset) @@ -166,14 +153,22 @@ static inline uint32_t vop_read_reg(struct vop *vop, uint32_t base, return (vop_readl(vop, base + reg->offset) >> reg->shift) & reg->mask; } -static inline void vop_mask_write(struct vop *vop, uint32_t offset, - uint32_t mask, uint32_t shift, uint32_t v, - bool write_mask, bool relaxed) +static void vop_reg_set(struct vop *vop, const struct vop_reg *reg, + uint32_t _offset, uint32_t _mask, uint32_t v, + const char *reg_name) { - if (!mask) + int offset, mask, shift; + + if (!reg || !reg->mask) { + DRM_DEV_DEBUG(vop->dev, "Warning: not support %s\n", reg_name); return; + } + + offset = reg->offset + _offset; + mask = reg->mask & _mask; + shift = reg->shift; - if (write_mask) { + if (reg->write_mask) { v = ((v << shift) & 0xffff) | (mask << (shift + 16)); } else { uint32_t cached_val = vop->regsbak[offset >> 2]; @@ -182,7 +177,7 @@ static inline void vop_mask_write(struct vop *vop, uint32_t offset, vop->regsbak[offset >> 2] = v; } - if (relaxed) + if (reg->relaxed) writel_relaxed(v, vop->regs + offset); else writel(v, vop->regs + offset); @@ -204,7 +199,7 @@ static inline uint32_t vop_get_intr_type(struct vop *vop, static inline void vop_cfg_done(struct vop *vop) { - VOP_CTRL_SET(vop, cfg_done, 1); + VOP_REG_SET(vop, common, cfg_done, 1); } static bool has_rb_swapped(uint32_t format) @@ -468,7 +463,7 @@ static bool vop_line_flag_irq_is_enabled(struct vop *vop) return !!line_flag_irq; } -static void vop_line_flag_irq_enable(struct vop *vop, int line_num) +static void vop_line_flag_irq_enable(struct vop *vop) { unsigned long flags; @@ -477,7 +472,6 @@ static void vop_line_flag_irq_enable(struct vop *vop, int line_num) spin_lock_irqsave(&vop->irq_lock, flags); - VOP_CTRL_SET(vop, line_flag_num[0], line_num); VOP_INTR_SET_TYPE(vop, clear, LINE_FLAG_INTR, 1); VOP_INTR_SET_TYPE(vop, enable, LINE_FLAG_INTR, 1); @@ -501,11 +495,11 @@ static void vop_line_flag_irq_disable(struct vop *vop) static int vop_enable(struct drm_crtc *crtc) { struct vop *vop = to_vop(crtc); - int ret; + int ret, i; ret = pm_runtime_get_sync(vop->dev); if (ret < 0) { - dev_err(vop->dev, "failed to get pm runtime: %d\n", ret); + DRM_DEV_ERROR(vop->dev, "failed to get pm runtime: %d\n", ret); return ret; } @@ -529,11 +523,26 @@ static int vop_enable(struct drm_crtc *crtc) */ ret = rockchip_drm_dma_attach_device(vop->drm_dev, vop->dev); if (ret) { - dev_err(vop->dev, "failed to attach dma mapping, %d\n", ret); + DRM_DEV_ERROR(vop->dev, + "failed to attach dma mapping, %d\n", ret); goto err_disable_aclk; } memcpy(vop->regs, vop->regsbak, vop->len); + /* + * We need to make sure that all windows are disabled before we + * enable the crtc. Otherwise we might try to scan from a destroyed + * buffer later. + */ + for (i = 0; i < vop->data->win_size; i++) { + struct vop_win *vop_win = &vop->win[i]; + const struct vop_win_data *win = vop_win->data; + + spin_lock(&vop->reg_lock); + VOP_WIN_SET(vop, win, enable, 0); + spin_unlock(&vop->reg_lock); + } + vop_cfg_done(vop); /* @@ -543,7 +552,7 @@ static int vop_enable(struct drm_crtc *crtc) spin_lock(&vop->reg_lock); - VOP_CTRL_SET(vop, standby, 0); + VOP_REG_SET(vop, common, standby, 1); spin_unlock(&vop->reg_lock); @@ -567,28 +576,11 @@ err_put_pm_runtime: static void vop_crtc_disable(struct drm_crtc *crtc) { struct vop *vop = to_vop(crtc); - int i; WARN_ON(vop->event); rockchip_drm_psr_deactivate(&vop->crtc); - /* - * We need to make sure that all windows are disabled before we - * disable that crtc. Otherwise we might try to scan from a destroyed - * buffer later. - */ - for (i = 0; i < vop->data->win_size; i++) { - struct vop_win *vop_win = &vop->win[i]; - const struct vop_win_data *win = vop_win->data; - - spin_lock(&vop->reg_lock); - VOP_WIN_SET(vop, win, enable, 0); - spin_unlock(&vop->reg_lock); - } - - vop_cfg_done(vop); - drm_crtc_vblank_off(crtc); /* @@ -603,7 +595,7 @@ static void vop_crtc_disable(struct drm_crtc *crtc) spin_lock(&vop->reg_lock); - VOP_CTRL_SET(vop, standby, 1); + VOP_REG_SET(vop, common, standby, 1); spin_unlock(&vop->reg_lock); @@ -683,8 +675,10 @@ static int vop_plane_atomic_check(struct drm_plane *plane, * Src.x1 can be odd when do clip, but yuv plane start point * need align with 2 pixel. */ - if (is_yuv_support(fb->format->format) && ((state->src.x1 >> 16) % 2)) + if (is_yuv_support(fb->format->format) && ((state->src.x1 >> 16) % 2)) { + DRM_ERROR("Invalid Source: Yuv format not support odd xpos\n"); return -EINVAL; + } return 0; } @@ -765,7 +759,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane, spin_lock(&vop->reg_lock); VOP_WIN_SET(vop, win, format, format); - VOP_WIN_SET(vop, win, yrgb_vir, fb->pitches[0] >> 2); + VOP_WIN_SET(vop, win, yrgb_vir, DIV_ROUND_UP(fb->pitches[0], 4)); VOP_WIN_SET(vop, win, yrgb_mst, dma_addr); if (is_yuv_support(fb->format->format)) { int hsub = drm_format_horz_chroma_subsampling(fb->format->format); @@ -779,7 +773,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane, offset += (src->y1 >> 16) * fb->pitches[1] / vsub; dma_addr = rk_uv_obj->dma_addr + offset + fb->offsets[1]; - VOP_WIN_SET(vop, win, uv_vir, fb->pitches[1] >> 2); + VOP_WIN_SET(vop, win, uv_vir, DIV_ROUND_UP(fb->pitches[1], 4)); VOP_WIN_SET(vop, win, uv_mst, dma_addr); } @@ -899,70 +893,34 @@ static void vop_crtc_enable(struct drm_crtc *crtc) return; } - /* - * If dclk rate is zero, mean that scanout is stop, - * we don't need wait any more. - */ - if (clk_get_rate(vop->dclk)) { - /* - * Rk3288 vop timing register is immediately, when configure - * display timing on display time, may cause tearing. - * - * Vop standby will take effect at end of current frame, - * if dsp hold valid irq happen, it means standby complete. - * - * mode set: - * standby and wait complete --> |---- - * | display time - * |---- - * |---> dsp hold irq - * configure display timing --> | - * standby exit | - * | new frame start. - */ - - reinit_completion(&vop->dsp_hold_completion); - vop_dsp_hold_valid_irq_enable(vop); - - spin_lock(&vop->reg_lock); - - VOP_CTRL_SET(vop, standby, 1); - - spin_unlock(&vop->reg_lock); - - wait_for_completion(&vop->dsp_hold_completion); - - vop_dsp_hold_valid_irq_disable(vop); - } - pin_pol = BIT(DCLK_INVERT); pin_pol |= (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) ? BIT(HSYNC_POSITIVE) : 0; pin_pol |= (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) ? BIT(VSYNC_POSITIVE) : 0; - VOP_CTRL_SET(vop, pin_pol, pin_pol); + VOP_REG_SET(vop, output, pin_pol, pin_pol); switch (s->output_type) { case DRM_MODE_CONNECTOR_LVDS: - VOP_CTRL_SET(vop, rgb_en, 1); - VOP_CTRL_SET(vop, rgb_pin_pol, pin_pol); + VOP_REG_SET(vop, output, rgb_en, 1); + VOP_REG_SET(vop, output, rgb_pin_pol, pin_pol); break; case DRM_MODE_CONNECTOR_eDP: - VOP_CTRL_SET(vop, edp_pin_pol, pin_pol); - VOP_CTRL_SET(vop, edp_en, 1); + VOP_REG_SET(vop, output, edp_pin_pol, pin_pol); + VOP_REG_SET(vop, output, edp_en, 1); break; case DRM_MODE_CONNECTOR_HDMIA: - VOP_CTRL_SET(vop, hdmi_pin_pol, pin_pol); - VOP_CTRL_SET(vop, hdmi_en, 1); + VOP_REG_SET(vop, output, hdmi_pin_pol, pin_pol); + VOP_REG_SET(vop, output, hdmi_en, 1); break; case DRM_MODE_CONNECTOR_DSI: - VOP_CTRL_SET(vop, mipi_pin_pol, pin_pol); - VOP_CTRL_SET(vop, mipi_en, 1); + VOP_REG_SET(vop, output, mipi_pin_pol, pin_pol); + VOP_REG_SET(vop, output, mipi_en, 1); break; case DRM_MODE_CONNECTOR_DisplayPort: pin_pol &= ~BIT(DCLK_INVERT); - VOP_CTRL_SET(vop, dp_pin_pol, pin_pol); - VOP_CTRL_SET(vop, dp_en, 1); + VOP_REG_SET(vop, output, dp_pin_pol, pin_pol); + VOP_REG_SET(vop, output, dp_en, 1); break; default: DRM_DEV_ERROR(vop->dev, "unsupported connector_type [%d]\n", @@ -975,23 +933,25 @@ static void vop_crtc_enable(struct drm_crtc *crtc) if (s->output_mode == ROCKCHIP_OUT_MODE_AAAA && !(vop_data->feature & VOP_FEATURE_OUTPUT_RGB10)) s->output_mode = ROCKCHIP_OUT_MODE_P888; - VOP_CTRL_SET(vop, out_mode, s->output_mode); + VOP_REG_SET(vop, common, out_mode, s->output_mode); - VOP_CTRL_SET(vop, htotal_pw, (htotal << 16) | hsync_len); + VOP_REG_SET(vop, modeset, htotal_pw, (htotal << 16) | hsync_len); val = hact_st << 16; val |= hact_end; - VOP_CTRL_SET(vop, hact_st_end, val); - VOP_CTRL_SET(vop, hpost_st_end, val); + VOP_REG_SET(vop, modeset, hact_st_end, val); + VOP_REG_SET(vop, modeset, hpost_st_end, val); - VOP_CTRL_SET(vop, vtotal_pw, (vtotal << 16) | vsync_len); + VOP_REG_SET(vop, modeset, vtotal_pw, (vtotal << 16) | vsync_len); val = vact_st << 16; val |= vact_end; - VOP_CTRL_SET(vop, vact_st_end, val); - VOP_CTRL_SET(vop, vpost_st_end, val); + VOP_REG_SET(vop, modeset, vact_st_end, val); + VOP_REG_SET(vop, modeset, vpost_st_end, val); + + VOP_REG_SET(vop, intr, line_flag_num[0], vact_end); clk_set_rate(vop->dclk, adjusted_mode->clock * 1000); - VOP_CTRL_SET(vop, standby, 0); + VOP_REG_SET(vop, common, standby, 0); rockchip_drm_psr_activate(&vop->crtc); } @@ -1026,7 +986,7 @@ static void vop_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_crtc_state *old_crtc_state) { struct drm_atomic_state *old_state = old_crtc_state->state; - struct drm_plane_state *old_plane_state; + struct drm_plane_state *old_plane_state, *new_plane_state; struct vop *vop = to_vop(crtc); struct drm_plane *plane; int i; @@ -1057,14 +1017,15 @@ static void vop_crtc_atomic_flush(struct drm_crtc *crtc, } spin_unlock_irq(&crtc->dev->event_lock); - for_each_plane_in_state(old_state, plane, old_plane_state, i) { + for_each_oldnew_plane_in_state(old_state, plane, old_plane_state, + new_plane_state, i) { if (!old_plane_state->fb) continue; - if (old_plane_state->fb == plane->state->fb) + if (old_plane_state->fb == new_plane_state->fb) continue; - drm_framebuffer_reference(old_plane_state->fb); + drm_framebuffer_get(old_plane_state->fb); drm_flip_work_queue(&vop->fb_unref_work, old_plane_state->fb); set_bit(VOP_PENDING_FB_UNREF, &vop->pending); WARN_ON(drm_crtc_vblank_get(crtc) != 0); @@ -1125,16 +1086,17 @@ static void vop_crtc_destroy_state(struct drm_crtc *crtc, #ifdef CONFIG_DRM_ANALOGIX_DP static struct drm_connector *vop_get_edp_connector(struct vop *vop) { - struct drm_crtc *crtc = &vop->crtc; struct drm_connector *connector; + struct drm_connector_list_iter conn_iter; - mutex_lock(&crtc->dev->mode_config.mutex); - drm_for_each_connector(connector, crtc->dev) + drm_connector_list_iter_begin(vop->drm_dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { - mutex_unlock(&crtc->dev->mode_config.mutex); + drm_connector_list_iter_end(&conn_iter); return connector; } - mutex_unlock(&crtc->dev->mode_config.mutex); + } + drm_connector_list_iter_end(&conn_iter); return NULL; } @@ -1187,7 +1149,7 @@ static void vop_fb_unref_worker(struct drm_flip_work *work, void *val) struct drm_framebuffer *fb = val; drm_crtc_vblank_put(&vop->crtc); - drm_framebuffer_unreference(fb); + drm_framebuffer_put(fb); } static void vop_handle_vblank(struct vop *vop) @@ -1393,48 +1355,47 @@ static void vop_destroy_crtc(struct vop *vop) static int vop_initial(struct vop *vop) { const struct vop_data *vop_data = vop->data; - const struct vop_reg_data *init_table = vop_data->init_table; struct reset_control *ahb_rst; int i, ret; vop->hclk = devm_clk_get(vop->dev, "hclk_vop"); if (IS_ERR(vop->hclk)) { - dev_err(vop->dev, "failed to get hclk source\n"); + DRM_DEV_ERROR(vop->dev, "failed to get hclk source\n"); return PTR_ERR(vop->hclk); } vop->aclk = devm_clk_get(vop->dev, "aclk_vop"); if (IS_ERR(vop->aclk)) { - dev_err(vop->dev, "failed to get aclk source\n"); + DRM_DEV_ERROR(vop->dev, "failed to get aclk source\n"); return PTR_ERR(vop->aclk); } vop->dclk = devm_clk_get(vop->dev, "dclk_vop"); if (IS_ERR(vop->dclk)) { - dev_err(vop->dev, "failed to get dclk source\n"); + DRM_DEV_ERROR(vop->dev, "failed to get dclk source\n"); return PTR_ERR(vop->dclk); } ret = pm_runtime_get_sync(vop->dev); if (ret < 0) { - dev_err(vop->dev, "failed to get pm runtime: %d\n", ret); + DRM_DEV_ERROR(vop->dev, "failed to get pm runtime: %d\n", ret); return ret; } ret = clk_prepare(vop->dclk); if (ret < 0) { - dev_err(vop->dev, "failed to prepare dclk\n"); + DRM_DEV_ERROR(vop->dev, "failed to prepare dclk\n"); goto err_put_pm_runtime; } /* Enable both the hclk and aclk to setup the vop */ ret = clk_prepare_enable(vop->hclk); if (ret < 0) { - dev_err(vop->dev, "failed to prepare/enable hclk\n"); + DRM_DEV_ERROR(vop->dev, "failed to prepare/enable hclk\n"); goto err_unprepare_dclk; } ret = clk_prepare_enable(vop->aclk); if (ret < 0) { - dev_err(vop->dev, "failed to prepare/enable aclk\n"); + DRM_DEV_ERROR(vop->dev, "failed to prepare/enable aclk\n"); goto err_disable_hclk; } @@ -1443,7 +1404,7 @@ static int vop_initial(struct vop *vop) */ ahb_rst = devm_reset_control_get(vop->dev, "ahb"); if (IS_ERR(ahb_rst)) { - dev_err(vop->dev, "failed to get ahb reset\n"); + DRM_DEV_ERROR(vop->dev, "failed to get ahb reset\n"); ret = PTR_ERR(ahb_rst); goto err_disable_aclk; } @@ -1453,13 +1414,16 @@ static int vop_initial(struct vop *vop) memcpy(vop->regsbak, vop->regs, vop->len); - for (i = 0; i < vop_data->table_size; i++) - vop_writel(vop, init_table[i].offset, init_table[i].value); + VOP_REG_SET(vop, misc, global_regdone_en, 1); + VOP_REG_SET(vop, common, dsp_blank, 0); for (i = 0; i < vop_data->win_size; i++) { const struct vop_win_data *win = &vop_data->win[i]; + int channel = i * 2 + 1; + VOP_WIN_SET(vop, win, channel, (channel + 1) << 4 | channel); VOP_WIN_SET(vop, win, enable, 0); + VOP_WIN_SET(vop, win, gate, 1); } vop_cfg_done(vop); @@ -1469,7 +1433,7 @@ static int vop_initial(struct vop *vop) */ vop->dclk_rst = devm_reset_control_get(vop->dev, "dclk"); if (IS_ERR(vop->dclk_rst)) { - dev_err(vop->dev, "failed to get dclk reset\n"); + DRM_DEV_ERROR(vop->dev, "failed to get dclk reset\n"); ret = PTR_ERR(vop->dclk_rst); goto err_disable_aclk; } @@ -1515,19 +1479,16 @@ static void vop_win_init(struct vop *vop) } /** - * rockchip_drm_wait_line_flag - acqiure the give line flag event + * rockchip_drm_wait_vact_end * @crtc: CRTC to enable line flag - * @line_num: interested line number * @mstimeout: millisecond for timeout * - * Driver would hold here until the interested line flag interrupt have - * happened or timeout to wait. + * Wait for vact_end line flag irq or timeout. * * Returns: * Zero on success, negative errno on failure. */ -int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int line_num, - unsigned int mstimeout) +int rockchip_drm_wait_vact_end(struct drm_crtc *crtc, unsigned int mstimeout) { struct vop *vop = to_vop(crtc); unsigned long jiffies_left; @@ -1535,27 +1496,27 @@ int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int line_num, if (!crtc || !vop->is_enabled) return -ENODEV; - if (line_num > crtc->mode.vtotal || mstimeout <= 0) + if (mstimeout <= 0) return -EINVAL; if (vop_line_flag_irq_is_enabled(vop)) return -EBUSY; reinit_completion(&vop->line_flag_completion); - vop_line_flag_irq_enable(vop, line_num); + vop_line_flag_irq_enable(vop); jiffies_left = wait_for_completion_timeout(&vop->line_flag_completion, msecs_to_jiffies(mstimeout)); vop_line_flag_irq_disable(vop); if (jiffies_left == 0) { - dev_err(vop->dev, "Timeout waiting for IRQ\n"); + DRM_DEV_ERROR(vop->dev, "Timeout waiting for IRQ\n"); return -ETIMEDOUT; } return 0; } -EXPORT_SYMBOL(rockchip_drm_wait_line_flag); +EXPORT_SYMBOL(rockchip_drm_wait_vact_end); static int vop_bind(struct device *dev, struct device *master, void *data) { @@ -1596,7 +1557,7 @@ static int vop_bind(struct device *dev, struct device *master, void *data) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(dev, "cannot find irq for vop\n"); + DRM_DEV_ERROR(dev, "cannot find irq for vop\n"); return irq; } vop->irq = (unsigned int)irq; @@ -1622,7 +1583,8 @@ static int vop_bind(struct device *dev, struct device *master, void *data) ret = vop_initial(vop); if (ret < 0) { - dev_err(&pdev->dev, "cannot initial vop dev - err %d\n", ret); + DRM_DEV_ERROR(&pdev->dev, + "cannot initial vop dev - err %d\n", ret); goto err_disable_pm_runtime; } diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h index 9979fd0c2282..56bbd2e2a8ef 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h @@ -15,6 +15,14 @@ #ifndef _ROCKCHIP_DRM_VOP_H #define _ROCKCHIP_DRM_VOP_H +/* + * major: IP major version, used for IP structure + * minor: big feature change under same structure + */ +#define VOP_VERSION(major, minor) ((major) << 8 | (minor)) +#define VOP_MAJOR(version) ((version) >> 8) +#define VOP_MINOR(version) ((version) & 0xff) + enum vop_data_format { VOP_FMT_ARGB8888 = 0, VOP_FMT_RGB888, @@ -24,53 +32,58 @@ enum vop_data_format { VOP_FMT_YUV444SP, }; -struct vop_reg_data { - uint32_t offset; - uint32_t value; -}; - struct vop_reg { - uint32_t offset; - uint32_t shift; uint32_t mask; + uint16_t offset; + uint8_t shift; bool write_mask; + bool relaxed; }; -struct vop_ctrl { - struct vop_reg standby; - struct vop_reg data_blank; - struct vop_reg gate_en; - struct vop_reg mmu_en; - struct vop_reg rgb_en; - struct vop_reg edp_en; - struct vop_reg hdmi_en; - struct vop_reg mipi_en; - struct vop_reg dp_en; - struct vop_reg out_mode; - struct vop_reg dither_down; - struct vop_reg dither_up; - struct vop_reg pin_pol; - struct vop_reg rgb_pin_pol; - struct vop_reg hdmi_pin_pol; - struct vop_reg edp_pin_pol; - struct vop_reg mipi_pin_pol; - struct vop_reg dp_pin_pol; - +struct vop_modeset { struct vop_reg htotal_pw; struct vop_reg hact_st_end; + struct vop_reg hpost_st_end; struct vop_reg vtotal_pw; struct vop_reg vact_st_end; - struct vop_reg hpost_st_end; struct vop_reg vpost_st_end; +}; - struct vop_reg line_flag_num[2]; +struct vop_output { + struct vop_reg pin_pol; + struct vop_reg dp_pin_pol; + struct vop_reg edp_pin_pol; + struct vop_reg hdmi_pin_pol; + struct vop_reg mipi_pin_pol; + struct vop_reg rgb_pin_pol; + struct vop_reg dp_en; + struct vop_reg edp_en; + struct vop_reg hdmi_en; + struct vop_reg mipi_en; + struct vop_reg rgb_en; +}; +struct vop_common { struct vop_reg cfg_done; + struct vop_reg dsp_blank; + struct vop_reg data_blank; + struct vop_reg dither_down; + struct vop_reg dither_up; + struct vop_reg gate_en; + struct vop_reg mmu_en; + struct vop_reg out_mode; + struct vop_reg standby; +}; + +struct vop_misc { + struct vop_reg global_regdone_en; }; struct vop_intr { const int *intrs; uint32_t nintrs; + + struct vop_reg line_flag_num[2]; struct vop_reg enable; struct vop_reg clear; struct vop_reg status; @@ -115,6 +128,7 @@ struct vop_win_phy { uint32_t nformats; struct vop_reg enable; + struct vop_reg gate; struct vop_reg format; struct vop_reg rb_swap; struct vop_reg act_info; @@ -127,6 +141,7 @@ struct vop_win_phy { struct vop_reg dst_alpha_ctl; struct vop_reg src_alpha_ctl; + struct vop_reg channel; }; struct vop_win_data { @@ -136,10 +151,12 @@ struct vop_win_data { }; struct vop_data { - const struct vop_reg_data *init_table; - unsigned int table_size; - const struct vop_ctrl *ctrl; + uint32_t version; const struct vop_intr *intr; + const struct vop_common *common; + const struct vop_misc *misc; + const struct vop_modeset *modeset; + const struct vop_output *output; const struct vop_win_data *win; unsigned int win_size; @@ -282,6 +299,9 @@ static inline uint16_t scl_get_bili_dn_vskip(int src_h, int dst_h, act_height = (src_h + vskiplines - 1) / vskiplines; + if (act_height == dst_h) + return GET_SCL_FT_BILI_DN(src_h, dst_h) / vskiplines; + return GET_SCL_FT_BILI_DN(act_height, dst_h); } diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.c b/drivers/gpu/drm/rockchip/rockchip_lvds.c new file mode 100644 index 000000000000..84911bdc27d1 --- /dev/null +++ b/drivers/gpu/drm/rockchip/rockchip_lvds.c @@ -0,0 +1,586 @@ +/* + * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd + * Author: + * Mark Yao <mark.yao@rock-chips.com> + * Sandy Huang <hjc@rock-chips.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <drm/drmP.h> +#include <drm/drm_atomic_helper.h> +#include <drm/drm_crtc_helper.h> +#include <drm/drm_dp_helper.h> +#include <drm/drm_panel.h> +#include <drm/drm_of.h> + +#include <linux/component.h> +#include <linux/clk.h> +#include <linux/mfd/syscon.h> +#include <linux/of_graph.h> +#include <linux/pm_runtime.h> +#include <linux/regmap.h> +#include <linux/reset.h> + +#include "rockchip_drm_drv.h" +#include "rockchip_drm_vop.h" +#include "rockchip_lvds.h" + +#define DISPLAY_OUTPUT_RGB 0 +#define DISPLAY_OUTPUT_LVDS 1 +#define DISPLAY_OUTPUT_DUAL_LVDS 2 + +#define connector_to_lvds(c) \ + container_of(c, struct rockchip_lvds, connector) + +#define encoder_to_lvds(c) \ + container_of(c, struct rockchip_lvds, encoder) + +/** + * rockchip_lvds_soc_data - rockchip lvds Soc private data + * @ch1_offset: lvds channel 1 registe offset + * grf_soc_con6: general registe offset for LVDS contrl + * grf_soc_con7: general registe offset for LVDS contrl + * has_vop_sel: to indicate whether need to choose from different VOP. + */ +struct rockchip_lvds_soc_data { + u32 ch1_offset; + int grf_soc_con6; + int grf_soc_con7; + bool has_vop_sel; +}; + +struct rockchip_lvds { + struct device *dev; + void __iomem *regs; + struct regmap *grf; + struct clk *pclk; + const struct rockchip_lvds_soc_data *soc_data; + int output; /* rgb lvds or dual lvds output */ + int format; /* vesa or jeida format */ + struct drm_device *drm_dev; + struct drm_panel *panel; + struct drm_bridge *bridge; + struct drm_connector connector; + struct drm_encoder encoder; + struct dev_pin_info *pins; +}; + +static inline void lvds_writel(struct rockchip_lvds *lvds, u32 offset, u32 val) +{ + writel_relaxed(val, lvds->regs + offset); + if (lvds->output == DISPLAY_OUTPUT_LVDS) + return; + writel_relaxed(val, lvds->regs + offset + lvds->soc_data->ch1_offset); +} + +static inline int lvds_name_to_format(const char *s) +{ + if (strncmp(s, "jeida-18", 8) == 0) + return LVDS_JEIDA_18; + else if (strncmp(s, "jeida-24", 8) == 0) + return LVDS_JEIDA_24; + else if (strncmp(s, "vesa-24", 7) == 0) + return LVDS_VESA_24; + + return -EINVAL; +} + +static inline int lvds_name_to_output(const char *s) +{ + if (strncmp(s, "rgb", 3) == 0) + return DISPLAY_OUTPUT_RGB; + else if (strncmp(s, "lvds", 4) == 0) + return DISPLAY_OUTPUT_LVDS; + else if (strncmp(s, "duallvds", 8) == 0) + return DISPLAY_OUTPUT_DUAL_LVDS; + + return -EINVAL; +} + +static int rockchip_lvds_poweron(struct rockchip_lvds *lvds) +{ + int ret; + u32 val; + + ret = clk_enable(lvds->pclk); + if (ret < 0) { + DRM_DEV_ERROR(lvds->dev, "failed to enable lvds pclk %d\n", ret); + return ret; + } + ret = pm_runtime_get_sync(lvds->dev); + if (ret < 0) { + DRM_DEV_ERROR(lvds->dev, "failed to get pm runtime: %d\n", ret); + clk_disable(lvds->pclk); + return ret; + } + val = RK3288_LVDS_CH0_REG0_LANE4_EN | RK3288_LVDS_CH0_REG0_LANE3_EN | + RK3288_LVDS_CH0_REG0_LANE2_EN | RK3288_LVDS_CH0_REG0_LANE1_EN | + RK3288_LVDS_CH0_REG0_LANE0_EN; + if (lvds->output == DISPLAY_OUTPUT_RGB) { + val |= RK3288_LVDS_CH0_REG0_TTL_EN | + RK3288_LVDS_CH0_REG0_LANECK_EN; + lvds_writel(lvds, RK3288_LVDS_CH0_REG0, val); + lvds_writel(lvds, RK3288_LVDS_CH0_REG2, + RK3288_LVDS_PLL_FBDIV_REG2(0x46)); + lvds_writel(lvds, RK3288_LVDS_CH0_REG4, + RK3288_LVDS_CH0_REG4_LANECK_TTL_MODE | + RK3288_LVDS_CH0_REG4_LANE4_TTL_MODE | + RK3288_LVDS_CH0_REG4_LANE3_TTL_MODE | + RK3288_LVDS_CH0_REG4_LANE2_TTL_MODE | + RK3288_LVDS_CH0_REG4_LANE1_TTL_MODE | + RK3288_LVDS_CH0_REG4_LANE0_TTL_MODE); + lvds_writel(lvds, RK3288_LVDS_CH0_REG5, + RK3288_LVDS_CH0_REG5_LANECK_TTL_DATA | + RK3288_LVDS_CH0_REG5_LANE4_TTL_DATA | + RK3288_LVDS_CH0_REG5_LANE3_TTL_DATA | + RK3288_LVDS_CH0_REG5_LANE2_TTL_DATA | + RK3288_LVDS_CH0_REG5_LANE1_TTL_DATA | + RK3288_LVDS_CH0_REG5_LANE0_TTL_DATA); + } else { + val |= RK3288_LVDS_CH0_REG0_LVDS_EN | + RK3288_LVDS_CH0_REG0_LANECK_EN; + lvds_writel(lvds, RK3288_LVDS_CH0_REG0, val); + lvds_writel(lvds, RK3288_LVDS_CH0_REG1, + RK3288_LVDS_CH0_REG1_LANECK_BIAS | + RK3288_LVDS_CH0_REG1_LANE4_BIAS | + RK3288_LVDS_CH0_REG1_LANE3_BIAS | + RK3288_LVDS_CH0_REG1_LANE2_BIAS | + RK3288_LVDS_CH0_REG1_LANE1_BIAS | + RK3288_LVDS_CH0_REG1_LANE0_BIAS); + lvds_writel(lvds, RK3288_LVDS_CH0_REG2, + RK3288_LVDS_CH0_REG2_RESERVE_ON | + RK3288_LVDS_CH0_REG2_LANECK_LVDS_MODE | + RK3288_LVDS_CH0_REG2_LANE4_LVDS_MODE | + RK3288_LVDS_CH0_REG2_LANE3_LVDS_MODE | + RK3288_LVDS_CH0_REG2_LANE2_LVDS_MODE | + RK3288_LVDS_CH0_REG2_LANE1_LVDS_MODE | + RK3288_LVDS_CH0_REG2_LANE0_LVDS_MODE | + RK3288_LVDS_PLL_FBDIV_REG2(0x46)); + lvds_writel(lvds, RK3288_LVDS_CH0_REG4, 0x00); + lvds_writel(lvds, RK3288_LVDS_CH0_REG5, 0x00); + } + lvds_writel(lvds, RK3288_LVDS_CH0_REG3, RK3288_LVDS_PLL_FBDIV_REG3(0x46)); + lvds_writel(lvds, RK3288_LVDS_CH0_REGD, RK3288_LVDS_PLL_PREDIV_REGD(0x0a)); + lvds_writel(lvds, RK3288_LVDS_CH0_REG20, RK3288_LVDS_CH0_REG20_LSB); + + lvds_writel(lvds, RK3288_LVDS_CFG_REGC, RK3288_LVDS_CFG_REGC_PLL_ENABLE); + lvds_writel(lvds, RK3288_LVDS_CFG_REG21, RK3288_LVDS_CFG_REG21_TX_ENABLE); + + return 0; +} + +static void rockchip_lvds_poweroff(struct rockchip_lvds *lvds) +{ + int ret; + u32 val; + + lvds_writel(lvds, RK3288_LVDS_CFG_REG21, RK3288_LVDS_CFG_REG21_TX_ENABLE); + lvds_writel(lvds, RK3288_LVDS_CFG_REGC, RK3288_LVDS_CFG_REGC_PLL_ENABLE); + val = LVDS_DUAL | LVDS_TTL_EN | LVDS_CH0_EN | LVDS_CH1_EN | LVDS_PWRDN; + val |= val << 16; + ret = regmap_write(lvds->grf, lvds->soc_data->grf_soc_con7, val); + if (ret != 0) + DRM_DEV_ERROR(lvds->dev, "Could not write to GRF: %d\n", ret); + + pm_runtime_put(lvds->dev); + clk_disable(lvds->pclk); +} + +static const struct drm_connector_funcs rockchip_lvds_connector_funcs = { + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = drm_connector_cleanup, + .reset = drm_atomic_helper_connector_reset, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, +}; + +static int rockchip_lvds_connector_get_modes(struct drm_connector *connector) +{ + struct rockchip_lvds *lvds = connector_to_lvds(connector); + struct drm_panel *panel = lvds->panel; + + return drm_panel_get_modes(panel); +} + +static const +struct drm_connector_helper_funcs rockchip_lvds_connector_helper_funcs = { + .get_modes = rockchip_lvds_connector_get_modes, +}; + +static void rockchip_lvds_grf_config(struct drm_encoder *encoder, + struct drm_display_mode *mode) +{ + struct rockchip_lvds *lvds = encoder_to_lvds(encoder); + u8 pin_hsync = (mode->flags & DRM_MODE_FLAG_PHSYNC) ? 1 : 0; + u8 pin_dclk = (mode->flags & DRM_MODE_FLAG_PCSYNC) ? 1 : 0; + u32 val; + int ret; + + /* iomux to LCD data/sync mode */ + if (lvds->output == DISPLAY_OUTPUT_RGB) + if (lvds->pins && !IS_ERR(lvds->pins->default_state)) + pinctrl_select_state(lvds->pins->p, + lvds->pins->default_state); + val = lvds->format | LVDS_CH0_EN; + if (lvds->output == DISPLAY_OUTPUT_RGB) + val |= LVDS_TTL_EN | LVDS_CH1_EN; + else if (lvds->output == DISPLAY_OUTPUT_DUAL_LVDS) + val |= LVDS_DUAL | LVDS_CH1_EN; + + if ((mode->htotal - mode->hsync_start) & 0x01) + val |= LVDS_START_PHASE_RST_1; + + val |= (pin_dclk << 8) | (pin_hsync << 9); + val |= (0xffff << 16); + ret = regmap_write(lvds->grf, lvds->soc_data->grf_soc_con7, val); + if (ret != 0) { + DRM_DEV_ERROR(lvds->dev, "Could not write to GRF: %d\n", ret); + return; + } +} + +static int rockchip_lvds_set_vop_source(struct rockchip_lvds *lvds, + struct drm_encoder *encoder) +{ + u32 val; + int ret; + + if (!lvds->soc_data->has_vop_sel) + return 0; + + ret = drm_of_encoder_active_endpoint_id(lvds->dev->of_node, encoder); + if (ret < 0) + return ret; + + val = RK3288_LVDS_SOC_CON6_SEL_VOP_LIT << 16; + if (ret) + val |= RK3288_LVDS_SOC_CON6_SEL_VOP_LIT; + + ret = regmap_write(lvds->grf, lvds->soc_data->grf_soc_con6, val); + if (ret < 0) + return ret; + + return 0; +} + +static int +rockchip_lvds_encoder_atomic_check(struct drm_encoder *encoder, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state); + + s->output_mode = ROCKCHIP_OUT_MODE_P888; + s->output_type = DRM_MODE_CONNECTOR_LVDS; + + return 0; +} + +static void rockchip_lvds_encoder_enable(struct drm_encoder *encoder) +{ + struct rockchip_lvds *lvds = encoder_to_lvds(encoder); + struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; + int ret; + + drm_panel_prepare(lvds->panel); + ret = rockchip_lvds_poweron(lvds); + if (ret < 0) { + DRM_DEV_ERROR(lvds->dev, "failed to power on lvds: %d\n", ret); + drm_panel_unprepare(lvds->panel); + } + rockchip_lvds_grf_config(encoder, mode); + rockchip_lvds_set_vop_source(lvds, encoder); + drm_panel_enable(lvds->panel); +} + +static void rockchip_lvds_encoder_disable(struct drm_encoder *encoder) +{ + struct rockchip_lvds *lvds = encoder_to_lvds(encoder); + + drm_panel_disable(lvds->panel); + rockchip_lvds_poweroff(lvds); + drm_panel_unprepare(lvds->panel); +} + +static const +struct drm_encoder_helper_funcs rockchip_lvds_encoder_helper_funcs = { + .enable = rockchip_lvds_encoder_enable, + .disable = rockchip_lvds_encoder_disable, + .atomic_check = rockchip_lvds_encoder_atomic_check, +}; + +static const struct drm_encoder_funcs rockchip_lvds_encoder_funcs = { + .destroy = drm_encoder_cleanup, +}; + +static const struct rockchip_lvds_soc_data rk3288_lvds_data = { + .ch1_offset = 0x100, + .grf_soc_con6 = 0x025c, + .grf_soc_con7 = 0x0260, + .has_vop_sel = true, +}; + +static const struct of_device_id rockchip_lvds_dt_ids[] = { + { + .compatible = "rockchip,rk3288-lvds", + .data = &rk3288_lvds_data + }, + {} +}; +MODULE_DEVICE_TABLE(of, rockchip_lvds_dt_ids); + +static int rockchip_lvds_bind(struct device *dev, struct device *master, + void *data) +{ + struct rockchip_lvds *lvds = dev_get_drvdata(dev); + struct drm_device *drm_dev = data; + struct drm_encoder *encoder; + struct drm_connector *connector; + struct device_node *remote = NULL; + struct device_node *port, *endpoint; + int ret = 0, child_count = 0; + const char *name; + u32 endpoint_id; + + lvds->drm_dev = drm_dev; + port = of_graph_get_port_by_id(dev->of_node, 1); + if (!port) { + DRM_DEV_ERROR(dev, + "can't found port point, please init lvds panel port!\n"); + return -EINVAL; + } + for_each_child_of_node(port, endpoint) { + child_count++; + of_property_read_u32(endpoint, "reg", &endpoint_id); + ret = drm_of_find_panel_or_bridge(dev->of_node, 1, endpoint_id, + &lvds->panel, &lvds->bridge); + if (!ret) + break; + } + if (!child_count) { + DRM_DEV_ERROR(dev, "lvds port does not have any children\n"); + ret = -EINVAL; + goto err_put_port; + } else if (ret) { + DRM_DEV_ERROR(dev, "failed to find panel and bridge node\n"); + ret = -EPROBE_DEFER; + goto err_put_port; + } + if (lvds->panel) + remote = lvds->panel->dev->of_node; + else + remote = lvds->bridge->of_node; + if (of_property_read_string(dev->of_node, "rockchip,output", &name)) + /* default set it as output rgb */ + lvds->output = DISPLAY_OUTPUT_RGB; + else + lvds->output = lvds_name_to_output(name); + + if (lvds->output < 0) { + DRM_DEV_ERROR(dev, "invalid output type [%s]\n", name); + ret = lvds->output; + goto err_put_remote; + } + + if (of_property_read_string(remote, "data-mapping", &name)) + /* default set it as format vesa 18 */ + lvds->format = LVDS_VESA_18; + else + lvds->format = lvds_name_to_format(name); + + if (lvds->format < 0) { + DRM_DEV_ERROR(dev, "invalid data-mapping format [%s]\n", name); + ret = lvds->format; + goto err_put_remote; + } + + encoder = &lvds->encoder; + encoder->possible_crtcs = drm_of_find_possible_crtcs(drm_dev, + dev->of_node); + + ret = drm_encoder_init(drm_dev, encoder, &rockchip_lvds_encoder_funcs, + DRM_MODE_ENCODER_LVDS, NULL); + if (ret < 0) { + DRM_DEV_ERROR(drm_dev->dev, + "failed to initialize encoder: %d\n", ret); + goto err_put_remote; + } + + drm_encoder_helper_add(encoder, &rockchip_lvds_encoder_helper_funcs); + + if (lvds->panel) { + connector = &lvds->connector; + connector->dpms = DRM_MODE_DPMS_OFF; + ret = drm_connector_init(drm_dev, connector, + &rockchip_lvds_connector_funcs, + DRM_MODE_CONNECTOR_LVDS); + if (ret < 0) { + DRM_DEV_ERROR(drm_dev->dev, + "failed to initialize connector: %d\n", ret); + goto err_free_encoder; + } + + drm_connector_helper_add(connector, + &rockchip_lvds_connector_helper_funcs); + + ret = drm_mode_connector_attach_encoder(connector, encoder); + if (ret < 0) { + DRM_DEV_ERROR(drm_dev->dev, + "failed to attach encoder: %d\n", ret); + goto err_free_connector; + } + + ret = drm_panel_attach(lvds->panel, connector); + if (ret < 0) { + DRM_DEV_ERROR(drm_dev->dev, + "failed to attach panel: %d\n", ret); + goto err_free_connector; + } + } else { + lvds->bridge->encoder = encoder; + ret = drm_bridge_attach(encoder, lvds->bridge, NULL); + if (ret) { + DRM_DEV_ERROR(drm_dev->dev, + "failed to attach bridge: %d\n", ret); + goto err_free_encoder; + } + encoder->bridge = lvds->bridge; + } + + pm_runtime_enable(dev); + of_node_put(remote); + of_node_put(port); + + return 0; + +err_free_connector: + drm_connector_cleanup(connector); +err_free_encoder: + drm_encoder_cleanup(encoder); +err_put_remote: + of_node_put(remote); +err_put_port: + of_node_put(port); + + return ret; +} + +static void rockchip_lvds_unbind(struct device *dev, struct device *master, + void *data) +{ + struct rockchip_lvds *lvds = dev_get_drvdata(dev); + + rockchip_lvds_encoder_disable(&lvds->encoder); + if (lvds->panel) + drm_panel_detach(lvds->panel); + pm_runtime_disable(dev); + drm_connector_cleanup(&lvds->connector); + drm_encoder_cleanup(&lvds->encoder); +} + +static const struct component_ops rockchip_lvds_component_ops = { + .bind = rockchip_lvds_bind, + .unbind = rockchip_lvds_unbind, +}; + +static int rockchip_lvds_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct rockchip_lvds *lvds; + const struct of_device_id *match; + struct resource *res; + int ret; + + if (!dev->of_node) + return -ENODEV; + + lvds = devm_kzalloc(&pdev->dev, sizeof(*lvds), GFP_KERNEL); + if (!lvds) + return -ENOMEM; + + lvds->dev = dev; + match = of_match_node(rockchip_lvds_dt_ids, dev->of_node); + if (!match) + return -ENODEV; + lvds->soc_data = match->data; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + lvds->regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(lvds->regs)) + return PTR_ERR(lvds->regs); + + lvds->pclk = devm_clk_get(&pdev->dev, "pclk_lvds"); + if (IS_ERR(lvds->pclk)) { + DRM_DEV_ERROR(dev, "could not get pclk_lvds\n"); + return PTR_ERR(lvds->pclk); + } + + lvds->pins = devm_kzalloc(lvds->dev, sizeof(*lvds->pins), + GFP_KERNEL); + if (!lvds->pins) + return -ENOMEM; + + lvds->pins->p = devm_pinctrl_get(lvds->dev); + if (IS_ERR(lvds->pins->p)) { + DRM_DEV_ERROR(dev, "no pinctrl handle\n"); + devm_kfree(lvds->dev, lvds->pins); + lvds->pins = NULL; + } else { + lvds->pins->default_state = + pinctrl_lookup_state(lvds->pins->p, "lcdc"); + if (IS_ERR(lvds->pins->default_state)) { + DRM_DEV_ERROR(dev, "no default pinctrl state\n"); + devm_kfree(lvds->dev, lvds->pins); + lvds->pins = NULL; + } + } + + lvds->grf = syscon_regmap_lookup_by_phandle(dev->of_node, + "rockchip,grf"); + if (IS_ERR(lvds->grf)) { + DRM_DEV_ERROR(dev, "missing rockchip,grf property\n"); + return PTR_ERR(lvds->grf); + } + + dev_set_drvdata(dev, lvds); + + ret = clk_prepare(lvds->pclk); + if (ret < 0) { + DRM_DEV_ERROR(dev, "failed to prepare pclk_lvds\n"); + return ret; + } + ret = component_add(&pdev->dev, &rockchip_lvds_component_ops); + if (ret < 0) { + DRM_DEV_ERROR(dev, "failed to add component\n"); + clk_unprepare(lvds->pclk); + } + + return ret; +} + +static int rockchip_lvds_remove(struct platform_device *pdev) +{ + struct rockchip_lvds *lvds = dev_get_drvdata(&pdev->dev); + + component_del(&pdev->dev, &rockchip_lvds_component_ops); + clk_unprepare(lvds->pclk); + + return 0; +} + +struct platform_driver rockchip_lvds_driver = { + .probe = rockchip_lvds_probe, + .remove = rockchip_lvds_remove, + .driver = { + .name = "rockchip-lvds", + .of_match_table = of_match_ptr(rockchip_lvds_dt_ids), + }, +}; diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.h b/drivers/gpu/drm/rockchip/rockchip_lvds.h new file mode 100644 index 000000000000..15810b737809 --- /dev/null +++ b/drivers/gpu/drm/rockchip/rockchip_lvds.h @@ -0,0 +1,114 @@ +/* + * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd + * Author: + * Sandy Huang <hjc@rock-chips.com> + * Mark Yao <mark.yao@rock-chips.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _ROCKCHIP_LVDS_ +#define _ROCKCHIP_LVDS_ + +#define RK3288_LVDS_CH0_REG0 0x00 +#define RK3288_LVDS_CH0_REG0_LVDS_EN BIT(7) +#define RK3288_LVDS_CH0_REG0_TTL_EN BIT(6) +#define RK3288_LVDS_CH0_REG0_LANECK_EN BIT(5) +#define RK3288_LVDS_CH0_REG0_LANE4_EN BIT(4) +#define RK3288_LVDS_CH0_REG0_LANE3_EN BIT(3) +#define RK3288_LVDS_CH0_REG0_LANE2_EN BIT(2) +#define RK3288_LVDS_CH0_REG0_LANE1_EN BIT(1) +#define RK3288_LVDS_CH0_REG0_LANE0_EN BIT(0) + +#define RK3288_LVDS_CH0_REG1 0x04 +#define RK3288_LVDS_CH0_REG1_LANECK_BIAS BIT(5) +#define RK3288_LVDS_CH0_REG1_LANE4_BIAS BIT(4) +#define RK3288_LVDS_CH0_REG1_LANE3_BIAS BIT(3) +#define RK3288_LVDS_CH0_REG1_LANE2_BIAS BIT(2) +#define RK3288_LVDS_CH0_REG1_LANE1_BIAS BIT(1) +#define RK3288_LVDS_CH0_REG1_LANE0_BIAS BIT(0) + +#define RK3288_LVDS_CH0_REG2 0x08 +#define RK3288_LVDS_CH0_REG2_RESERVE_ON BIT(7) +#define RK3288_LVDS_CH0_REG2_LANECK_LVDS_MODE BIT(6) +#define RK3288_LVDS_CH0_REG2_LANE4_LVDS_MODE BIT(5) +#define RK3288_LVDS_CH0_REG2_LANE3_LVDS_MODE BIT(4) +#define RK3288_LVDS_CH0_REG2_LANE2_LVDS_MODE BIT(3) +#define RK3288_LVDS_CH0_REG2_LANE1_LVDS_MODE BIT(2) +#define RK3288_LVDS_CH0_REG2_LANE0_LVDS_MODE BIT(1) +#define RK3288_LVDS_CH0_REG2_PLL_FBDIV8 BIT(0) + +#define RK3288_LVDS_CH0_REG3 0x0c +#define RK3288_LVDS_CH0_REG3_PLL_FBDIV_MASK 0xff + +#define RK3288_LVDS_CH0_REG4 0x10 +#define RK3288_LVDS_CH0_REG4_LANECK_TTL_MODE BIT(5) +#define RK3288_LVDS_CH0_REG4_LANE4_TTL_MODE BIT(4) +#define RK3288_LVDS_CH0_REG4_LANE3_TTL_MODE BIT(3) +#define RK3288_LVDS_CH0_REG4_LANE2_TTL_MODE BIT(2) +#define RK3288_LVDS_CH0_REG4_LANE1_TTL_MODE BIT(1) +#define RK3288_LVDS_CH0_REG4_LANE0_TTL_MODE BIT(0) + +#define RK3288_LVDS_CH0_REG5 0x14 +#define RK3288_LVDS_CH0_REG5_LANECK_TTL_DATA BIT(5) +#define RK3288_LVDS_CH0_REG5_LANE4_TTL_DATA BIT(4) +#define RK3288_LVDS_CH0_REG5_LANE3_TTL_DATA BIT(3) +#define RK3288_LVDS_CH0_REG5_LANE2_TTL_DATA BIT(2) +#define RK3288_LVDS_CH0_REG5_LANE1_TTL_DATA BIT(1) +#define RK3288_LVDS_CH0_REG5_LANE0_TTL_DATA BIT(0) + +#define RK3288_LVDS_CFG_REGC 0x30 +#define RK3288_LVDS_CFG_REGC_PLL_ENABLE 0x00 +#define RK3288_LVDS_CFG_REGC_PLL_DISABLE 0xff + +#define RK3288_LVDS_CH0_REGD 0x34 +#define RK3288_LVDS_CH0_REGD_PLL_PREDIV_MASK 0x1f + +#define RK3288_LVDS_CH0_REG20 0x80 +#define RK3288_LVDS_CH0_REG20_MSB 0x45 +#define RK3288_LVDS_CH0_REG20_LSB 0x44 + +#define RK3288_LVDS_CFG_REG21 0x84 +#define RK3288_LVDS_CFG_REG21_TX_ENABLE 0x92 +#define RK3288_LVDS_CFG_REG21_TX_DISABLE 0x00 +#define RK3288_LVDS_CH1_OFFSET 0x100 + +/* fbdiv value is split over 2 registers, with bit8 in reg2 */ +#define RK3288_LVDS_PLL_FBDIV_REG2(_fbd) \ + (_fbd & BIT(8) ? RK3288_LVDS_CH0_REG2_PLL_FBDIV8 : 0) +#define RK3288_LVDS_PLL_FBDIV_REG3(_fbd) \ + (_fbd & RK3288_LVDS_CH0_REG3_PLL_FBDIV_MASK) +#define RK3288_LVDS_PLL_PREDIV_REGD(_pd) \ + (_pd & RK3288_LVDS_CH0_REGD_PLL_PREDIV_MASK) + +#define RK3288_LVDS_SOC_CON6_SEL_VOP_LIT BIT(3) + +#define LVDS_FMT_MASK (0x07 << 16) +#define LVDS_MSB BIT(3) +#define LVDS_DUAL BIT(4) +#define LVDS_FMT_1 BIT(5) +#define LVDS_TTL_EN BIT(6) +#define LVDS_START_PHASE_RST_1 BIT(7) +#define LVDS_DCLK_INV BIT(8) +#define LVDS_CH0_EN BIT(11) +#define LVDS_CH1_EN BIT(12) +#define LVDS_PWRDN BIT(15) + +#define LVDS_24BIT (0 << 1) +#define LVDS_18BIT (1 << 1) +#define LVDS_FORMAT_VESA (0 << 0) +#define LVDS_FORMAT_JEIDA (1 << 0) + +#define LVDS_VESA_24 0 +#define LVDS_JEIDA_24 1 +#define LVDS_VESA_18 2 +#define LVDS_JEIDA_18 3 + +#endif /* _ROCKCHIP_LVDS_ */ diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c index bafd698a28b1..4a39049e901a 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c @@ -20,17 +20,23 @@ #include "rockchip_drm_vop.h" #include "rockchip_vop_reg.h" -#define VOP_REG(off, _mask, s) \ - {.offset = off, \ +#define _VOP_REG(off, _mask, _shift, _write_mask, _relaxed) \ + { \ + .offset = off, \ .mask = _mask, \ - .shift = s, \ - .write_mask = false,} + .shift = _shift, \ + .write_mask = _write_mask, \ + .relaxed = _relaxed, \ + } -#define VOP_REG_MASK(off, _mask, s) \ - {.offset = off, \ - .mask = _mask, \ - .shift = s, \ - .write_mask = true,} +#define VOP_REG(off, _mask, _shift) \ + _VOP_REG(off, _mask, _shift, false, true) + +#define VOP_REG_SYNC(off, _mask, _shift) \ + _VOP_REG(off, _mask, _shift, false, false) + +#define VOP_REG_MASK_SYNC(off, _mask, _shift) \ + _VOP_REG(off, _mask, _shift, true, false) static const uint32_t formats_win_full[] = { DRM_FORMAT_XRGB8888, @@ -110,32 +116,35 @@ static const int rk3036_vop_intrs[] = { static const struct vop_intr rk3036_intr = { .intrs = rk3036_vop_intrs, .nintrs = ARRAY_SIZE(rk3036_vop_intrs), - .status = VOP_REG(RK3036_INT_STATUS, 0xf, 0), - .enable = VOP_REG(RK3036_INT_STATUS, 0xf, 4), - .clear = VOP_REG(RK3036_INT_STATUS, 0xf, 8), + .line_flag_num[0] = VOP_REG(RK3036_INT_STATUS, 0xfff, 12), + .status = VOP_REG_SYNC(RK3036_INT_STATUS, 0xf, 0), + .enable = VOP_REG_SYNC(RK3036_INT_STATUS, 0xf, 4), + .clear = VOP_REG_SYNC(RK3036_INT_STATUS, 0xf, 8), }; -static const struct vop_ctrl rk3036_ctrl_data = { - .standby = VOP_REG(RK3036_SYS_CTRL, 0x1, 30), - .out_mode = VOP_REG(RK3036_DSP_CTRL0, 0xf, 0), - .pin_pol = VOP_REG(RK3036_DSP_CTRL0, 0xf, 4), +static const struct vop_modeset rk3036_modeset = { .htotal_pw = VOP_REG(RK3036_DSP_HTOTAL_HS_END, 0x1fff1fff, 0), .hact_st_end = VOP_REG(RK3036_DSP_HACT_ST_END, 0x1fff1fff, 0), .vtotal_pw = VOP_REG(RK3036_DSP_VTOTAL_VS_END, 0x1fff1fff, 0), .vact_st_end = VOP_REG(RK3036_DSP_VACT_ST_END, 0x1fff1fff, 0), - .line_flag_num[0] = VOP_REG(RK3036_INT_STATUS, 0xfff, 12), - .cfg_done = VOP_REG(RK3036_REG_CFG_DONE, 0x1, 0), }; -static const struct vop_reg_data rk3036_vop_init_reg_table[] = { - {RK3036_DSP_CTRL1, 0x00000000}, +static const struct vop_output rk3036_output = { + .pin_pol = VOP_REG(RK3036_DSP_CTRL0, 0xf, 4), +}; + +static const struct vop_common rk3036_common = { + .standby = VOP_REG_SYNC(RK3036_SYS_CTRL, 0x1, 30), + .out_mode = VOP_REG(RK3036_DSP_CTRL0, 0xf, 0), + .dsp_blank = VOP_REG(RK3036_DSP_CTRL1, 0x1, 24), + .cfg_done = VOP_REG_SYNC(RK3036_REG_CFG_DONE, 0x1, 0), }; static const struct vop_data rk3036_vop = { - .init_table = rk3036_vop_init_reg_table, - .table_size = ARRAY_SIZE(rk3036_vop_init_reg_table), - .ctrl = &rk3036_ctrl_data, .intr = &rk3036_intr, + .common = &rk3036_common, + .modeset = &rk3036_modeset, + .output = &rk3036_output, .win = rk3036_vop_win_data, .win_size = ARRAY_SIZE(rk3036_vop_win_data), }; @@ -188,12 +197,14 @@ static const struct vop_win_phy rk3288_win01_data = { .uv_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 16), .src_alpha_ctl = VOP_REG(RK3288_WIN0_SRC_ALPHA_CTRL, 0xff, 0), .dst_alpha_ctl = VOP_REG(RK3288_WIN0_DST_ALPHA_CTRL, 0xff, 0), + .channel = VOP_REG(RK3288_WIN0_CTRL2, 0xff, 0), }; static const struct vop_win_phy rk3288_win23_data = { .data_formats = formats_win_lite, .nformats = ARRAY_SIZE(formats_win_lite), - .enable = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 0), + .enable = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 4), + .gate = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 0), .format = VOP_REG(RK3288_WIN2_CTRL0, 0x7, 1), .rb_swap = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 12), .dsp_info = VOP_REG(RK3288_WIN2_DSP_INFO0, 0x0fff0fff, 0), @@ -204,40 +215,33 @@ static const struct vop_win_phy rk3288_win23_data = { .dst_alpha_ctl = VOP_REG(RK3288_WIN2_DST_ALPHA_CTRL, 0xff, 0), }; -static const struct vop_ctrl rk3288_ctrl_data = { - .standby = VOP_REG(RK3288_SYS_CTRL, 0x1, 22), - .gate_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 23), - .mmu_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 20), - .rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12), - .hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13), - .edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14), - .mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15), - .dither_down = VOP_REG(RK3288_DSP_CTRL1, 0xf, 1), - .dither_up = VOP_REG(RK3288_DSP_CTRL1, 0x1, 6), - .data_blank = VOP_REG(RK3288_DSP_CTRL0, 0x1, 19), - .out_mode = VOP_REG(RK3288_DSP_CTRL0, 0xf, 0), - .pin_pol = VOP_REG(RK3288_DSP_CTRL0, 0xf, 4), +static const struct vop_modeset rk3288_modeset = { .htotal_pw = VOP_REG(RK3288_DSP_HTOTAL_HS_END, 0x1fff1fff, 0), .hact_st_end = VOP_REG(RK3288_DSP_HACT_ST_END, 0x1fff1fff, 0), .vtotal_pw = VOP_REG(RK3288_DSP_VTOTAL_VS_END, 0x1fff1fff, 0), .vact_st_end = VOP_REG(RK3288_DSP_VACT_ST_END, 0x1fff1fff, 0), .hpost_st_end = VOP_REG(RK3288_POST_DSP_HACT_INFO, 0x1fff1fff, 0), .vpost_st_end = VOP_REG(RK3288_POST_DSP_VACT_INFO, 0x1fff1fff, 0), - .line_flag_num[0] = VOP_REG(RK3288_INTR_CTRL0, 0x1fff, 12), - .cfg_done = VOP_REG(RK3288_REG_CFG_DONE, 0x1, 0), }; -static const struct vop_reg_data rk3288_init_reg_table[] = { - {RK3288_SYS_CTRL, 0x00c00000}, - {RK3288_DSP_CTRL0, 0x00000000}, - {RK3288_WIN0_CTRL0, 0x00000080}, - {RK3288_WIN1_CTRL0, 0x00000080}, - /* TODO: Win2/3 support multiple area function, but we haven't found - * a suitable way to use it yet, so let's just use them as other windows - * with only area 0 enabled. - */ - {RK3288_WIN2_CTRL0, 0x00000010}, - {RK3288_WIN3_CTRL0, 0x00000010}, +static const struct vop_output rk3288_output = { + .pin_pol = VOP_REG(RK3288_DSP_CTRL0, 0xf, 4), + .rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12), + .hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13), + .edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14), + .mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15), +}; + +static const struct vop_common rk3288_common = { + .standby = VOP_REG_SYNC(RK3288_SYS_CTRL, 0x1, 22), + .gate_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 23), + .mmu_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 20), + .dither_down = VOP_REG(RK3288_DSP_CTRL1, 0xf, 1), + .dither_up = VOP_REG(RK3288_DSP_CTRL1, 0x1, 6), + .data_blank = VOP_REG(RK3288_DSP_CTRL0, 0x1, 19), + .dsp_blank = VOP_REG(RK3288_DSP_CTRL0, 0x3, 18), + .out_mode = VOP_REG(RK3288_DSP_CTRL0, 0xf, 0), + .cfg_done = VOP_REG_SYNC(RK3288_REG_CFG_DONE, 0x1, 0), }; /* @@ -267,50 +271,24 @@ static const int rk3288_vop_intrs[] = { static const struct vop_intr rk3288_vop_intr = { .intrs = rk3288_vop_intrs, .nintrs = ARRAY_SIZE(rk3288_vop_intrs), + .line_flag_num[0] = VOP_REG(RK3288_INTR_CTRL0, 0x1fff, 12), .status = VOP_REG(RK3288_INTR_CTRL0, 0xf, 0), .enable = VOP_REG(RK3288_INTR_CTRL0, 0xf, 4), .clear = VOP_REG(RK3288_INTR_CTRL0, 0xf, 8), }; static const struct vop_data rk3288_vop = { - .init_table = rk3288_init_reg_table, - .table_size = ARRAY_SIZE(rk3288_init_reg_table), + .version = VOP_VERSION(3, 1), .feature = VOP_FEATURE_OUTPUT_RGB10, .intr = &rk3288_vop_intr, - .ctrl = &rk3288_ctrl_data, + .common = &rk3288_common, + .modeset = &rk3288_modeset, + .output = &rk3288_output, .win = rk3288_vop_win_data, .win_size = ARRAY_SIZE(rk3288_vop_win_data), }; -static const struct vop_ctrl rk3399_ctrl_data = { - .standby = VOP_REG(RK3399_SYS_CTRL, 0x1, 22), - .gate_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 23), - .dp_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 11), - .rgb_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 12), - .hdmi_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 13), - .edp_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 14), - .mipi_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 15), - .dither_down = VOP_REG(RK3399_DSP_CTRL1, 0xf, 1), - .dither_up = VOP_REG(RK3399_DSP_CTRL1, 0x1, 6), - .data_blank = VOP_REG(RK3399_DSP_CTRL0, 0x1, 19), - .out_mode = VOP_REG(RK3399_DSP_CTRL0, 0xf, 0), - .rgb_pin_pol = VOP_REG(RK3399_DSP_CTRL1, 0xf, 16), - .dp_pin_pol = VOP_REG(RK3399_DSP_CTRL1, 0xf, 16), - .hdmi_pin_pol = VOP_REG(RK3399_DSP_CTRL1, 0xf, 20), - .edp_pin_pol = VOP_REG(RK3399_DSP_CTRL1, 0xf, 24), - .mipi_pin_pol = VOP_REG(RK3399_DSP_CTRL1, 0xf, 28), - .htotal_pw = VOP_REG(RK3399_DSP_HTOTAL_HS_END, 0x1fff1fff, 0), - .hact_st_end = VOP_REG(RK3399_DSP_HACT_ST_END, 0x1fff1fff, 0), - .vtotal_pw = VOP_REG(RK3399_DSP_VTOTAL_VS_END, 0x1fff1fff, 0), - .vact_st_end = VOP_REG(RK3399_DSP_VACT_ST_END, 0x1fff1fff, 0), - .hpost_st_end = VOP_REG(RK3399_POST_DSP_HACT_INFO, 0x1fff1fff, 0), - .vpost_st_end = VOP_REG(RK3399_POST_DSP_VACT_INFO, 0x1fff1fff, 0), - .line_flag_num[0] = VOP_REG(RK3399_LINE_FLAG, 0xffff, 0), - .line_flag_num[1] = VOP_REG(RK3399_LINE_FLAG, 0xffff, 16), - .cfg_done = VOP_REG_MASK(RK3399_REG_CFG_DONE, 0x1, 0), -}; - -static const int rk3399_vop_intrs[] = { +static const int rk3368_vop_intrs[] = { FS_INTR, 0, 0, LINE_FLAG_INTR, @@ -320,69 +298,232 @@ static const int rk3399_vop_intrs[] = { DSP_HOLD_VALID_INTR, }; -static const struct vop_intr rk3399_vop_intr = { - .intrs = rk3399_vop_intrs, - .nintrs = ARRAY_SIZE(rk3399_vop_intrs), - .status = VOP_REG_MASK(RK3399_INTR_STATUS0, 0xffff, 0), - .enable = VOP_REG_MASK(RK3399_INTR_EN0, 0xffff, 0), - .clear = VOP_REG_MASK(RK3399_INTR_CLEAR0, 0xffff, 0), +static const struct vop_intr rk3368_vop_intr = { + .intrs = rk3368_vop_intrs, + .nintrs = ARRAY_SIZE(rk3368_vop_intrs), + .line_flag_num[0] = VOP_REG(RK3368_LINE_FLAG, 0xffff, 0), + .line_flag_num[1] = VOP_REG(RK3368_LINE_FLAG, 0xffff, 16), + .status = VOP_REG_MASK_SYNC(RK3368_INTR_STATUS, 0x3fff, 0), + .enable = VOP_REG_MASK_SYNC(RK3368_INTR_EN, 0x3fff, 0), + .clear = VOP_REG_MASK_SYNC(RK3368_INTR_CLEAR, 0x3fff, 0), }; -static const struct vop_reg_data rk3399_init_reg_table[] = { - {RK3399_SYS_CTRL, 0x2000f800}, - {RK3399_DSP_CTRL0, 0x00000000}, - {RK3399_WIN0_CTRL0, 0x00000080}, - {RK3399_WIN1_CTRL0, 0x00000080}, - /* TODO: Win2/3 support multiple area function, but we haven't found - * a suitable way to use it yet, so let's just use them as other windows - * with only area 0 enabled. - */ - {RK3399_WIN2_CTRL0, 0x00000010}, - {RK3399_WIN3_CTRL0, 0x00000010}, +static const struct vop_win_phy rk3368_win23_data = { + .data_formats = formats_win_lite, + .nformats = ARRAY_SIZE(formats_win_lite), + .gate = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 0), + .enable = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 4), + .format = VOP_REG(RK3368_WIN2_CTRL0, 0x3, 5), + .rb_swap = VOP_REG(RK3368_WIN2_CTRL0, 0x1, 20), + .dsp_info = VOP_REG(RK3368_WIN2_DSP_INFO0, 0x0fff0fff, 0), + .dsp_st = VOP_REG(RK3368_WIN2_DSP_ST0, 0x1fff1fff, 0), + .yrgb_mst = VOP_REG(RK3368_WIN2_MST0, 0xffffffff, 0), + .yrgb_vir = VOP_REG(RK3368_WIN2_VIR0_1, 0x1fff, 0), + .src_alpha_ctl = VOP_REG(RK3368_WIN2_SRC_ALPHA_CTRL, 0xff, 0), + .dst_alpha_ctl = VOP_REG(RK3368_WIN2_DST_ALPHA_CTRL, 0xff, 0), +}; + +static const struct vop_win_data rk3368_vop_win_data[] = { + { .base = 0x00, .phy = &rk3288_win01_data, + .type = DRM_PLANE_TYPE_PRIMARY }, + { .base = 0x40, .phy = &rk3288_win01_data, + .type = DRM_PLANE_TYPE_OVERLAY }, + { .base = 0x00, .phy = &rk3368_win23_data, + .type = DRM_PLANE_TYPE_OVERLAY }, + { .base = 0x50, .phy = &rk3368_win23_data, + .type = DRM_PLANE_TYPE_CURSOR }, +}; + +static const struct vop_output rk3368_output = { + .rgb_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 16), + .hdmi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 20), + .edp_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 24), + .mipi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 28), + .rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12), + .hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13), + .edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14), + .mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15), +}; + +static const struct vop_misc rk3368_misc = { + .global_regdone_en = VOP_REG(RK3368_SYS_CTRL, 0x1, 11), +}; + +static const struct vop_data rk3368_vop = { + .version = VOP_VERSION(3, 2), + .intr = &rk3368_vop_intr, + .common = &rk3288_common, + .modeset = &rk3288_modeset, + .output = &rk3368_output, + .misc = &rk3368_misc, + .win = rk3368_vop_win_data, + .win_size = ARRAY_SIZE(rk3368_vop_win_data), +}; + +static const struct vop_intr rk3366_vop_intr = { + .intrs = rk3368_vop_intrs, + .nintrs = ARRAY_SIZE(rk3368_vop_intrs), + .line_flag_num[0] = VOP_REG(RK3366_LINE_FLAG, 0xffff, 0), + .line_flag_num[1] = VOP_REG(RK3366_LINE_FLAG, 0xffff, 16), + .status = VOP_REG_MASK_SYNC(RK3366_INTR_STATUS0, 0xffff, 0), + .enable = VOP_REG_MASK_SYNC(RK3366_INTR_EN0, 0xffff, 0), + .clear = VOP_REG_MASK_SYNC(RK3366_INTR_CLEAR0, 0xffff, 0), +}; + +static const struct vop_data rk3366_vop = { + .version = VOP_VERSION(3, 4), + .intr = &rk3366_vop_intr, + .common = &rk3288_common, + .modeset = &rk3288_modeset, + .output = &rk3368_output, + .misc = &rk3368_misc, + .win = rk3368_vop_win_data, + .win_size = ARRAY_SIZE(rk3368_vop_win_data), +}; + +static const struct vop_output rk3399_output = { + .dp_pin_pol = VOP_REG(RK3399_DSP_CTRL1, 0xf, 16), + .rgb_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 16), + .hdmi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 20), + .edp_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 24), + .mipi_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 28), + .dp_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 11), + .rgb_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 12), + .hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13), + .edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14), + .mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15), }; static const struct vop_data rk3399_vop_big = { - .init_table = rk3399_init_reg_table, - .table_size = ARRAY_SIZE(rk3399_init_reg_table), + .version = VOP_VERSION(3, 5), .feature = VOP_FEATURE_OUTPUT_RGB10, - .intr = &rk3399_vop_intr, - .ctrl = &rk3399_ctrl_data, - /* - * rk3399 vop big windows register layout is same as rk3288. - */ - .win = rk3288_vop_win_data, - .win_size = ARRAY_SIZE(rk3288_vop_win_data), + .intr = &rk3366_vop_intr, + .common = &rk3288_common, + .modeset = &rk3288_modeset, + .output = &rk3399_output, + .misc = &rk3368_misc, + .win = rk3368_vop_win_data, + .win_size = ARRAY_SIZE(rk3368_vop_win_data), }; static const struct vop_win_data rk3399_vop_lit_win_data[] = { { .base = 0x00, .phy = &rk3288_win01_data, .type = DRM_PLANE_TYPE_PRIMARY }, - { .base = 0x00, .phy = &rk3288_win23_data, + { .base = 0x00, .phy = &rk3368_win23_data, .type = DRM_PLANE_TYPE_CURSOR}, }; static const struct vop_data rk3399_vop_lit = { - .init_table = rk3399_init_reg_table, - .table_size = ARRAY_SIZE(rk3399_init_reg_table), - .intr = &rk3399_vop_intr, - .ctrl = &rk3399_ctrl_data, - /* - * rk3399 vop lit windows register layout is same as rk3288, - * but cut off the win1 and win3 windows. - */ + .version = VOP_VERSION(3, 6), + .intr = &rk3366_vop_intr, + .common = &rk3288_common, + .modeset = &rk3288_modeset, + .output = &rk3399_output, + .misc = &rk3368_misc, .win = rk3399_vop_lit_win_data, .win_size = ARRAY_SIZE(rk3399_vop_lit_win_data), }; +static const struct vop_win_data rk3228_vop_win_data[] = { + { .base = 0x00, .phy = &rk3288_win01_data, + .type = DRM_PLANE_TYPE_PRIMARY }, + { .base = 0x40, .phy = &rk3288_win01_data, + .type = DRM_PLANE_TYPE_CURSOR }, +}; + +static const struct vop_data rk3228_vop = { + .version = VOP_VERSION(3, 7), + .feature = VOP_FEATURE_OUTPUT_RGB10, + .intr = &rk3366_vop_intr, + .common = &rk3288_common, + .modeset = &rk3288_modeset, + .output = &rk3399_output, + .misc = &rk3368_misc, + .win = rk3228_vop_win_data, + .win_size = ARRAY_SIZE(rk3228_vop_win_data), +}; + +static const struct vop_modeset rk3328_modeset = { + .htotal_pw = VOP_REG(RK3328_DSP_HTOTAL_HS_END, 0x1fff1fff, 0), + .hact_st_end = VOP_REG(RK3328_DSP_HACT_ST_END, 0x1fff1fff, 0), + .vtotal_pw = VOP_REG(RK3328_DSP_VTOTAL_VS_END, 0x1fff1fff, 0), + .vact_st_end = VOP_REG(RK3328_DSP_VACT_ST_END, 0x1fff1fff, 0), + .hpost_st_end = VOP_REG(RK3328_POST_DSP_HACT_INFO, 0x1fff1fff, 0), + .vpost_st_end = VOP_REG(RK3328_POST_DSP_VACT_INFO, 0x1fff1fff, 0), +}; + +static const struct vop_output rk3328_output = { + .rgb_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 12), + .hdmi_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 13), + .edp_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 14), + .mipi_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 15), + .rgb_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0xf, 16), + .hdmi_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0xf, 20), + .edp_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0xf, 24), + .mipi_pin_pol = VOP_REG(RK3328_DSP_CTRL1, 0xf, 28), +}; + +static const struct vop_misc rk3328_misc = { + .global_regdone_en = VOP_REG(RK3328_SYS_CTRL, 0x1, 11), +}; + +static const struct vop_common rk3328_common = { + .standby = VOP_REG_SYNC(RK3328_SYS_CTRL, 0x1, 22), + .dither_down = VOP_REG(RK3328_DSP_CTRL1, 0xf, 1), + .dither_up = VOP_REG(RK3328_DSP_CTRL1, 0x1, 6), + .dsp_blank = VOP_REG(RK3328_DSP_CTRL0, 0x3, 18), + .out_mode = VOP_REG(RK3328_DSP_CTRL0, 0xf, 0), + .cfg_done = VOP_REG_SYNC(RK3328_REG_CFG_DONE, 0x1, 0), +}; + +static const struct vop_intr rk3328_vop_intr = { + .intrs = rk3368_vop_intrs, + .nintrs = ARRAY_SIZE(rk3368_vop_intrs), + .line_flag_num[0] = VOP_REG(RK3328_LINE_FLAG, 0xffff, 0), + .line_flag_num[1] = VOP_REG(RK3328_LINE_FLAG, 0xffff, 16), + .status = VOP_REG_MASK_SYNC(RK3328_INTR_STATUS0, 0xffff, 0), + .enable = VOP_REG_MASK_SYNC(RK3328_INTR_EN0, 0xffff, 0), + .clear = VOP_REG_MASK_SYNC(RK3328_INTR_CLEAR0, 0xffff, 0), +}; + +static const struct vop_win_data rk3328_vop_win_data[] = { + { .base = 0xd0, .phy = &rk3288_win01_data, + .type = DRM_PLANE_TYPE_PRIMARY }, + { .base = 0x1d0, .phy = &rk3288_win01_data, + .type = DRM_PLANE_TYPE_OVERLAY }, + { .base = 0x2d0, .phy = &rk3288_win01_data, + .type = DRM_PLANE_TYPE_CURSOR }, +}; + +static const struct vop_data rk3328_vop = { + .version = VOP_VERSION(3, 8), + .feature = VOP_FEATURE_OUTPUT_RGB10, + .intr = &rk3328_vop_intr, + .common = &rk3328_common, + .modeset = &rk3328_modeset, + .output = &rk3328_output, + .misc = &rk3328_misc, + .win = rk3328_vop_win_data, + .win_size = ARRAY_SIZE(rk3328_vop_win_data), +}; + static const struct of_device_id vop_driver_dt_match[] = { { .compatible = "rockchip,rk3036-vop", .data = &rk3036_vop }, { .compatible = "rockchip,rk3288-vop", .data = &rk3288_vop }, + { .compatible = "rockchip,rk3368-vop", + .data = &rk3368_vop }, + { .compatible = "rockchip,rk3366-vop", + .data = &rk3366_vop }, { .compatible = "rockchip,rk3399-vop-big", .data = &rk3399_vop_big }, { .compatible = "rockchip,rk3399-vop-lit", .data = &rk3399_vop_lit }, + { .compatible = "rockchip,rk3228-vop", + .data = &rk3228_vop }, + { .compatible = "rockchip,rk3328-vop", + .data = &rk3328_vop }, {}, }; MODULE_DEVICE_TABLE(of, vop_driver_dt_match); @@ -392,7 +533,7 @@ static int vop_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; if (!dev->of_node) { - dev_err(dev, "can't find vop devices\n"); + DRM_DEV_ERROR(dev, "can't find vop devices\n"); return -ENODEV; } diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.h b/drivers/gpu/drm/rockchip/rockchip_vop_reg.h index cd197260ece5..4a4799ff65de 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.h +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.h @@ -41,6 +41,7 @@ #define RK3288_WIN0_SRC_ALPHA_CTRL 0x0060 #define RK3288_WIN0_DST_ALPHA_CTRL 0x0064 #define RK3288_WIN0_FADING_CTRL 0x0068 +#define RK3288_WIN0_CTRL2 0x006c /* win1 register */ #define RK3288_WIN1_CTRL0 0x0070 @@ -122,6 +123,717 @@ #define RK3288_DSP_VACT_ST_END_F1 0x019c /* register definition end */ +/* rk3368 register definition */ +#define RK3368_REG_CFG_DONE 0x0000 +#define RK3368_VERSION_INFO 0x0004 +#define RK3368_SYS_CTRL 0x0008 +#define RK3368_SYS_CTRL1 0x000c +#define RK3368_DSP_CTRL0 0x0010 +#define RK3368_DSP_CTRL1 0x0014 +#define RK3368_DSP_BG 0x0018 +#define RK3368_MCU_CTRL 0x001c +#define RK3368_LINE_FLAG 0x0020 +#define RK3368_INTR_EN 0x0024 +#define RK3368_INTR_CLEAR 0x0028 +#define RK3368_INTR_STATUS 0x002c +#define RK3368_WIN0_CTRL0 0x0030 +#define RK3368_WIN0_CTRL1 0x0034 +#define RK3368_WIN0_COLOR_KEY 0x0038 +#define RK3368_WIN0_VIR 0x003c +#define RK3368_WIN0_YRGB_MST 0x0040 +#define RK3368_WIN0_CBR_MST 0x0044 +#define RK3368_WIN0_ACT_INFO 0x0048 +#define RK3368_WIN0_DSP_INFO 0x004c +#define RK3368_WIN0_DSP_ST 0x0050 +#define RK3368_WIN0_SCL_FACTOR_YRGB 0x0054 +#define RK3368_WIN0_SCL_FACTOR_CBR 0x0058 +#define RK3368_WIN0_SCL_OFFSET 0x005c +#define RK3368_WIN0_SRC_ALPHA_CTRL 0x0060 +#define RK3368_WIN0_DST_ALPHA_CTRL 0x0064 +#define RK3368_WIN0_FADING_CTRL 0x0068 +#define RK3368_WIN0_CTRL2 0x006c +#define RK3368_WIN1_CTRL0 0x0070 +#define RK3368_WIN1_CTRL1 0x0074 +#define RK3368_WIN1_COLOR_KEY 0x0078 +#define RK3368_WIN1_VIR 0x007c +#define RK3368_WIN1_YRGB_MST 0x0080 +#define RK3368_WIN1_CBR_MST 0x0084 +#define RK3368_WIN1_ACT_INFO 0x0088 +#define RK3368_WIN1_DSP_INFO 0x008c +#define RK3368_WIN1_DSP_ST 0x0090 +#define RK3368_WIN1_SCL_FACTOR_YRGB 0x0094 +#define RK3368_WIN1_SCL_FACTOR_CBR 0x0098 +#define RK3368_WIN1_SCL_OFFSET 0x009c +#define RK3368_WIN1_SRC_ALPHA_CTRL 0x00a0 +#define RK3368_WIN1_DST_ALPHA_CTRL 0x00a4 +#define RK3368_WIN1_FADING_CTRL 0x00a8 +#define RK3368_WIN1_CTRL2 0x00ac +#define RK3368_WIN2_CTRL0 0x00b0 +#define RK3368_WIN2_CTRL1 0x00b4 +#define RK3368_WIN2_VIR0_1 0x00b8 +#define RK3368_WIN2_VIR2_3 0x00bc +#define RK3368_WIN2_MST0 0x00c0 +#define RK3368_WIN2_DSP_INFO0 0x00c4 +#define RK3368_WIN2_DSP_ST0 0x00c8 +#define RK3368_WIN2_COLOR_KEY 0x00cc +#define RK3368_WIN2_MST1 0x00d0 +#define RK3368_WIN2_DSP_INFO1 0x00d4 +#define RK3368_WIN2_DSP_ST1 0x00d8 +#define RK3368_WIN2_SRC_ALPHA_CTRL 0x00dc +#define RK3368_WIN2_MST2 0x00e0 +#define RK3368_WIN2_DSP_INFO2 0x00e4 +#define RK3368_WIN2_DSP_ST2 0x00e8 +#define RK3368_WIN2_DST_ALPHA_CTRL 0x00ec +#define RK3368_WIN2_MST3 0x00f0 +#define RK3368_WIN2_DSP_INFO3 0x00f4 +#define RK3368_WIN2_DSP_ST3 0x00f8 +#define RK3368_WIN2_FADING_CTRL 0x00fc +#define RK3368_WIN3_CTRL0 0x0100 +#define RK3368_WIN3_CTRL1 0x0104 +#define RK3368_WIN3_VIR0_1 0x0108 +#define RK3368_WIN3_VIR2_3 0x010c +#define RK3368_WIN3_MST0 0x0110 +#define RK3368_WIN3_DSP_INFO0 0x0114 +#define RK3368_WIN3_DSP_ST0 0x0118 +#define RK3368_WIN3_COLOR_KEY 0x011c +#define RK3368_WIN3_MST1 0x0120 +#define RK3368_WIN3_DSP_INFO1 0x0124 +#define RK3368_WIN3_DSP_ST1 0x0128 +#define RK3368_WIN3_SRC_ALPHA_CTRL 0x012c +#define RK3368_WIN3_MST2 0x0130 +#define RK3368_WIN3_DSP_INFO2 0x0134 +#define RK3368_WIN3_DSP_ST2 0x0138 +#define RK3368_WIN3_DST_ALPHA_CTRL 0x013c +#define RK3368_WIN3_MST3 0x0140 +#define RK3368_WIN3_DSP_INFO3 0x0144 +#define RK3368_WIN3_DSP_ST3 0x0148 +#define RK3368_WIN3_FADING_CTRL 0x014c +#define RK3368_HWC_CTRL0 0x0150 +#define RK3368_HWC_CTRL1 0x0154 +#define RK3368_HWC_MST 0x0158 +#define RK3368_HWC_DSP_ST 0x015c +#define RK3368_HWC_SRC_ALPHA_CTRL 0x0160 +#define RK3368_HWC_DST_ALPHA_CTRL 0x0164 +#define RK3368_HWC_FADING_CTRL 0x0168 +#define RK3368_HWC_RESERVED1 0x016c +#define RK3368_POST_DSP_HACT_INFO 0x0170 +#define RK3368_POST_DSP_VACT_INFO 0x0174 +#define RK3368_POST_SCL_FACTOR_YRGB 0x0178 +#define RK3368_POST_RESERVED 0x017c +#define RK3368_POST_SCL_CTRL 0x0180 +#define RK3368_POST_DSP_VACT_INFO_F1 0x0184 +#define RK3368_DSP_HTOTAL_HS_END 0x0188 +#define RK3368_DSP_HACT_ST_END 0x018c +#define RK3368_DSP_VTOTAL_VS_END 0x0190 +#define RK3368_DSP_VACT_ST_END 0x0194 +#define RK3368_DSP_VS_ST_END_F1 0x0198 +#define RK3368_DSP_VACT_ST_END_F1 0x019c +#define RK3368_PWM_CTRL 0x01a0 +#define RK3368_PWM_PERIOD_HPR 0x01a4 +#define RK3368_PWM_DUTY_LPR 0x01a8 +#define RK3368_PWM_CNT 0x01ac +#define RK3368_BCSH_COLOR_BAR 0x01b0 +#define RK3368_BCSH_BCS 0x01b4 +#define RK3368_BCSH_H 0x01b8 +#define RK3368_BCSH_CTRL 0x01bc +#define RK3368_CABC_CTRL0 0x01c0 +#define RK3368_CABC_CTRL1 0x01c4 +#define RK3368_CABC_CTRL2 0x01c8 +#define RK3368_CABC_CTRL3 0x01cc +#define RK3368_CABC_GAUSS_LINE0_0 0x01d0 +#define RK3368_CABC_GAUSS_LINE0_1 0x01d4 +#define RK3368_CABC_GAUSS_LINE1_0 0x01d8 +#define RK3368_CABC_GAUSS_LINE1_1 0x01dc +#define RK3368_CABC_GAUSS_LINE2_0 0x01e0 +#define RK3368_CABC_GAUSS_LINE2_1 0x01e4 +#define RK3368_FRC_LOWER01_0 0x01e8 +#define RK3368_FRC_LOWER01_1 0x01ec +#define RK3368_FRC_LOWER10_0 0x01f0 +#define RK3368_FRC_LOWER10_1 0x01f4 +#define RK3368_FRC_LOWER11_0 0x01f8 +#define RK3368_FRC_LOWER11_1 0x01fc +#define RK3368_IFBDC_CTRL 0x0200 +#define RK3368_IFBDC_TILES_NUM 0x0204 +#define RK3368_IFBDC_FRAME_RST_CYCLE 0x0208 +#define RK3368_IFBDC_BASE_ADDR 0x020c +#define RK3368_IFBDC_MB_SIZE 0x0210 +#define RK3368_IFBDC_CMP_INDEX_INIT 0x0214 +#define RK3368_IFBDC_VIR 0x0220 +#define RK3368_IFBDC_DEBUG0 0x0230 +#define RK3368_IFBDC_DEBUG1 0x0234 +#define RK3368_LATENCY_CTRL0 0x0250 +#define RK3368_RD_MAX_LATENCY_NUM0 0x0254 +#define RK3368_RD_LATENCY_THR_NUM0 0x0258 +#define RK3368_RD_LATENCY_SAMP_NUM0 0x025c +#define RK3368_WIN0_DSP_BG 0x0260 +#define RK3368_WIN1_DSP_BG 0x0264 +#define RK3368_WIN2_DSP_BG 0x0268 +#define RK3368_WIN3_DSP_BG 0x026c +#define RK3368_SCAN_LINE_NUM 0x0270 +#define RK3368_CABC_DEBUG0 0x0274 +#define RK3368_CABC_DEBUG1 0x0278 +#define RK3368_CABC_DEBUG2 0x027c +#define RK3368_DBG_REG_000 0x0280 +#define RK3368_DBG_REG_001 0x0284 +#define RK3368_DBG_REG_002 0x0288 +#define RK3368_DBG_REG_003 0x028c +#define RK3368_DBG_REG_004 0x0290 +#define RK3368_DBG_REG_005 0x0294 +#define RK3368_DBG_REG_006 0x0298 +#define RK3368_DBG_REG_007 0x029c +#define RK3368_DBG_REG_008 0x02a0 +#define RK3368_DBG_REG_016 0x02c0 +#define RK3368_DBG_REG_017 0x02c4 +#define RK3368_DBG_REG_018 0x02c8 +#define RK3368_DBG_REG_019 0x02cc +#define RK3368_DBG_REG_020 0x02d0 +#define RK3368_DBG_REG_021 0x02d4 +#define RK3368_DBG_REG_022 0x02d8 +#define RK3368_DBG_REG_023 0x02dc +#define RK3368_DBG_REG_028 0x02f0 +#define RK3368_MMU_DTE_ADDR 0x0300 +#define RK3368_MMU_STATUS 0x0304 +#define RK3368_MMU_COMMAND 0x0308 +#define RK3368_MMU_PAGE_FAULT_ADDR 0x030c +#define RK3368_MMU_ZAP_ONE_LINE 0x0310 +#define RK3368_MMU_INT_RAWSTAT 0x0314 +#define RK3368_MMU_INT_CLEAR 0x0318 +#define RK3368_MMU_INT_MASK 0x031c +#define RK3368_MMU_INT_STATUS 0x0320 +#define RK3368_MMU_AUTO_GATING 0x0324 +#define RK3368_WIN2_LUT_ADDR 0x0400 +#define RK3368_WIN3_LUT_ADDR 0x0800 +#define RK3368_HWC_LUT_ADDR 0x0c00 +#define RK3368_GAMMA_LUT_ADDR 0x1000 +#define RK3368_CABC_GAMMA_LUT_ADDR 0x1800 +#define RK3368_MCU_BYPASS_WPORT 0x2200 +#define RK3368_MCU_BYPASS_RPORT 0x2300 +/* rk3368 register definition end */ + +#define RK3366_REG_CFG_DONE 0x0000 +#define RK3366_VERSION_INFO 0x0004 +#define RK3366_SYS_CTRL 0x0008 +#define RK3366_SYS_CTRL1 0x000c +#define RK3366_DSP_CTRL0 0x0010 +#define RK3366_DSP_CTRL1 0x0014 +#define RK3366_DSP_BG 0x0018 +#define RK3366_MCU_CTRL 0x001c +#define RK3366_WB_CTRL0 0x0020 +#define RK3366_WB_CTRL1 0x0024 +#define RK3366_WB_YRGB_MST 0x0028 +#define RK3366_WB_CBR_MST 0x002c +#define RK3366_WIN0_CTRL0 0x0030 +#define RK3366_WIN0_CTRL1 0x0034 +#define RK3366_WIN0_COLOR_KEY 0x0038 +#define RK3366_WIN0_VIR 0x003c +#define RK3366_WIN0_YRGB_MST 0x0040 +#define RK3366_WIN0_CBR_MST 0x0044 +#define RK3366_WIN0_ACT_INFO 0x0048 +#define RK3366_WIN0_DSP_INFO 0x004c +#define RK3366_WIN0_DSP_ST 0x0050 +#define RK3366_WIN0_SCL_FACTOR_YRGB 0x0054 +#define RK3366_WIN0_SCL_FACTOR_CBR 0x0058 +#define RK3366_WIN0_SCL_OFFSET 0x005c +#define RK3366_WIN0_SRC_ALPHA_CTRL 0x0060 +#define RK3366_WIN0_DST_ALPHA_CTRL 0x0064 +#define RK3366_WIN0_FADING_CTRL 0x0068 +#define RK3366_WIN0_CTRL2 0x006c +#define RK3366_WIN1_CTRL0 0x0070 +#define RK3366_WIN1_CTRL1 0x0074 +#define RK3366_WIN1_COLOR_KEY 0x0078 +#define RK3366_WIN1_VIR 0x007c +#define RK3366_WIN1_YRGB_MST 0x0080 +#define RK3366_WIN1_CBR_MST 0x0084 +#define RK3366_WIN1_ACT_INFO 0x0088 +#define RK3366_WIN1_DSP_INFO 0x008c +#define RK3366_WIN1_DSP_ST 0x0090 +#define RK3366_WIN1_SCL_FACTOR_YRGB 0x0094 +#define RK3366_WIN1_SCL_FACTOR_CBR 0x0098 +#define RK3366_WIN1_SCL_OFFSET 0x009c +#define RK3366_WIN1_SRC_ALPHA_CTRL 0x00a0 +#define RK3366_WIN1_DST_ALPHA_CTRL 0x00a4 +#define RK3366_WIN1_FADING_CTRL 0x00a8 +#define RK3366_WIN1_CTRL2 0x00ac +#define RK3366_WIN2_CTRL0 0x00b0 +#define RK3366_WIN2_CTRL1 0x00b4 +#define RK3366_WIN2_VIR0_1 0x00b8 +#define RK3366_WIN2_VIR2_3 0x00bc +#define RK3366_WIN2_MST0 0x00c0 +#define RK3366_WIN2_DSP_INFO0 0x00c4 +#define RK3366_WIN2_DSP_ST0 0x00c8 +#define RK3366_WIN2_COLOR_KEY 0x00cc +#define RK3366_WIN2_MST1 0x00d0 +#define RK3366_WIN2_DSP_INFO1 0x00d4 +#define RK3366_WIN2_DSP_ST1 0x00d8 +#define RK3366_WIN2_SRC_ALPHA_CTRL 0x00dc +#define RK3366_WIN2_MST2 0x00e0 +#define RK3366_WIN2_DSP_INFO2 0x00e4 +#define RK3366_WIN2_DSP_ST2 0x00e8 +#define RK3366_WIN2_DST_ALPHA_CTRL 0x00ec +#define RK3366_WIN2_MST3 0x00f0 +#define RK3366_WIN2_DSP_INFO3 0x00f4 +#define RK3366_WIN2_DSP_ST3 0x00f8 +#define RK3366_WIN2_FADING_CTRL 0x00fc +#define RK3366_WIN3_CTRL0 0x0100 +#define RK3366_WIN3_CTRL1 0x0104 +#define RK3366_WIN3_VIR0_1 0x0108 +#define RK3366_WIN3_VIR2_3 0x010c +#define RK3366_WIN3_MST0 0x0110 +#define RK3366_WIN3_DSP_INFO0 0x0114 +#define RK3366_WIN3_DSP_ST0 0x0118 +#define RK3366_WIN3_COLOR_KEY 0x011c +#define RK3366_WIN3_MST1 0x0120 +#define RK3366_WIN3_DSP_INFO1 0x0124 +#define RK3366_WIN3_DSP_ST1 0x0128 +#define RK3366_WIN3_SRC_ALPHA_CTRL 0x012c +#define RK3366_WIN3_MST2 0x0130 +#define RK3366_WIN3_DSP_INFO2 0x0134 +#define RK3366_WIN3_DSP_ST2 0x0138 +#define RK3366_WIN3_DST_ALPHA_CTRL 0x013c +#define RK3366_WIN3_MST3 0x0140 +#define RK3366_WIN3_DSP_INFO3 0x0144 +#define RK3366_WIN3_DSP_ST3 0x0148 +#define RK3366_WIN3_FADING_CTRL 0x014c +#define RK3366_HWC_CTRL0 0x0150 +#define RK3366_HWC_CTRL1 0x0154 +#define RK3366_HWC_MST 0x0158 +#define RK3366_HWC_DSP_ST 0x015c +#define RK3366_HWC_SRC_ALPHA_CTRL 0x0160 +#define RK3366_HWC_DST_ALPHA_CTRL 0x0164 +#define RK3366_HWC_FADING_CTRL 0x0168 +#define RK3366_HWC_RESERVED1 0x016c +#define RK3366_POST_DSP_HACT_INFO 0x0170 +#define RK3366_POST_DSP_VACT_INFO 0x0174 +#define RK3366_POST_SCL_FACTOR_YRGB 0x0178 +#define RK3366_POST_RESERVED 0x017c +#define RK3366_POST_SCL_CTRL 0x0180 +#define RK3366_POST_DSP_VACT_INFO_F1 0x0184 +#define RK3366_DSP_HTOTAL_HS_END 0x0188 +#define RK3366_DSP_HACT_ST_END 0x018c +#define RK3366_DSP_VTOTAL_VS_END 0x0190 +#define RK3366_DSP_VACT_ST_END 0x0194 +#define RK3366_DSP_VS_ST_END_F1 0x0198 +#define RK3366_DSP_VACT_ST_END_F1 0x019c +#define RK3366_PWM_CTRL 0x01a0 +#define RK3366_PWM_PERIOD_HPR 0x01a4 +#define RK3366_PWM_DUTY_LPR 0x01a8 +#define RK3366_PWM_CNT 0x01ac +#define RK3366_BCSH_COLOR_BAR 0x01b0 +#define RK3366_BCSH_BCS 0x01b4 +#define RK3366_BCSH_H 0x01b8 +#define RK3366_BCSH_CTRL 0x01bc +#define RK3366_CABC_CTRL0 0x01c0 +#define RK3366_CABC_CTRL1 0x01c4 +#define RK3366_CABC_CTRL2 0x01c8 +#define RK3366_CABC_CTRL3 0x01cc +#define RK3366_CABC_GAUSS_LINE0_0 0x01d0 +#define RK3366_CABC_GAUSS_LINE0_1 0x01d4 +#define RK3366_CABC_GAUSS_LINE1_0 0x01d8 +#define RK3366_CABC_GAUSS_LINE1_1 0x01dc +#define RK3366_CABC_GAUSS_LINE2_0 0x01e0 +#define RK3366_CABC_GAUSS_LINE2_1 0x01e4 +#define RK3366_FRC_LOWER01_0 0x01e8 +#define RK3366_FRC_LOWER01_1 0x01ec +#define RK3366_FRC_LOWER10_0 0x01f0 +#define RK3366_FRC_LOWER10_1 0x01f4 +#define RK3366_FRC_LOWER11_0 0x01f8 +#define RK3366_FRC_LOWER11_1 0x01fc +#define RK3366_INTR_EN0 0x0280 +#define RK3366_INTR_CLEAR0 0x0284 +#define RK3366_INTR_STATUS0 0x0288 +#define RK3366_INTR_RAW_STATUS0 0x028c +#define RK3366_INTR_EN1 0x0290 +#define RK3366_INTR_CLEAR1 0x0294 +#define RK3366_INTR_STATUS1 0x0298 +#define RK3366_INTR_RAW_STATUS1 0x029c +#define RK3366_LINE_FLAG 0x02a0 +#define RK3366_VOP_STATUS 0x02a4 +#define RK3366_BLANKING_VALUE 0x02a8 +#define RK3366_WIN0_DSP_BG 0x02b0 +#define RK3366_WIN1_DSP_BG 0x02b4 +#define RK3366_WIN2_DSP_BG 0x02b8 +#define RK3366_WIN3_DSP_BG 0x02bc +#define RK3366_WIN2_LUT_ADDR 0x0400 +#define RK3366_WIN3_LUT_ADDR 0x0800 +#define RK3366_HWC_LUT_ADDR 0x0c00 +#define RK3366_GAMMA0_LUT_ADDR 0x1000 +#define RK3366_GAMMA1_LUT_ADDR 0x1400 +#define RK3366_CABC_GAMMA_LUT_ADDR 0x1800 +#define RK3366_MCU_BYPASS_WPORT 0x2200 +#define RK3366_MCU_BYPASS_RPORT 0x2300 +#define RK3366_MMU_DTE_ADDR 0x2400 +#define RK3366_MMU_STATUS 0x2404 +#define RK3366_MMU_COMMAND 0x2408 +#define RK3366_MMU_PAGE_FAULT_ADDR 0x240c +#define RK3366_MMU_ZAP_ONE_LINE 0x2410 +#define RK3366_MMU_INT_RAWSTAT 0x2414 +#define RK3366_MMU_INT_CLEAR 0x2418 +#define RK3366_MMU_INT_MASK 0x241c +#define RK3366_MMU_INT_STATUS 0x2420 +#define RK3366_MMU_AUTO_GATING 0x2424 + +/* rk3399 register definition */ +#define RK3399_REG_CFG_DONE 0x0000 +#define RK3399_VERSION_INFO 0x0004 +#define RK3399_SYS_CTRL 0x0008 +#define RK3399_SYS_CTRL1 0x000c +#define RK3399_DSP_CTRL0 0x0010 +#define RK3399_DSP_CTRL1 0x0014 +#define RK3399_DSP_BG 0x0018 +#define RK3399_MCU_CTRL 0x001c +#define RK3399_WB_CTRL0 0x0020 +#define RK3399_WB_CTRL1 0x0024 +#define RK3399_WB_YRGB_MST 0x0028 +#define RK3399_WB_CBR_MST 0x002c +#define RK3399_WIN0_CTRL0 0x0030 +#define RK3399_WIN0_CTRL1 0x0034 +#define RK3399_WIN0_COLOR_KEY 0x0038 +#define RK3399_WIN0_VIR 0x003c +#define RK3399_WIN0_YRGB_MST 0x0040 +#define RK3399_WIN0_CBR_MST 0x0044 +#define RK3399_WIN0_ACT_INFO 0x0048 +#define RK3399_WIN0_DSP_INFO 0x004c +#define RK3399_WIN0_DSP_ST 0x0050 +#define RK3399_WIN0_SCL_FACTOR_YRGB 0x0054 +#define RK3399_WIN0_SCL_FACTOR_CBR 0x0058 +#define RK3399_WIN0_SCL_OFFSET 0x005c +#define RK3399_WIN0_SRC_ALPHA_CTRL 0x0060 +#define RK3399_WIN0_DST_ALPHA_CTRL 0x0064 +#define RK3399_WIN0_FADING_CTRL 0x0068 +#define RK3399_WIN0_CTRL2 0x006c +#define RK3399_WIN1_CTRL0 0x0070 +#define RK3399_WIN1_CTRL1 0x0074 +#define RK3399_WIN1_COLOR_KEY 0x0078 +#define RK3399_WIN1_VIR 0x007c +#define RK3399_WIN1_YRGB_MST 0x0080 +#define RK3399_WIN1_CBR_MST 0x0084 +#define RK3399_WIN1_ACT_INFO 0x0088 +#define RK3399_WIN1_DSP_INFO 0x008c +#define RK3399_WIN1_DSP_ST 0x0090 +#define RK3399_WIN1_SCL_FACTOR_YRGB 0x0094 +#define RK3399_WIN1_SCL_FACTOR_CBR 0x0098 +#define RK3399_WIN1_SCL_OFFSET 0x009c +#define RK3399_WIN1_SRC_ALPHA_CTRL 0x00a0 +#define RK3399_WIN1_DST_ALPHA_CTRL 0x00a4 +#define RK3399_WIN1_FADING_CTRL 0x00a8 +#define RK3399_WIN1_CTRL2 0x00ac +#define RK3399_WIN2_CTRL0 0x00b0 +#define RK3399_WIN2_CTRL1 0x00b4 +#define RK3399_WIN2_VIR0_1 0x00b8 +#define RK3399_WIN2_VIR2_3 0x00bc +#define RK3399_WIN2_MST0 0x00c0 +#define RK3399_WIN2_DSP_INFO0 0x00c4 +#define RK3399_WIN2_DSP_ST0 0x00c8 +#define RK3399_WIN2_COLOR_KEY 0x00cc +#define RK3399_WIN2_MST1 0x00d0 +#define RK3399_WIN2_DSP_INFO1 0x00d4 +#define RK3399_WIN2_DSP_ST1 0x00d8 +#define RK3399_WIN2_SRC_ALPHA_CTRL 0x00dc +#define RK3399_WIN2_MST2 0x00e0 +#define RK3399_WIN2_DSP_INFO2 0x00e4 +#define RK3399_WIN2_DSP_ST2 0x00e8 +#define RK3399_WIN2_DST_ALPHA_CTRL 0x00ec +#define RK3399_WIN2_MST3 0x00f0 +#define RK3399_WIN2_DSP_INFO3 0x00f4 +#define RK3399_WIN2_DSP_ST3 0x00f8 +#define RK3399_WIN2_FADING_CTRL 0x00fc +#define RK3399_WIN3_CTRL0 0x0100 +#define RK3399_WIN3_CTRL1 0x0104 +#define RK3399_WIN3_VIR0_1 0x0108 +#define RK3399_WIN3_VIR2_3 0x010c +#define RK3399_WIN3_MST0 0x0110 +#define RK3399_WIN3_DSP_INFO0 0x0114 +#define RK3399_WIN3_DSP_ST0 0x0118 +#define RK3399_WIN3_COLOR_KEY 0x011c +#define RK3399_WIN3_MST1 0x0120 +#define RK3399_WIN3_DSP_INFO1 0x0124 +#define RK3399_WIN3_DSP_ST1 0x0128 +#define RK3399_WIN3_SRC_ALPHA_CTRL 0x012c +#define RK3399_WIN3_MST2 0x0130 +#define RK3399_WIN3_DSP_INFO2 0x0134 +#define RK3399_WIN3_DSP_ST2 0x0138 +#define RK3399_WIN3_DST_ALPHA_CTRL 0x013c +#define RK3399_WIN3_MST3 0x0140 +#define RK3399_WIN3_DSP_INFO3 0x0144 +#define RK3399_WIN3_DSP_ST3 0x0148 +#define RK3399_WIN3_FADING_CTRL 0x014c +#define RK3399_HWC_CTRL0 0x0150 +#define RK3399_HWC_CTRL1 0x0154 +#define RK3399_HWC_MST 0x0158 +#define RK3399_HWC_DSP_ST 0x015c +#define RK3399_HWC_SRC_ALPHA_CTRL 0x0160 +#define RK3399_HWC_DST_ALPHA_CTRL 0x0164 +#define RK3399_HWC_FADING_CTRL 0x0168 +#define RK3399_HWC_RESERVED1 0x016c +#define RK3399_POST_DSP_HACT_INFO 0x0170 +#define RK3399_POST_DSP_VACT_INFO 0x0174 +#define RK3399_POST_SCL_FACTOR_YRGB 0x0178 +#define RK3399_POST_RESERVED 0x017c +#define RK3399_POST_SCL_CTRL 0x0180 +#define RK3399_POST_DSP_VACT_INFO_F1 0x0184 +#define RK3399_DSP_HTOTAL_HS_END 0x0188 +#define RK3399_DSP_HACT_ST_END 0x018c +#define RK3399_DSP_VTOTAL_VS_END 0x0190 +#define RK3399_DSP_VACT_ST_END 0x0194 +#define RK3399_DSP_VS_ST_END_F1 0x0198 +#define RK3399_DSP_VACT_ST_END_F1 0x019c +#define RK3399_PWM_CTRL 0x01a0 +#define RK3399_PWM_PERIOD_HPR 0x01a4 +#define RK3399_PWM_DUTY_LPR 0x01a8 +#define RK3399_PWM_CNT 0x01ac +#define RK3399_BCSH_COLOR_BAR 0x01b0 +#define RK3399_BCSH_BCS 0x01b4 +#define RK3399_BCSH_H 0x01b8 +#define RK3399_BCSH_CTRL 0x01bc +#define RK3399_CABC_CTRL0 0x01c0 +#define RK3399_CABC_CTRL1 0x01c4 +#define RK3399_CABC_CTRL2 0x01c8 +#define RK3399_CABC_CTRL3 0x01cc +#define RK3399_CABC_GAUSS_LINE0_0 0x01d0 +#define RK3399_CABC_GAUSS_LINE0_1 0x01d4 +#define RK3399_CABC_GAUSS_LINE1_0 0x01d8 +#define RK3399_CABC_GAUSS_LINE1_1 0x01dc +#define RK3399_CABC_GAUSS_LINE2_0 0x01e0 +#define RK3399_CABC_GAUSS_LINE2_1 0x01e4 +#define RK3399_FRC_LOWER01_0 0x01e8 +#define RK3399_FRC_LOWER01_1 0x01ec +#define RK3399_FRC_LOWER10_0 0x01f0 +#define RK3399_FRC_LOWER10_1 0x01f4 +#define RK3399_FRC_LOWER11_0 0x01f8 +#define RK3399_FRC_LOWER11_1 0x01fc +#define RK3399_AFBCD0_CTRL 0x0200 +#define RK3399_AFBCD0_HDR_PTR 0x0204 +#define RK3399_AFBCD0_PIC_SIZE 0x0208 +#define RK3399_AFBCD0_STATUS 0x020c +#define RK3399_AFBCD1_CTRL 0x0220 +#define RK3399_AFBCD1_HDR_PTR 0x0224 +#define RK3399_AFBCD1_PIC_SIZE 0x0228 +#define RK3399_AFBCD1_STATUS 0x022c +#define RK3399_AFBCD2_CTRL 0x0240 +#define RK3399_AFBCD2_HDR_PTR 0x0244 +#define RK3399_AFBCD2_PIC_SIZE 0x0248 +#define RK3399_AFBCD2_STATUS 0x024c +#define RK3399_AFBCD3_CTRL 0x0260 +#define RK3399_AFBCD3_HDR_PTR 0x0264 +#define RK3399_AFBCD3_PIC_SIZE 0x0268 +#define RK3399_AFBCD3_STATUS 0x026c +#define RK3399_INTR_EN0 0x0280 +#define RK3399_INTR_CLEAR0 0x0284 +#define RK3399_INTR_STATUS0 0x0288 +#define RK3399_INTR_RAW_STATUS0 0x028c +#define RK3399_INTR_EN1 0x0290 +#define RK3399_INTR_CLEAR1 0x0294 +#define RK3399_INTR_STATUS1 0x0298 +#define RK3399_INTR_RAW_STATUS1 0x029c +#define RK3399_LINE_FLAG 0x02a0 +#define RK3399_VOP_STATUS 0x02a4 +#define RK3399_BLANKING_VALUE 0x02a8 +#define RK3399_MCU_BYPASS_PORT 0x02ac +#define RK3399_WIN0_DSP_BG 0x02b0 +#define RK3399_WIN1_DSP_BG 0x02b4 +#define RK3399_WIN2_DSP_BG 0x02b8 +#define RK3399_WIN3_DSP_BG 0x02bc +#define RK3399_YUV2YUV_WIN 0x02c0 +#define RK3399_YUV2YUV_POST 0x02c4 +#define RK3399_AUTO_GATING_EN 0x02cc +#define RK3399_WIN0_CSC_COE 0x03a0 +#define RK3399_WIN1_CSC_COE 0x03c0 +#define RK3399_WIN2_CSC_COE 0x03e0 +#define RK3399_WIN3_CSC_COE 0x0400 +#define RK3399_HWC_CSC_COE 0x0420 +#define RK3399_BCSH_R2Y_CSC_COE 0x0440 +#define RK3399_BCSH_Y2R_CSC_COE 0x0460 +#define RK3399_POST_YUV2YUV_Y2R_COE 0x0480 +#define RK3399_POST_YUV2YUV_3X3_COE 0x04a0 +#define RK3399_POST_YUV2YUV_R2Y_COE 0x04c0 +#define RK3399_WIN0_YUV2YUV_Y2R 0x04e0 +#define RK3399_WIN0_YUV2YUV_3X3 0x0500 +#define RK3399_WIN0_YUV2YUV_R2Y 0x0520 +#define RK3399_WIN1_YUV2YUV_Y2R 0x0540 +#define RK3399_WIN1_YUV2YUV_3X3 0x0560 +#define RK3399_WIN1_YUV2YUV_R2Y 0x0580 +#define RK3399_WIN2_YUV2YUV_Y2R 0x05a0 +#define RK3399_WIN2_YUV2YUV_3X3 0x05c0 +#define RK3399_WIN2_YUV2YUV_R2Y 0x05e0 +#define RK3399_WIN3_YUV2YUV_Y2R 0x0600 +#define RK3399_WIN3_YUV2YUV_3X3 0x0620 +#define RK3399_WIN3_YUV2YUV_R2Y 0x0640 +#define RK3399_WIN2_LUT_ADDR 0x1000 +#define RK3399_WIN3_LUT_ADDR 0x1400 +#define RK3399_HWC_LUT_ADDR 0x1800 +#define RK3399_CABC_GAMMA_LUT_ADDR 0x1c00 +#define RK3399_GAMMA_LUT_ADDR 0x2000 +/* rk3399 register definition end */ + +/* rk3328 register definition end */ +#define RK3328_REG_CFG_DONE 0x00000000 +#define RK3328_VERSION_INFO 0x00000004 +#define RK3328_SYS_CTRL 0x00000008 +#define RK3328_SYS_CTRL1 0x0000000c +#define RK3328_DSP_CTRL0 0x00000010 +#define RK3328_DSP_CTRL1 0x00000014 +#define RK3328_DSP_BG 0x00000018 +#define RK3328_AUTO_GATING_EN 0x0000003c +#define RK3328_LINE_FLAG 0x00000040 +#define RK3328_VOP_STATUS 0x00000044 +#define RK3328_BLANKING_VALUE 0x00000048 +#define RK3328_WIN0_DSP_BG 0x00000050 +#define RK3328_WIN1_DSP_BG 0x00000054 +#define RK3328_DBG_PERF_LATENCY_CTRL0 0x000000c0 +#define RK3328_DBG_PERF_RD_MAX_LATENCY_NUM0 0x000000c4 +#define RK3328_DBG_PERF_RD_LATENCY_THR_NUM0 0x000000c8 +#define RK3328_DBG_PERF_RD_LATENCY_SAMP_NUM0 0x000000cc +#define RK3328_INTR_EN0 0x000000e0 +#define RK3328_INTR_CLEAR0 0x000000e4 +#define RK3328_INTR_STATUS0 0x000000e8 +#define RK3328_INTR_RAW_STATUS0 0x000000ec +#define RK3328_INTR_EN1 0x000000f0 +#define RK3328_INTR_CLEAR1 0x000000f4 +#define RK3328_INTR_STATUS1 0x000000f8 +#define RK3328_INTR_RAW_STATUS1 0x000000fc +#define RK3328_WIN0_CTRL0 0x00000100 +#define RK3328_WIN0_CTRL1 0x00000104 +#define RK3328_WIN0_COLOR_KEY 0x00000108 +#define RK3328_WIN0_VIR 0x0000010c +#define RK3328_WIN0_YRGB_MST 0x00000110 +#define RK3328_WIN0_CBR_MST 0x00000114 +#define RK3328_WIN0_ACT_INFO 0x00000118 +#define RK3328_WIN0_DSP_INFO 0x0000011c +#define RK3328_WIN0_DSP_ST 0x00000120 +#define RK3328_WIN0_SCL_FACTOR_YRGB 0x00000124 +#define RK3328_WIN0_SCL_FACTOR_CBR 0x00000128 +#define RK3328_WIN0_SCL_OFFSET 0x0000012c +#define RK3328_WIN0_SRC_ALPHA_CTRL 0x00000130 +#define RK3328_WIN0_DST_ALPHA_CTRL 0x00000134 +#define RK3328_WIN0_FADING_CTRL 0x00000138 +#define RK3328_WIN0_CTRL2 0x0000013c +#define RK3328_DBG_WIN0_REG0 0x000001f0 +#define RK3328_DBG_WIN0_REG1 0x000001f4 +#define RK3328_DBG_WIN0_REG2 0x000001f8 +#define RK3328_DBG_WIN0_RESERVED 0x000001fc +#define RK3328_WIN1_CTRL0 0x00000200 +#define RK3328_WIN1_CTRL1 0x00000204 +#define RK3328_WIN1_COLOR_KEY 0x00000208 +#define RK3328_WIN1_VIR 0x0000020c +#define RK3328_WIN1_YRGB_MST 0x00000210 +#define RK3328_WIN1_CBR_MST 0x00000214 +#define RK3328_WIN1_ACT_INFO 0x00000218 +#define RK3328_WIN1_DSP_INFO 0x0000021c +#define RK3328_WIN1_DSP_ST 0x00000220 +#define RK3328_WIN1_SCL_FACTOR_YRGB 0x00000224 +#define RK3328_WIN1_SCL_FACTOR_CBR 0x00000228 +#define RK3328_WIN1_SCL_OFFSET 0x0000022c +#define RK3328_WIN1_SRC_ALPHA_CTRL 0x00000230 +#define RK3328_WIN1_DST_ALPHA_CTRL 0x00000234 +#define RK3328_WIN1_FADING_CTRL 0x00000238 +#define RK3328_WIN1_CTRL2 0x0000023c +#define RK3328_DBG_WIN1_REG0 0x000002f0 +#define RK3328_DBG_WIN1_REG1 0x000002f4 +#define RK3328_DBG_WIN1_REG2 0x000002f8 +#define RK3328_DBG_WIN1_RESERVED 0x000002fc +#define RK3328_WIN2_CTRL0 0x00000300 +#define RK3328_WIN2_CTRL1 0x00000304 +#define RK3328_WIN2_COLOR_KEY 0x00000308 +#define RK3328_WIN2_VIR 0x0000030c +#define RK3328_WIN2_YRGB_MST 0x00000310 +#define RK3328_WIN2_CBR_MST 0x00000314 +#define RK3328_WIN2_ACT_INFO 0x00000318 +#define RK3328_WIN2_DSP_INFO 0x0000031c +#define RK3328_WIN2_DSP_ST 0x00000320 +#define RK3328_WIN2_SCL_FACTOR_YRGB 0x00000324 +#define RK3328_WIN2_SCL_FACTOR_CBR 0x00000328 +#define RK3328_WIN2_SCL_OFFSET 0x0000032c +#define RK3328_WIN2_SRC_ALPHA_CTRL 0x00000330 +#define RK3328_WIN2_DST_ALPHA_CTRL 0x00000334 +#define RK3328_WIN2_FADING_CTRL 0x00000338 +#define RK3328_WIN2_CTRL2 0x0000033c +#define RK3328_DBG_WIN2_REG0 0x000003f0 +#define RK3328_DBG_WIN2_REG1 0x000003f4 +#define RK3328_DBG_WIN2_REG2 0x000003f8 +#define RK3328_DBG_WIN2_RESERVED 0x000003fc +#define RK3328_WIN3_CTRL0 0x00000400 +#define RK3328_WIN3_CTRL1 0x00000404 +#define RK3328_WIN3_COLOR_KEY 0x00000408 +#define RK3328_WIN3_VIR 0x0000040c +#define RK3328_WIN3_YRGB_MST 0x00000410 +#define RK3328_WIN3_CBR_MST 0x00000414 +#define RK3328_WIN3_ACT_INFO 0x00000418 +#define RK3328_WIN3_DSP_INFO 0x0000041c +#define RK3328_WIN3_DSP_ST 0x00000420 +#define RK3328_WIN3_SCL_FACTOR_YRGB 0x00000424 +#define RK3328_WIN3_SCL_FACTOR_CBR 0x00000428 +#define RK3328_WIN3_SCL_OFFSET 0x0000042c +#define RK3328_WIN3_SRC_ALPHA_CTRL 0x00000430 +#define RK3328_WIN3_DST_ALPHA_CTRL 0x00000434 +#define RK3328_WIN3_FADING_CTRL 0x00000438 +#define RK3328_WIN3_CTRL2 0x0000043c +#define RK3328_DBG_WIN3_REG0 0x000004f0 +#define RK3328_DBG_WIN3_REG1 0x000004f4 +#define RK3328_DBG_WIN3_REG2 0x000004f8 +#define RK3328_DBG_WIN3_RESERVED 0x000004fc + +#define RK3328_HWC_CTRL0 0x00000500 +#define RK3328_HWC_CTRL1 0x00000504 +#define RK3328_HWC_MST 0x00000508 +#define RK3328_HWC_DSP_ST 0x0000050c +#define RK3328_HWC_SRC_ALPHA_CTRL 0x00000510 +#define RK3328_HWC_DST_ALPHA_CTRL 0x00000514 +#define RK3328_HWC_FADING_CTRL 0x00000518 +#define RK3328_HWC_RESERVED1 0x0000051c +#define RK3328_POST_DSP_HACT_INFO 0x00000600 +#define RK3328_POST_DSP_VACT_INFO 0x00000604 +#define RK3328_POST_SCL_FACTOR_YRGB 0x00000608 +#define RK3328_POST_RESERVED 0x0000060c +#define RK3328_POST_SCL_CTRL 0x00000610 +#define RK3328_POST_DSP_VACT_INFO_F1 0x00000614 +#define RK3328_DSP_HTOTAL_HS_END 0x00000618 +#define RK3328_DSP_HACT_ST_END 0x0000061c +#define RK3328_DSP_VTOTAL_VS_END 0x00000620 +#define RK3328_DSP_VACT_ST_END 0x00000624 +#define RK3328_DSP_VS_ST_END_F1 0x00000628 +#define RK3328_DSP_VACT_ST_END_F1 0x0000062c +#define RK3328_BCSH_COLOR_BAR 0x00000640 +#define RK3328_BCSH_BCS 0x00000644 +#define RK3328_BCSH_H 0x00000648 +#define RK3328_BCSH_CTRL 0x0000064c +#define RK3328_FRC_LOWER01_0 0x00000678 +#define RK3328_FRC_LOWER01_1 0x0000067c +#define RK3328_FRC_LOWER10_0 0x00000680 +#define RK3328_FRC_LOWER10_1 0x00000684 +#define RK3328_FRC_LOWER11_0 0x00000688 +#define RK3328_FRC_LOWER11_1 0x0000068c +#define RK3328_DBG_POST_REG0 0x000006e8 +#define RK3328_DBG_POST_RESERVED 0x000006ec +#define RK3328_DBG_DATAO 0x000006f0 +#define RK3328_DBG_DATAO_2 0x000006f4 + +/* sdr to hdr */ +#define RK3328_SDR2HDR_CTRL 0x00000700 +#define RK3328_EOTF_OETF_Y0 0x00000704 +#define RK3328_RESERVED0001 0x00000708 +#define RK3328_RESERVED0002 0x0000070c +#define RK3328_EOTF_OETF_Y1 0x00000710 +#define RK3328_EOTF_OETF_Y64 0x0000080c +#define RK3328_OETF_DX_DXPOW1 0x00000810 +#define RK3328_OETF_DX_DXPOW64 0x0000090c +#define RK3328_OETF_XN1 0x00000910 +#define RK3328_OETF_XN63 0x00000a08 + +/* hdr to sdr */ +#define RK3328_HDR2SDR_CTRL 0x00000a10 +#define RK3328_HDR2SDR_SRC_RANGE 0x00000a14 +#define RK3328_HDR2SDR_NORMFACEETF 0x00000a18 +#define RK3328_RESERVED0003 0x00000a1c +#define RK3328_HDR2SDR_DST_RANGE 0x00000a20 +#define RK3328_HDR2SDR_NORMFACCGAMMA 0x00000a24 +#define RK3328_EETF_OETF_Y0 0x00000a28 +#define RK3328_SAT_Y0 0x00000a2c +#define RK3328_EETF_OETF_Y1 0x00000a30 +#define RK3328_SAT_Y1 0x00000ab0 +#define RK3328_SAT_Y8 0x00000acc + +#define RK3328_HWC_LUT_ADDR 0x00000c00 + /* rk3036 register definition */ #define RK3036_SYS_CTRL 0x00 #define RK3036_DSP_CTRL0 0x04 @@ -166,197 +878,4 @@ #define RK3036_HWC_LUT_ADDR 0x800 /* rk3036 register definition end */ -/* rk3399 register definition */ -#define RK3399_REG_CFG_DONE 0x00000 -#define RK3399_VERSION_INFO 0x00004 -#define RK3399_SYS_CTRL 0x00008 -#define RK3399_SYS_CTRL1 0x0000c -#define RK3399_DSP_CTRL0 0x00010 -#define RK3399_DSP_CTRL1 0x00014 -#define RK3399_DSP_BG 0x00018 -#define RK3399_MCU_CTRL 0x0001c -#define RK3399_WB_CTRL0 0x00020 -#define RK3399_WB_CTRL1 0x00024 -#define RK3399_WB_YRGB_MST 0x00028 -#define RK3399_WB_CBR_MST 0x0002c -#define RK3399_WIN0_CTRL0 0x00030 -#define RK3399_WIN0_CTRL1 0x00034 -#define RK3399_WIN0_COLOR_KEY 0x00038 -#define RK3399_WIN0_VIR 0x0003c -#define RK3399_WIN0_YRGB_MST 0x00040 -#define RK3399_WIN0_CBR_MST 0x00044 -#define RK3399_WIN0_ACT_INFO 0x00048 -#define RK3399_WIN0_DSP_INFO 0x0004c -#define RK3399_WIN0_DSP_ST 0x00050 -#define RK3399_WIN0_SCL_FACTOR_YRGB 0x00054 -#define RK3399_WIN0_SCL_FACTOR_CBR 0x00058 -#define RK3399_WIN0_SCL_OFFSET 0x0005c -#define RK3399_WIN0_SRC_ALPHA_CTRL 0x00060 -#define RK3399_WIN0_DST_ALPHA_CTRL 0x00064 -#define RK3399_WIN0_FADING_CTRL 0x00068 -#define RK3399_WIN0_CTRL2 0x0006c -#define RK3399_WIN1_CTRL0 0x00070 -#define RK3399_WIN1_CTRL1 0x00074 -#define RK3399_WIN1_COLOR_KEY 0x00078 -#define RK3399_WIN1_VIR 0x0007c -#define RK3399_WIN1_YRGB_MST 0x00080 -#define RK3399_WIN1_CBR_MST 0x00084 -#define RK3399_WIN1_ACT_INFO 0x00088 -#define RK3399_WIN1_DSP_INFO 0x0008c -#define RK3399_WIN1_DSP_ST 0x00090 -#define RK3399_WIN1_SCL_FACTOR_YRGB 0x00094 -#define RK3399_WIN1_SCL_FACTOR_CBR 0x00098 -#define RK3399_WIN1_SCL_OFFSET 0x0009c -#define RK3399_WIN1_SRC_ALPHA_CTRL 0x000a0 -#define RK3399_WIN1_DST_ALPHA_CTRL 0x000a4 -#define RK3399_WIN1_FADING_CTRL 0x000a8 -#define RK3399_WIN1_CTRL2 0x000ac -#define RK3399_WIN2_CTRL0 0x000b0 -#define RK3399_WIN2_CTRL1 0x000b4 -#define RK3399_WIN2_VIR0_1 0x000b8 -#define RK3399_WIN2_VIR2_3 0x000bc -#define RK3399_WIN2_MST0 0x000c0 -#define RK3399_WIN2_DSP_INFO0 0x000c4 -#define RK3399_WIN2_DSP_ST0 0x000c8 -#define RK3399_WIN2_COLOR_KEY 0x000cc -#define RK3399_WIN2_MST1 0x000d0 -#define RK3399_WIN2_DSP_INFO1 0x000d4 -#define RK3399_WIN2_DSP_ST1 0x000d8 -#define RK3399_WIN2_SRC_ALPHA_CTRL 0x000dc -#define RK3399_WIN2_MST2 0x000e0 -#define RK3399_WIN2_DSP_INFO2 0x000e4 -#define RK3399_WIN2_DSP_ST2 0x000e8 -#define RK3399_WIN2_DST_ALPHA_CTRL 0x000ec -#define RK3399_WIN2_MST3 0x000f0 -#define RK3399_WIN2_DSP_INFO3 0x000f4 -#define RK3399_WIN2_DSP_ST3 0x000f8 -#define RK3399_WIN2_FADING_CTRL 0x000fc -#define RK3399_WIN3_CTRL0 0x00100 -#define RK3399_WIN3_CTRL1 0x00104 -#define RK3399_WIN3_VIR0_1 0x00108 -#define RK3399_WIN3_VIR2_3 0x0010c -#define RK3399_WIN3_MST0 0x00110 -#define RK3399_WIN3_DSP_INFO0 0x00114 -#define RK3399_WIN3_DSP_ST0 0x00118 -#define RK3399_WIN3_COLOR_KEY 0x0011c -#define RK3399_WIN3_MST1 0x00120 -#define RK3399_WIN3_DSP_INFO1 0x00124 -#define RK3399_WIN3_DSP_ST1 0x00128 -#define RK3399_WIN3_SRC_ALPHA_CTRL 0x0012c -#define RK3399_WIN3_MST2 0x00130 -#define RK3399_WIN3_DSP_INFO2 0x00134 -#define RK3399_WIN3_DSP_ST2 0x00138 -#define RK3399_WIN3_DST_ALPHA_CTRL 0x0013c -#define RK3399_WIN3_MST3 0x00140 -#define RK3399_WIN3_DSP_INFO3 0x00144 -#define RK3399_WIN3_DSP_ST3 0x00148 -#define RK3399_WIN3_FADING_CTRL 0x0014c -#define RK3399_HWC_CTRL0 0x00150 -#define RK3399_HWC_CTRL1 0x00154 -#define RK3399_HWC_MST 0x00158 -#define RK3399_HWC_DSP_ST 0x0015c -#define RK3399_HWC_SRC_ALPHA_CTRL 0x00160 -#define RK3399_HWC_DST_ALPHA_CTRL 0x00164 -#define RK3399_HWC_FADING_CTRL 0x00168 -#define RK3399_HWC_RESERVED1 0x0016c -#define RK3399_POST_DSP_HACT_INFO 0x00170 -#define RK3399_POST_DSP_VACT_INFO 0x00174 -#define RK3399_POST_SCL_FACTOR_YRGB 0x00178 -#define RK3399_POST_RESERVED 0x0017c -#define RK3399_POST_SCL_CTRL 0x00180 -#define RK3399_POST_DSP_VACT_INFO_F1 0x00184 -#define RK3399_DSP_HTOTAL_HS_END 0x00188 -#define RK3399_DSP_HACT_ST_END 0x0018c -#define RK3399_DSP_VTOTAL_VS_END 0x00190 -#define RK3399_DSP_VACT_ST_END 0x00194 -#define RK3399_DSP_VS_ST_END_F1 0x00198 -#define RK3399_DSP_VACT_ST_END_F1 0x0019c -#define RK3399_PWM_CTRL 0x001a0 -#define RK3399_PWM_PERIOD_HPR 0x001a4 -#define RK3399_PWM_DUTY_LPR 0x001a8 -#define RK3399_PWM_CNT 0x001ac -#define RK3399_BCSH_COLOR_BAR 0x001b0 -#define RK3399_BCSH_BCS 0x001b4 -#define RK3399_BCSH_H 0x001b8 -#define RK3399_BCSH_CTRL 0x001bc -#define RK3399_CABC_CTRL0 0x001c0 -#define RK3399_CABC_CTRL1 0x001c4 -#define RK3399_CABC_CTRL2 0x001c8 -#define RK3399_CABC_CTRL3 0x001cc -#define RK3399_CABC_GAUSS_LINE0_0 0x001d0 -#define RK3399_CABC_GAUSS_LINE0_1 0x001d4 -#define RK3399_CABC_GAUSS_LINE1_0 0x001d8 -#define RK3399_CABC_GAUSS_LINE1_1 0x001dc -#define RK3399_CABC_GAUSS_LINE2_0 0x001e0 -#define RK3399_CABC_GAUSS_LINE2_1 0x001e4 -#define RK3399_FRC_LOWER01_0 0x001e8 -#define RK3399_FRC_LOWER01_1 0x001ec -#define RK3399_FRC_LOWER10_0 0x001f0 -#define RK3399_FRC_LOWER10_1 0x001f4 -#define RK3399_FRC_LOWER11_0 0x001f8 -#define RK3399_FRC_LOWER11_1 0x001fc -#define RK3399_AFBCD0_CTRL 0x00200 -#define RK3399_AFBCD0_HDR_PTR 0x00204 -#define RK3399_AFBCD0_PIC_SIZE 0x00208 -#define RK3399_AFBCD0_STATUS 0x0020c -#define RK3399_AFBCD1_CTRL 0x00220 -#define RK3399_AFBCD1_HDR_PTR 0x00224 -#define RK3399_AFBCD1_PIC_SIZE 0x00228 -#define RK3399_AFBCD1_STATUS 0x0022c -#define RK3399_AFBCD2_CTRL 0x00240 -#define RK3399_AFBCD2_HDR_PTR 0x00244 -#define RK3399_AFBCD2_PIC_SIZE 0x00248 -#define RK3399_AFBCD2_STATUS 0x0024c -#define RK3399_AFBCD3_CTRL 0x00260 -#define RK3399_AFBCD3_HDR_PTR 0x00264 -#define RK3399_AFBCD3_PIC_SIZE 0x00268 -#define RK3399_AFBCD3_STATUS 0x0026c -#define RK3399_INTR_EN0 0x00280 -#define RK3399_INTR_CLEAR0 0x00284 -#define RK3399_INTR_STATUS0 0x00288 -#define RK3399_INTR_RAW_STATUS0 0x0028c -#define RK3399_INTR_EN1 0x00290 -#define RK3399_INTR_CLEAR1 0x00294 -#define RK3399_INTR_STATUS1 0x00298 -#define RK3399_INTR_RAW_STATUS1 0x0029c -#define RK3399_LINE_FLAG 0x002a0 -#define RK3399_VOP_STATUS 0x002a4 -#define RK3399_BLANKING_VALUE 0x002a8 -#define RK3399_MCU_BYPASS_PORT 0x002ac -#define RK3399_WIN0_DSP_BG 0x002b0 -#define RK3399_WIN1_DSP_BG 0x002b4 -#define RK3399_WIN2_DSP_BG 0x002b8 -#define RK3399_WIN3_DSP_BG 0x002bc -#define RK3399_YUV2YUV_WIN 0x002c0 -#define RK3399_YUV2YUV_POST 0x002c4 -#define RK3399_AUTO_GATING_EN 0x002cc -#define RK3399_WIN0_CSC_COE 0x003a0 -#define RK3399_WIN1_CSC_COE 0x003c0 -#define RK3399_WIN2_CSC_COE 0x003e0 -#define RK3399_WIN3_CSC_COE 0x00400 -#define RK3399_HWC_CSC_COE 0x00420 -#define RK3399_BCSH_R2Y_CSC_COE 0x00440 -#define RK3399_BCSH_Y2R_CSC_COE 0x00460 -#define RK3399_POST_YUV2YUV_Y2R_COE 0x00480 -#define RK3399_POST_YUV2YUV_3X3_COE 0x004a0 -#define RK3399_POST_YUV2YUV_R2Y_COE 0x004c0 -#define RK3399_WIN0_YUV2YUV_Y2R 0x004e0 -#define RK3399_WIN0_YUV2YUV_3X3 0x00500 -#define RK3399_WIN0_YUV2YUV_R2Y 0x00520 -#define RK3399_WIN1_YUV2YUV_Y2R 0x00540 -#define RK3399_WIN1_YUV2YUV_3X3 0x00560 -#define RK3399_WIN1_YUV2YUV_R2Y 0x00580 -#define RK3399_WIN2_YUV2YUV_Y2R 0x005a0 -#define RK3399_WIN2_YUV2YUV_3X3 0x005c0 -#define RK3399_WIN2_YUV2YUV_R2Y 0x005e0 -#define RK3399_WIN3_YUV2YUV_Y2R 0x00600 -#define RK3399_WIN3_YUV2YUV_3X3 0x00620 -#define RK3399_WIN3_YUV2YUV_R2Y 0x00640 -#define RK3399_WIN2_LUT_ADDR 0x01000 -#define RK3399_WIN3_LUT_ADDR 0x01400 -#define RK3399_HWC_LUT_ADDR 0x01800 -#define RK3399_CABC_GAMMA_LUT_ADDR 0x01c00 -#define RK3399_GAMMA_LUT_ADDR 0x02000 -/* rk3399 register definition end */ - #endif /* _ROCKCHIP_VOP_REG_H */ diff --git a/drivers/iio/adc/rockchip_saradc.c b/drivers/iio/adc/rockchip_saradc.c index ae6d3324f518..5f612d694b33 100644 --- a/drivers/iio/adc/rockchip_saradc.c +++ b/drivers/iio/adc/rockchip_saradc.c @@ -224,6 +224,11 @@ static int rockchip_saradc_probe(struct platform_device *pdev) info = iio_priv(indio_dev); match = of_match_device(rockchip_saradc_match, &pdev->dev); + if (!match) { + dev_err(&pdev->dev, "failed to match device\n"); + return -ENODEV; + } + info->data = match->data; mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -235,7 +240,8 @@ static int rockchip_saradc_probe(struct platform_device *pdev) * The reset should be an optional property, as it should work * with old devicetrees as well */ - info->reset = devm_reset_control_get(&pdev->dev, "saradc-apb"); + info->reset = devm_reset_control_get_exclusive(&pdev->dev, + "saradc-apb"); if (IS_ERR(info->reset)) { ret = PTR_ERR(info->reset); if (ret != -ENOENT) diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index 6ee3a25ae731..99c6366a2551 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -219,7 +219,7 @@ config OMAP_IOMMU_DEBUG config ROCKCHIP_IOMMU bool "Rockchip IOMMU Support" - depends on ARM + depends on ARM || ARM64 depends on ARCH_ROCKCHIP || COMPILE_TEST select IOMMU_API select ARM_DMA_USE_IOMMU diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c index 4ba48a26b389..78ea341c7c75 100644 --- a/drivers/iommu/rockchip-iommu.c +++ b/drivers/iommu/rockchip-iommu.c @@ -90,7 +90,9 @@ struct rk_iommu { struct device *dev; void __iomem **bases; int num_mmu; - int irq; + int *irq; + int num_irq; + bool reset_disabled; struct iommu_device iommu; struct list_head node; /* entry in rk_iommu_domain.iommus */ struct iommu_domain *domain; /* domain to which iommu is attached */ @@ -414,6 +416,9 @@ static int rk_iommu_force_reset(struct rk_iommu *iommu) int ret, i; u32 dte_addr; + if (iommu->reset_disabled) + return 0; + /* * Check if register DTE_ADDR is working by writing DTE_ADDR_DUMMY * and verifying that upper 5 nybbles are read back. @@ -825,10 +830,12 @@ static int rk_iommu_attach_device(struct iommu_domain *domain, iommu->domain = domain; - ret = devm_request_irq(iommu->dev, iommu->irq, rk_iommu_irq, - IRQF_SHARED, dev_name(dev), iommu); - if (ret) - return ret; + for (i = 0; i < iommu->num_irq; i++) { + ret = devm_request_irq(iommu->dev, iommu->irq[i], rk_iommu_irq, + IRQF_SHARED, dev_name(dev), iommu); + if (ret) + return ret; + } for (i = 0; i < iommu->num_mmu; i++) { rk_iommu_write(iommu->bases[i], RK_MMU_DTE_ADDR, @@ -878,7 +885,8 @@ static void rk_iommu_detach_device(struct iommu_domain *domain, } rk_iommu_disable_stall(iommu); - devm_free_irq(iommu->dev, iommu->irq, iommu); + for (i = 0; i < iommu->num_irq; i++) + devm_free_irq(iommu->dev, iommu->irq[i], iommu); iommu->domain = NULL; @@ -1157,12 +1165,28 @@ static int rk_iommu_probe(struct platform_device *pdev) if (iommu->num_mmu == 0) return PTR_ERR(iommu->bases[0]); - iommu->irq = platform_get_irq(pdev, 0); - if (iommu->irq < 0) { - dev_err(dev, "Failed to get IRQ, %d\n", iommu->irq); + iommu->num_irq = platform_irq_count(pdev); + if (iommu->num_irq < 0) + return iommu->num_irq; + if (iommu->num_irq == 0) return -ENXIO; + + iommu->irq = devm_kcalloc(dev, iommu->num_irq, sizeof(*iommu->irq), + GFP_KERNEL); + if (!iommu->irq) + return -ENOMEM; + + for (i = 0; i < iommu->num_irq; i++) { + iommu->irq[i] = platform_get_irq(pdev, i); + if (iommu->irq[i] < 0) { + dev_err(dev, "Failed to get IRQ, %d\n", iommu->irq[i]); + return -ENXIO; + } } + iommu->reset_disabled = device_property_read_bool(dev, + "rockchip,disable-mmu-reset"); + err = iommu_device_sysfs_add(&iommu->iommu, dev, NULL, dev_name(dev)); if (err) return err; diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c index fd087cbb0bde..8e60ebaeaadb 100644 --- a/drivers/mfd/rk808.c +++ b/drivers/mfd/rk808.c @@ -325,7 +325,7 @@ static int rk808_probe(struct i2c_client *client, void (*pm_pwroff_fn)(void); int nr_pre_init_regs; int nr_cells; - int pm_off = 0; + int pm_off = 0, msb, lsb; int ret; int i; @@ -333,14 +333,23 @@ static int rk808_probe(struct i2c_client *client, if (!rk808) return -ENOMEM; - rk808->variant = i2c_smbus_read_word_data(client, RK808_ID_MSB); - if (rk808->variant < 0) { - dev_err(&client->dev, "Failed to read the chip id at 0x%02x\n", + /* Read chip variant */ + msb = i2c_smbus_read_byte_data(client, RK808_ID_MSB); + if (msb < 0) { + dev_err(&client->dev, "failed to read the chip id at 0x%x\n", RK808_ID_MSB); - return rk808->variant; + return msb; } - dev_dbg(&client->dev, "Chip id: 0x%x\n", (unsigned int)rk808->variant); + lsb = i2c_smbus_read_byte_data(client, RK808_ID_LSB); + if (lsb < 0) { + dev_err(&client->dev, "failed to read the chip id at 0x%x\n", + RK808_ID_LSB); + return lsb; + } + + rk808->variant = ((msb << 8) | lsb) & RK8XX_ID_MSK; + dev_info(&client->dev, "chip id: 0x%x\n", (unsigned int)rk808->variant); switch (rk808->variant) { case RK808_ID: diff --git a/drivers/pci/host/pcie-rockchip.c b/drivers/pci/host/pcie-rockchip.c index 4590eb95d5d8..4a0dfff94fa6 100644 --- a/drivers/pci/host/pcie-rockchip.c +++ b/drivers/pci/host/pcie-rockchip.c @@ -47,6 +47,7 @@ #define HIWORD_UPDATE_BIT(val) HIWORD_UPDATE(val, val) #define ENCODE_LANES(x) ((((x) >> 1) & 3) << 4) +#define MAX_LANE_NUM 4 #define PCIE_CLIENT_BASE 0x0 #define PCIE_CLIENT_CONFIG (PCIE_CLIENT_BASE + 0x00) @@ -204,7 +205,8 @@ struct rockchip_pcie { void __iomem *reg_base; /* DT axi-base */ void __iomem *apb_base; /* DT apb-base */ - struct phy *phy; + bool legacy_phy; + struct phy *phys[MAX_LANE_NUM]; struct reset_control *core_rst; struct reset_control *mgmt_rst; struct reset_control *mgmt_sticky_rst; @@ -474,7 +476,7 @@ static void rockchip_pcie_set_power_limit(struct rockchip_pcie *rockchip) static int rockchip_pcie_init_port(struct rockchip_pcie *rockchip) { struct device *dev = rockchip->dev; - int err; + int err, i; u32 status; gpiod_set_value(rockchip->ep_gpio, 0); @@ -497,10 +499,12 @@ static int rockchip_pcie_init_port(struct rockchip_pcie *rockchip) return err; } - err = phy_init(rockchip->phy); - if (err < 0) { - dev_err(dev, "fail to init phy, err %d\n", err); - return err; + for (i = 0; i < MAX_LANE_NUM; i++) { + err = phy_init(rockchip->phys[i]); + if (err) { + dev_err(dev, "init phy%d err %d\n", i, err); + return err; + } } err = reset_control_assert(rockchip->core_rst); @@ -562,10 +566,12 @@ static int rockchip_pcie_init_port(struct rockchip_pcie *rockchip) PCIE_CLIENT_MODE_RC, PCIE_CLIENT_CONFIG); - err = phy_power_on(rockchip->phy); - if (err) { - dev_err(dev, "fail to power on phy, err %d\n", err); - return err; + for (i = 0; i < MAX_LANE_NUM; i++) { + err = phy_power_on(rockchip->phys[i]); + if (err) { + dev_err(dev, "power on phy%d err %d\n", i, err); + return err; + } } /* @@ -818,6 +824,46 @@ static void rockchip_pcie_legacy_int_handler(struct irq_desc *desc) chained_irq_exit(chip, desc); } +static int rockchip_pcie_get_phys(struct rockchip_pcie *rockchip) +{ + struct device *dev = rockchip->dev; + struct phy *phy; + char *name; + u32 i; + + phy = devm_phy_get(dev, "pcie-phy"); + if (!IS_ERR(phy)) { + rockchip->legacy_phy = true; + rockchip->phys[0] = phy; + dev_warn(dev, "legacy phy model is deprecated!\n"); + return 0; + } + + if (PTR_ERR(phy) == -EPROBE_DEFER) + return PTR_ERR(phy); + + dev_dbg(dev, "missing legacy phy; search for per-lane PHY\n"); + + for (i = 0; i < MAX_LANE_NUM; i++) { + name = kasprintf(GFP_KERNEL, "pcie-phy-%u", i); + if (!name) + return -ENOMEM; + + phy = devm_of_phy_get(dev, dev->of_node, name); + kfree(name); + + if (IS_ERR(phy)) { + if (PTR_ERR(phy) != -EPROBE_DEFER) + dev_err(dev, "missing phy for lane %d: %ld\n", + i, PTR_ERR(phy)); + return PTR_ERR(phy); + } + + rockchip->phys[i] = phy; + } + + return 0; +} /** * rockchip_pcie_parse_dt - Parse Device Tree @@ -848,12 +894,9 @@ static int rockchip_pcie_parse_dt(struct rockchip_pcie *rockchip) if (IS_ERR(rockchip->apb_base)) return PTR_ERR(rockchip->apb_base); - rockchip->phy = devm_phy_get(dev, "pcie-phy"); - if (IS_ERR(rockchip->phy)) { - if (PTR_ERR(rockchip->phy) != -EPROBE_DEFER) - dev_err(dev, "missing phy\n"); - return PTR_ERR(rockchip->phy); - } + err = rockchip_pcie_get_phys(rockchip); + if (err) + return err; rockchip->lanes = 1; err = of_property_read_u32(node, "num-lanes", &rockchip->lanes); @@ -1235,7 +1278,7 @@ static int rockchip_pcie_wait_l2(struct rockchip_pcie *rockchip) static int __maybe_unused rockchip_pcie_suspend_noirq(struct device *dev) { struct rockchip_pcie *rockchip = dev_get_drvdata(dev); - int ret; + int ret, i; /* disable core and cli int since we don't need to ack PME_ACK */ rockchip_pcie_write(rockchip, (PCIE_CLIENT_INT_CLI << 16) | @@ -1248,8 +1291,10 @@ static int __maybe_unused rockchip_pcie_suspend_noirq(struct device *dev) return ret; } - phy_power_off(rockchip->phy); - phy_exit(rockchip->phy); + for (i = 0; i < MAX_LANE_NUM; i++) { + phy_power_off(rockchip->phys[i]); + phy_exit(rockchip->phys[i]); + } clk_disable_unprepare(rockchip->clk_pcie_pm); clk_disable_unprepare(rockchip->hclk_pcie); @@ -1441,14 +1486,17 @@ static int rockchip_pcie_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct rockchip_pcie *rockchip = dev_get_drvdata(dev); + int i; pci_stop_root_bus(rockchip->root_bus); pci_remove_root_bus(rockchip->root_bus); pci_unmap_iospace(rockchip->io); irq_domain_remove(rockchip->irq_domain); - phy_power_off(rockchip->phy); - phy_exit(rockchip->phy); + for (i = 0; i < MAX_LANE_NUM; i++) { + phy_power_off(rockchip->phys[i]); + phy_exit(rockchip->phys[i]); + } clk_disable_unprepare(rockchip->clk_pcie_pm); clk_disable_unprepare(rockchip->hclk_pcie); diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index afaf7b643eeb..01009b2a7d74 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -15,73 +15,6 @@ config GENERIC_PHY phy users can obtain reference to the PHY. All the users of this framework should select this config. -config PHY_BCM_NS_USB2 - tristate "Broadcom Northstar USB 2.0 PHY Driver" - depends on ARCH_BCM_IPROC || COMPILE_TEST - depends on HAS_IOMEM && OF - select GENERIC_PHY - help - Enable this to support Broadcom USB 2.0 PHY connected to the USB - controller on Northstar family. - -config PHY_BCM_NS_USB3 - tristate "Broadcom Northstar USB 3.0 PHY Driver" - depends on ARCH_BCM_IPROC || COMPILE_TEST - depends on HAS_IOMEM && OF - select GENERIC_PHY - help - Enable this to support Broadcom USB 3.0 PHY connected to the USB - controller on Northstar family. - -config PHY_BERLIN_USB - tristate "Marvell Berlin USB PHY Driver" - depends on ARCH_BERLIN && RESET_CONTROLLER && HAS_IOMEM && OF - select GENERIC_PHY - help - Enable this to support the USB PHY on Marvell Berlin SoCs. - -config PHY_BERLIN_SATA - tristate "Marvell Berlin SATA PHY driver" - depends on ARCH_BERLIN && HAS_IOMEM && OF - select GENERIC_PHY - help - Enable this to support the SATA PHY on Marvell Berlin SoCs. - -config ARMADA375_USBCLUSTER_PHY - def_bool y - depends on MACH_ARMADA_375 || COMPILE_TEST - depends on OF && HAS_IOMEM - select GENERIC_PHY - -config PHY_DA8XX_USB - tristate "TI DA8xx USB PHY Driver" - depends on ARCH_DAVINCI_DA8XX - select GENERIC_PHY - select MFD_SYSCON - help - Enable this to support the USB PHY on DA8xx SoCs. - - This driver controls both the USB 1.1 PHY and the USB 2.0 PHY. - -config PHY_DM816X_USB - tristate "TI dm816x USB PHY driver" - depends on ARCH_OMAP2PLUS - depends on USB_SUPPORT - select GENERIC_PHY - select USB_PHY - help - Enable this for dm816x USB to work. - -config PHY_EXYNOS_MIPI_VIDEO - tristate "S5P/EXYNOS SoC series MIPI CSI-2/DSI PHY driver" - depends on HAS_IOMEM - depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST - select GENERIC_PHY - default y if ARCH_S5PV210 || ARCH_EXYNOS - help - Support for MIPI CSI-2 and MIPI DSI DPHY found on Samsung S5P - and EXYNOS SoCs. - config PHY_LPC18XX_USB_OTG tristate "NXP LPC18xx/43xx SoC USB OTG PHY driver" depends on OF && (ARCH_LPC18XX || COMPILE_TEST) @@ -93,146 +26,6 @@ config PHY_LPC18XX_USB_OTG This driver is need for USB0 support on LPC18xx/43xx and takes care of enabling and clock setup. -config PHY_PXA_28NM_HSIC - tristate "Marvell USB HSIC 28nm PHY Driver" - depends on HAS_IOMEM - select GENERIC_PHY - help - Enable this to support Marvell USB HSIC PHY driver for Marvell - SoC. This driver will do the PHY initialization and shutdown. - The PHY driver will be used by Marvell ehci driver. - - To compile this driver as a module, choose M here. - -config PHY_PXA_28NM_USB2 - tristate "Marvell USB 2.0 28nm PHY Driver" - depends on HAS_IOMEM - select GENERIC_PHY - help - Enable this to support Marvell USB 2.0 PHY driver for Marvell - SoC. This driver will do the PHY initialization and shutdown. - The PHY driver will be used by Marvell udc/ehci/otg driver. - - To compile this driver as a module, choose M here. - -config PHY_MVEBU_SATA - def_bool y - depends on ARCH_DOVE || MACH_DOVE || MACH_KIRKWOOD - depends on OF - select GENERIC_PHY - -config PHY_MIPHY28LP - tristate "STMicroelectronics MIPHY28LP PHY driver for STiH407" - depends on ARCH_STI - select GENERIC_PHY - help - Enable this to support the miphy transceiver (for SATA/PCIE/USB3) - that is part of STMicroelectronics STiH407 SoC. - -config PHY_RCAR_GEN2 - tristate "Renesas R-Car generation 2 USB PHY driver" - depends on ARCH_RENESAS - depends on GENERIC_PHY - help - Support for USB PHY found on Renesas R-Car generation 2 SoCs. - -config PHY_RCAR_GEN3_USB2 - tristate "Renesas R-Car generation 3 USB 2.0 PHY driver" - depends on ARCH_RENESAS - depends on EXTCON - select GENERIC_PHY - help - Support for USB 2.0 PHY found on Renesas R-Car generation 3 SoCs. - -config OMAP_CONTROL_PHY - tristate "OMAP CONTROL PHY Driver" - depends on ARCH_OMAP2PLUS || COMPILE_TEST - help - Enable this to add support for the PHY part present in the control - module. This driver has API to power on the USB2 PHY and to write to - the mailbox. The mailbox is present only in omap4 and the register to - power on the USB2 PHY is present in OMAP4 and OMAP5. OMAP5 has an - additional register to power on USB3 PHY/SATA PHY/PCIE PHY - (PIPE3 PHY). - -config OMAP_USB2 - tristate "OMAP USB2 PHY Driver" - depends on ARCH_OMAP2PLUS - depends on USB_SUPPORT - select GENERIC_PHY - select USB_PHY - select OMAP_CONTROL_PHY - depends on OMAP_OCP2SCP - help - Enable this to support the transceiver that is part of SOC. This - driver takes care of all the PHY functionality apart from comparator. - The USB OTG controller communicates with the comparator using this - driver. - -config TI_PIPE3 - tristate "TI PIPE3 PHY Driver" - depends on ARCH_OMAP2PLUS || COMPILE_TEST - select GENERIC_PHY - select OMAP_CONTROL_PHY - depends on OMAP_OCP2SCP - help - Enable this to support the PIPE3 PHY that is part of TI SOCs. This - driver takes care of all the PHY functionality apart from comparator. - This driver interacts with the "OMAP Control PHY Driver" to power - on/off the PHY. - -config TWL4030_USB - tristate "TWL4030 USB Transceiver Driver" - depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS - depends on USB_SUPPORT - depends on USB_GADGET || !USB_GADGET # if USB_GADGET=m, this can't 'y' - select GENERIC_PHY - select USB_PHY - help - Enable this to support the USB OTG transceiver on TWL4030 - family chips (including the TWL5030 and TPS659x0 devices). - This transceiver supports high and full speed devices plus, - in host mode, low speed. - -config PHY_EXYNOS_DP_VIDEO - tristate "EXYNOS SoC series Display Port PHY driver" - depends on OF - depends on ARCH_EXYNOS || COMPILE_TEST - default ARCH_EXYNOS - select GENERIC_PHY - help - Support for Display Port PHY found on Samsung EXYNOS SoCs. - -config BCM_KONA_USB2_PHY - tristate "Broadcom Kona USB2 PHY Driver" - depends on HAS_IOMEM - select GENERIC_PHY - help - Enable this to support the Broadcom Kona USB 2.0 PHY. - -config PHY_EXYNOS5250_SATA - tristate "Exynos5250 Sata SerDes/PHY driver" - depends on SOC_EXYNOS5250 - depends on HAS_IOMEM - depends on OF - select GENERIC_PHY - select I2C - select I2C_S3C2410 - select MFD_SYSCON - help - Enable this to support SATA SerDes/Phy found on Samsung's - Exynos5250 based SoCs.This SerDes/Phy supports SATA 1.5 Gb/s, - SATA 3.0 Gb/s, SATA 6.0 Gb/s speeds. It supports one SATA host - port to accept one SATA device. - -config PHY_HIX5HD2_SATA - tristate "HIX5HD2 SATA PHY Driver" - depends on ARCH_HIX5HD2 && OF && HAS_IOMEM - select GENERIC_PHY - select MFD_SYSCON - help - Support for SATA PHY on Hisilicon hix5hd2 Soc. - config PHY_MT65XX_USB3 tristate "Mediatek USB3.0 PHY Driver" depends on ARCH_MEDIATEK && OF @@ -241,104 +34,6 @@ config PHY_MT65XX_USB3 Say 'Y' here to add support for Mediatek USB3.0 PHY driver, it supports multiple usb2.0 and usb3.0 ports. -config PHY_HI6220_USB - tristate "hi6220 USB PHY support" - depends on (ARCH_HISI && ARM64) || COMPILE_TEST - select GENERIC_PHY - select MFD_SYSCON - help - Enable this to support the HISILICON HI6220 USB PHY. - - To compile this driver as a module, choose M here. - -config PHY_SUN4I_USB - tristate "Allwinner sunxi SoC USB PHY driver" - depends on ARCH_SUNXI && HAS_IOMEM && OF - depends on RESET_CONTROLLER - depends on EXTCON - depends on POWER_SUPPLY - depends on USB_SUPPORT - select GENERIC_PHY - select USB_COMMON - help - Enable this to support the transceiver that is part of Allwinner - sunxi SoCs. - - This driver controls the entire USB PHY block, both the USB OTG - parts, as well as the 2 regular USB 2 host PHYs. - -config PHY_SUN9I_USB - tristate "Allwinner sun9i SoC USB PHY driver" - depends on ARCH_SUNXI && HAS_IOMEM && OF - depends on RESET_CONTROLLER - depends on USB_SUPPORT - select USB_COMMON - select GENERIC_PHY - help - Enable this to support the transceiver that is part of Allwinner - sun9i SoCs. - - This driver controls each individual USB 2 host PHY. - -config PHY_SAMSUNG_USB2 - tristate "Samsung USB 2.0 PHY driver" - depends on HAS_IOMEM - depends on USB_EHCI_EXYNOS || USB_OHCI_EXYNOS || USB_DWC2 - select GENERIC_PHY - select MFD_SYSCON - default ARCH_EXYNOS - help - Enable this to support the Samsung USB 2.0 PHY driver for Samsung - SoCs. This driver provides the interface for USB 2.0 PHY. Support - for particular PHYs will be enabled based on the SoC type in addition - to this driver. - -config PHY_S5PV210_USB2 - bool "Support for S5PV210" - depends on PHY_SAMSUNG_USB2 - depends on ARCH_S5PV210 - help - Enable USB PHY support for S5PV210. This option requires that Samsung - USB 2.0 PHY driver is enabled and means that support for this - particular SoC is compiled in the driver. In case of S5PV210 two phys - are available - device and host. - -config PHY_EXYNOS4210_USB2 - bool - depends on PHY_SAMSUNG_USB2 - default CPU_EXYNOS4210 - -config PHY_EXYNOS4X12_USB2 - bool - depends on PHY_SAMSUNG_USB2 - default SOC_EXYNOS3250 || SOC_EXYNOS4212 || SOC_EXYNOS4412 - -config PHY_EXYNOS5250_USB2 - bool - depends on PHY_SAMSUNG_USB2 - default SOC_EXYNOS5250 || SOC_EXYNOS5420 - -config PHY_EXYNOS5_USBDRD - tristate "Exynos5 SoC series USB DRD PHY driver" - depends on ARCH_EXYNOS && OF - depends on HAS_IOMEM - depends on USB_DWC3_EXYNOS - select GENERIC_PHY - select MFD_SYSCON - default y - help - Enable USB DRD PHY support for Exynos 5 SoC series. - This driver provides PHY interface for USB 3.0 DRD controller - present on Exynos5 SoC series. - -config PHY_EXYNOS_PCIE - bool "Exynos PCIe PHY driver" - depends on OF && (ARCH_EXYNOS || COMPILE_TEST) - select GENERIC_PHY - help - Enable PCIe PHY support for Exynos SoC series. - This driver provides PHY interface for Exynos PCIe controller. - config PHY_PISTACHIO_USB tristate "IMG Pistachio USB2.0 PHY driver" depends on MACH_PISTACHIO @@ -346,83 +41,6 @@ config PHY_PISTACHIO_USB help Enable this to support the USB2.0 PHY on the IMG Pistachio SoC. -config PHY_QCOM_APQ8064_SATA - tristate "Qualcomm APQ8064 SATA SerDes/PHY driver" - depends on ARCH_QCOM - depends on HAS_IOMEM - depends on OF - select GENERIC_PHY - -config PHY_QCOM_IPQ806X_SATA - tristate "Qualcomm IPQ806x SATA SerDes/PHY driver" - depends on ARCH_QCOM - depends on HAS_IOMEM - depends on OF - select GENERIC_PHY - -config PHY_ROCKCHIP_USB - tristate "Rockchip USB2 PHY Driver" - depends on ARCH_ROCKCHIP && OF - select GENERIC_PHY - help - Enable this to support the Rockchip USB 2.0 PHY. - -config PHY_ROCKCHIP_INNO_USB2 - tristate "Rockchip INNO USB2PHY Driver" - depends on (ARCH_ROCKCHIP || COMPILE_TEST) && OF - depends on COMMON_CLK - depends on EXTCON - depends on USB_SUPPORT - select GENERIC_PHY - select USB_COMMON - help - Support for Rockchip USB2.0 PHY with Innosilicon IP block. - -config PHY_ROCKCHIP_EMMC - tristate "Rockchip EMMC PHY Driver" - depends on ARCH_ROCKCHIP && OF - select GENERIC_PHY - help - Enable this to support the Rockchip EMMC PHY. - -config PHY_ROCKCHIP_DP - tristate "Rockchip Display Port PHY Driver" - depends on ARCH_ROCKCHIP && OF - select GENERIC_PHY - help - Enable this to support the Rockchip Display Port PHY. - -config PHY_ROCKCHIP_PCIE - tristate "Rockchip PCIe PHY Driver" - depends on (ARCH_ROCKCHIP && OF) || COMPILE_TEST - select GENERIC_PHY - select MFD_SYSCON - help - Enable this to support the Rockchip PCIe PHY. - -config PHY_ROCKCHIP_TYPEC - tristate "Rockchip TYPEC PHY Driver" - depends on OF && (ARCH_ROCKCHIP || COMPILE_TEST) - select EXTCON - select GENERIC_PHY - select RESET_CONTROLLER - help - Enable this to support the Rockchip USB TYPEC PHY. - -config PHY_ST_SPEAR1310_MIPHY - tristate "ST SPEAR1310-MIPHY driver" - select GENERIC_PHY - depends on MACH_SPEAR1310 || COMPILE_TEST - help - Support for ST SPEAr1310 MIPHY which can be used for PCIe and SATA. - -config PHY_ST_SPEAR1340_MIPHY - tristate "ST SPEAR1340-MIPHY driver" - select GENERIC_PHY - depends on MACH_SPEAR1340 || COMPILE_TEST - help - Support for ST SPEAr1340 MIPHY which can be used for PCIe and SATA. - config PHY_XGENE tristate "APM X-Gene 15Gbps PHY support" depends on HAS_IOMEM && OF && (ARM64 || COMPILE_TEST) @@ -430,104 +48,17 @@ config PHY_XGENE help This option enables support for APM X-Gene SoC multi-purpose PHY. -config PHY_STIH407_USB - tristate "STMicroelectronics USB2 picoPHY driver for STiH407 family" - depends on RESET_CONTROLLER - depends on ARCH_STI || COMPILE_TEST - select GENERIC_PHY - help - Enable this support to enable the picoPHY device used by USB2 - and USB3 controllers on STMicroelectronics STiH407 SoC families. - -config PHY_QCOM_QMP - tristate "Qualcomm QMP PHY Driver" - depends on OF && COMMON_CLK && (ARCH_QCOM || COMPILE_TEST) - select GENERIC_PHY - help - Enable this to support the QMP PHY transceiver that is used - with controllers such as PCIe, UFS, and USB on Qualcomm chips. - -config PHY_QCOM_QUSB2 - tristate "Qualcomm QUSB2 PHY Driver" - depends on OF && (ARCH_QCOM || COMPILE_TEST) - depends on NVMEM || !NVMEM - select GENERIC_PHY - help - Enable this to support the HighSpeed QUSB2 PHY transceiver for USB - controllers on Qualcomm chips. This driver supports the high-speed - PHY which is usually paired with either the ChipIdea or Synopsys DWC3 - USB IPs on MSM SOCs. - -config PHY_QCOM_UFS - tristate "Qualcomm UFS PHY driver" - depends on OF && ARCH_QCOM - select GENERIC_PHY - help - Support for UFS PHY on QCOM chipsets. - -config PHY_QCOM_USB_HS - tristate "Qualcomm USB HS PHY module" - depends on USB_ULPI_BUS - depends on EXTCON || !EXTCON # if EXTCON=m, this cannot be built-in - select GENERIC_PHY - help - Support for the USB high-speed ULPI compliant phy on Qualcomm - chipsets. - -config PHY_QCOM_USB_HSIC - tristate "Qualcomm USB HSIC ULPI PHY module" - depends on USB_ULPI_BUS - select GENERIC_PHY - help - Support for the USB HSIC ULPI compliant PHY on QCOM chipsets. - -config PHY_TUSB1210 - tristate "TI TUSB1210 ULPI PHY module" - depends on USB_ULPI_BUS - select GENERIC_PHY - help - Support for TI TUSB1210 USB ULPI PHY. - -config PHY_BRCM_SATA - tristate "Broadcom SATA PHY driver" - depends on ARCH_BRCMSTB || ARCH_BCM_IPROC || BMIPS_GENERIC || COMPILE_TEST - depends on OF - select GENERIC_PHY - default ARCH_BCM_IPROC - help - Enable this to support the Broadcom SATA PHY. - If unsure, say N. - -config PHY_CYGNUS_PCIE - tristate "Broadcom Cygnus PCIe PHY driver" - depends on OF && (ARCH_BCM_CYGNUS || COMPILE_TEST) - select GENERIC_PHY - default ARCH_BCM_CYGNUS - help - Enable this to support the Broadcom Cygnus PCIe PHY. - If unsure, say N. - +source "drivers/phy/allwinner/Kconfig" +source "drivers/phy/amlogic/Kconfig" +source "drivers/phy/broadcom/Kconfig" +source "drivers/phy/hisilicon/Kconfig" +source "drivers/phy/marvell/Kconfig" +source "drivers/phy/qualcomm/Kconfig" +source "drivers/phy/renesas/Kconfig" +source "drivers/phy/rockchip/Kconfig" +source "drivers/phy/samsung/Kconfig" +source "drivers/phy/st/Kconfig" source "drivers/phy/tegra/Kconfig" - -config PHY_NS2_PCIE - tristate "Broadcom Northstar2 PCIe PHY driver" - depends on OF && MDIO_BUS_MUX_BCM_IPROC - select GENERIC_PHY - default ARCH_BCM_IPROC - help - Enable this to support the Broadcom Northstar2 PCIe PHY. - If unsure, say N. - -config PHY_MESON8B_USB2 - tristate "Meson8b and GXBB USB2 PHY driver" - default ARCH_MESON - depends on OF && (ARCH_MESON || COMPILE_TEST) - depends on USB_SUPPORT - select USB_COMMON - select GENERIC_PHY - help - Enable this to support the Meson USB2 PHYs found in Meson8b - and GXBB SoCs. - If unsure, say N. +source "drivers/phy/ti/Kconfig" endmenu diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index f8047b4639fa..c1bd1fa3c853 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -3,64 +3,20 @@ # obj-$(CONFIG_GENERIC_PHY) += phy-core.o -obj-$(CONFIG_PHY_BCM_NS_USB2) += phy-bcm-ns-usb2.o -obj-$(CONFIG_PHY_BCM_NS_USB3) += phy-bcm-ns-usb3.o -obj-$(CONFIG_PHY_BERLIN_USB) += phy-berlin-usb.o -obj-$(CONFIG_PHY_BERLIN_SATA) += phy-berlin-sata.o -obj-$(CONFIG_PHY_DA8XX_USB) += phy-da8xx-usb.o -obj-$(CONFIG_PHY_DM816X_USB) += phy-dm816x-usb.o -obj-$(CONFIG_ARMADA375_USBCLUSTER_PHY) += phy-armada375-usb2.o -obj-$(CONFIG_BCM_KONA_USB2_PHY) += phy-bcm-kona-usb2.o -obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO) += phy-exynos-dp-video.o -obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO) += phy-exynos-mipi-video.o obj-$(CONFIG_PHY_LPC18XX_USB_OTG) += phy-lpc18xx-usb-otg.o -obj-$(CONFIG_PHY_PXA_28NM_USB2) += phy-pxa-28nm-usb2.o -obj-$(CONFIG_PHY_PXA_28NM_HSIC) += phy-pxa-28nm-hsic.o -obj-$(CONFIG_PHY_MVEBU_SATA) += phy-mvebu-sata.o -obj-$(CONFIG_PHY_MIPHY28LP) += phy-miphy28lp.o -obj-$(CONFIG_PHY_RCAR_GEN2) += phy-rcar-gen2.o -obj-$(CONFIG_PHY_RCAR_GEN3_USB2) += phy-rcar-gen3-usb2.o -obj-$(CONFIG_OMAP_CONTROL_PHY) += phy-omap-control.o -obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o -obj-$(CONFIG_TI_PIPE3) += phy-ti-pipe3.o -obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o -obj-$(CONFIG_PHY_EXYNOS5250_SATA) += phy-exynos5250-sata.o -obj-$(CONFIG_PHY_HIX5HD2_SATA) += phy-hix5hd2-sata.o -obj-$(CONFIG_PHY_HI6220_USB) += phy-hi6220-usb.o obj-$(CONFIG_PHY_MT65XX_USB3) += phy-mt65xx-usb3.o -obj-$(CONFIG_PHY_SUN4I_USB) += phy-sun4i-usb.o -obj-$(CONFIG_PHY_SUN9I_USB) += phy-sun9i-usb.o -obj-$(CONFIG_PHY_SAMSUNG_USB2) += phy-exynos-usb2.o -phy-exynos-usb2-y += phy-samsung-usb2.o -phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4210_USB2) += phy-exynos4210-usb2.o -phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4X12_USB2) += phy-exynos4x12-usb2.o -phy-exynos-usb2-$(CONFIG_PHY_EXYNOS5250_USB2) += phy-exynos5250-usb2.o -phy-exynos-usb2-$(CONFIG_PHY_S5PV210_USB2) += phy-s5pv210-usb2.o -obj-$(CONFIG_PHY_EXYNOS5_USBDRD) += phy-exynos5-usbdrd.o -obj-$(CONFIG_PHY_EXYNOS_PCIE) += phy-exynos-pcie.o -obj-$(CONFIG_PHY_QCOM_APQ8064_SATA) += phy-qcom-apq8064-sata.o -obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o -obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2) += phy-rockchip-inno-usb2.o -obj-$(CONFIG_PHY_ROCKCHIP_EMMC) += phy-rockchip-emmc.o -obj-$(CONFIG_PHY_ROCKCHIP_PCIE) += phy-rockchip-pcie.o -obj-$(CONFIG_PHY_ROCKCHIP_DP) += phy-rockchip-dp.o -obj-$(CONFIG_PHY_ROCKCHIP_TYPEC) += phy-rockchip-typec.o -obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o -obj-$(CONFIG_PHY_ST_SPEAR1310_MIPHY) += phy-spear1310-miphy.o -obj-$(CONFIG_PHY_ST_SPEAR1340_MIPHY) += phy-spear1340-miphy.o obj-$(CONFIG_PHY_XGENE) += phy-xgene.o -obj-$(CONFIG_PHY_STIH407_USB) += phy-stih407-usb.o -obj-$(CONFIG_PHY_QCOM_QMP) += phy-qcom-qmp.o -obj-$(CONFIG_PHY_QCOM_QUSB2) += phy-qcom-qusb2.o -obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs.o -obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-20nm.o -obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-14nm.o -obj-$(CONFIG_PHY_QCOM_USB_HS) += phy-qcom-usb-hs.o -obj-$(CONFIG_PHY_QCOM_USB_HSIC) += phy-qcom-usb-hsic.o -obj-$(CONFIG_PHY_TUSB1210) += phy-tusb1210.o -obj-$(CONFIG_PHY_BRCM_SATA) += phy-brcm-sata.o obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o -obj-$(CONFIG_PHY_CYGNUS_PCIE) += phy-bcm-cygnus-pcie.o -obj-$(CONFIG_ARCH_TEGRA) += tegra/ -obj-$(CONFIG_PHY_NS2_PCIE) += phy-bcm-ns2-pcie.o -obj-$(CONFIG_PHY_MESON8B_USB2) += phy-meson8b-usb2.o + +obj-$(CONFIG_ARCH_SUNXI) += allwinner/ +obj-$(CONFIG_ARCH_MESON) += amlogic/ +obj-$(CONFIG_ARCH_RENESAS) += renesas/ +obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ +obj-$(CONFIG_ARCH_TEGRA) += tegra/ +obj-y += broadcom/ \ + hisilicon/ \ + marvell/ \ + qualcomm/ \ + samsung/ \ + st/ \ + ti/ diff --git a/drivers/phy/allwinner/Kconfig b/drivers/phy/allwinner/Kconfig new file mode 100644 index 000000000000..cdc1e745ba47 --- /dev/null +++ b/drivers/phy/allwinner/Kconfig @@ -0,0 +1,31 @@ +# +# Phy drivers for Allwinner platforms +# +config PHY_SUN4I_USB + tristate "Allwinner sunxi SoC USB PHY driver" + depends on ARCH_SUNXI && HAS_IOMEM && OF + depends on RESET_CONTROLLER + depends on EXTCON + depends on POWER_SUPPLY + depends on USB_SUPPORT + select GENERIC_PHY + select USB_COMMON + help + Enable this to support the transceiver that is part of Allwinner + sunxi SoCs. + + This driver controls the entire USB PHY block, both the USB OTG + parts, as well as the 2 regular USB 2 host PHYs. + +config PHY_SUN9I_USB + tristate "Allwinner sun9i SoC USB PHY driver" + depends on ARCH_SUNXI && HAS_IOMEM && OF + depends on RESET_CONTROLLER + depends on USB_SUPPORT + select USB_COMMON + select GENERIC_PHY + help + Enable this to support the transceiver that is part of Allwinner + sun9i SoCs. + + This driver controls each individual USB 2 host PHY. diff --git a/drivers/phy/allwinner/Makefile b/drivers/phy/allwinner/Makefile new file mode 100644 index 000000000000..8605529c01a1 --- /dev/null +++ b/drivers/phy/allwinner/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_PHY_SUN4I_USB) += phy-sun4i-usb.o +obj-$(CONFIG_PHY_SUN9I_USB) += phy-sun9i-usb.o diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c index bbf06cfe5898..bbf06cfe5898 100644 --- a/drivers/phy/phy-sun4i-usb.c +++ b/drivers/phy/allwinner/phy-sun4i-usb.c diff --git a/drivers/phy/phy-sun9i-usb.c b/drivers/phy/allwinner/phy-sun9i-usb.c index 28fce4bce638..28fce4bce638 100644 --- a/drivers/phy/phy-sun9i-usb.c +++ b/drivers/phy/allwinner/phy-sun9i-usb.c diff --git a/drivers/phy/amlogic/Kconfig b/drivers/phy/amlogic/Kconfig new file mode 100644 index 000000000000..edcd5b65179f --- /dev/null +++ b/drivers/phy/amlogic/Kconfig @@ -0,0 +1,14 @@ +# +# Phy drivers for Amlogic platforms +# +config PHY_MESON8B_USB2 + tristate "Meson8b and GXBB USB2 PHY driver" + default ARCH_MESON + depends on OF && (ARCH_MESON || COMPILE_TEST) + depends on USB_SUPPORT + select USB_COMMON + select GENERIC_PHY + help + Enable this to support the Meson USB2 PHYs found in Meson8b + and GXBB SoCs. + If unsure, say N. diff --git a/drivers/phy/amlogic/Makefile b/drivers/phy/amlogic/Makefile new file mode 100644 index 000000000000..47b6eecc3864 --- /dev/null +++ b/drivers/phy/amlogic/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_PHY_MESON8B_USB2) += phy-meson8b-usb2.o diff --git a/drivers/phy/phy-meson8b-usb2.c b/drivers/phy/amlogic/phy-meson8b-usb2.c index 30f56a6a411f..30f56a6a411f 100644 --- a/drivers/phy/phy-meson8b-usb2.c +++ b/drivers/phy/amlogic/phy-meson8b-usb2.c diff --git a/drivers/phy/broadcom/Kconfig b/drivers/phy/broadcom/Kconfig new file mode 100644 index 000000000000..d2d99023ec50 --- /dev/null +++ b/drivers/phy/broadcom/Kconfig @@ -0,0 +1,55 @@ +# +# Phy drivers for Broadcom platforms +# +config PHY_CYGNUS_PCIE + tristate "Broadcom Cygnus PCIe PHY driver" + depends on OF && (ARCH_BCM_CYGNUS || COMPILE_TEST) + select GENERIC_PHY + default ARCH_BCM_CYGNUS + help + Enable this to support the Broadcom Cygnus PCIe PHY. + If unsure, say N. + +config BCM_KONA_USB2_PHY + tristate "Broadcom Kona USB2 PHY Driver" + depends on HAS_IOMEM + select GENERIC_PHY + help + Enable this to support the Broadcom Kona USB 2.0 PHY. + +config PHY_BCM_NS_USB2 + tristate "Broadcom Northstar USB 2.0 PHY Driver" + depends on ARCH_BCM_IPROC || COMPILE_TEST + depends on HAS_IOMEM && OF + select GENERIC_PHY + help + Enable this to support Broadcom USB 2.0 PHY connected to the USB + controller on Northstar family. + +config PHY_BCM_NS_USB3 + tristate "Broadcom Northstar USB 3.0 PHY Driver" + depends on ARCH_BCM_IPROC || COMPILE_TEST + depends on HAS_IOMEM && OF + select GENERIC_PHY + help + Enable this to support Broadcom USB 3.0 PHY connected to the USB + controller on Northstar family. + +config PHY_NS2_PCIE + tristate "Broadcom Northstar2 PCIe PHY driver" + depends on OF && MDIO_BUS_MUX_BCM_IPROC + select GENERIC_PHY + default ARCH_BCM_IPROC + help + Enable this to support the Broadcom Northstar2 PCIe PHY. + If unsure, say N. + +config PHY_BRCM_SATA + tristate "Broadcom SATA PHY driver" + depends on ARCH_BRCMSTB || ARCH_BCM_IPROC || BMIPS_GENERIC || COMPILE_TEST + depends on OF + select GENERIC_PHY + default ARCH_BCM_IPROC + help + Enable this to support the Broadcom SATA PHY. + If unsure, say N. diff --git a/drivers/phy/broadcom/Makefile b/drivers/phy/broadcom/Makefile new file mode 100644 index 000000000000..357a7d16529f --- /dev/null +++ b/drivers/phy/broadcom/Makefile @@ -0,0 +1,6 @@ +obj-$(CONFIG_PHY_CYGNUS_PCIE) += phy-bcm-cygnus-pcie.o +obj-$(CONFIG_BCM_KONA_USB2_PHY) += phy-bcm-kona-usb2.o +obj-$(CONFIG_PHY_BCM_NS_USB2) += phy-bcm-ns-usb2.o +obj-$(CONFIG_PHY_BCM_NS_USB3) += phy-bcm-ns-usb3.o +obj-$(CONFIG_PHY_NS2_PCIE) += phy-bcm-ns2-pcie.o +obj-$(CONFIG_PHY_BRCM_SATA) += phy-brcm-sata.o diff --git a/drivers/phy/phy-bcm-cygnus-pcie.c b/drivers/phy/broadcom/phy-bcm-cygnus-pcie.c index 0f4ac5d63cff..0f4ac5d63cff 100644 --- a/drivers/phy/phy-bcm-cygnus-pcie.c +++ b/drivers/phy/broadcom/phy-bcm-cygnus-pcie.c diff --git a/drivers/phy/phy-bcm-kona-usb2.c b/drivers/phy/broadcom/phy-bcm-kona-usb2.c index 7b67fe49e30b..7b67fe49e30b 100644 --- a/drivers/phy/phy-bcm-kona-usb2.c +++ b/drivers/phy/broadcom/phy-bcm-kona-usb2.c diff --git a/drivers/phy/phy-bcm-ns-usb2.c b/drivers/phy/broadcom/phy-bcm-ns-usb2.c index 58dff80e9386..58dff80e9386 100644 --- a/drivers/phy/phy-bcm-ns-usb2.c +++ b/drivers/phy/broadcom/phy-bcm-ns-usb2.c diff --git a/drivers/phy/phy-bcm-ns-usb3.c b/drivers/phy/broadcom/phy-bcm-ns-usb3.c index 22b5e7047fa6..22b5e7047fa6 100644 --- a/drivers/phy/phy-bcm-ns-usb3.c +++ b/drivers/phy/broadcom/phy-bcm-ns-usb3.c diff --git a/drivers/phy/phy-bcm-ns2-pcie.c b/drivers/phy/broadcom/phy-bcm-ns2-pcie.c index 4c7d11d2b378..4c7d11d2b378 100644 --- a/drivers/phy/phy-bcm-ns2-pcie.c +++ b/drivers/phy/broadcom/phy-bcm-ns2-pcie.c diff --git a/drivers/phy/phy-brcm-sata.c b/drivers/phy/broadcom/phy-brcm-sata.c index ccbc3d994998..ccbc3d994998 100644 --- a/drivers/phy/phy-brcm-sata.c +++ b/drivers/phy/broadcom/phy-brcm-sata.c diff --git a/drivers/phy/hisilicon/Kconfig b/drivers/phy/hisilicon/Kconfig new file mode 100644 index 000000000000..6164c4cd0f65 --- /dev/null +++ b/drivers/phy/hisilicon/Kconfig @@ -0,0 +1,20 @@ +# +# Phy drivers for Hisilicon platforms +# +config PHY_HI6220_USB + tristate "hi6220 USB PHY support" + depends on (ARCH_HISI && ARM64) || COMPILE_TEST + select GENERIC_PHY + select MFD_SYSCON + help + Enable this to support the HISILICON HI6220 USB PHY. + + To compile this driver as a module, choose M here. + +config PHY_HIX5HD2_SATA + tristate "HIX5HD2 SATA PHY Driver" + depends on ARCH_HIX5HD2 && OF && HAS_IOMEM + select GENERIC_PHY + select MFD_SYSCON + help + Support for SATA PHY on Hisilicon hix5hd2 Soc. diff --git a/drivers/phy/hisilicon/Makefile b/drivers/phy/hisilicon/Makefile new file mode 100644 index 000000000000..541b348187a8 --- /dev/null +++ b/drivers/phy/hisilicon/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_PHY_HI6220_USB) += phy-hi6220-usb.o +obj-$(CONFIG_PHY_HIX5HD2_SATA) += phy-hix5hd2-sata.o diff --git a/drivers/phy/phy-hi6220-usb.c b/drivers/phy/hisilicon/phy-hi6220-usb.c index 398c1021deec..398c1021deec 100644 --- a/drivers/phy/phy-hi6220-usb.c +++ b/drivers/phy/hisilicon/phy-hi6220-usb.c diff --git a/drivers/phy/phy-hix5hd2-sata.c b/drivers/phy/hisilicon/phy-hix5hd2-sata.c index e5ab3aa78b9d..e5ab3aa78b9d 100644 --- a/drivers/phy/phy-hix5hd2-sata.c +++ b/drivers/phy/hisilicon/phy-hix5hd2-sata.c diff --git a/drivers/phy/marvell/Kconfig b/drivers/phy/marvell/Kconfig new file mode 100644 index 000000000000..048d8893bc2e --- /dev/null +++ b/drivers/phy/marvell/Kconfig @@ -0,0 +1,50 @@ +# +# Phy drivers for Marvell platforms +# +config ARMADA375_USBCLUSTER_PHY + def_bool y + depends on MACH_ARMADA_375 || COMPILE_TEST + depends on OF && HAS_IOMEM + select GENERIC_PHY + +config PHY_BERLIN_SATA + tristate "Marvell Berlin SATA PHY driver" + depends on ARCH_BERLIN && HAS_IOMEM && OF + select GENERIC_PHY + help + Enable this to support the SATA PHY on Marvell Berlin SoCs. + +config PHY_BERLIN_USB + tristate "Marvell Berlin USB PHY Driver" + depends on ARCH_BERLIN && RESET_CONTROLLER && HAS_IOMEM && OF + select GENERIC_PHY + help + Enable this to support the USB PHY on Marvell Berlin SoCs. + +config PHY_MVEBU_SATA + def_bool y + depends on ARCH_DOVE || MACH_DOVE || MACH_KIRKWOOD + depends on OF + select GENERIC_PHY + +config PHY_PXA_28NM_HSIC + tristate "Marvell USB HSIC 28nm PHY Driver" + depends on HAS_IOMEM + select GENERIC_PHY + help + Enable this to support Marvell USB HSIC PHY driver for Marvell + SoC. This driver will do the PHY initialization and shutdown. + The PHY driver will be used by Marvell ehci driver. + + To compile this driver as a module, choose M here. + +config PHY_PXA_28NM_USB2 + tristate "Marvell USB 2.0 28nm PHY Driver" + depends on HAS_IOMEM + select GENERIC_PHY + help + Enable this to support Marvell USB 2.0 PHY driver for Marvell + SoC. This driver will do the PHY initialization and shutdown. + The PHY driver will be used by Marvell udc/ehci/otg driver. + + To compile this driver as a module, choose M here. diff --git a/drivers/phy/marvell/Makefile b/drivers/phy/marvell/Makefile new file mode 100644 index 000000000000..3fc188f59118 --- /dev/null +++ b/drivers/phy/marvell/Makefile @@ -0,0 +1,6 @@ +obj-$(CONFIG_ARMADA375_USBCLUSTER_PHY) += phy-armada375-usb2.o +obj-$(CONFIG_PHY_BERLIN_SATA) += phy-berlin-sata.o +obj-$(CONFIG_PHY_BERLIN_USB) += phy-berlin-usb.o +obj-$(CONFIG_PHY_MVEBU_SATA) += phy-mvebu-sata.o +obj-$(CONFIG_PHY_PXA_28NM_HSIC) += phy-pxa-28nm-hsic.o +obj-$(CONFIG_PHY_PXA_28NM_USB2) += phy-pxa-28nm-usb2.o diff --git a/drivers/phy/phy-armada375-usb2.c b/drivers/phy/marvell/phy-armada375-usb2.c index 1a3db288c0a9..1a3db288c0a9 100644 --- a/drivers/phy/phy-armada375-usb2.c +++ b/drivers/phy/marvell/phy-armada375-usb2.c diff --git a/drivers/phy/phy-berlin-sata.c b/drivers/phy/marvell/phy-berlin-sata.c index 2c7a57f2d595..2c7a57f2d595 100644 --- a/drivers/phy/phy-berlin-sata.c +++ b/drivers/phy/marvell/phy-berlin-sata.c diff --git a/drivers/phy/phy-berlin-usb.c b/drivers/phy/marvell/phy-berlin-usb.c index 2017751ede26..2017751ede26 100644 --- a/drivers/phy/phy-berlin-usb.c +++ b/drivers/phy/marvell/phy-berlin-usb.c diff --git a/drivers/phy/phy-mvebu-sata.c b/drivers/phy/marvell/phy-mvebu-sata.c index 768ce92e81ce..768ce92e81ce 100644 --- a/drivers/phy/phy-mvebu-sata.c +++ b/drivers/phy/marvell/phy-mvebu-sata.c diff --git a/drivers/phy/phy-pxa-28nm-hsic.c b/drivers/phy/marvell/phy-pxa-28nm-hsic.c index 234aacf4db20..234aacf4db20 100644 --- a/drivers/phy/phy-pxa-28nm-hsic.c +++ b/drivers/phy/marvell/phy-pxa-28nm-hsic.c diff --git a/drivers/phy/phy-pxa-28nm-usb2.c b/drivers/phy/marvell/phy-pxa-28nm-usb2.c index 37e9c8ca4983..37e9c8ca4983 100644 --- a/drivers/phy/phy-pxa-28nm-usb2.c +++ b/drivers/phy/marvell/phy-pxa-28nm-usb2.c diff --git a/drivers/phy/qualcomm/Kconfig b/drivers/phy/qualcomm/Kconfig new file mode 100644 index 000000000000..7bfa64baf837 --- /dev/null +++ b/drivers/phy/qualcomm/Kconfig @@ -0,0 +1,58 @@ +# +# Phy drivers for Qualcomm platforms +# +config PHY_QCOM_APQ8064_SATA + tristate "Qualcomm APQ8064 SATA SerDes/PHY driver" + depends on ARCH_QCOM + depends on HAS_IOMEM + depends on OF + select GENERIC_PHY + +config PHY_QCOM_IPQ806X_SATA + tristate "Qualcomm IPQ806x SATA SerDes/PHY driver" + depends on ARCH_QCOM + depends on HAS_IOMEM + depends on OF + select GENERIC_PHY + +config PHY_QCOM_QMP + tristate "Qualcomm QMP PHY Driver" + depends on OF && COMMON_CLK && (ARCH_QCOM || COMPILE_TEST) + select GENERIC_PHY + help + Enable this to support the QMP PHY transceiver that is used + with controllers such as PCIe, UFS, and USB on Qualcomm chips. + +config PHY_QCOM_QUSB2 + tristate "Qualcomm QUSB2 PHY Driver" + depends on OF && (ARCH_QCOM || COMPILE_TEST) + depends on NVMEM || !NVMEM + select GENERIC_PHY + help + Enable this to support the HighSpeed QUSB2 PHY transceiver for USB + controllers on Qualcomm chips. This driver supports the high-speed + PHY which is usually paired with either the ChipIdea or Synopsys DWC3 + USB IPs on MSM SOCs. + +config PHY_QCOM_UFS + tristate "Qualcomm UFS PHY driver" + depends on OF && ARCH_QCOM + select GENERIC_PHY + help + Support for UFS PHY on QCOM chipsets. + +config PHY_QCOM_USB_HS + tristate "Qualcomm USB HS PHY module" + depends on USB_ULPI_BUS + depends on EXTCON || !EXTCON # if EXTCON=m, this cannot be built-in + select GENERIC_PHY + help + Support for the USB high-speed ULPI compliant phy on Qualcomm + chipsets. + +config PHY_QCOM_USB_HSIC + tristate "Qualcomm USB HSIC ULPI PHY module" + depends on USB_ULPI_BUS + select GENERIC_PHY + help + Support for the USB HSIC ULPI compliant PHY on QCOM chipsets. diff --git a/drivers/phy/qualcomm/Makefile b/drivers/phy/qualcomm/Makefile new file mode 100644 index 000000000000..2e183d7695fd --- /dev/null +++ b/drivers/phy/qualcomm/Makefile @@ -0,0 +1,9 @@ +obj-$(CONFIG_PHY_QCOM_APQ8064_SATA) += phy-qcom-apq8064-sata.o +obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o +obj-$(CONFIG_PHY_QCOM_QMP) += phy-qcom-qmp.o +obj-$(CONFIG_PHY_QCOM_QUSB2) += phy-qcom-qusb2.o +obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs.o +obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-14nm.o +obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-20nm.o +obj-$(CONFIG_PHY_QCOM_USB_HS) += phy-qcom-usb-hs.o +obj-$(CONFIG_PHY_QCOM_USB_HSIC) += phy-qcom-usb-hsic.o diff --git a/drivers/phy/phy-qcom-apq8064-sata.c b/drivers/phy/qualcomm/phy-qcom-apq8064-sata.c index 69ce2afac015..69ce2afac015 100644 --- a/drivers/phy/phy-qcom-apq8064-sata.c +++ b/drivers/phy/qualcomm/phy-qcom-apq8064-sata.c diff --git a/drivers/phy/phy-qcom-ipq806x-sata.c b/drivers/phy/qualcomm/phy-qcom-ipq806x-sata.c index 0ad127cc9298..0ad127cc9298 100644 --- a/drivers/phy/phy-qcom-ipq806x-sata.c +++ b/drivers/phy/qualcomm/phy-qcom-ipq806x-sata.c diff --git a/drivers/phy/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c index 78ca62897784..78ca62897784 100644 --- a/drivers/phy/phy-qcom-qmp.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp.c diff --git a/drivers/phy/phy-qcom-qusb2.c b/drivers/phy/qualcomm/phy-qcom-qusb2.c index 6c575244c0fb..6c575244c0fb 100644 --- a/drivers/phy/phy-qcom-qusb2.c +++ b/drivers/phy/qualcomm/phy-qcom-qusb2.c diff --git a/drivers/phy/phy-qcom-ufs-i.h b/drivers/phy/qualcomm/phy-qcom-ufs-i.h index 13b02b7de30b..13b02b7de30b 100644 --- a/drivers/phy/phy-qcom-ufs-i.h +++ b/drivers/phy/qualcomm/phy-qcom-ufs-i.h diff --git a/drivers/phy/phy-qcom-ufs-qmp-14nm.c b/drivers/phy/qualcomm/phy-qcom-ufs-qmp-14nm.c index 12a1b498dc4b..12a1b498dc4b 100644 --- a/drivers/phy/phy-qcom-ufs-qmp-14nm.c +++ b/drivers/phy/qualcomm/phy-qcom-ufs-qmp-14nm.c diff --git a/drivers/phy/phy-qcom-ufs-qmp-14nm.h b/drivers/phy/qualcomm/phy-qcom-ufs-qmp-14nm.h index 3aefdbacbcd0..3aefdbacbcd0 100644 --- a/drivers/phy/phy-qcom-ufs-qmp-14nm.h +++ b/drivers/phy/qualcomm/phy-qcom-ufs-qmp-14nm.h diff --git a/drivers/phy/phy-qcom-ufs-qmp-20nm.c b/drivers/phy/qualcomm/phy-qcom-ufs-qmp-20nm.c index 4f68acb58b73..4f68acb58b73 100644 --- a/drivers/phy/phy-qcom-ufs-qmp-20nm.c +++ b/drivers/phy/qualcomm/phy-qcom-ufs-qmp-20nm.c diff --git a/drivers/phy/phy-qcom-ufs-qmp-20nm.h b/drivers/phy/qualcomm/phy-qcom-ufs-qmp-20nm.h index 4f3076bb3d71..4f3076bb3d71 100644 --- a/drivers/phy/phy-qcom-ufs-qmp-20nm.h +++ b/drivers/phy/qualcomm/phy-qcom-ufs-qmp-20nm.h diff --git a/drivers/phy/phy-qcom-ufs.c b/drivers/phy/qualcomm/phy-qcom-ufs.c index 43865ef340e2..43865ef340e2 100644 --- a/drivers/phy/phy-qcom-ufs.c +++ b/drivers/phy/qualcomm/phy-qcom-ufs.c diff --git a/drivers/phy/phy-qcom-usb-hs.c b/drivers/phy/qualcomm/phy-qcom-usb-hs.c index 94dfbfd739c3..4b20abc3ae2f 100644 --- a/drivers/phy/phy-qcom-usb-hs.c +++ b/drivers/phy/qualcomm/phy-qcom-usb-hs.c @@ -11,12 +11,11 @@ #include <linux/clk.h> #include <linux/regulator/consumer.h> #include <linux/of_device.h> +#include <linux/phy/phy.h> #include <linux/reset.h> #include <linux/extcon.h> #include <linux/notifier.h> -#include "ulpi_phy.h" - #define ULPI_PWR_CLK_MNG_REG 0x88 # define ULPI_PWR_OTG_COMP_DISABLE BIT(0) diff --git a/drivers/phy/phy-qcom-usb-hsic.c b/drivers/phy/qualcomm/phy-qcom-usb-hsic.c index 47690f9945b9..c110563a73cb 100644 --- a/drivers/phy/phy-qcom-usb-hsic.c +++ b/drivers/phy/qualcomm/phy-qcom-usb-hsic.c @@ -8,13 +8,12 @@ #include <linux/module.h> #include <linux/ulpi/driver.h> #include <linux/ulpi/regs.h> +#include <linux/phy/phy.h> #include <linux/pinctrl/consumer.h> #include <linux/pinctrl/pinctrl-state.h> #include <linux/delay.h> #include <linux/clk.h> -#include "ulpi_phy.h" - #define ULPI_HSIC_CFG 0x30 #define ULPI_HSIC_IO_CAL 0x33 diff --git a/drivers/phy/renesas/Kconfig b/drivers/phy/renesas/Kconfig new file mode 100644 index 000000000000..432e2715e9c4 --- /dev/null +++ b/drivers/phy/renesas/Kconfig @@ -0,0 +1,17 @@ +# +# Phy drivers for Renesas platforms +# +config PHY_RCAR_GEN2 + tristate "Renesas R-Car generation 2 USB PHY driver" + depends on ARCH_RENESAS + depends on GENERIC_PHY + help + Support for USB PHY found on Renesas R-Car generation 2 SoCs. + +config PHY_RCAR_GEN3_USB2 + tristate "Renesas R-Car generation 3 USB 2.0 PHY driver" + depends on ARCH_RENESAS + depends on EXTCON + select GENERIC_PHY + help + Support for USB 2.0 PHY found on Renesas R-Car generation 3 SoCs. diff --git a/drivers/phy/renesas/Makefile b/drivers/phy/renesas/Makefile new file mode 100644 index 000000000000..695241aebf69 --- /dev/null +++ b/drivers/phy/renesas/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_PHY_RCAR_GEN2) += phy-rcar-gen2.o +obj-$(CONFIG_PHY_RCAR_GEN3_USB2) += phy-rcar-gen3-usb2.o diff --git a/drivers/phy/phy-rcar-gen2.c b/drivers/phy/renesas/phy-rcar-gen2.c index 97d4dd6ea924..97d4dd6ea924 100644 --- a/drivers/phy/phy-rcar-gen2.c +++ b/drivers/phy/renesas/phy-rcar-gen2.c diff --git a/drivers/phy/phy-rcar-gen3-usb2.c b/drivers/phy/renesas/phy-rcar-gen3-usb2.c index 54c34298a000..54c34298a000 100644 --- a/drivers/phy/phy-rcar-gen3-usb2.c +++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c diff --git a/drivers/phy/rockchip/Kconfig b/drivers/phy/rockchip/Kconfig new file mode 100644 index 000000000000..f5325b2b679e --- /dev/null +++ b/drivers/phy/rockchip/Kconfig @@ -0,0 +1,51 @@ +# +# Phy drivers for Rockchip platforms +# +config PHY_ROCKCHIP_DP + tristate "Rockchip Display Port PHY Driver" + depends on ARCH_ROCKCHIP && OF + select GENERIC_PHY + help + Enable this to support the Rockchip Display Port PHY. + +config PHY_ROCKCHIP_EMMC + tristate "Rockchip EMMC PHY Driver" + depends on ARCH_ROCKCHIP && OF + select GENERIC_PHY + help + Enable this to support the Rockchip EMMC PHY. + +config PHY_ROCKCHIP_INNO_USB2 + tristate "Rockchip INNO USB2PHY Driver" + depends on (ARCH_ROCKCHIP || COMPILE_TEST) && OF + depends on COMMON_CLK + depends on EXTCON + depends on USB_SUPPORT + select GENERIC_PHY + select USB_COMMON + help + Support for Rockchip USB2.0 PHY with Innosilicon IP block. + +config PHY_ROCKCHIP_PCIE + tristate "Rockchip PCIe PHY Driver" + depends on (ARCH_ROCKCHIP && OF) || COMPILE_TEST + select GENERIC_PHY + select MFD_SYSCON + help + Enable this to support the Rockchip PCIe PHY. + +config PHY_ROCKCHIP_TYPEC + tristate "Rockchip TYPEC PHY Driver" + depends on OF && (ARCH_ROCKCHIP || COMPILE_TEST) + select EXTCON + select GENERIC_PHY + select RESET_CONTROLLER + help + Enable this to support the Rockchip USB TYPEC PHY. + +config PHY_ROCKCHIP_USB + tristate "Rockchip USB2 PHY Driver" + depends on ARCH_ROCKCHIP && OF + select GENERIC_PHY + help + Enable this to support the Rockchip USB 2.0 PHY. diff --git a/drivers/phy/rockchip/Makefile b/drivers/phy/rockchip/Makefile new file mode 100644 index 000000000000..bd0acdf38e0f --- /dev/null +++ b/drivers/phy/rockchip/Makefile @@ -0,0 +1,6 @@ +obj-$(CONFIG_PHY_ROCKCHIP_DP) += phy-rockchip-dp.o +obj-$(CONFIG_PHY_ROCKCHIP_EMMC) += phy-rockchip-emmc.o +obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2) += phy-rockchip-inno-usb2.o +obj-$(CONFIG_PHY_ROCKCHIP_PCIE) += phy-rockchip-pcie.o +obj-$(CONFIG_PHY_ROCKCHIP_TYPEC) += phy-rockchip-typec.o +obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o diff --git a/drivers/phy/phy-rockchip-dp.c b/drivers/phy/rockchip/phy-rockchip-dp.c index 8b267a746576..8b267a746576 100644 --- a/drivers/phy/phy-rockchip-dp.c +++ b/drivers/phy/rockchip/phy-rockchip-dp.c diff --git a/drivers/phy/phy-rockchip-emmc.c b/drivers/phy/rockchip/phy-rockchip-emmc.c index f1b24f18e9b2..f1b24f18e9b2 100644 --- a/drivers/phy/phy-rockchip-emmc.c +++ b/drivers/phy/rockchip/phy-rockchip-emmc.c diff --git a/drivers/phy/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c index 8efe78a49916..ee7ce5ee53f9 100644 --- a/drivers/phy/phy-rockchip-inno-usb2.c +++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c @@ -172,6 +172,8 @@ struct rockchip_usb2phy_cfg { * @vbus_attached: otg device vbus status. * @bvalid_irq: IRQ number assigned for vbus valid rise detection. * @ls_irq: IRQ number assigned for linestate detection. + * @otg_mux_irq: IRQ number which multiplex otg-id/otg-bvalid/linestate + * irqs to one irq in otg-port. * @mutex: for register updating in sm_work. * @chg_work: charge detect work. * @otg_sm_work: OTG state machine work. @@ -189,6 +191,7 @@ struct rockchip_usb2phy_port { bool vbus_attached; int bvalid_irq; int ls_irq; + int otg_mux_irq; struct mutex mutex; struct delayed_work chg_work; struct delayed_work otg_sm_work; @@ -202,6 +205,7 @@ struct rockchip_usb2phy_port { /** * struct rockchip_usb2phy: usb2.0 phy driver data. * @grf: General Register Files regmap. + * @usbgrf: USB General Register Files regmap. * @clk: clock struct of phy input clk. * @clk480m: clock struct of phy output clk. * @clk_hw: clock struct of phy output clk management. @@ -216,6 +220,7 @@ struct rockchip_usb2phy_port { struct rockchip_usb2phy { struct device *dev; struct regmap *grf; + struct regmap *usbgrf; struct clk *clk; struct clk *clk480m; struct clk_hw clk480m_hw; @@ -227,7 +232,12 @@ struct rockchip_usb2phy { struct rockchip_usb2phy_port ports[USB2PHY_NUM_PORTS]; }; -static inline int property_enable(struct rockchip_usb2phy *rphy, +static inline struct regmap *get_reg_base(struct rockchip_usb2phy *rphy) +{ + return rphy->usbgrf == NULL ? rphy->grf : rphy->usbgrf; +} + +static inline int property_enable(struct regmap *base, const struct usb2phy_reg *reg, bool en) { unsigned int val, mask, tmp; @@ -236,17 +246,17 @@ static inline int property_enable(struct rockchip_usb2phy *rphy, mask = GENMASK(reg->bitend, reg->bitstart); val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT); - return regmap_write(rphy->grf, reg->offset, val); + return regmap_write(base, reg->offset, val); } -static inline bool property_enabled(struct rockchip_usb2phy *rphy, +static inline bool property_enabled(struct regmap *base, const struct usb2phy_reg *reg) { int ret; unsigned int tmp, orig; unsigned int mask = GENMASK(reg->bitend, reg->bitstart); - ret = regmap_read(rphy->grf, reg->offset, &orig); + ret = regmap_read(base, reg->offset, &orig); if (ret) return false; @@ -258,11 +268,12 @@ static int rockchip_usb2phy_clk480m_prepare(struct clk_hw *hw) { struct rockchip_usb2phy *rphy = container_of(hw, struct rockchip_usb2phy, clk480m_hw); + struct regmap *base = get_reg_base(rphy); int ret; /* turn on 480m clk output if it is off */ - if (!property_enabled(rphy, &rphy->phy_cfg->clkout_ctl)) { - ret = property_enable(rphy, &rphy->phy_cfg->clkout_ctl, true); + if (!property_enabled(base, &rphy->phy_cfg->clkout_ctl)) { + ret = property_enable(base, &rphy->phy_cfg->clkout_ctl, true); if (ret) return ret; @@ -277,17 +288,19 @@ static void rockchip_usb2phy_clk480m_unprepare(struct clk_hw *hw) { struct rockchip_usb2phy *rphy = container_of(hw, struct rockchip_usb2phy, clk480m_hw); + struct regmap *base = get_reg_base(rphy); /* turn off 480m clk output */ - property_enable(rphy, &rphy->phy_cfg->clkout_ctl, false); + property_enable(base, &rphy->phy_cfg->clkout_ctl, false); } static int rockchip_usb2phy_clk480m_prepared(struct clk_hw *hw) { struct rockchip_usb2phy *rphy = container_of(hw, struct rockchip_usb2phy, clk480m_hw); + struct regmap *base = get_reg_base(rphy); - return property_enabled(rphy, &rphy->phy_cfg->clkout_ctl); + return property_enabled(base, &rphy->phy_cfg->clkout_ctl); } static unsigned long @@ -406,33 +419,36 @@ static int rockchip_usb2phy_init(struct phy *phy) mutex_lock(&rport->mutex); if (rport->port_id == USB2PHY_PORT_OTG) { - if (rport->mode != USB_DR_MODE_HOST) { + if (rport->mode != USB_DR_MODE_HOST && + rport->mode != USB_DR_MODE_UNKNOWN) { /* clear bvalid status and enable bvalid detect irq */ - ret = property_enable(rphy, + ret = property_enable(rphy->grf, &rport->port_cfg->bvalid_det_clr, true); if (ret) goto out; - ret = property_enable(rphy, + ret = property_enable(rphy->grf, &rport->port_cfg->bvalid_det_en, true); if (ret) goto out; schedule_delayed_work(&rport->otg_sm_work, - OTG_SCHEDULE_DELAY); + OTG_SCHEDULE_DELAY * 3); } else { /* If OTG works in host only mode, do nothing. */ dev_dbg(&rport->phy->dev, "mode %d\n", rport->mode); } } else if (rport->port_id == USB2PHY_PORT_HOST) { /* clear linestate and enable linestate detect irq */ - ret = property_enable(rphy, &rport->port_cfg->ls_det_clr, true); + ret = property_enable(rphy->grf, + &rport->port_cfg->ls_det_clr, true); if (ret) goto out; - ret = property_enable(rphy, &rport->port_cfg->ls_det_en, true); + ret = property_enable(rphy->grf, + &rport->port_cfg->ls_det_en, true); if (ret) goto out; @@ -448,6 +464,7 @@ static int rockchip_usb2phy_power_on(struct phy *phy) { struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy); struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent); + struct regmap *base = get_reg_base(rphy); int ret; dev_dbg(&rport->phy->dev, "port power on\n"); @@ -459,10 +476,13 @@ static int rockchip_usb2phy_power_on(struct phy *phy) if (ret) return ret; - ret = property_enable(rphy, &rport->port_cfg->phy_sus, false); + ret = property_enable(base, &rport->port_cfg->phy_sus, false); if (ret) return ret; + /* waiting for the utmi_clk to become stable */ + usleep_range(1500, 2000); + rport->suspended = false; return 0; } @@ -471,6 +491,7 @@ static int rockchip_usb2phy_power_off(struct phy *phy) { struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy); struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent); + struct regmap *base = get_reg_base(rphy); int ret; dev_dbg(&rport->phy->dev, "port power off\n"); @@ -478,7 +499,7 @@ static int rockchip_usb2phy_power_off(struct phy *phy) if (rport->suspended) return 0; - ret = property_enable(rphy, &rport->port_cfg->phy_sus, true); + ret = property_enable(base, &rport->port_cfg->phy_sus, true); if (ret) return ret; @@ -493,7 +514,8 @@ static int rockchip_usb2phy_exit(struct phy *phy) struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy); if (rport->port_id == USB2PHY_PORT_OTG && - rport->mode != USB_DR_MODE_HOST) { + rport->mode != USB_DR_MODE_HOST && + rport->mode != USB_DR_MODE_UNKNOWN) { cancel_delayed_work_sync(&rport->otg_sm_work); cancel_delayed_work_sync(&rport->chg_work); } else if (rport->port_id == USB2PHY_PORT_HOST) @@ -521,11 +543,11 @@ static void rockchip_usb2phy_otg_sm_work(struct work_struct *work) bool vbus_attach, sch_work, notify_charger; if (rport->utmi_avalid) - vbus_attach = - property_enabled(rphy, &rport->port_cfg->utmi_avalid); + vbus_attach = property_enabled(rphy->grf, + &rport->port_cfg->utmi_avalid); else - vbus_attach = - property_enabled(rphy, &rport->port_cfg->utmi_bvalid); + vbus_attach = property_enabled(rphy->grf, + &rport->port_cfg->utmi_bvalid); sch_work = false; notify_charger = false; @@ -540,7 +562,7 @@ static void rockchip_usb2phy_otg_sm_work(struct work_struct *work) rockchip_usb2phy_power_off(rport->phy); /* fall through */ case OTG_STATE_B_IDLE: - if (extcon_get_cable_state_(rphy->edev, EXTCON_USB_HOST) > 0) { + if (extcon_get_state(rphy->edev, EXTCON_USB_HOST) > 0) { dev_dbg(&rport->phy->dev, "usb otg host connect\n"); rport->state = OTG_STATE_A_HOST; rockchip_usb2phy_power_on(rport->phy); @@ -593,7 +615,7 @@ static void rockchip_usb2phy_otg_sm_work(struct work_struct *work) rport->vbus_attached = vbus_attach; if (notify_charger && rphy->edev) { - extcon_set_cable_state_(rphy->edev, + extcon_set_state_sync(rphy->edev, cable, vbus_attach); if (cable == EXTCON_CHG_USB_SDP) extcon_set_state_sync(rphy->edev, @@ -614,7 +636,7 @@ static void rockchip_usb2phy_otg_sm_work(struct work_struct *work) sch_work = true; break; case OTG_STATE_A_HOST: - if (extcon_get_cable_state_(rphy->edev, EXTCON_USB_HOST) == 0) { + if (extcon_get_state(rphy->edev, EXTCON_USB_HOST) == 0) { dev_dbg(&rport->phy->dev, "usb otg host disconnect\n"); rport->state = OTG_STATE_B_IDLE; rockchip_usb2phy_power_off(rport->phy); @@ -645,22 +667,28 @@ static const char *chg_to_string(enum power_supply_type chg_type) static void rockchip_chg_enable_dcd(struct rockchip_usb2phy *rphy, bool en) { - property_enable(rphy, &rphy->phy_cfg->chg_det.rdm_pdwn_en, en); - property_enable(rphy, &rphy->phy_cfg->chg_det.idp_src_en, en); + struct regmap *base = get_reg_base(rphy); + + property_enable(base, &rphy->phy_cfg->chg_det.rdm_pdwn_en, en); + property_enable(base, &rphy->phy_cfg->chg_det.idp_src_en, en); } static void rockchip_chg_enable_primary_det(struct rockchip_usb2phy *rphy, bool en) { - property_enable(rphy, &rphy->phy_cfg->chg_det.vdp_src_en, en); - property_enable(rphy, &rphy->phy_cfg->chg_det.idm_sink_en, en); + struct regmap *base = get_reg_base(rphy); + + property_enable(base, &rphy->phy_cfg->chg_det.vdp_src_en, en); + property_enable(base, &rphy->phy_cfg->chg_det.idm_sink_en, en); } static void rockchip_chg_enable_secondary_det(struct rockchip_usb2phy *rphy, bool en) { - property_enable(rphy, &rphy->phy_cfg->chg_det.vdm_src_en, en); - property_enable(rphy, &rphy->phy_cfg->chg_det.idp_sink_en, en); + struct regmap *base = get_reg_base(rphy); + + property_enable(base, &rphy->phy_cfg->chg_det.vdm_src_en, en); + property_enable(base, &rphy->phy_cfg->chg_det.idp_sink_en, en); } #define CHG_DCD_POLL_TIME (100 * HZ / 1000) @@ -672,6 +700,7 @@ static void rockchip_chg_detect_work(struct work_struct *work) struct rockchip_usb2phy_port *rport = container_of(work, struct rockchip_usb2phy_port, chg_work.work); struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); + struct regmap *base = get_reg_base(rphy); bool is_dcd, tmout, vout; unsigned long delay; @@ -682,7 +711,7 @@ static void rockchip_chg_detect_work(struct work_struct *work) if (!rport->suspended) rockchip_usb2phy_power_off(rport->phy); /* put the controller in non-driving mode */ - property_enable(rphy, &rphy->phy_cfg->chg_det.opmode, false); + property_enable(base, &rphy->phy_cfg->chg_det.opmode, false); /* Start DCD processing stage 1 */ rockchip_chg_enable_dcd(rphy, true); rphy->chg_state = USB_CHG_STATE_WAIT_FOR_DCD; @@ -691,7 +720,8 @@ static void rockchip_chg_detect_work(struct work_struct *work) break; case USB_CHG_STATE_WAIT_FOR_DCD: /* get data contact detection status */ - is_dcd = property_enabled(rphy, &rphy->phy_cfg->chg_det.dp_det); + is_dcd = property_enabled(rphy->grf, + &rphy->phy_cfg->chg_det.dp_det); tmout = ++rphy->dcd_retries == CHG_DCD_MAX_RETRIES; /* stage 2 */ if (is_dcd || tmout) { @@ -708,7 +738,8 @@ static void rockchip_chg_detect_work(struct work_struct *work) } break; case USB_CHG_STATE_DCD_DONE: - vout = property_enabled(rphy, &rphy->phy_cfg->chg_det.cp_det); + vout = property_enabled(rphy->grf, + &rphy->phy_cfg->chg_det.cp_det); rockchip_chg_enable_primary_det(rphy, false); if (vout) { /* Voltage Source on DM, Probe on DP */ @@ -729,7 +760,8 @@ static void rockchip_chg_detect_work(struct work_struct *work) } break; case USB_CHG_STATE_PRIMARY_DONE: - vout = property_enabled(rphy, &rphy->phy_cfg->chg_det.dcp_det); + vout = property_enabled(rphy->grf, + &rphy->phy_cfg->chg_det.dcp_det); /* Turn off voltage source */ rockchip_chg_enable_secondary_det(rphy, false); if (vout) @@ -743,7 +775,7 @@ static void rockchip_chg_detect_work(struct work_struct *work) /* fall through */ case USB_CHG_STATE_DETECTED: /* put the controller in normal mode */ - property_enable(rphy, &rphy->phy_cfg->chg_det.opmode, true); + property_enable(base, &rphy->phy_cfg->chg_det.opmode, true); rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work); dev_info(&rport->phy->dev, "charger = %s\n", chg_to_string(rphy->chg_type)); @@ -785,8 +817,7 @@ static void rockchip_usb2phy_sm_work(struct work_struct *work) if (ret < 0) goto next_schedule; - ret = regmap_read(rphy->grf, rport->port_cfg->utmi_hstdet.offset, - &uhd); + ret = regmap_read(rphy->grf, rport->port_cfg->utmi_hstdet.offset, &uhd); if (ret < 0) goto next_schedule; @@ -840,8 +871,8 @@ static void rockchip_usb2phy_sm_work(struct work_struct *work) * activate the linestate detection to get the next device * plug-in irq. */ - property_enable(rphy, &rport->port_cfg->ls_det_clr, true); - property_enable(rphy, &rport->port_cfg->ls_det_en, true); + property_enable(rphy->grf, &rport->port_cfg->ls_det_clr, true); + property_enable(rphy->grf, &rport->port_cfg->ls_det_en, true); /* * we don't need to rearm the delayed work when the phy port @@ -864,14 +895,14 @@ static irqreturn_t rockchip_usb2phy_linestate_irq(int irq, void *data) struct rockchip_usb2phy_port *rport = data; struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); - if (!property_enabled(rphy, &rport->port_cfg->ls_det_st)) + if (!property_enabled(rphy->grf, &rport->port_cfg->ls_det_st)) return IRQ_NONE; mutex_lock(&rport->mutex); /* disable linestate detect irq and clear its status */ - property_enable(rphy, &rport->port_cfg->ls_det_en, false); - property_enable(rphy, &rport->port_cfg->ls_det_clr, true); + property_enable(rphy->grf, &rport->port_cfg->ls_det_en, false); + property_enable(rphy->grf, &rport->port_cfg->ls_det_clr, true); mutex_unlock(&rport->mutex); @@ -891,13 +922,13 @@ static irqreturn_t rockchip_usb2phy_bvalid_irq(int irq, void *data) struct rockchip_usb2phy_port *rport = data; struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); - if (!property_enabled(rphy, &rport->port_cfg->bvalid_det_st)) + if (!property_enabled(rphy->grf, &rport->port_cfg->bvalid_det_st)) return IRQ_NONE; mutex_lock(&rport->mutex); /* clear bvalid detect irq pending status */ - property_enable(rphy, &rport->port_cfg->bvalid_det_clr, true); + property_enable(rphy->grf, &rport->port_cfg->bvalid_det_clr, true); mutex_unlock(&rport->mutex); @@ -906,6 +937,17 @@ static irqreturn_t rockchip_usb2phy_bvalid_irq(int irq, void *data) return IRQ_HANDLED; } +static irqreturn_t rockchip_usb2phy_otg_mux_irq(int irq, void *data) +{ + struct rockchip_usb2phy_port *rport = data; + struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); + + if (property_enabled(rphy->grf, &rport->port_cfg->bvalid_det_st)) + return rockchip_usb2phy_bvalid_irq(irq, data); + else + return IRQ_NONE; +} + static int rockchip_usb2phy_host_port_init(struct rockchip_usb2phy *rphy, struct rockchip_usb2phy_port *rport, struct device_node *child_np) @@ -970,7 +1012,8 @@ static int rockchip_usb2phy_otg_port_init(struct rockchip_usb2phy *rphy, mutex_init(&rport->mutex); rport->mode = of_usb_get_dr_mode_by_phy(child_np, -1); - if (rport->mode == USB_DR_MODE_HOST) { + if (rport->mode == USB_DR_MODE_HOST || + rport->mode == USB_DR_MODE_UNKNOWN) { ret = 0; goto out; } @@ -981,27 +1024,50 @@ static int rockchip_usb2phy_otg_port_init(struct rockchip_usb2phy *rphy, rport->utmi_avalid = of_property_read_bool(child_np, "rockchip,utmi-avalid"); - rport->bvalid_irq = of_irq_get_byname(child_np, "otg-bvalid"); - if (rport->bvalid_irq < 0) { - dev_err(rphy->dev, "no vbus valid irq provided\n"); - ret = rport->bvalid_irq; - goto out; - } + /* + * Some SoCs use one interrupt with otg-id/otg-bvalid/linestate + * interrupts muxed together, so probe the otg-mux interrupt first, + * if not found, then look for the regular interrupts one by one. + */ + rport->otg_mux_irq = of_irq_get_byname(child_np, "otg-mux"); + if (rport->otg_mux_irq > 0) { + ret = devm_request_threaded_irq(rphy->dev, rport->otg_mux_irq, + NULL, + rockchip_usb2phy_otg_mux_irq, + IRQF_ONESHOT, + "rockchip_usb2phy_otg", + rport); + if (ret) { + dev_err(rphy->dev, + "failed to request otg-mux irq handle\n"); + goto out; + } + } else { + rport->bvalid_irq = of_irq_get_byname(child_np, "otg-bvalid"); + if (rport->bvalid_irq < 0) { + dev_err(rphy->dev, "no vbus valid irq provided\n"); + ret = rport->bvalid_irq; + goto out; + } - ret = devm_request_threaded_irq(rphy->dev, rport->bvalid_irq, NULL, - rockchip_usb2phy_bvalid_irq, - IRQF_ONESHOT, - "rockchip_usb2phy_bvalid", rport); - if (ret) { - dev_err(rphy->dev, "failed to request otg-bvalid irq handle\n"); - goto out; + ret = devm_request_threaded_irq(rphy->dev, rport->bvalid_irq, + NULL, + rockchip_usb2phy_bvalid_irq, + IRQF_ONESHOT, + "rockchip_usb2phy_bvalid", + rport); + if (ret) { + dev_err(rphy->dev, + "failed to request otg-bvalid irq handle\n"); + goto out; + } } if (!IS_ERR(rphy->edev)) { rport->event_nb.notifier_call = rockchip_otg_event; - ret = extcon_register_notifier(rphy->edev, EXTCON_USB_HOST, - &rport->event_nb); + ret = devm_extcon_register_notifier(rphy->dev, rphy->edev, + EXTCON_USB_HOST, &rport->event_nb); if (ret) dev_err(rphy->dev, "register USB HOST notifier failed\n"); } @@ -1039,6 +1105,16 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev) if (IS_ERR(rphy->grf)) return PTR_ERR(rphy->grf); + if (of_device_is_compatible(np, "rockchip,rv1108-usb2phy")) { + rphy->usbgrf = + syscon_regmap_lookup_by_phandle(dev->of_node, + "rockchip,usbgrf"); + if (IS_ERR(rphy->usbgrf)) + return PTR_ERR(rphy->usbgrf); + } else { + rphy->usbgrf = NULL; + } + if (of_property_read_u32(np, "reg", ®)) { dev_err(dev, "the reg property is not assigned in %s node\n", np->name); @@ -1138,6 +1214,65 @@ disable_clks: return ret; } +static const struct rockchip_usb2phy_cfg rk3228_phy_cfgs[] = { + { + .reg = 0x760, + .num_ports = 2, + .clkout_ctl = { 0x0768, 4, 4, 1, 0 }, + .port_cfgs = { + [USB2PHY_PORT_OTG] = { + .phy_sus = { 0x0760, 15, 0, 0, 0x1d1 }, + .bvalid_det_en = { 0x0680, 3, 3, 0, 1 }, + .bvalid_det_st = { 0x0690, 3, 3, 0, 1 }, + .bvalid_det_clr = { 0x06a0, 3, 3, 0, 1 }, + .ls_det_en = { 0x0680, 2, 2, 0, 1 }, + .ls_det_st = { 0x0690, 2, 2, 0, 1 }, + .ls_det_clr = { 0x06a0, 2, 2, 0, 1 }, + .utmi_bvalid = { 0x0480, 4, 4, 0, 1 }, + .utmi_ls = { 0x0480, 3, 2, 0, 1 }, + }, + [USB2PHY_PORT_HOST] = { + .phy_sus = { 0x0764, 15, 0, 0, 0x1d1 }, + .ls_det_en = { 0x0680, 4, 4, 0, 1 }, + .ls_det_st = { 0x0690, 4, 4, 0, 1 }, + .ls_det_clr = { 0x06a0, 4, 4, 0, 1 } + } + }, + .chg_det = { + .opmode = { 0x0760, 3, 0, 5, 1 }, + .cp_det = { 0x0884, 4, 4, 0, 1 }, + .dcp_det = { 0x0884, 3, 3, 0, 1 }, + .dp_det = { 0x0884, 5, 5, 0, 1 }, + .idm_sink_en = { 0x0768, 8, 8, 0, 1 }, + .idp_sink_en = { 0x0768, 7, 7, 0, 1 }, + .idp_src_en = { 0x0768, 9, 9, 0, 1 }, + .rdm_pdwn_en = { 0x0768, 10, 10, 0, 1 }, + .vdm_src_en = { 0x0768, 12, 12, 0, 1 }, + .vdp_src_en = { 0x0768, 11, 11, 0, 1 }, + }, + }, + { + .reg = 0x800, + .num_ports = 2, + .clkout_ctl = { 0x0808, 4, 4, 1, 0 }, + .port_cfgs = { + [USB2PHY_PORT_OTG] = { + .phy_sus = { 0x800, 15, 0, 0, 0x1d1 }, + .ls_det_en = { 0x0684, 0, 0, 0, 1 }, + .ls_det_st = { 0x0694, 0, 0, 0, 1 }, + .ls_det_clr = { 0x06a4, 0, 0, 0, 1 } + }, + [USB2PHY_PORT_HOST] = { + .phy_sus = { 0x804, 15, 0, 0, 0x1d1 }, + .ls_det_en = { 0x0684, 1, 1, 0, 1 }, + .ls_det_st = { 0x0694, 1, 1, 0, 1 }, + .ls_det_clr = { 0x06a4, 1, 1, 0, 1 } + } + }, + }, + { /* sentinel */ } +}; + static const struct rockchip_usb2phy_cfg rk3328_phy_cfgs[] = { { .reg = 0x100, @@ -1262,10 +1397,54 @@ static const struct rockchip_usb2phy_cfg rk3399_phy_cfgs[] = { { /* sentinel */ } }; +static const struct rockchip_usb2phy_cfg rv1108_phy_cfgs[] = { + { + .reg = 0x100, + .num_ports = 2, + .clkout_ctl = { 0x108, 4, 4, 1, 0 }, + .port_cfgs = { + [USB2PHY_PORT_OTG] = { + .phy_sus = { 0x0100, 15, 0, 0, 0x1d1 }, + .bvalid_det_en = { 0x0680, 3, 3, 0, 1 }, + .bvalid_det_st = { 0x0690, 3, 3, 0, 1 }, + .bvalid_det_clr = { 0x06a0, 3, 3, 0, 1 }, + .ls_det_en = { 0x0680, 2, 2, 0, 1 }, + .ls_det_st = { 0x0690, 2, 2, 0, 1 }, + .ls_det_clr = { 0x06a0, 2, 2, 0, 1 }, + .utmi_bvalid = { 0x0804, 10, 10, 0, 1 }, + .utmi_ls = { 0x0804, 13, 12, 0, 1 }, + }, + [USB2PHY_PORT_HOST] = { + .phy_sus = { 0x0104, 15, 0, 0, 0x1d1 }, + .ls_det_en = { 0x0680, 4, 4, 0, 1 }, + .ls_det_st = { 0x0690, 4, 4, 0, 1 }, + .ls_det_clr = { 0x06a0, 4, 4, 0, 1 }, + .utmi_ls = { 0x0804, 9, 8, 0, 1 }, + .utmi_hstdet = { 0x0804, 7, 7, 0, 1 } + } + }, + .chg_det = { + .opmode = { 0x0100, 3, 0, 5, 1 }, + .cp_det = { 0x0804, 1, 1, 0, 1 }, + .dcp_det = { 0x0804, 0, 0, 0, 1 }, + .dp_det = { 0x0804, 2, 2, 0, 1 }, + .idm_sink_en = { 0x0108, 8, 8, 0, 1 }, + .idp_sink_en = { 0x0108, 7, 7, 0, 1 }, + .idp_src_en = { 0x0108, 9, 9, 0, 1 }, + .rdm_pdwn_en = { 0x0108, 10, 10, 0, 1 }, + .vdm_src_en = { 0x0108, 12, 12, 0, 1 }, + .vdp_src_en = { 0x0108, 11, 11, 0, 1 }, + }, + }, + { /* sentinel */ } +}; + static const struct of_device_id rockchip_usb2phy_dt_match[] = { + { .compatible = "rockchip,rk3228-usb2phy", .data = &rk3228_phy_cfgs }, { .compatible = "rockchip,rk3328-usb2phy", .data = &rk3328_phy_cfgs }, { .compatible = "rockchip,rk3366-usb2phy", .data = &rk3366_phy_cfgs }, { .compatible = "rockchip,rk3399-usb2phy", .data = &rk3399_phy_cfgs }, + { .compatible = "rockchip,rv1108-usb2phy", .data = &rv1108_phy_cfgs }, {} }; MODULE_DEVICE_TABLE(of, rockchip_usb2phy_dt_match); diff --git a/drivers/phy/phy-rockchip-pcie.c b/drivers/phy/rockchip/phy-rockchip-pcie.c index 6904633cad68..7cbdde029c0a 100644 --- a/drivers/phy/phy-rockchip-pcie.c +++ b/drivers/phy/rockchip/phy-rockchip-pcie.c @@ -73,10 +73,38 @@ struct rockchip_pcie_data { struct rockchip_pcie_phy { struct rockchip_pcie_data *phy_data; struct regmap *reg_base; + struct phy_pcie_instance { + struct phy *phy; + u32 index; + } phys[PHY_MAX_LANE_NUM]; + struct mutex pcie_mutex; struct reset_control *phy_rst; struct clk *clk_pciephy_ref; + int pwr_cnt; + int init_cnt; }; +static struct rockchip_pcie_phy *to_pcie_phy(struct phy_pcie_instance *inst) +{ + return container_of(inst, struct rockchip_pcie_phy, + phys[inst->index]); +} + +static struct phy *rockchip_pcie_phy_of_xlate(struct device *dev, + struct of_phandle_args *args) +{ + struct rockchip_pcie_phy *rk_phy = dev_get_drvdata(dev); + + if (args->args_count == 0) + return rk_phy->phys[0].phy; + + if (WARN_ON(args->args[0] >= PHY_MAX_LANE_NUM)) + return ERR_PTR(-ENODEV); + + return rk_phy->phys[args->args[0]].phy; +} + + static inline void phy_wr_cfg(struct rockchip_pcie_phy *rk_phy, u32 addr, u32 data) { @@ -116,29 +144,59 @@ static inline u32 phy_rd_cfg(struct rockchip_pcie_phy *rk_phy, static int rockchip_pcie_phy_power_off(struct phy *phy) { - struct rockchip_pcie_phy *rk_phy = phy_get_drvdata(phy); + struct phy_pcie_instance *inst = phy_get_drvdata(phy); + struct rockchip_pcie_phy *rk_phy = to_pcie_phy(inst); int err = 0; + mutex_lock(&rk_phy->pcie_mutex); + + regmap_write(rk_phy->reg_base, + rk_phy->phy_data->pcie_laneoff, + HIWORD_UPDATE(PHY_LANE_IDLE_OFF, + PHY_LANE_IDLE_MASK, + PHY_LANE_IDLE_A_SHIFT + inst->index)); + + if (--rk_phy->pwr_cnt) + goto err_out; + err = reset_control_assert(rk_phy->phy_rst); if (err) { dev_err(&phy->dev, "assert phy_rst err %d\n", err); - return err; + goto err_restore; } +err_out: + mutex_unlock(&rk_phy->pcie_mutex); return 0; + +err_restore: + rk_phy->pwr_cnt++; + regmap_write(rk_phy->reg_base, + rk_phy->phy_data->pcie_laneoff, + HIWORD_UPDATE(!PHY_LANE_IDLE_OFF, + PHY_LANE_IDLE_MASK, + PHY_LANE_IDLE_A_SHIFT + inst->index)); + mutex_unlock(&rk_phy->pcie_mutex); + return err; } static int rockchip_pcie_phy_power_on(struct phy *phy) { - struct rockchip_pcie_phy *rk_phy = phy_get_drvdata(phy); + struct phy_pcie_instance *inst = phy_get_drvdata(phy); + struct rockchip_pcie_phy *rk_phy = to_pcie_phy(inst); int err = 0; u32 status; unsigned long timeout; + mutex_lock(&rk_phy->pcie_mutex); + + if (rk_phy->pwr_cnt++) + goto err_out; + err = reset_control_deassert(rk_phy->phy_rst); if (err) { dev_err(&phy->dev, "deassert phy_rst err %d\n", err); - return err; + goto err_pwr_cnt; } regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf, @@ -146,6 +204,12 @@ static int rockchip_pcie_phy_power_on(struct phy *phy) PHY_CFG_ADDR_MASK, PHY_CFG_ADDR_SHIFT)); + regmap_write(rk_phy->reg_base, + rk_phy->phy_data->pcie_laneoff, + HIWORD_UPDATE(!PHY_LANE_IDLE_OFF, + PHY_LANE_IDLE_MASK, + PHY_LANE_IDLE_A_SHIFT + inst->index)); + /* * No documented timeout value for phy operation below, * so we make it large enough here. And we use loop-break @@ -214,18 +278,29 @@ static int rockchip_pcie_phy_power_on(struct phy *phy) goto err_pll_lock; } +err_out: + mutex_unlock(&rk_phy->pcie_mutex); return 0; err_pll_lock: reset_control_assert(rk_phy->phy_rst); +err_pwr_cnt: + rk_phy->pwr_cnt--; + mutex_unlock(&rk_phy->pcie_mutex); return err; } static int rockchip_pcie_phy_init(struct phy *phy) { - struct rockchip_pcie_phy *rk_phy = phy_get_drvdata(phy); + struct phy_pcie_instance *inst = phy_get_drvdata(phy); + struct rockchip_pcie_phy *rk_phy = to_pcie_phy(inst); int err = 0; + mutex_lock(&rk_phy->pcie_mutex); + + if (rk_phy->init_cnt++) + goto err_out; + err = clk_prepare_enable(rk_phy->clk_pciephy_ref); if (err) { dev_err(&phy->dev, "Fail to enable pcie ref clock.\n"); @@ -238,20 +313,33 @@ static int rockchip_pcie_phy_init(struct phy *phy) goto err_reset; } - return err; +err_out: + mutex_unlock(&rk_phy->pcie_mutex); + return 0; err_reset: + clk_disable_unprepare(rk_phy->clk_pciephy_ref); err_refclk: + rk_phy->init_cnt--; + mutex_unlock(&rk_phy->pcie_mutex); return err; } static int rockchip_pcie_phy_exit(struct phy *phy) { - struct rockchip_pcie_phy *rk_phy = phy_get_drvdata(phy); + struct phy_pcie_instance *inst = phy_get_drvdata(phy); + struct rockchip_pcie_phy *rk_phy = to_pcie_phy(inst); + + mutex_lock(&rk_phy->pcie_mutex); + + if (--rk_phy->init_cnt) + goto err_init_cnt; clk_disable_unprepare(rk_phy->clk_pciephy_ref); +err_init_cnt: + mutex_unlock(&rk_phy->pcie_mutex); return 0; } @@ -283,10 +371,11 @@ static int rockchip_pcie_phy_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct rockchip_pcie_phy *rk_phy; - struct phy *generic_phy; struct phy_provider *phy_provider; struct regmap *grf; const struct of_device_id *of_id; + int i; + u32 phy_num; grf = syscon_node_to_regmap(dev->parent->of_node); if (IS_ERR(grf)) { @@ -305,6 +394,8 @@ static int rockchip_pcie_phy_probe(struct platform_device *pdev) rk_phy->phy_data = (struct rockchip_pcie_data *)of_id->data; rk_phy->reg_base = grf; + mutex_init(&rk_phy->pcie_mutex); + rk_phy->phy_rst = devm_reset_control_get(dev, "phy"); if (IS_ERR(rk_phy->phy_rst)) { if (PTR_ERR(rk_phy->phy_rst) != -EPROBE_DEFER) @@ -319,14 +410,26 @@ static int rockchip_pcie_phy_probe(struct platform_device *pdev) return PTR_ERR(rk_phy->clk_pciephy_ref); } - generic_phy = devm_phy_create(dev, dev->of_node, &ops); - if (IS_ERR(generic_phy)) { - dev_err(dev, "failed to create PHY\n"); - return PTR_ERR(generic_phy); + /* parse #phy-cells to see if it's legacy PHY model */ + if (of_property_read_u32(dev->of_node, "#phy-cells", &phy_num)) + return -ENOENT; + + phy_num = (phy_num == 0) ? 1 : PHY_MAX_LANE_NUM; + dev_dbg(dev, "phy number is %d\n", phy_num); + + for (i = 0; i < phy_num; i++) { + rk_phy->phys[i].phy = devm_phy_create(dev, dev->of_node, &ops); + if (IS_ERR(rk_phy->phys[i].phy)) { + dev_err(dev, "failed to create PHY%d\n", i); + return PTR_ERR(rk_phy->phys[i].phy); + } + rk_phy->phys[i].index = i; + phy_set_drvdata(rk_phy->phys[i].phy, &rk_phy->phys[i]); } - phy_set_drvdata(generic_phy, rk_phy); - phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); + platform_set_drvdata(pdev, rk_phy); + phy_provider = devm_of_phy_provider_register(dev, + rockchip_pcie_phy_of_xlate); return PTR_ERR_OR_ZERO(phy_provider); } diff --git a/drivers/phy/phy-rockchip-typec.c b/drivers/phy/rockchip/phy-rockchip-typec.c index 7cfb0f8995de..ee85fa0ca4b0 100644 --- a/drivers/phy/phy-rockchip-typec.c +++ b/drivers/phy/rockchip/phy-rockchip-typec.c @@ -102,9 +102,40 @@ #define CMN_PLL1_SS_CTRL1 (0xb8 << 2) #define CMN_PLL1_SS_CTRL2 (0xb9 << 2) #define CMN_RXCAL_OVRD (0xd1 << 2) + #define CMN_TXPUCAL_CTRL (0xe0 << 2) #define CMN_TXPUCAL_OVRD (0xe1 << 2) +#define CMN_TXPDCAL_CTRL (0xf0 << 2) #define CMN_TXPDCAL_OVRD (0xf1 << 2) + +/* For CMN_TXPUCAL_CTRL, CMN_TXPDCAL_CTRL */ +#define CMN_TXPXCAL_START BIT(15) +#define CMN_TXPXCAL_DONE BIT(14) +#define CMN_TXPXCAL_NO_RESPONSE BIT(13) +#define CMN_TXPXCAL_CURRENT_RESPONSE BIT(12) + +#define CMN_TXPU_ADJ_CTRL (0x108 << 2) +#define CMN_TXPD_ADJ_CTRL (0x10c << 2) + +/* + * For CMN_TXPUCAL_CTRL, CMN_TXPDCAL_CTRL, + * CMN_TXPU_ADJ_CTRL, CMN_TXPDCAL_CTRL + * + * NOTE: some of these registers are documented to be 2's complement + * signed numbers, but then documented to be always positive. Weird. + * In such a case, using CMN_CALIB_CODE_POS() avoids the unnecessary + * sign extension. + */ +#define CMN_CALIB_CODE_WIDTH 7 +#define CMN_CALIB_CODE_OFFSET 0 +#define CMN_CALIB_CODE_MASK GENMASK(CMN_CALIB_CODE_WIDTH, 0) +#define CMN_CALIB_CODE(x) \ + sign_extend32((x) >> CMN_CALIB_CODE_OFFSET, CMN_CALIB_CODE_WIDTH) + +#define CMN_CALIB_CODE_POS_MASK GENMASK(CMN_CALIB_CODE_WIDTH - 1, 0) +#define CMN_CALIB_CODE_POS(x) \ + (((x) >> CMN_CALIB_CODE_OFFSET) & CMN_CALIB_CODE_POS_MASK) + #define CMN_DIAG_PLL0_FBH_OVRD (0x1c0 << 2) #define CMN_DIAG_PLL0_FBL_OVRD (0x1c1 << 2) #define CMN_DIAG_PLL0_OVRD (0x1c2 << 2) @@ -138,6 +169,15 @@ #define TX_TXCC_MGNFS_MULT_101(n) ((0x4055 | ((n) << 9)) << 2) #define TX_TXCC_MGNFS_MULT_110(n) ((0x4056 | ((n) << 9)) << 2) #define TX_TXCC_MGNFS_MULT_111(n) ((0x4057 | ((n) << 9)) << 2) +#define TX_TXCC_MGNLS_MULT_000(n) ((0x4058 | ((n) << 9)) << 2) +#define TX_TXCC_MGNLS_MULT_001(n) ((0x4059 | ((n) << 9)) << 2) +#define TX_TXCC_MGNLS_MULT_010(n) ((0x405a | ((n) << 9)) << 2) +#define TX_TXCC_MGNLS_MULT_011(n) ((0x405b | ((n) << 9)) << 2) +#define TX_TXCC_MGNLS_MULT_100(n) ((0x405c | ((n) << 9)) << 2) +#define TX_TXCC_MGNLS_MULT_101(n) ((0x405d | ((n) << 9)) << 2) +#define TX_TXCC_MGNLS_MULT_110(n) ((0x405e | ((n) << 9)) << 2) +#define TX_TXCC_MGNLS_MULT_111(n) ((0x405f | ((n) << 9)) << 2) + #define XCVR_DIAG_PLLDRC_CTRL(n) ((0x40e0 | ((n) << 9)) << 2) #define XCVR_DIAG_BIDI_CTRL(n) ((0x40e8 | ((n) << 9)) << 2) #define XCVR_DIAG_LANE_FCM_EN_MGN(n) ((0x40f2 | ((n) << 9)) << 2) @@ -150,10 +190,63 @@ #define TX_RCVDET_ST_TMR(n) ((0x4123 | ((n) << 9)) << 2) #define TX_DIAG_TX_DRV(n) ((0x41e1 | ((n) << 9)) << 2) #define TX_DIAG_BGREF_PREDRV_DELAY (0x41e7 << 2) + +/* Use this for "n" in macros like "_MULT_XXX" to target the aux channel */ +#define AUX_CH_LANE 8 + #define TX_ANA_CTRL_REG_1 (0x5020 << 2) + +#define TXDA_DP_AUX_EN BIT(15) +#define AUXDA_SE_EN BIT(14) +#define TXDA_CAL_LATCH_EN BIT(13) +#define AUXDA_POLARITY BIT(12) +#define TXDA_DRV_POWER_ISOLATION_EN BIT(11) +#define TXDA_DRV_POWER_EN_PH_2_N BIT(10) +#define TXDA_DRV_POWER_EN_PH_1_N BIT(9) +#define TXDA_BGREF_EN BIT(8) +#define TXDA_DRV_LDO_EN BIT(7) +#define TXDA_DECAP_EN_DEL BIT(6) +#define TXDA_DECAP_EN BIT(5) +#define TXDA_UPHY_SUPPLY_EN_DEL BIT(4) +#define TXDA_UPHY_SUPPLY_EN BIT(3) +#define TXDA_LOW_LEAKAGE_EN BIT(2) +#define TXDA_DRV_IDLE_LOWI_EN BIT(1) +#define TXDA_DRV_CMN_MODE_EN BIT(0) + #define TX_ANA_CTRL_REG_2 (0x5021 << 2) + +#define AUXDA_DEBOUNCING_CLK BIT(15) +#define TXDA_LPBK_RECOVERED_CLK_EN BIT(14) +#define TXDA_LPBK_ISI_GEN_EN BIT(13) +#define TXDA_LPBK_SERIAL_EN BIT(12) +#define TXDA_LPBK_LINE_EN BIT(11) +#define TXDA_DRV_LDO_REDC_SINKIQ BIT(10) +#define XCVR_DECAP_EN_DEL BIT(9) +#define XCVR_DECAP_EN BIT(8) +#define TXDA_MPHY_ENABLE_HS_NT BIT(7) +#define TXDA_MPHY_SA_MODE BIT(6) +#define TXDA_DRV_LDO_RBYR_FB_EN BIT(5) +#define TXDA_DRV_RST_PULL_DOWN BIT(4) +#define TXDA_DRV_LDO_BG_FB_EN BIT(3) +#define TXDA_DRV_LDO_BG_REF_EN BIT(2) +#define TXDA_DRV_PREDRV_EN_DEL BIT(1) +#define TXDA_DRV_PREDRV_EN BIT(0) + #define TXDA_COEFF_CALC_CTRL (0x5022 << 2) + +#define TX_HIGH_Z BIT(6) +#define TX_VMARGIN_OFFSET 3 +#define TX_VMARGIN_MASK 0x7 +#define LOW_POWER_SWING_EN BIT(2) +#define TX_FCM_DRV_MAIN_EN BIT(1) +#define TX_FCM_FULL_MARGIN BIT(0) + #define TX_DIG_CTRL_REG_2 (0x5024 << 2) + +#define TX_HIGH_Z_TM_EN BIT(15) +#define TX_RESCAL_CODE_OFFSET 0 +#define TX_RESCAL_CODE_MASK 0x3f + #define TXDA_CYA_AUXDA_CYA (0x5025 << 2) #define TX_ANA_CTRL_REG_3 (0x5026 << 2) #define TX_ANA_CTRL_REG_4 (0x5027 << 2) @@ -443,47 +536,86 @@ static inline int property_enable(struct rockchip_typec_phy *tcphy, return regmap_write(tcphy->grf_regs, reg->offset, val | mask); } -static void tcphy_dp_aux_calibration(struct rockchip_typec_phy *tcphy) +static void tcphy_dp_aux_set_flip(struct rockchip_typec_phy *tcphy) { - u16 rdata, rdata2, val; + u16 tx_ana_ctrl_reg_1; - /* disable txda_cal_latch_en for rewrite the calibration values */ - rdata = readl(tcphy->base + TX_ANA_CTRL_REG_1); - val = rdata & 0xdfff; - writel(val, tcphy->base + TX_ANA_CTRL_REG_1); + /* + * Select the polarity of the xcvr: + * 1, Reverses the polarity (If TYPEC, Pulls ups aux_p and pull + * down aux_m) + * 0, Normal polarity (if TYPEC, pulls up aux_m and pulls down + * aux_p) + */ + tx_ana_ctrl_reg_1 = readl(tcphy->base + TX_ANA_CTRL_REG_1); + if (!tcphy->flip) + tx_ana_ctrl_reg_1 |= AUXDA_POLARITY; + else + tx_ana_ctrl_reg_1 &= ~AUXDA_POLARITY; + writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1); +} + +static void tcphy_dp_aux_calibration(struct rockchip_typec_phy *tcphy) +{ + u16 val; + u16 tx_ana_ctrl_reg_1; + u16 tx_ana_ctrl_reg_2; + s32 pu_calib_code, pd_calib_code; + s32 pu_adj, pd_adj; + u16 calib; /* - * read a resistor calibration code from CMN_TXPUCAL_CTRL[6:0] and - * write it to TX_DIG_CTRL_REG_2[6:0], and delay 1ms to make sure it - * works. + * Calculate calibration code as per docs: use an average of the + * pull down and pull up. Then add in adjustments. */ - rdata = readl(tcphy->base + TX_DIG_CTRL_REG_2); - rdata = rdata & 0xffc0; + val = readl(tcphy->base + CMN_TXPUCAL_CTRL); + pu_calib_code = CMN_CALIB_CODE_POS(val); + val = readl(tcphy->base + CMN_TXPDCAL_CTRL); + pd_calib_code = CMN_CALIB_CODE_POS(val); + val = readl(tcphy->base + CMN_TXPU_ADJ_CTRL); + pu_adj = CMN_CALIB_CODE(val); + val = readl(tcphy->base + CMN_TXPD_ADJ_CTRL); + pd_adj = CMN_CALIB_CODE(val); + calib = (pu_calib_code + pd_calib_code) / 2 + pu_adj + pd_adj; - rdata2 = readl(tcphy->base + CMN_TXPUCAL_CTRL); - rdata2 = rdata2 & 0x3f; + /* disable txda_cal_latch_en for rewrite the calibration values */ + tx_ana_ctrl_reg_1 = readl(tcphy->base + TX_ANA_CTRL_REG_1); + tx_ana_ctrl_reg_1 &= ~TXDA_CAL_LATCH_EN; + writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1); - val = rdata | rdata2; + /* write the calibration, then delay 10 ms as sample in docs */ + val = readl(tcphy->base + TX_DIG_CTRL_REG_2); + val &= ~(TX_RESCAL_CODE_MASK << TX_RESCAL_CODE_OFFSET); + val |= calib << TX_RESCAL_CODE_OFFSET; writel(val, tcphy->base + TX_DIG_CTRL_REG_2); - usleep_range(1000, 1050); + usleep_range(10000, 10050); /* * Enable signal for latch that sample and holds calibration values. * Activate this signal for 1 clock cycle to sample new calibration * values. */ - rdata = readl(tcphy->base + TX_ANA_CTRL_REG_1); - val = rdata | 0x2000; - writel(val, tcphy->base + TX_ANA_CTRL_REG_1); + tx_ana_ctrl_reg_1 |= TXDA_CAL_LATCH_EN; + writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1); usleep_range(150, 200); /* set TX Voltage Level and TX Deemphasis to 0 */ writel(0, tcphy->base + PHY_DP_TX_CTL); + /* re-enable decap */ - writel(0x100, tcphy->base + TX_ANA_CTRL_REG_2); - writel(0x300, tcphy->base + TX_ANA_CTRL_REG_2); - writel(0x2008, tcphy->base + TX_ANA_CTRL_REG_1); - writel(0x2018, tcphy->base + TX_ANA_CTRL_REG_1); + tx_ana_ctrl_reg_2 = XCVR_DECAP_EN; + writel(tx_ana_ctrl_reg_2, tcphy->base + TX_ANA_CTRL_REG_2); + udelay(1); + tx_ana_ctrl_reg_2 |= XCVR_DECAP_EN_DEL; + writel(tx_ana_ctrl_reg_2, tcphy->base + TX_ANA_CTRL_REG_2); + + writel(0, tcphy->base + TX_ANA_CTRL_REG_3); + + tx_ana_ctrl_reg_1 |= TXDA_UPHY_SUPPLY_EN; + writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1); + udelay(1); + tx_ana_ctrl_reg_1 |= TXDA_UPHY_SUPPLY_EN_DEL; + writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1); writel(0, tcphy->base + TX_ANA_CTRL_REG_5); @@ -494,43 +626,66 @@ static void tcphy_dp_aux_calibration(struct rockchip_typec_phy *tcphy) writel(0x1001, tcphy->base + TX_ANA_CTRL_REG_4); /* re-enables Bandgap reference for LDO */ - writel(0x2098, tcphy->base + TX_ANA_CTRL_REG_1); - writel(0x2198, tcphy->base + TX_ANA_CTRL_REG_1); + tx_ana_ctrl_reg_1 |= TXDA_DRV_LDO_EN; + writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1); + udelay(5); + tx_ana_ctrl_reg_1 |= TXDA_BGREF_EN; + writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1); /* * re-enables the transmitter pre-driver, driver data selection MUX, * and receiver detect circuits. */ - writel(0x301, tcphy->base + TX_ANA_CTRL_REG_2); - writel(0x303, tcphy->base + TX_ANA_CTRL_REG_2); + tx_ana_ctrl_reg_2 |= TXDA_DRV_PREDRV_EN; + writel(tx_ana_ctrl_reg_2, tcphy->base + TX_ANA_CTRL_REG_2); + udelay(1); + tx_ana_ctrl_reg_2 |= TXDA_DRV_PREDRV_EN_DEL; + writel(tx_ana_ctrl_reg_2, tcphy->base + TX_ANA_CTRL_REG_2); /* - * BIT 12: Controls auxda_polarity, which selects the polarity of the - * xcvr: - * 1, Reverses the polarity (If TYPEC, Pulls ups aux_p and pull - * down aux_m) - * 0, Normal polarity (if TYPE_C, pulls up aux_m and pulls down - * aux_p) + * Do all the undocumented magic: + * - Turn on TXDA_DP_AUX_EN, whatever that is, even though sample + * never shows this going on. + * - Turn on TXDA_DECAP_EN (and TXDA_DECAP_EN_DEL) even though + * docs say for aux it's always 0. + * - Turn off the LDO and BGREF, which we just spent time turning + * on above (???). + * + * Without this magic, things seem worse. */ - val = 0xa078; - if (!tcphy->flip) - val |= BIT(12); - writel(val, tcphy->base + TX_ANA_CTRL_REG_1); - - writel(0, tcphy->base + TX_ANA_CTRL_REG_3); - writel(0, tcphy->base + TX_ANA_CTRL_REG_4); - writel(0, tcphy->base + TX_ANA_CTRL_REG_5); + tx_ana_ctrl_reg_1 |= TXDA_DP_AUX_EN; + tx_ana_ctrl_reg_1 |= TXDA_DECAP_EN; + tx_ana_ctrl_reg_1 &= ~TXDA_DRV_LDO_EN; + tx_ana_ctrl_reg_1 &= ~TXDA_BGREF_EN; + writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1); + udelay(1); + tx_ana_ctrl_reg_1 |= TXDA_DECAP_EN_DEL; + writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1); /* - * Controls low_power_swing_en, set the voltage swing of the driver - * to 400mv. The values below are peak to peak (differential) values. + * Undo the work we did to set the LDO voltage. + * This doesn't seem to help nor hurt, but it kinda goes with the + * undocumented magic above. */ - writel(4, tcphy->base + TXDA_COEFF_CALC_CTRL); + writel(0, tcphy->base + TX_ANA_CTRL_REG_4); + + /* Don't set voltage swing to 400 mV peak to peak (differential) */ + writel(0, tcphy->base + TXDA_COEFF_CALC_CTRL); + + /* Init TXDA_CYA_AUXDA_CYA for unknown magic reasons */ writel(0, tcphy->base + TXDA_CYA_AUXDA_CYA); - /* Controls tx_high_z_tm_en */ + /* + * More undocumented magic, presumably the goal of which is to + * make the "auxda_source_aux_oen" be ignored and instead to decide + * about "high impedance state" based on what software puts in the + * register TXDA_COEFF_CALC_CTRL (see TX_HIGH_Z). Since we only + * program that register once and we don't set the bit TX_HIGH_Z, + * presumably the goal here is that we should never put the analog + * driver in high impedance state. + */ val = readl(tcphy->base + TX_DIG_CTRL_REG_2); - val |= BIT(15); + val |= TX_HIGH_Z_TM_EN; writel(val, tcphy->base + TX_DIG_CTRL_REG_2); } @@ -555,6 +710,7 @@ static int tcphy_phy_init(struct rockchip_typec_phy *tcphy, u8 mode) reset_control_deassert(tcphy->tcphy_rst); property_enable(tcphy, &cfg->typec_conn_dir, tcphy->flip); + tcphy_dp_aux_set_flip(tcphy); tcphy_cfg_24m(tcphy); @@ -622,12 +778,11 @@ static int tcphy_get_mode(struct rockchip_typec_phy *tcphy) struct extcon_dev *edev = tcphy->extcon; union extcon_property_value property; unsigned int id; - bool dfp, ufp, dp; + bool ufp, dp; u8 mode; int ret; ufp = extcon_get_state(edev, EXTCON_USB); - dfp = extcon_get_state(edev, EXTCON_USB_HOST); dp = extcon_get_state(edev, EXTCON_DISP_DP); mode = MODE_DFP_USB; @@ -686,8 +841,11 @@ static int rockchip_usb3_phy_power_on(struct phy *phy) if (tcphy->mode == new_mode) goto unlock_ret; - if (tcphy->mode == MODE_DISCONNECT) - tcphy_phy_init(tcphy, new_mode); + if (tcphy->mode == MODE_DISCONNECT) { + ret = tcphy_phy_init(tcphy, new_mode); + if (ret) + goto unlock_ret; + } /* wait TCPHY for pipe ready */ for (timeout = 0; timeout < 100; timeout++) { @@ -761,10 +919,12 @@ static int rockchip_dp_phy_power_on(struct phy *phy) */ if (new_mode == MODE_DFP_DP && tcphy->mode != MODE_DISCONNECT) { tcphy_phy_deinit(tcphy); - tcphy_phy_init(tcphy, new_mode); + ret = tcphy_phy_init(tcphy, new_mode); } else if (tcphy->mode == MODE_DISCONNECT) { - tcphy_phy_init(tcphy, new_mode); + ret = tcphy_phy_init(tcphy, new_mode); } + if (ret) + goto unlock_ret; ret = readx_poll_timeout(readl, tcphy->base + DP_MODE_CTL, val, val & DP_MODE_A2, 1000, diff --git a/drivers/phy/phy-rockchip-usb.c b/drivers/phy/rockchip/phy-rockchip-usb.c index 3378eeb7a562..3378eeb7a562 100644 --- a/drivers/phy/phy-rockchip-usb.c +++ b/drivers/phy/rockchip/phy-rockchip-usb.c diff --git a/drivers/phy/samsung/Kconfig b/drivers/phy/samsung/Kconfig new file mode 100644 index 000000000000..b7e0645a7bd9 --- /dev/null +++ b/drivers/phy/samsung/Kconfig @@ -0,0 +1,95 @@ +# +# Phy drivers for Samsung platforms +# +config PHY_EXYNOS_DP_VIDEO + tristate "EXYNOS SoC series Display Port PHY driver" + depends on OF + depends on ARCH_EXYNOS || COMPILE_TEST + default ARCH_EXYNOS + select GENERIC_PHY + help + Support for Display Port PHY found on Samsung EXYNOS SoCs. + +config PHY_EXYNOS_MIPI_VIDEO + tristate "S5P/EXYNOS SoC series MIPI CSI-2/DSI PHY driver" + depends on HAS_IOMEM + depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST + select GENERIC_PHY + default y if ARCH_S5PV210 || ARCH_EXYNOS + help + Support for MIPI CSI-2 and MIPI DSI DPHY found on Samsung S5P + and EXYNOS SoCs. + +config PHY_EXYNOS_PCIE + bool "Exynos PCIe PHY driver" + depends on OF && (ARCH_EXYNOS || COMPILE_TEST) + select GENERIC_PHY + help + Enable PCIe PHY support for Exynos SoC series. + This driver provides PHY interface for Exynos PCIe controller. + +config PHY_SAMSUNG_USB2 + tristate "Samsung USB 2.0 PHY driver" + depends on HAS_IOMEM + depends on USB_EHCI_EXYNOS || USB_OHCI_EXYNOS || USB_DWC2 + select GENERIC_PHY + select MFD_SYSCON + default ARCH_EXYNOS + help + Enable this to support the Samsung USB 2.0 PHY driver for Samsung + SoCs. This driver provides the interface for USB 2.0 PHY. Support + for particular PHYs will be enabled based on the SoC type in addition + to this driver. + +config PHY_EXYNOS4210_USB2 + bool + depends on PHY_SAMSUNG_USB2 + default CPU_EXYNOS4210 + +config PHY_EXYNOS4X12_USB2 + bool + depends on PHY_SAMSUNG_USB2 + default SOC_EXYNOS3250 || SOC_EXYNOS4212 || SOC_EXYNOS4412 + +config PHY_EXYNOS5250_USB2 + bool + depends on PHY_SAMSUNG_USB2 + default SOC_EXYNOS5250 || SOC_EXYNOS5420 + +config PHY_S5PV210_USB2 + bool "Support for S5PV210" + depends on PHY_SAMSUNG_USB2 + depends on ARCH_S5PV210 + help + Enable USB PHY support for S5PV210. This option requires that Samsung + USB 2.0 PHY driver is enabled and means that support for this + particular SoC is compiled in the driver. In case of S5PV210 two phys + are available - device and host. + +config PHY_EXYNOS5_USBDRD + tristate "Exynos5 SoC series USB DRD PHY driver" + depends on ARCH_EXYNOS && OF + depends on HAS_IOMEM + depends on USB_DWC3_EXYNOS + select GENERIC_PHY + select MFD_SYSCON + default y + help + Enable USB DRD PHY support for Exynos 5 SoC series. + This driver provides PHY interface for USB 3.0 DRD controller + present on Exynos5 SoC series. + +config PHY_EXYNOS5250_SATA + tristate "Exynos5250 Sata SerDes/PHY driver" + depends on SOC_EXYNOS5250 + depends on HAS_IOMEM + depends on OF + select GENERIC_PHY + select I2C + select I2C_S3C2410 + select MFD_SYSCON + help + Enable this to support SATA SerDes/Phy found on Samsung's + Exynos5250 based SoCs.This SerDes/Phy supports SATA 1.5 Gb/s, + SATA 3.0 Gb/s, SATA 6.0 Gb/s speeds. It supports one SATA host + port to accept one SATA device. diff --git a/drivers/phy/samsung/Makefile b/drivers/phy/samsung/Makefile new file mode 100644 index 000000000000..20d7f2424772 --- /dev/null +++ b/drivers/phy/samsung/Makefile @@ -0,0 +1,11 @@ +obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO) += phy-exynos-dp-video.o +obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO) += phy-exynos-mipi-video.o +obj-$(CONFIG_PHY_EXYNOS_PCIE) += phy-exynos-pcie.o +obj-$(CONFIG_PHY_SAMSUNG_USB2) += phy-exynos-usb2.o +phy-exynos-usb2-y += phy-samsung-usb2.o +phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4210_USB2) += phy-exynos4210-usb2.o +phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4X12_USB2) += phy-exynos4x12-usb2.o +phy-exynos-usb2-$(CONFIG_PHY_EXYNOS5250_USB2) += phy-exynos5250-usb2.o +phy-exynos-usb2-$(CONFIG_PHY_S5PV210_USB2) += phy-s5pv210-usb2.o +obj-$(CONFIG_PHY_EXYNOS5_USBDRD) += phy-exynos5-usbdrd.o +obj-$(CONFIG_PHY_EXYNOS5250_SATA) += phy-exynos5250-sata.o diff --git a/drivers/phy/phy-exynos-dp-video.c b/drivers/phy/samsung/phy-exynos-dp-video.c index bb3279dbf88c..bb3279dbf88c 100644 --- a/drivers/phy/phy-exynos-dp-video.c +++ b/drivers/phy/samsung/phy-exynos-dp-video.c diff --git a/drivers/phy/phy-exynos-mipi-video.c b/drivers/phy/samsung/phy-exynos-mipi-video.c index c198886f80a3..c198886f80a3 100644 --- a/drivers/phy/phy-exynos-mipi-video.c +++ b/drivers/phy/samsung/phy-exynos-mipi-video.c diff --git a/drivers/phy/phy-exynos-pcie.c b/drivers/phy/samsung/phy-exynos-pcie.c index a89c12faff39..a89c12faff39 100644 --- a/drivers/phy/phy-exynos-pcie.c +++ b/drivers/phy/samsung/phy-exynos-pcie.c diff --git a/drivers/phy/phy-exynos4210-usb2.c b/drivers/phy/samsung/phy-exynos4210-usb2.c index 1f50e1004828..1f50e1004828 100644 --- a/drivers/phy/phy-exynos4210-usb2.c +++ b/drivers/phy/samsung/phy-exynos4210-usb2.c diff --git a/drivers/phy/phy-exynos4x12-usb2.c b/drivers/phy/samsung/phy-exynos4x12-usb2.c index 7f27a91acf87..7f27a91acf87 100644 --- a/drivers/phy/phy-exynos4x12-usb2.c +++ b/drivers/phy/samsung/phy-exynos4x12-usb2.c diff --git a/drivers/phy/phy-exynos5-usbdrd.c b/drivers/phy/samsung/phy-exynos5-usbdrd.c index 7c41daa2c625..7c41daa2c625 100644 --- a/drivers/phy/phy-exynos5-usbdrd.c +++ b/drivers/phy/samsung/phy-exynos5-usbdrd.c diff --git a/drivers/phy/phy-exynos5250-sata.c b/drivers/phy/samsung/phy-exynos5250-sata.c index 60e13afcd9b8..60e13afcd9b8 100644 --- a/drivers/phy/phy-exynos5250-sata.c +++ b/drivers/phy/samsung/phy-exynos5250-sata.c diff --git a/drivers/phy/phy-exynos5250-usb2.c b/drivers/phy/samsung/phy-exynos5250-usb2.c index aad806272305..aad806272305 100644 --- a/drivers/phy/phy-exynos5250-usb2.c +++ b/drivers/phy/samsung/phy-exynos5250-usb2.c diff --git a/drivers/phy/phy-s5pv210-usb2.c b/drivers/phy/samsung/phy-s5pv210-usb2.c index f6f72339bbc3..f6f72339bbc3 100644 --- a/drivers/phy/phy-s5pv210-usb2.c +++ b/drivers/phy/samsung/phy-s5pv210-usb2.c diff --git a/drivers/phy/phy-samsung-usb2.c b/drivers/phy/samsung/phy-samsung-usb2.c index 1d22d93b552d..1d22d93b552d 100644 --- a/drivers/phy/phy-samsung-usb2.c +++ b/drivers/phy/samsung/phy-samsung-usb2.c diff --git a/drivers/phy/phy-samsung-usb2.h b/drivers/phy/samsung/phy-samsung-usb2.h index 6563e7ca0ac4..6563e7ca0ac4 100644 --- a/drivers/phy/phy-samsung-usb2.h +++ b/drivers/phy/samsung/phy-samsung-usb2.h diff --git a/drivers/phy/st/Kconfig b/drivers/phy/st/Kconfig new file mode 100644 index 000000000000..0814d3f87ec6 --- /dev/null +++ b/drivers/phy/st/Kconfig @@ -0,0 +1,33 @@ +# +# Phy drivers for STMicro platforms +# +config PHY_MIPHY28LP + tristate "STMicroelectronics MIPHY28LP PHY driver for STiH407" + depends on ARCH_STI + select GENERIC_PHY + help + Enable this to support the miphy transceiver (for SATA/PCIE/USB3) + that is part of STMicroelectronics STiH407 SoC. + +config PHY_ST_SPEAR1310_MIPHY + tristate "ST SPEAR1310-MIPHY driver" + select GENERIC_PHY + depends on MACH_SPEAR1310 || COMPILE_TEST + help + Support for ST SPEAr1310 MIPHY which can be used for PCIe and SATA. + +config PHY_ST_SPEAR1340_MIPHY + tristate "ST SPEAR1340-MIPHY driver" + select GENERIC_PHY + depends on MACH_SPEAR1340 || COMPILE_TEST + help + Support for ST SPEAr1340 MIPHY which can be used for PCIe and SATA. + +config PHY_STIH407_USB + tristate "STMicroelectronics USB2 picoPHY driver for STiH407 family" + depends on RESET_CONTROLLER + depends on ARCH_STI || COMPILE_TEST + select GENERIC_PHY + help + Enable this support to enable the picoPHY device used by USB2 + and USB3 controllers on STMicroelectronics STiH407 SoC families. diff --git a/drivers/phy/st/Makefile b/drivers/phy/st/Makefile new file mode 100644 index 000000000000..e2adfe2166d2 --- /dev/null +++ b/drivers/phy/st/Makefile @@ -0,0 +1,4 @@ +obj-$(CONFIG_PHY_MIPHY28LP) += phy-miphy28lp.o +obj-$(CONFIG_PHY_ST_SPEAR1310_MIPHY) += phy-spear1310-miphy.o +obj-$(CONFIG_PHY_ST_SPEAR1340_MIPHY) += phy-spear1340-miphy.o +obj-$(CONFIG_PHY_STIH407_USB) += phy-stih407-usb.o diff --git a/drivers/phy/phy-miphy28lp.c b/drivers/phy/st/phy-miphy28lp.c index 213e2e15339c..213e2e15339c 100644 --- a/drivers/phy/phy-miphy28lp.c +++ b/drivers/phy/st/phy-miphy28lp.c diff --git a/drivers/phy/phy-spear1310-miphy.c b/drivers/phy/st/phy-spear1310-miphy.c index ed67e98e54ca..ed67e98e54ca 100644 --- a/drivers/phy/phy-spear1310-miphy.c +++ b/drivers/phy/st/phy-spear1310-miphy.c diff --git a/drivers/phy/phy-spear1340-miphy.c b/drivers/phy/st/phy-spear1340-miphy.c index 97280c0cf612..97280c0cf612 100644 --- a/drivers/phy/phy-spear1340-miphy.c +++ b/drivers/phy/st/phy-spear1340-miphy.c diff --git a/drivers/phy/phy-stih407-usb.c b/drivers/phy/st/phy-stih407-usb.c index b1f44ab669fb..b1f44ab669fb 100644 --- a/drivers/phy/phy-stih407-usb.c +++ b/drivers/phy/st/phy-stih407-usb.c diff --git a/drivers/phy/ti/Kconfig b/drivers/phy/ti/Kconfig new file mode 100644 index 000000000000..20503562666c --- /dev/null +++ b/drivers/phy/ti/Kconfig @@ -0,0 +1,78 @@ +# +# Phy drivers for TI platforms +# +config PHY_DA8XX_USB + tristate "TI DA8xx USB PHY Driver" + depends on ARCH_DAVINCI_DA8XX + select GENERIC_PHY + select MFD_SYSCON + help + Enable this to support the USB PHY on DA8xx SoCs. + + This driver controls both the USB 1.1 PHY and the USB 2.0 PHY. + +config PHY_DM816X_USB + tristate "TI dm816x USB PHY driver" + depends on ARCH_OMAP2PLUS + depends on USB_SUPPORT + select GENERIC_PHY + select USB_PHY + help + Enable this for dm816x USB to work. + +config OMAP_CONTROL_PHY + tristate "OMAP CONTROL PHY Driver" + depends on ARCH_OMAP2PLUS || COMPILE_TEST + help + Enable this to add support for the PHY part present in the control + module. This driver has API to power on the USB2 PHY and to write to + the mailbox. The mailbox is present only in omap4 and the register to + power on the USB2 PHY is present in OMAP4 and OMAP5. OMAP5 has an + additional register to power on USB3 PHY/SATA PHY/PCIE PHY + (PIPE3 PHY). + +config OMAP_USB2 + tristate "OMAP USB2 PHY Driver" + depends on ARCH_OMAP2PLUS + depends on USB_SUPPORT + select GENERIC_PHY + select USB_PHY + select OMAP_CONTROL_PHY + depends on OMAP_OCP2SCP + help + Enable this to support the transceiver that is part of SOC. This + driver takes care of all the PHY functionality apart from comparator. + The USB OTG controller communicates with the comparator using this + driver. + +config TI_PIPE3 + tristate "TI PIPE3 PHY Driver" + depends on ARCH_OMAP2PLUS || COMPILE_TEST + select GENERIC_PHY + select OMAP_CONTROL_PHY + depends on OMAP_OCP2SCP + help + Enable this to support the PIPE3 PHY that is part of TI SOCs. This + driver takes care of all the PHY functionality apart from comparator. + This driver interacts with the "OMAP Control PHY Driver" to power + on/off the PHY. + +config PHY_TUSB1210 + tristate "TI TUSB1210 ULPI PHY module" + depends on USB_ULPI_BUS + select GENERIC_PHY + help + Support for TI TUSB1210 USB ULPI PHY. + +config TWL4030_USB + tristate "TWL4030 USB Transceiver Driver" + depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS + depends on USB_SUPPORT + depends on USB_GADGET || !USB_GADGET # if USB_GADGET=m, this can't 'y' + select GENERIC_PHY + select USB_PHY + help + Enable this to support the USB OTG transceiver on TWL4030 + family chips (including the TWL5030 and TPS659x0 devices). + This transceiver supports high and full speed devices plus, + in host mode, low speed. diff --git a/drivers/phy/ti/Makefile b/drivers/phy/ti/Makefile new file mode 100644 index 000000000000..0cc3a1a557a3 --- /dev/null +++ b/drivers/phy/ti/Makefile @@ -0,0 +1,7 @@ +obj-$(CONFIG_PHY_DA8XX_USB) += phy-da8xx-usb.o +obj-$(CONFIG_PHY_DM816X_USB) += phy-dm816x-usb.o +obj-$(CONFIG_OMAP_CONTROL_PHY) += phy-omap-control.o +obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o +obj-$(CONFIG_TI_PIPE3) += phy-ti-pipe3.o +obj-$(CONFIG_PHY_TUSB1210) += phy-tusb1210.o +obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o diff --git a/drivers/phy/phy-da8xx-usb.c b/drivers/phy/ti/phy-da8xx-usb.c index 1b82bff6330f..1b82bff6330f 100644 --- a/drivers/phy/phy-da8xx-usb.c +++ b/drivers/phy/ti/phy-da8xx-usb.c diff --git a/drivers/phy/phy-dm816x-usb.c b/drivers/phy/ti/phy-dm816x-usb.c index cbcce7cf0028..cbcce7cf0028 100644 --- a/drivers/phy/phy-dm816x-usb.c +++ b/drivers/phy/ti/phy-dm816x-usb.c diff --git a/drivers/phy/phy-omap-control.c b/drivers/phy/ti/phy-omap-control.c index e9c41b3fa0ee..e9c41b3fa0ee 100644 --- a/drivers/phy/phy-omap-control.c +++ b/drivers/phy/ti/phy-omap-control.c diff --git a/drivers/phy/phy-omap-usb2.c b/drivers/phy/ti/phy-omap-usb2.c index fe909fd8144f..fe909fd8144f 100644 --- a/drivers/phy/phy-omap-usb2.c +++ b/drivers/phy/ti/phy-omap-usb2.c diff --git a/drivers/phy/phy-ti-pipe3.c b/drivers/phy/ti/phy-ti-pipe3.c index 9c84d32c6f60..9c84d32c6f60 100644 --- a/drivers/phy/phy-ti-pipe3.c +++ b/drivers/phy/ti/phy-ti-pipe3.c diff --git a/drivers/phy/phy-tusb1210.c b/drivers/phy/ti/phy-tusb1210.c index 4f6d5e71507d..bb3fb031c478 100644 --- a/drivers/phy/phy-tusb1210.c +++ b/drivers/phy/ti/phy-tusb1210.c @@ -12,8 +12,7 @@ #include <linux/module.h> #include <linux/ulpi/driver.h> #include <linux/gpio/consumer.h> - -#include "ulpi_phy.h" +#include <linux/phy/ulpi_phy.h> #define TUSB1210_VENDOR_SPECIFIC2 0x80 #define TUSB1210_VENDOR_SPECIFIC2_IHSTX_SHIFT 0 diff --git a/drivers/phy/phy-twl4030-usb.c b/drivers/phy/ti/phy-twl4030-usb.c index 2990b3965460..2990b3965460 100644 --- a/drivers/phy/phy-twl4030-usb.c +++ b/drivers/phy/ti/phy-twl4030-usb.c diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c index 9dd981ddbb17..a1928ebb6388 100644 --- a/drivers/pinctrl/pinctrl-rockchip.c +++ b/drivers/pinctrl/pinctrl-rockchip.c @@ -76,7 +76,6 @@ enum rockchip_pinctrl_type { #define IOMUX_SOURCE_PMU BIT(2) #define IOMUX_UNROUTED BIT(3) #define IOMUX_WIDTH_3BIT BIT(4) -#define IOMUX_RECALCED BIT(5) /** * @type: iomux variant using IOMUX_* constants @@ -143,6 +142,7 @@ struct rockchip_drv { * @gpio_chip: gpiolib chip * @grange: gpio range * @slock: spinlock for the gpio bank + * @route_mask: bits describing the routing pins of per bank */ struct rockchip_pin_bank { void __iomem *reg_base; @@ -165,6 +165,8 @@ struct rockchip_pin_bank { struct pinctrl_gpio_range grange; raw_spinlock_t slock; u32 toggle_edge_mode; + u32 recalced_mask; + u32 route_mask; }; #define PIN_BANK(id, pins, label) \ @@ -288,6 +290,38 @@ struct rockchip_pin_bank { } /** + * struct rockchip_mux_recalced_data: represent a pin iomux data. + * @num: bank number. + * @pin: pin number. + * @bit: index at register. + * @reg: register offset. + * @mask: mask bit + */ +struct rockchip_mux_recalced_data { + u8 num; + u8 pin; + u8 reg; + u8 bit; + u8 mask; +}; + +/** + * struct rockchip_mux_recalced_data: represent a pin iomux data. + * @bank_num: bank number. + * @pin: index at register or used to calc index. + * @func: the min pin. + * @route_offset: the max pin. + * @route_val: the register offset. + */ +struct rockchip_mux_route_data { + u8 bank_num; + u8 pin; + u8 func; + u32 route_offset; + u32 route_val; +}; + +/** */ struct rockchip_pin_ctrl { struct rockchip_pin_bank *pin_banks; @@ -299,6 +333,10 @@ struct rockchip_pin_ctrl { int pmu_mux_offset; int grf_drv_offset; int pmu_drv_offset; + struct rockchip_mux_recalced_data *iomux_recalced; + u32 niomux_recalced; + struct rockchip_mux_route_data *iomux_routes; + u32 niomux_routes; void (*pull_calc_reg)(struct rockchip_pin_bank *bank, int pin_num, struct regmap **regmap, @@ -306,8 +344,6 @@ struct rockchip_pin_ctrl { void (*drv_calc_reg)(struct rockchip_pin_bank *bank, int pin_num, struct regmap **regmap, int *reg, u8 *bit); - void (*iomux_recalc)(u8 bank_num, int pin, int *reg, - u8 *bit, int *mask); int (*schmitt_calc_reg)(struct rockchip_pin_bank *bank, int pin_num, struct regmap **regmap, int *reg, u8 *bit); @@ -362,22 +398,6 @@ struct rockchip_pinctrl { unsigned int nfunctions; }; -/** - * struct rockchip_mux_recalced_data: represent a pin iomux data. - * @num: bank number. - * @pin: pin number. - * @bit: index at register. - * @reg: register offset. - * @mask: mask bit - */ -struct rockchip_mux_recalced_data { - u8 num; - u8 pin; - u8 reg; - u8 bit; - u8 mask; -}; - static struct regmap_config rockchip_regmap_config = { .reg_bits = 32, .val_bits = 32, @@ -537,7 +557,7 @@ static const struct pinctrl_ops rockchip_pctrl_ops = { * Hardware access */ -static const struct rockchip_mux_recalced_data rk3328_mux_recalced_data[] = { +static struct rockchip_mux_recalced_data rk3328_mux_recalced_data[] = { { .num = 2, .pin = 12, @@ -559,20 +579,22 @@ static const struct rockchip_mux_recalced_data rk3328_mux_recalced_data[] = { }, }; -static void rk3328_recalc_mux(u8 bank_num, int pin, int *reg, - u8 *bit, int *mask) +static void rockchip_get_recalced_mux(struct rockchip_pin_bank *bank, int pin, + int *reg, u8 *bit, int *mask) { - const struct rockchip_mux_recalced_data *data = NULL; + struct rockchip_pinctrl *info = bank->drvdata; + struct rockchip_pin_ctrl *ctrl = info->ctrl; + struct rockchip_mux_recalced_data *data; int i; - for (i = 0; i < ARRAY_SIZE(rk3328_mux_recalced_data); i++) - if (rk3328_mux_recalced_data[i].num == bank_num && - rk3328_mux_recalced_data[i].pin == pin) { - data = &rk3328_mux_recalced_data[i]; + for (i = 0; i < ctrl->niomux_recalced; i++) { + data = &ctrl->iomux_recalced[i]; + if (data->num == bank->bank_num && + data->pin == pin) break; - } + } - if (!data) + if (i >= ctrl->niomux_recalced) return; *reg = data->reg; @@ -580,10 +602,283 @@ static void rk3328_recalc_mux(u8 bank_num, int pin, int *reg, *bit = data->bit; } -static int rockchip_get_mux(struct rockchip_pin_bank *bank, int pin) +static struct rockchip_mux_route_data rk3228_mux_route_data[] = { + { + /* pwm0-0 */ + .bank_num = 0, + .pin = 26, + .func = 1, + .route_offset = 0x50, + .route_val = BIT(16), + }, { + /* pwm0-1 */ + .bank_num = 3, + .pin = 21, + .func = 1, + .route_offset = 0x50, + .route_val = BIT(16) | BIT(0), + }, { + /* pwm1-0 */ + .bank_num = 0, + .pin = 27, + .func = 1, + .route_offset = 0x50, + .route_val = BIT(16 + 1), + }, { + /* pwm1-1 */ + .bank_num = 0, + .pin = 30, + .func = 2, + .route_offset = 0x50, + .route_val = BIT(16 + 1) | BIT(1), + }, { + /* pwm2-0 */ + .bank_num = 0, + .pin = 28, + .func = 1, + .route_offset = 0x50, + .route_val = BIT(16 + 2), + }, { + /* pwm2-1 */ + .bank_num = 1, + .pin = 12, + .func = 2, + .route_offset = 0x50, + .route_val = BIT(16 + 2) | BIT(2), + }, { + /* pwm3-0 */ + .bank_num = 3, + .pin = 26, + .func = 1, + .route_offset = 0x50, + .route_val = BIT(16 + 3), + }, { + /* pwm3-1 */ + .bank_num = 1, + .pin = 11, + .func = 2, + .route_offset = 0x50, + .route_val = BIT(16 + 3) | BIT(3), + }, { + /* sdio-0_d0 */ + .bank_num = 1, + .pin = 1, + .func = 1, + .route_offset = 0x50, + .route_val = BIT(16 + 4), + }, { + /* sdio-1_d0 */ + .bank_num = 3, + .pin = 2, + .func = 1, + .route_offset = 0x50, + .route_val = BIT(16 + 4) | BIT(4), + }, { + /* spi-0_rx */ + .bank_num = 0, + .pin = 13, + .func = 2, + .route_offset = 0x50, + .route_val = BIT(16 + 5), + }, { + /* spi-1_rx */ + .bank_num = 2, + .pin = 0, + .func = 2, + .route_offset = 0x50, + .route_val = BIT(16 + 5) | BIT(5), + }, { + /* emmc-0_cmd */ + .bank_num = 1, + .pin = 22, + .func = 2, + .route_offset = 0x50, + .route_val = BIT(16 + 7), + }, { + /* emmc-1_cmd */ + .bank_num = 2, + .pin = 4, + .func = 2, + .route_offset = 0x50, + .route_val = BIT(16 + 7) | BIT(7), + }, { + /* uart2-0_rx */ + .bank_num = 1, + .pin = 19, + .func = 2, + .route_offset = 0x50, + .route_val = BIT(16 + 8), + }, { + /* uart2-1_rx */ + .bank_num = 1, + .pin = 10, + .func = 2, + .route_offset = 0x50, + .route_val = BIT(16 + 8) | BIT(8), + }, { + /* uart1-0_rx */ + .bank_num = 1, + .pin = 10, + .func = 1, + .route_offset = 0x50, + .route_val = BIT(16 + 11), + }, { + /* uart1-1_rx */ + .bank_num = 3, + .pin = 13, + .func = 1, + .route_offset = 0x50, + .route_val = BIT(16 + 11) | BIT(11), + }, +}; + +static struct rockchip_mux_route_data rk3328_mux_route_data[] = { + { + /* uart2dbg_rxm0 */ + .bank_num = 1, + .pin = 1, + .func = 2, + .route_offset = 0x50, + .route_val = BIT(16) | BIT(16 + 1), + }, { + /* uart2dbg_rxm1 */ + .bank_num = 2, + .pin = 1, + .func = 1, + .route_offset = 0x50, + .route_val = BIT(16) | BIT(16 + 1) | BIT(0), + }, { + /* gmac-m1-optimized_rxd0 */ + .bank_num = 1, + .pin = 11, + .func = 2, + .route_offset = 0x50, + .route_val = BIT(16 + 2) | BIT(16 + 10) | BIT(2) | BIT(10), + }, { + /* pdm_sdi0m0 */ + .bank_num = 2, + .pin = 19, + .func = 2, + .route_offset = 0x50, + .route_val = BIT(16 + 3), + }, { + /* pdm_sdi0m1 */ + .bank_num = 1, + .pin = 23, + .func = 3, + .route_offset = 0x50, + .route_val = BIT(16 + 3) | BIT(3), + }, { + /* spi_rxdm2 */ + .bank_num = 3, + .pin = 2, + .func = 4, + .route_offset = 0x50, + .route_val = BIT(16 + 4) | BIT(16 + 5) | BIT(5), + }, { + /* i2s2_sdim0 */ + .bank_num = 1, + .pin = 24, + .func = 1, + .route_offset = 0x50, + .route_val = BIT(16 + 6), + }, { + /* i2s2_sdim1 */ + .bank_num = 3, + .pin = 2, + .func = 6, + .route_offset = 0x50, + .route_val = BIT(16 + 6) | BIT(6), + }, { + /* card_iom1 */ + .bank_num = 2, + .pin = 22, + .func = 3, + .route_offset = 0x50, + .route_val = BIT(16 + 7) | BIT(7), + }, { + /* tsp_d5m1 */ + .bank_num = 2, + .pin = 16, + .func = 3, + .route_offset = 0x50, + .route_val = BIT(16 + 8) | BIT(8), + }, { + /* cif_data5m1 */ + .bank_num = 2, + .pin = 16, + .func = 4, + .route_offset = 0x50, + .route_val = BIT(16 + 9) | BIT(9), + }, +}; + +static struct rockchip_mux_route_data rk3399_mux_route_data[] = { + { + /* uart2dbga_rx */ + .bank_num = 4, + .pin = 8, + .func = 2, + .route_offset = 0xe21c, + .route_val = BIT(16 + 10) | BIT(16 + 11), + }, { + /* uart2dbgb_rx */ + .bank_num = 4, + .pin = 16, + .func = 2, + .route_offset = 0xe21c, + .route_val = BIT(16 + 10) | BIT(16 + 11) | BIT(10), + }, { + /* uart2dbgc_rx */ + .bank_num = 4, + .pin = 19, + .func = 1, + .route_offset = 0xe21c, + .route_val = BIT(16 + 10) | BIT(16 + 11) | BIT(11), + }, { + /* pcie_clkreqn */ + .bank_num = 2, + .pin = 26, + .func = 2, + .route_offset = 0xe21c, + .route_val = BIT(16 + 14), + }, { + /* pcie_clkreqnb */ + .bank_num = 4, + .pin = 24, + .func = 1, + .route_offset = 0xe21c, + .route_val = BIT(16 + 14) | BIT(14), + }, +}; + +static bool rockchip_get_mux_route(struct rockchip_pin_bank *bank, int pin, + int mux, u32 *reg, u32 *value) { struct rockchip_pinctrl *info = bank->drvdata; struct rockchip_pin_ctrl *ctrl = info->ctrl; + struct rockchip_mux_route_data *data; + int i; + + for (i = 0; i < ctrl->niomux_routes; i++) { + data = &ctrl->iomux_routes[i]; + if ((data->bank_num == bank->bank_num) && + (data->pin == pin) && (data->func == mux)) + break; + } + + if (i >= ctrl->niomux_routes) + return false; + + *reg = data->route_offset; + *value = data->route_val; + + return true; +} + +static int rockchip_get_mux(struct rockchip_pin_bank *bank, int pin) +{ + struct rockchip_pinctrl *info = bank->drvdata; int iomux_num = (pin / 8); struct regmap *regmap; unsigned int val; @@ -622,8 +917,8 @@ static int rockchip_get_mux(struct rockchip_pin_bank *bank, int pin) mask = 0x3; } - if (ctrl->iomux_recalc && (mux_type & IOMUX_RECALCED)) - ctrl->iomux_recalc(bank->bank_num, pin, ®, &bit, &mask); + if (bank->recalced_mask & BIT(pin)) + rockchip_get_recalced_mux(bank, pin, ®, &bit, &mask); ret = regmap_read(regmap, reg, &val); if (ret) @@ -673,12 +968,11 @@ static int rockchip_verify_mux(struct rockchip_pin_bank *bank, static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux) { struct rockchip_pinctrl *info = bank->drvdata; - struct rockchip_pin_ctrl *ctrl = info->ctrl; int iomux_num = (pin / 8); struct regmap *regmap; int reg, ret, mask, mux_type; u8 bit; - u32 data, rmask; + u32 data, rmask, route_reg, route_val; ret = rockchip_verify_mux(bank, pin, mux); if (ret < 0) @@ -711,8 +1005,17 @@ static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux) mask = 0x3; } - if (ctrl->iomux_recalc && (mux_type & IOMUX_RECALCED)) - ctrl->iomux_recalc(bank->bank_num, pin, ®, &bit, &mask); + if (bank->recalced_mask & BIT(pin)) + rockchip_get_recalced_mux(bank, pin, ®, &bit, &mask); + + if (bank->route_mask & BIT(pin)) { + if (rockchip_get_mux_route(bank, pin, mux, &route_reg, + &route_val)) { + ret = regmap_write(regmap, route_reg, route_val); + if (ret) + return ret; + } + } data = (mask << (bit + 16)); rmask = data | (data >> 16); @@ -2549,6 +2852,26 @@ static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data( bank_pins += 8; } + + /* calculate the per-bank recalced_mask */ + for (j = 0; j < ctrl->niomux_recalced; j++) { + int pin = 0; + + if (ctrl->iomux_recalced[j].num == bank->bank_num) { + pin = ctrl->iomux_recalced[j].pin; + bank->recalced_mask |= BIT(pin); + } + } + + /* calculate the per-bank route_mask */ + for (j = 0; j < ctrl->niomux_routes; j++) { + int pin = 0; + + if (ctrl->iomux_routes[j].bank_num == bank->bank_num) { + pin = ctrl->iomux_routes[j].pin; + bank->route_mask |= BIT(pin); + } + } } return ctrl; @@ -2799,6 +3122,8 @@ static struct rockchip_pin_ctrl rk3228_pin_ctrl = { .label = "RK3228-GPIO", .type = RK3288, .grf_mux_offset = 0x0, + .iomux_routes = rk3228_mux_route_data, + .niomux_routes = ARRAY_SIZE(rk3228_mux_route_data), .pull_calc_reg = rk3228_calc_pull_reg_and_bit, .drv_calc_reg = rk3228_calc_drv_reg_and_bit, }; @@ -2850,12 +3175,12 @@ static struct rockchip_pin_bank rk3328_pin_banks[] = { PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", 0, 0, 0, 0), PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", 0, 0, 0, 0), PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", 0, - IOMUX_WIDTH_3BIT | IOMUX_RECALCED, - IOMUX_WIDTH_3BIT | IOMUX_RECALCED, + IOMUX_WIDTH_3BIT, + IOMUX_WIDTH_3BIT, 0), PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3", IOMUX_WIDTH_3BIT, - IOMUX_WIDTH_3BIT | IOMUX_RECALCED, + IOMUX_WIDTH_3BIT, 0, 0), }; @@ -2866,9 +3191,12 @@ static struct rockchip_pin_ctrl rk3328_pin_ctrl = { .label = "RK3328-GPIO", .type = RK3288, .grf_mux_offset = 0x0, + .iomux_recalced = rk3328_mux_recalced_data, + .niomux_recalced = ARRAY_SIZE(rk3328_mux_recalced_data), + .iomux_routes = rk3328_mux_route_data, + .niomux_routes = ARRAY_SIZE(rk3328_mux_route_data), .pull_calc_reg = rk3228_calc_pull_reg_and_bit, .drv_calc_reg = rk3228_calc_drv_reg_and_bit, - .iomux_recalc = rk3328_recalc_mux, .schmitt_calc_reg = rk3328_calc_schmitt_reg_and_bit, }; @@ -2904,8 +3232,8 @@ static struct rockchip_pin_bank rk3399_pin_banks[] = { DRV_TYPE_IO_1V8_ONLY, DRV_TYPE_IO_DEFAULT, DRV_TYPE_IO_DEFAULT, - 0x0, - 0x8, + 0x80, + 0x88, -1, -1, PULL_TYPE_IO_1V8_ONLY, @@ -2921,10 +3249,10 @@ static struct rockchip_pin_bank rk3399_pin_banks[] = { DRV_TYPE_IO_1V8_OR_3V0, DRV_TYPE_IO_1V8_OR_3V0, DRV_TYPE_IO_1V8_OR_3V0, - 0x20, - 0x28, - 0x30, - 0x38 + 0xa0, + 0xa8, + 0xb0, + 0xb8 ), PIN_BANK_DRV_FLAGS_PULL_FLAGS(2, 32, "gpio2", DRV_TYPE_IO_1V8_OR_3V0, DRV_TYPE_IO_1V8_OR_3V0, @@ -2956,33 +3284,35 @@ static struct rockchip_pin_ctrl rk3399_pin_ctrl = { .pmu_mux_offset = 0x0, .grf_drv_offset = 0xe100, .pmu_drv_offset = 0x80, + .iomux_routes = rk3399_mux_route_data, + .niomux_routes = ARRAY_SIZE(rk3399_mux_route_data), .pull_calc_reg = rk3399_calc_pull_reg_and_bit, .drv_calc_reg = rk3399_calc_drv_reg_and_bit, }; static const struct of_device_id rockchip_pinctrl_dt_match[] = { { .compatible = "rockchip,rv1108-pinctrl", - .data = (void *)&rv1108_pin_ctrl }, + .data = &rv1108_pin_ctrl }, { .compatible = "rockchip,rk2928-pinctrl", - .data = (void *)&rk2928_pin_ctrl }, + .data = &rk2928_pin_ctrl }, { .compatible = "rockchip,rk3036-pinctrl", - .data = (void *)&rk3036_pin_ctrl }, + .data = &rk3036_pin_ctrl }, { .compatible = "rockchip,rk3066a-pinctrl", - .data = (void *)&rk3066a_pin_ctrl }, + .data = &rk3066a_pin_ctrl }, { .compatible = "rockchip,rk3066b-pinctrl", - .data = (void *)&rk3066b_pin_ctrl }, + .data = &rk3066b_pin_ctrl }, { .compatible = "rockchip,rk3188-pinctrl", - .data = (void *)&rk3188_pin_ctrl }, + .data = &rk3188_pin_ctrl }, { .compatible = "rockchip,rk3228-pinctrl", - .data = (void *)&rk3228_pin_ctrl }, + .data = &rk3228_pin_ctrl }, { .compatible = "rockchip,rk3288-pinctrl", - .data = (void *)&rk3288_pin_ctrl }, + .data = &rk3288_pin_ctrl }, { .compatible = "rockchip,rk3328-pinctrl", - .data = (void *)&rk3328_pin_ctrl }, + .data = &rk3328_pin_ctrl }, { .compatible = "rockchip,rk3368-pinctrl", - .data = (void *)&rk3368_pin_ctrl }, + .data = &rk3368_pin_ctrl }, { .compatible = "rockchip,rk3399-pinctrl", - .data = (void *)&rk3399_pin_ctrl }, + .data = &rk3399_pin_ctrl }, {}, }; diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c index 744d56197286..a3fcb404036d 100644 --- a/drivers/pwm/pwm-rockchip.c +++ b/drivers/pwm/pwm-rockchip.c @@ -27,12 +27,14 @@ #define PWM_DUTY_NEGATIVE (0 << 3) #define PWM_INACTIVE_NEGATIVE (0 << 4) #define PWM_INACTIVE_POSITIVE (1 << 4) +#define PWM_POLARITY_MASK (PWM_DUTY_POSITIVE | PWM_INACTIVE_POSITIVE) #define PWM_OUTPUT_LEFT (0 << 5) #define PWM_LP_DISABLE (0 << 8) struct rockchip_pwm_chip { struct pwm_chip chip; struct clk *clk; + struct clk *pclk; const struct rockchip_pwm_data *data; void __iomem *base; }; @@ -48,13 +50,7 @@ struct rockchip_pwm_data { struct rockchip_pwm_regs regs; unsigned int prescaler; bool supports_polarity; - const struct pwm_ops *ops; - - void (*set_enable)(struct pwm_chip *chip, - struct pwm_device *pwm, bool enable, - enum pwm_polarity polarity); - void (*get_state)(struct pwm_chip *chip, struct pwm_device *pwm, - struct pwm_state *state); + u32 enable_conf; }; static inline struct rockchip_pwm_chip *to_rockchip_pwm_chip(struct pwm_chip *c) @@ -62,90 +58,18 @@ static inline struct rockchip_pwm_chip *to_rockchip_pwm_chip(struct pwm_chip *c) return container_of(c, struct rockchip_pwm_chip, chip); } -static void rockchip_pwm_set_enable_v1(struct pwm_chip *chip, - struct pwm_device *pwm, bool enable, - enum pwm_polarity polarity) -{ - struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); - u32 enable_conf = PWM_CTRL_OUTPUT_EN | PWM_CTRL_TIMER_EN; - u32 val; - - val = readl_relaxed(pc->base + pc->data->regs.ctrl); - - if (enable) - val |= enable_conf; - else - val &= ~enable_conf; - - writel_relaxed(val, pc->base + pc->data->regs.ctrl); -} - -static void rockchip_pwm_get_state_v1(struct pwm_chip *chip, - struct pwm_device *pwm, - struct pwm_state *state) -{ - struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); - u32 enable_conf = PWM_CTRL_OUTPUT_EN | PWM_CTRL_TIMER_EN; - u32 val; - - val = readl_relaxed(pc->base + pc->data->regs.ctrl); - if ((val & enable_conf) == enable_conf) - state->enabled = true; -} - -static void rockchip_pwm_set_enable_v2(struct pwm_chip *chip, - struct pwm_device *pwm, bool enable, - enum pwm_polarity polarity) -{ - struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); - u32 enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE | - PWM_CONTINUOUS; - u32 val; - - if (polarity == PWM_POLARITY_INVERSED) - enable_conf |= PWM_DUTY_NEGATIVE | PWM_INACTIVE_POSITIVE; - else - enable_conf |= PWM_DUTY_POSITIVE | PWM_INACTIVE_NEGATIVE; - - val = readl_relaxed(pc->base + pc->data->regs.ctrl); - - if (enable) - val |= enable_conf; - else - val &= ~enable_conf; - - writel_relaxed(val, pc->base + pc->data->regs.ctrl); -} - -static void rockchip_pwm_get_state_v2(struct pwm_chip *chip, - struct pwm_device *pwm, - struct pwm_state *state) -{ - struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); - u32 enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE | - PWM_CONTINUOUS; - u32 val; - - val = readl_relaxed(pc->base + pc->data->regs.ctrl); - if ((val & enable_conf) != enable_conf) - return; - - state->enabled = true; - - if (!(val & PWM_DUTY_POSITIVE)) - state->polarity = PWM_POLARITY_INVERSED; -} - static void rockchip_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, struct pwm_state *state) { struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); + u32 enable_conf = pc->data->enable_conf; unsigned long clk_rate; u64 tmp; + u32 val; int ret; - ret = clk_enable(pc->clk); + ret = clk_enable(pc->pclk); if (ret) return; @@ -157,19 +81,31 @@ static void rockchip_pwm_get_state(struct pwm_chip *chip, tmp = readl_relaxed(pc->base + pc->data->regs.duty); tmp *= pc->data->prescaler * NSEC_PER_SEC; - state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, clk_rate); + state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, clk_rate); - pc->data->get_state(chip, pwm, state); + val = readl_relaxed(pc->base + pc->data->regs.ctrl); + if (pc->data->supports_polarity) + state->enabled = ((val & enable_conf) != enable_conf) ? + false : true; + else + state->enabled = ((val & enable_conf) == enable_conf) ? + true : false; - clk_disable(pc->clk); + if (pc->data->supports_polarity) { + if (!(val & PWM_DUTY_POSITIVE)) + state->polarity = PWM_POLARITY_INVERSED; + } + + clk_disable(pc->pclk); } -static int rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, - int duty_ns, int period_ns) +static void rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, + struct pwm_state *state) { struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); unsigned long period, duty; u64 clk_rate, div; + u32 ctrl; clk_rate = clk_get_rate(pc->clk); @@ -178,26 +114,35 @@ static int rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, * bits, every possible input period can be obtained using the * default prescaler value for all practical clock rate values. */ - div = clk_rate * period_ns; + div = clk_rate * state->period; period = DIV_ROUND_CLOSEST_ULL(div, pc->data->prescaler * NSEC_PER_SEC); - div = clk_rate * duty_ns; + div = clk_rate * state->duty_cycle; duty = DIV_ROUND_CLOSEST_ULL(div, pc->data->prescaler * NSEC_PER_SEC); writel(period, pc->base + pc->data->regs.period); writel(duty, pc->base + pc->data->regs.duty); - return 0; + ctrl = readl_relaxed(pc->base + pc->data->regs.ctrl); + if (pc->data->supports_polarity) { + ctrl &= ~PWM_POLARITY_MASK; + if (state->polarity == PWM_POLARITY_INVERSED) + ctrl |= PWM_DUTY_NEGATIVE | PWM_INACTIVE_POSITIVE; + else + ctrl |= PWM_DUTY_POSITIVE | PWM_INACTIVE_NEGATIVE; + } + writel(ctrl, pc->base + pc->data->regs.ctrl); } static int rockchip_pwm_enable(struct pwm_chip *chip, - struct pwm_device *pwm, - bool enable, - enum pwm_polarity polarity) + struct pwm_device *pwm, + bool enable) { struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); + u32 enable_conf = pc->data->enable_conf; int ret; + u32 val; if (enable) { ret = clk_enable(pc->clk); @@ -205,7 +150,14 @@ static int rockchip_pwm_enable(struct pwm_chip *chip, return ret; } - pc->data->set_enable(chip, pwm, enable, polarity); + val = readl_relaxed(pc->base + pc->data->regs.ctrl); + + if (enable) + val |= enable_conf; + else + val &= ~enable_conf; + + writel_relaxed(val, pc->base + pc->data->regs.ctrl); if (!enable) clk_disable(pc->clk); @@ -219,33 +171,25 @@ static int rockchip_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); struct pwm_state curstate; bool enabled; - int ret; - - pwm_get_state(pwm, &curstate); - enabled = curstate.enabled; + int ret = 0; - ret = clk_enable(pc->clk); + ret = clk_enable(pc->pclk); if (ret) return ret; + pwm_get_state(pwm, &curstate); + enabled = curstate.enabled; + if (state->polarity != curstate.polarity && enabled) { - ret = rockchip_pwm_enable(chip, pwm, false, state->polarity); + ret = rockchip_pwm_enable(chip, pwm, false); if (ret) goto out; enabled = false; } - ret = rockchip_pwm_config(chip, pwm, state->duty_cycle, state->period); - if (ret) { - if (enabled != curstate.enabled) - rockchip_pwm_enable(chip, pwm, !enabled, - state->polarity); - goto out; - } - + rockchip_pwm_config(chip, pwm, state); if (state->enabled != enabled) { - ret = rockchip_pwm_enable(chip, pwm, state->enabled, - state->polarity); + ret = rockchip_pwm_enable(chip, pwm, state->enabled); if (ret) goto out; } @@ -257,18 +201,12 @@ static int rockchip_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, rockchip_pwm_get_state(chip, pwm, state); out: - clk_disable(pc->clk); + clk_disable(pc->pclk); return ret; } -static const struct pwm_ops rockchip_pwm_ops_v1 = { - .get_state = rockchip_pwm_get_state, - .apply = rockchip_pwm_apply, - .owner = THIS_MODULE, -}; - -static const struct pwm_ops rockchip_pwm_ops_v2 = { +static const struct pwm_ops rockchip_pwm_ops = { .get_state = rockchip_pwm_get_state, .apply = rockchip_pwm_apply, .owner = THIS_MODULE, @@ -282,9 +220,8 @@ static const struct rockchip_pwm_data pwm_data_v1 = { .ctrl = 0x0c, }, .prescaler = 2, - .ops = &rockchip_pwm_ops_v1, - .set_enable = rockchip_pwm_set_enable_v1, - .get_state = rockchip_pwm_get_state_v1, + .supports_polarity = false, + .enable_conf = PWM_CTRL_OUTPUT_EN | PWM_CTRL_TIMER_EN, }; static const struct rockchip_pwm_data pwm_data_v2 = { @@ -296,9 +233,8 @@ static const struct rockchip_pwm_data pwm_data_v2 = { }, .prescaler = 1, .supports_polarity = true, - .ops = &rockchip_pwm_ops_v2, - .set_enable = rockchip_pwm_set_enable_v2, - .get_state = rockchip_pwm_get_state_v2, + .enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE | + PWM_CONTINUOUS, }; static const struct rockchip_pwm_data pwm_data_vop = { @@ -310,9 +246,8 @@ static const struct rockchip_pwm_data pwm_data_vop = { }, .prescaler = 1, .supports_polarity = true, - .ops = &rockchip_pwm_ops_v2, - .set_enable = rockchip_pwm_set_enable_v2, - .get_state = rockchip_pwm_get_state_v2, + .enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE | + PWM_CONTINUOUS, }; static const struct of_device_id rockchip_pwm_dt_ids[] = { @@ -328,7 +263,7 @@ static int rockchip_pwm_probe(struct platform_device *pdev) const struct of_device_id *id; struct rockchip_pwm_chip *pc; struct resource *r; - int ret; + int ret, count; id = of_match_device(rockchip_pwm_dt_ids, &pdev->dev); if (!id) @@ -343,19 +278,49 @@ static int rockchip_pwm_probe(struct platform_device *pdev) if (IS_ERR(pc->base)) return PTR_ERR(pc->base); - pc->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(pc->clk)) - return PTR_ERR(pc->clk); + pc->clk = devm_clk_get(&pdev->dev, "pwm"); + if (IS_ERR(pc->clk)) { + pc->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(pc->clk)) { + ret = PTR_ERR(pc->clk); + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "Can't get bus clk: %d\n", + ret); + return ret; + } + } + + count = of_count_phandle_with_args(pdev->dev.of_node, + "clocks", "#clock-cells"); + if (count == 2) + pc->pclk = devm_clk_get(&pdev->dev, "pclk"); + else + pc->pclk = pc->clk; + + if (IS_ERR(pc->pclk)) { + ret = PTR_ERR(pc->pclk); + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "Can't get APB clk: %d\n", ret); + return ret; + } ret = clk_prepare_enable(pc->clk); - if (ret) + if (ret) { + dev_err(&pdev->dev, "Can't prepare enable bus clk: %d\n", ret); return ret; + } + + ret = clk_prepare(pc->pclk); + if (ret) { + dev_err(&pdev->dev, "Can't prepare APB clk: %d\n", ret); + goto err_clk; + } platform_set_drvdata(pdev, pc); pc->data = id->data; pc->chip.dev = &pdev->dev; - pc->chip.ops = pc->data->ops; + pc->chip.ops = &rockchip_pwm_ops; pc->chip.base = -1; pc->chip.npwm = 1; @@ -368,12 +333,20 @@ static int rockchip_pwm_probe(struct platform_device *pdev) if (ret < 0) { clk_unprepare(pc->clk); dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); + goto err_pclk; } /* Keep the PWM clk enabled if the PWM appears to be up and running. */ if (!pwm_is_enabled(pc->chip.pwms)) clk_disable(pc->clk); + return 0; + +err_pclk: + clk_unprepare(pc->pclk); +err_clk: + clk_disable_unprepare(pc->clk); + return ret; } @@ -395,6 +368,7 @@ static int rockchip_pwm_remove(struct platform_device *pdev) if (pwm_is_enabled(pc->chip.pwms)) clk_disable(pc->clk); + clk_unprepare(pc->pclk); clk_unprepare(pc->clk); return pwmchip_remove(&pc->chip); diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c index acf31f36b898..7df207f176fc 100644 --- a/drivers/spi/spi-rockchip.c +++ b/drivers/spi/spi-rockchip.c @@ -25,6 +25,11 @@ #define DRIVER_NAME "rockchip-spi" +#define ROCKCHIP_SPI_CLR_BITS(reg, bits) \ + writel_relaxed(readl_relaxed(reg) & ~(bits), reg) +#define ROCKCHIP_SPI_SET_BITS(reg, bits) \ + writel_relaxed(readl_relaxed(reg) | (bits), reg) + /* SPI register offsets */ #define ROCKCHIP_SPI_CTRLR0 0x0000 #define ROCKCHIP_SPI_CTRLR1 0x0004 @@ -149,6 +154,8 @@ */ #define ROCKCHIP_SPI_MAX_TRANLEN 0xffff +#define ROCKCHIP_SPI_MAX_CS_NUM 2 + enum rockchip_ssi_type { SSI_MOTO_SPI = 0, SSI_TI_SSP, @@ -193,6 +200,8 @@ struct rockchip_spi { /* protect state */ spinlock_t lock; + bool cs_asserted[ROCKCHIP_SPI_MAX_CS_NUM]; + u32 use_dma; struct sg_table tx_sg; struct sg_table rx_sg; @@ -264,37 +273,29 @@ static inline u32 rx_max(struct rockchip_spi *rs) static void rockchip_spi_set_cs(struct spi_device *spi, bool enable) { - u32 ser; struct spi_master *master = spi->master; struct rockchip_spi *rs = spi_master_get_devdata(master); + bool cs_asserted = !enable; - pm_runtime_get_sync(rs->dev); + /* Return immediately for no-op */ + if (cs_asserted == rs->cs_asserted[spi->chip_select]) + return; - ser = readl_relaxed(rs->regs + ROCKCHIP_SPI_SER) & SER_MASK; + if (cs_asserted) { + /* Keep things powered as long as CS is asserted */ + pm_runtime_get_sync(rs->dev); - /* - * drivers/spi/spi.c: - * static void spi_set_cs(struct spi_device *spi, bool enable) - * { - * if (spi->mode & SPI_CS_HIGH) - * enable = !enable; - * - * if (spi->cs_gpio >= 0) - * gpio_set_value(spi->cs_gpio, !enable); - * else if (spi->master->set_cs) - * spi->master->set_cs(spi, !enable); - * } - * - * Note: enable(rockchip_spi_set_cs) = !enable(spi_set_cs) - */ - if (!enable) - ser |= 1 << spi->chip_select; - else - ser &= ~(1 << spi->chip_select); + ROCKCHIP_SPI_SET_BITS(rs->regs + ROCKCHIP_SPI_SER, + BIT(spi->chip_select)); + } else { + ROCKCHIP_SPI_CLR_BITS(rs->regs + ROCKCHIP_SPI_SER, + BIT(spi->chip_select)); - writel_relaxed(ser, rs->regs + ROCKCHIP_SPI_SER); + /* Drop reference from when we first asserted CS */ + pm_runtime_put(rs->dev); + } - pm_runtime_put_sync(rs->dev); + rs->cs_asserted[spi->chip_select] = cs_asserted; } static int rockchip_spi_prepare_message(struct spi_master *master, @@ -567,7 +568,13 @@ static void rockchip_spi_config(struct rockchip_spi *rs) writel_relaxed(cr0, rs->regs + ROCKCHIP_SPI_CTRLR0); - writel_relaxed(rs->len - 1, rs->regs + ROCKCHIP_SPI_CTRLR1); + if (rs->n_bytes == 1) + writel_relaxed(rs->len - 1, rs->regs + ROCKCHIP_SPI_CTRLR1); + else if (rs->n_bytes == 2) + writel_relaxed((rs->len / 2) - 1, rs->regs + ROCKCHIP_SPI_CTRLR1); + else + writel_relaxed((rs->len * 2) - 1, rs->regs + ROCKCHIP_SPI_CTRLR1); + writel_relaxed(rs->fifo_len / 2 - 1, rs->regs + ROCKCHIP_SPI_TXFTLR); writel_relaxed(rs->fifo_len / 2 - 1, rs->regs + ROCKCHIP_SPI_RXFTLR); @@ -665,7 +672,7 @@ static bool rockchip_spi_can_dma(struct spi_master *master, static int rockchip_spi_probe(struct platform_device *pdev) { - int ret = 0; + int ret; struct rockchip_spi *rs; struct spi_master *master; struct resource *mem; @@ -684,33 +691,33 @@ static int rockchip_spi_probe(struct platform_device *pdev) rs->regs = devm_ioremap_resource(&pdev->dev, mem); if (IS_ERR(rs->regs)) { ret = PTR_ERR(rs->regs); - goto err_ioremap_resource; + goto err_put_master; } rs->apb_pclk = devm_clk_get(&pdev->dev, "apb_pclk"); if (IS_ERR(rs->apb_pclk)) { dev_err(&pdev->dev, "Failed to get apb_pclk\n"); ret = PTR_ERR(rs->apb_pclk); - goto err_ioremap_resource; + goto err_put_master; } rs->spiclk = devm_clk_get(&pdev->dev, "spiclk"); if (IS_ERR(rs->spiclk)) { dev_err(&pdev->dev, "Failed to get spi_pclk\n"); ret = PTR_ERR(rs->spiclk); - goto err_ioremap_resource; + goto err_put_master; } ret = clk_prepare_enable(rs->apb_pclk); - if (ret) { + if (ret < 0) { dev_err(&pdev->dev, "Failed to enable apb_pclk\n"); - goto err_ioremap_resource; + goto err_put_master; } ret = clk_prepare_enable(rs->spiclk); - if (ret) { + if (ret < 0) { dev_err(&pdev->dev, "Failed to enable spi_clk\n"); - goto err_spiclk_enable; + goto err_disable_apbclk; } spi_enable_chip(rs, 0); @@ -728,7 +735,7 @@ static int rockchip_spi_probe(struct platform_device *pdev) if (!rs->fifo_len) { dev_err(&pdev->dev, "Failed to get fifo length\n"); ret = -EINVAL; - goto err_get_fifo_len; + goto err_disable_spiclk; } spin_lock_init(&rs->lock); @@ -739,7 +746,7 @@ static int rockchip_spi_probe(struct platform_device *pdev) master->auto_runtime_pm = true; master->bus_num = pdev->id; master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LOOP; - master->num_chipselect = 2; + master->num_chipselect = ROCKCHIP_SPI_MAX_CS_NUM; master->dev.of_node = pdev->dev.of_node; master->bits_per_word_mask = SPI_BPW_MASK(16) | SPI_BPW_MASK(8); @@ -749,13 +756,14 @@ static int rockchip_spi_probe(struct platform_device *pdev) master->transfer_one = rockchip_spi_transfer_one; master->max_transfer_size = rockchip_spi_max_transfer_size; master->handle_err = rockchip_spi_handle_err; + master->flags = SPI_MASTER_GPIO_SS; rs->dma_tx.ch = dma_request_chan(rs->dev, "tx"); if (IS_ERR(rs->dma_tx.ch)) { /* Check tx to see if we need defer probing driver */ if (PTR_ERR(rs->dma_tx.ch) == -EPROBE_DEFER) { ret = -EPROBE_DEFER; - goto err_get_fifo_len; + goto err_disable_pm_runtime; } dev_warn(rs->dev, "Failed to request TX DMA channel\n"); rs->dma_tx.ch = NULL; @@ -784,25 +792,26 @@ static int rockchip_spi_probe(struct platform_device *pdev) } ret = devm_spi_register_master(&pdev->dev, master); - if (ret) { + if (ret < 0) { dev_err(&pdev->dev, "Failed to register master\n"); - goto err_register_master; + goto err_free_dma_rx; } return 0; -err_register_master: - pm_runtime_disable(&pdev->dev); +err_free_dma_rx: if (rs->dma_rx.ch) dma_release_channel(rs->dma_rx.ch); err_free_dma_tx: if (rs->dma_tx.ch) dma_release_channel(rs->dma_tx.ch); -err_get_fifo_len: +err_disable_pm_runtime: + pm_runtime_disable(&pdev->dev); +err_disable_spiclk: clk_disable_unprepare(rs->spiclk); -err_spiclk_enable: +err_disable_apbclk: clk_disable_unprepare(rs->apb_pclk); -err_ioremap_resource: +err_put_master: spi_master_put(master); return ret; @@ -813,11 +822,15 @@ static int rockchip_spi_remove(struct platform_device *pdev) struct spi_master *master = spi_master_get(platform_get_drvdata(pdev)); struct rockchip_spi *rs = spi_master_get_devdata(master); - pm_runtime_disable(&pdev->dev); + pm_runtime_get_sync(&pdev->dev); clk_disable_unprepare(rs->spiclk); clk_disable_unprepare(rs->apb_pclk); + pm_runtime_put_noidle(&pdev->dev); + pm_runtime_disable(&pdev->dev); + pm_runtime_set_suspended(&pdev->dev); + if (rs->dma_tx.ch) dma_release_channel(rs->dma_tx.ch); if (rs->dma_rx.ch) @@ -831,43 +844,34 @@ static int rockchip_spi_remove(struct platform_device *pdev) #ifdef CONFIG_PM_SLEEP static int rockchip_spi_suspend(struct device *dev) { - int ret = 0; + int ret; struct spi_master *master = dev_get_drvdata(dev); struct rockchip_spi *rs = spi_master_get_devdata(master); ret = spi_master_suspend(rs->master); - if (ret) + if (ret < 0) return ret; - if (!pm_runtime_suspended(dev)) { - clk_disable_unprepare(rs->spiclk); - clk_disable_unprepare(rs->apb_pclk); - } + ret = pm_runtime_force_suspend(dev); + if (ret < 0) + return ret; pinctrl_pm_select_sleep_state(dev); - return ret; + return 0; } static int rockchip_spi_resume(struct device *dev) { - int ret = 0; + int ret; struct spi_master *master = dev_get_drvdata(dev); struct rockchip_spi *rs = spi_master_get_devdata(master); pinctrl_pm_select_default_state(dev); - if (!pm_runtime_suspended(dev)) { - ret = clk_prepare_enable(rs->apb_pclk); - if (ret < 0) - return ret; - - ret = clk_prepare_enable(rs->spiclk); - if (ret < 0) { - clk_disable_unprepare(rs->apb_pclk); - return ret; - } - } + ret = pm_runtime_force_resume(dev); + if (ret < 0) + return ret; ret = spi_master_resume(rs->master); if (ret < 0) { @@ -875,7 +879,7 @@ static int rockchip_spi_resume(struct device *dev) clk_disable_unprepare(rs->apb_pclk); } - return ret; + return 0; } #endif /* CONFIG_PM_SLEEP */ @@ -898,14 +902,14 @@ static int rockchip_spi_runtime_resume(struct device *dev) struct rockchip_spi *rs = spi_master_get_devdata(master); ret = clk_prepare_enable(rs->apb_pclk); - if (ret) + if (ret < 0) return ret; ret = clk_prepare_enable(rs->spiclk); - if (ret) + if (ret < 0) clk_disable_unprepare(rs->apb_pclk); - return ret; + return 0; } #endif /* CONFIG_PM */ diff --git a/include/dt-bindings/clock/rk3128-cru.h b/include/dt-bindings/clock/rk3128-cru.h new file mode 100644 index 000000000000..92894f4306cf --- /dev/null +++ b/include/dt-bindings/clock/rk3128-cru.h @@ -0,0 +1,282 @@ +/* + * Copyright (c) 2017 Rockchip Electronics Co. Ltd. + * Author: Elaine <zhangqing@rock-chips.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _DT_BINDINGS_CLK_ROCKCHIP_RK3128_H +#define _DT_BINDINGS_CLK_ROCKCHIP_RK3128_H + +/* core clocks */ +#define PLL_APLL 1 +#define PLL_DPLL 2 +#define PLL_CPLL 3 +#define PLL_GPLL 4 +#define ARMCLK 5 +#define PLL_GPLL_DIV2 6 +#define PLL_GPLL_DIV3 7 + +/* sclk gates (special clocks) */ +#define SCLK_SPI0 65 +#define SCLK_NANDC 67 +#define SCLK_SDMMC 68 +#define SCLK_SDIO 69 +#define SCLK_EMMC 71 +#define SCLK_UART0 77 +#define SCLK_UART1 78 +#define SCLK_UART2 79 +#define SCLK_I2S0 80 +#define SCLK_I2S1 81 +#define SCLK_SPDIF 83 +#define SCLK_TIMER0 85 +#define SCLK_TIMER1 86 +#define SCLK_TIMER2 87 +#define SCLK_TIMER3 88 +#define SCLK_TIMER4 89 +#define SCLK_TIMER5 90 +#define SCLK_SARADC 91 +#define SCLK_I2S_OUT 113 +#define SCLK_SDMMC_DRV 114 +#define SCLK_SDIO_DRV 115 +#define SCLK_EMMC_DRV 117 +#define SCLK_SDMMC_SAMPLE 118 +#define SCLK_SDIO_SAMPLE 119 +#define SCLK_EMMC_SAMPLE 121 +#define SCLK_VOP 122 +#define SCLK_MAC_SRC 124 +#define SCLK_MAC 126 +#define SCLK_MAC_REFOUT 127 +#define SCLK_MAC_REF 128 +#define SCLK_MAC_RX 129 +#define SCLK_MAC_TX 130 +#define SCLK_HEVC_CORE 134 +#define SCLK_RGA 135 +#define SCLK_CRYPTO 138 +#define SCLK_TSP 139 +#define SCLK_OTGPHY0 142 +#define SCLK_OTGPHY1 143 +#define SCLK_DDRC 144 +#define SCLK_PVTM_FUNC 145 +#define SCLK_PVTM_CORE 146 +#define SCLK_PVTM_GPU 147 +#define SCLK_MIPI_24M 148 +#define SCLK_PVTM 149 +#define SCLK_CIF_SRC 150 +#define SCLK_CIF_OUT_SRC 151 +#define SCLK_CIF_OUT 152 +#define SCLK_SFC 153 +#define SCLK_USB480M 154 + +/* dclk gates */ +#define DCLK_VOP 190 +#define DCLK_EBC 191 + +/* aclk gates */ +#define ACLK_VIO0 192 +#define ACLK_VIO1 193 +#define ACLK_DMAC 194 +#define ACLK_CPU 195 +#define ACLK_VEPU 196 +#define ACLK_VDPU 197 +#define ACLK_CIF 198 +#define ACLK_IEP 199 +#define ACLK_LCDC0 204 +#define ACLK_RGA 205 +#define ACLK_PERI 210 +#define ACLK_VOP 211 +#define ACLK_GMAC 212 +#define ACLK_GPU 213 + +/* pclk gates */ +#define PCLK_SARADC 318 +#define PCLK_WDT 319 +#define PCLK_GPIO0 320 +#define PCLK_GPIO1 321 +#define PCLK_GPIO2 322 +#define PCLK_GPIO3 323 +#define PCLK_VIO_H2P 324 +#define PCLK_MIPI 325 +#define PCLK_EFUSE 326 +#define PCLK_HDMI 327 +#define PCLK_ACODEC 328 +#define PCLK_GRF 329 +#define PCLK_I2C0 332 +#define PCLK_I2C1 333 +#define PCLK_I2C2 334 +#define PCLK_I2C3 335 +#define PCLK_SPI0 338 +#define PCLK_UART0 341 +#define PCLK_UART1 342 +#define PCLK_UART2 343 +#define PCLK_TSADC 344 +#define PCLK_PWM 350 +#define PCLK_TIMER 353 +#define PCLK_CPU 354 +#define PCLK_PERI 363 +#define PCLK_GMAC 367 +#define PCLK_PMU_PRE 368 +#define PCLK_SIM_CARD 369 + +/* hclk gates */ +#define HCLK_SPDIF 440 +#define HCLK_GPS 441 +#define HCLK_USBHOST 442 +#define HCLK_I2S_8CH 443 +#define HCLK_I2S_2CH 444 +#define HCLK_VOP 452 +#define HCLK_NANDC 453 +#define HCLK_SDMMC 456 +#define HCLK_SDIO 457 +#define HCLK_EMMC 459 +#define HCLK_CPU 460 +#define HCLK_VEPU 461 +#define HCLK_VDPU 462 +#define HCLK_LCDC0 463 +#define HCLK_EBC 465 +#define HCLK_VIO 466 +#define HCLK_RGA 467 +#define HCLK_IEP 468 +#define HCLK_VIO_H2P 469 +#define HCLK_CIF 470 +#define HCLK_HOST2 473 +#define HCLK_OTG 474 +#define HCLK_TSP 475 +#define HCLK_CRYPTO 476 +#define HCLK_PERI 478 + +#define CLK_NR_CLKS (HCLK_PERI + 1) + +/* soft-reset indices */ +#define SRST_CORE0_PO 0 +#define SRST_CORE1_PO 1 +#define SRST_CORE2_PO 2 +#define SRST_CORE3_PO 3 +#define SRST_CORE0 4 +#define SRST_CORE1 5 +#define SRST_CORE2 6 +#define SRST_CORE3 7 +#define SRST_CORE0_DBG 8 +#define SRST_CORE1_DBG 9 +#define SRST_CORE2_DBG 10 +#define SRST_CORE3_DBG 11 +#define SRST_TOPDBG 12 +#define SRST_ACLK_CORE 13 +#define SRST_STRC_SYS_A 14 +#define SRST_L2C 15 + +#define SRST_CPUSYS_H 18 +#define SRST_AHB2APBSYS_H 19 +#define SRST_SPDIF 20 +#define SRST_INTMEM 21 +#define SRST_ROM 22 +#define SRST_PERI_NIU 23 +#define SRST_I2S_2CH 24 +#define SRST_I2S_8CH 25 +#define SRST_GPU_PVTM 26 +#define SRST_FUNC_PVTM 27 +#define SRST_CORE_PVTM 29 +#define SRST_EFUSE_P 30 +#define SRST_ACODEC_P 31 + +#define SRST_GPIO0 32 +#define SRST_GPIO1 33 +#define SRST_GPIO2 34 +#define SRST_GPIO3 35 +#define SRST_MIPIPHY_P 36 +#define SRST_UART0 39 +#define SRST_UART1 40 +#define SRST_UART2 41 +#define SRST_I2C0 43 +#define SRST_I2C1 44 +#define SRST_I2C2 45 +#define SRST_I2C3 46 +#define SRST_SFC 47 + +#define SRST_PWM 48 +#define SRST_DAP_PO 50 +#define SRST_DAP 51 +#define SRST_DAP_SYS 52 +#define SRST_CRYPTO 53 +#define SRST_GRF 55 +#define SRST_GMAC 56 +#define SRST_PERIPH_SYS_A 57 +#define SRST_PERIPH_SYS_H 58 +#define SRST_PERIPH_SYS_P 59 +#define SRST_SMART_CARD 60 +#define SRST_CPU_PERI 61 +#define SRST_EMEM_PERI 62 +#define SRST_USB_PERI 63 + +#define SRST_DMA 64 +#define SRST_GPS 67 +#define SRST_NANDC 68 +#define SRST_USBOTG0 69 +#define SRST_OTGC0 71 +#define SRST_USBOTG1 72 +#define SRST_OTGC1 74 +#define SRST_DDRMSCH 79 + +#define SRST_SDMMC 81 +#define SRST_SDIO 82 +#define SRST_EMMC 83 +#define SRST_SPI 84 +#define SRST_WDT 86 +#define SRST_SARADC 87 +#define SRST_DDRPHY 88 +#define SRST_DDRPHY_P 89 +#define SRST_DDRCTRL 90 +#define SRST_DDRCTRL_P 91 +#define SRST_TSP 92 +#define SRST_TSP_CLKIN 93 +#define SRST_HOST0_ECHI 94 + +#define SRST_HDMI_P 96 +#define SRST_VIO_ARBI_H 97 +#define SRST_VIO0_A 98 +#define SRST_VIO_BUS_H 99 +#define SRST_VOP_A 100 +#define SRST_VOP_H 101 +#define SRST_VOP_D 102 +#define SRST_UTMI0 103 +#define SRST_UTMI1 104 +#define SRST_USBPOR 105 +#define SRST_IEP_A 106 +#define SRST_IEP_H 107 +#define SRST_RGA_A 108 +#define SRST_RGA_H 109 +#define SRST_CIF0 110 +#define SRST_PMU 111 + +#define SRST_VCODEC_A 112 +#define SRST_VCODEC_H 113 +#define SRST_VIO1_A 114 +#define SRST_HEVC_CORE 115 +#define SRST_VCODEC_NIU_A 116 +#define SRST_PMU_NIU_P 117 +#define SRST_LCDC0_S 119 +#define SRST_GPU 120 +#define SRST_GPU_NIU_A 122 +#define SRST_EBC_A 123 +#define SRST_EBC_H 124 + +#define SRST_CORE_DBG 128 +#define SRST_DBG_P 129 +#define SRST_TIMER0 130 +#define SRST_TIMER1 131 +#define SRST_TIMER2 132 +#define SRST_TIMER3 133 +#define SRST_TIMER4 134 +#define SRST_TIMER5 135 +#define SRST_VIO_H2P 136 +#define SRST_VIO_MIPI_DSI 137 + +#endif diff --git a/include/dt-bindings/clock/rk3399-cru.h b/include/dt-bindings/clock/rk3399-cru.h index 220a60f20d3b..22cb1dfa9004 100644 --- a/include/dt-bindings/clock/rk3399-cru.h +++ b/include/dt-bindings/clock/rk3399-cru.h @@ -132,6 +132,8 @@ #define SCLK_RMII_SRC 166 #define SCLK_PCIEPHY_REF100M 167 #define SCLK_DDRC 168 +#define SCLK_TESTCLKOUT1 169 +#define SCLK_TESTCLKOUT2 170 #define DCLK_VOP0 180 #define DCLK_VOP1 181 diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index a428aec36ace..1bbd5a4a4616 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -564,6 +564,9 @@ struct clk_fractional_divider { u8 nwidth; u32 nmask; u8 flags; + void (*approximation)(struct clk_hw *hw, + unsigned long rate, unsigned long *parent_rate, + unsigned long *m, unsigned long *n); spinlock_t *lock; }; diff --git a/include/linux/mfd/rk808.h b/include/linux/mfd/rk808.h index 83701ef7d3c7..54feb140c210 100644 --- a/include/linux/mfd/rk808.h +++ b/include/linux/mfd/rk808.h @@ -298,6 +298,7 @@ enum rk818_reg { #define VOUT_LO_INT BIT(0) #define CLK32KOUT2_EN BIT(0) +#define RK8XX_ID_MSK 0xfff0 enum { BUCK_ILMIN_50MA, BUCK_ILMIN_100MA, diff --git a/drivers/phy/ulpi_phy.h b/include/linux/phy/ulpi_phy.h index f2ebe490a4bc..f2ebe490a4bc 100644 --- a/drivers/phy/ulpi_phy.h +++ b/include/linux/phy/ulpi_phy.h diff --git a/lib/mpi/mpi-pow.c b/lib/mpi/mpi-pow.c index e24388a863a7..468fb7cd1221 100644 --- a/lib/mpi/mpi-pow.c +++ b/lib/mpi/mpi-pow.c @@ -26,6 +26,7 @@ * however I decided to publish this code under the plain GPL. */ +#include <linux/sched.h> #include <linux/string.h> #include "mpi-internal.h" #include "longlong.h" @@ -256,6 +257,7 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod) } e <<= 1; c--; + cond_resched(); } i--; |