mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-04 20:19:47 +08:00

To configure and enable the DSI PHY PLL clocks, the MDSS AHB clock must be active for MMIO operations. Typically, this AHB clock is enabled as part of the DSI PHY interface enabling (dsi_phy_enable_resource). However, since these PLL clocks are registered as clock entities, they can be enabled independently of the DSI PHY interface, leading to enabling failures and subsequent warnings: ``` msm_dsi_phy 5e94400.phy: [drm:dsi_pll_14nm_vco_prepare] *ERROR* DSI PLL lock failed ------------[ cut here ]------------ dsi0pllbyte already disabled WARNING: CPU: 3 PID: 1 at drivers/clk/clk.c:1194 clk_core_disable+0xa4/0xac CPU: 3 UID: 0 PID: 1 Comm: swapper/0 Tainted: Tainted: [W]=WARN Hardware name: Qualcomm Technologies, Inc. Robotics RB1 (DT) pstate: 600000c5 (nZCv daIF -PAN -UAO -TCO -DIT -SSBS BTYPE=--) [...] ``` This issue is particularly prevalent at boot time during the disabling of unused clocks (clk_disable_unused()) which includes enabling the parent clock(s) when CLK_OPS_PARENT_ENABLE flag is set (this is the case for the 14nm DSI PHY PLL consumers). To resolve this issue, we move the AHB clock as a PM dependency of the DSI PHY device (via pm_clk). Since the DSI PHY device is the parent of the PLL clocks, this resolves the PLL/AHB dependency. Now the AHB clock is enabled prior the PLL clk_prepare callback, as part of the runtime-resume chain. We also eliminate dsi_phy_[enable|disable]_resource functions, which are superseded by runtime PM. Note that it breaks compatibility with kernels before 6.0, as we do not support anymore the legacy `iface_clk` name. Signed-off-by: Loic Poulain <loic.poulain@oss.qualcomm.com> Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com> Patchwork: https://patchwork.freedesktop.org/patch/663239/ Link: https://lore.kernel.org/r/20250709140836.124143-1-loic.poulain@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
140 lines
4.1 KiB
C
140 lines
4.1 KiB
C
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
/*
|
|
* Copyright (c) 2015, The Linux Foundation. All rights reserved.
|
|
*/
|
|
|
|
#ifndef __DSI_PHY_H__
|
|
#define __DSI_PHY_H__
|
|
|
|
#include <dt-bindings/clock/qcom,dsi-phy-28nm.h>
|
|
#include <linux/clk-provider.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/regulator/consumer.h>
|
|
|
|
#include "dsi.h"
|
|
|
|
struct msm_dsi_phy_ops {
|
|
int (*pll_init)(struct msm_dsi_phy *phy);
|
|
int (*enable)(struct msm_dsi_phy *phy,
|
|
struct msm_dsi_phy_clk_request *clk_req);
|
|
void (*disable)(struct msm_dsi_phy *phy);
|
|
void (*save_pll_state)(struct msm_dsi_phy *phy);
|
|
int (*restore_pll_state)(struct msm_dsi_phy *phy);
|
|
bool (*set_continuous_clock)(struct msm_dsi_phy *phy, bool enable);
|
|
int (*parse_dt_properties)(struct msm_dsi_phy *phy);
|
|
};
|
|
|
|
struct msm_dsi_phy_cfg {
|
|
const struct regulator_bulk_data *regulator_data;
|
|
int num_regulators;
|
|
struct msm_dsi_phy_ops ops;
|
|
|
|
unsigned long min_pll_rate;
|
|
unsigned long max_pll_rate;
|
|
|
|
const resource_size_t io_start[DSI_MAX];
|
|
const int num_dsi_phy;
|
|
const int quirks;
|
|
bool has_phy_regulator;
|
|
bool has_phy_lane;
|
|
};
|
|
|
|
extern const struct msm_dsi_phy_cfg dsi_phy_28nm_hpm_cfgs;
|
|
extern const struct msm_dsi_phy_cfg dsi_phy_28nm_hpm_famb_cfgs;
|
|
extern const struct msm_dsi_phy_cfg dsi_phy_28nm_lp_cfgs;
|
|
extern const struct msm_dsi_phy_cfg dsi_phy_28nm_8226_cfgs;
|
|
extern const struct msm_dsi_phy_cfg dsi_phy_28nm_8937_cfgs;
|
|
extern const struct msm_dsi_phy_cfg dsi_phy_28nm_8960_cfgs;
|
|
extern const struct msm_dsi_phy_cfg dsi_phy_20nm_cfgs;
|
|
extern const struct msm_dsi_phy_cfg dsi_phy_14nm_cfgs;
|
|
extern const struct msm_dsi_phy_cfg dsi_phy_14nm_6150_cfgs;
|
|
extern const struct msm_dsi_phy_cfg dsi_phy_14nm_660_cfgs;
|
|
extern const struct msm_dsi_phy_cfg dsi_phy_14nm_2290_cfgs;
|
|
extern const struct msm_dsi_phy_cfg dsi_phy_14nm_8953_cfgs;
|
|
extern const struct msm_dsi_phy_cfg dsi_phy_10nm_cfgs;
|
|
extern const struct msm_dsi_phy_cfg dsi_phy_10nm_8998_cfgs;
|
|
extern const struct msm_dsi_phy_cfg dsi_phy_7nm_cfgs;
|
|
extern const struct msm_dsi_phy_cfg dsi_phy_7nm_6375_cfgs;
|
|
extern const struct msm_dsi_phy_cfg dsi_phy_7nm_8150_cfgs;
|
|
extern const struct msm_dsi_phy_cfg dsi_phy_7nm_7280_cfgs;
|
|
extern const struct msm_dsi_phy_cfg dsi_phy_5nm_8350_cfgs;
|
|
extern const struct msm_dsi_phy_cfg dsi_phy_5nm_8450_cfgs;
|
|
extern const struct msm_dsi_phy_cfg dsi_phy_5nm_8775p_cfgs;
|
|
extern const struct msm_dsi_phy_cfg dsi_phy_5nm_sar2130p_cfgs;
|
|
extern const struct msm_dsi_phy_cfg dsi_phy_4nm_8550_cfgs;
|
|
extern const struct msm_dsi_phy_cfg dsi_phy_4nm_8650_cfgs;
|
|
extern const struct msm_dsi_phy_cfg dsi_phy_3nm_8750_cfgs;
|
|
|
|
struct msm_dsi_dphy_timing {
|
|
u32 clk_zero;
|
|
u32 clk_trail;
|
|
u32 clk_prepare;
|
|
u32 hs_exit;
|
|
u32 hs_zero;
|
|
u32 hs_prepare;
|
|
u32 hs_trail;
|
|
u32 hs_rqst;
|
|
u32 ta_go;
|
|
u32 ta_sure;
|
|
u32 ta_get;
|
|
|
|
struct msm_dsi_phy_shared_timings shared_timings;
|
|
|
|
/* For PHY v2 only */
|
|
u32 hs_rqst_ckln;
|
|
u32 hs_prep_dly;
|
|
u32 hs_prep_dly_ckln;
|
|
u8 hs_halfbyte_en;
|
|
u8 hs_halfbyte_en_ckln;
|
|
};
|
|
|
|
#define NUM_PROVIDED_CLKS (DSI_PIXEL_PLL_CLK + 1)
|
|
|
|
#define DSI_LANE_MAX 5
|
|
|
|
struct msm_dsi_phy {
|
|
struct platform_device *pdev;
|
|
void __iomem *base;
|
|
void __iomem *pll_base;
|
|
void __iomem *reg_base;
|
|
void __iomem *lane_base;
|
|
phys_addr_t base_size;
|
|
phys_addr_t pll_size;
|
|
phys_addr_t reg_size;
|
|
phys_addr_t lane_size;
|
|
int id;
|
|
|
|
struct regulator_bulk_data *supplies;
|
|
|
|
struct msm_dsi_dphy_timing timing;
|
|
const struct msm_dsi_phy_cfg *cfg;
|
|
void *tuning_cfg;
|
|
|
|
enum msm_dsi_phy_usecase usecase;
|
|
bool regulator_ldo_mode;
|
|
bool cphy_mode;
|
|
|
|
struct clk_hw *vco_hw;
|
|
bool pll_on;
|
|
|
|
struct clk_hw_onecell_data *provided_clocks;
|
|
|
|
bool state_saved;
|
|
};
|
|
|
|
/*
|
|
* PHY internal functions
|
|
*/
|
|
int msm_dsi_dphy_timing_calc(struct msm_dsi_dphy_timing *timing,
|
|
struct msm_dsi_phy_clk_request *clk_req);
|
|
int msm_dsi_dphy_timing_calc_v2(struct msm_dsi_dphy_timing *timing,
|
|
struct msm_dsi_phy_clk_request *clk_req);
|
|
int msm_dsi_dphy_timing_calc_v3(struct msm_dsi_dphy_timing *timing,
|
|
struct msm_dsi_phy_clk_request *clk_req);
|
|
int msm_dsi_dphy_timing_calc_v4(struct msm_dsi_dphy_timing *timing,
|
|
struct msm_dsi_phy_clk_request *clk_req);
|
|
int msm_dsi_cphy_timing_calc_v4(struct msm_dsi_dphy_timing *timing,
|
|
struct msm_dsi_phy_clk_request *clk_req);
|
|
|
|
#endif /* __DSI_PHY_H__ */
|