1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
|
// SPDX-License-Identifier: GPL-2.0
/*
* MediaTek DisplayPort PHY driver
*
* Copyright (c) 2022, BayLibre Inc.
* Copyright (c) 2022, MediaTek Inc.
*/
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/mfd/syscon.h>
#include <linux/of.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#define PHY_OFFSET 0x1000
#define MTK_DP_PHY_DIG_PLL_CTL_1 (PHY_OFFSET + 0x14)
#define TPLL_SSC_EN BIT(3)
#define MTK_DP_PHY_DIG_BIT_RATE (PHY_OFFSET + 0x3C)
#define BIT_RATE_RBR 0
#define BIT_RATE_HBR 1
#define BIT_RATE_HBR2 2
#define BIT_RATE_HBR3 3
#define MTK_DP_PHY_DIG_SW_RST (PHY_OFFSET + 0x38)
#define DP_GLB_SW_RST_PHYD BIT(0)
#define MTK_DP_LANE0_DRIVING_PARAM_3 (PHY_OFFSET + 0x138)
#define MTK_DP_LANE1_DRIVING_PARAM_3 (PHY_OFFSET + 0x238)
#define MTK_DP_LANE2_DRIVING_PARAM_3 (PHY_OFFSET + 0x338)
#define MTK_DP_LANE3_DRIVING_PARAM_3 (PHY_OFFSET + 0x438)
#define XTP_LN_TX_LCTXC0_SW0_PRE0_DEFAULT BIT(4)
#define XTP_LN_TX_LCTXC0_SW0_PRE1_DEFAULT (BIT(10) | BIT(12))
#define XTP_LN_TX_LCTXC0_SW0_PRE2_DEFAULT GENMASK(20, 19)
#define XTP_LN_TX_LCTXC0_SW0_PRE3_DEFAULT GENMASK(29, 29)
#define DRIVING_PARAM_3_DEFAULT (XTP_LN_TX_LCTXC0_SW0_PRE0_DEFAULT | \
XTP_LN_TX_LCTXC0_SW0_PRE1_DEFAULT | \
XTP_LN_TX_LCTXC0_SW0_PRE2_DEFAULT | \
XTP_LN_TX_LCTXC0_SW0_PRE3_DEFAULT)
#define XTP_LN_TX_LCTXC0_SW1_PRE0_DEFAULT GENMASK(4, 3)
#define XTP_LN_TX_LCTXC0_SW1_PRE1_DEFAULT GENMASK(12, 9)
#define XTP_LN_TX_LCTXC0_SW1_PRE2_DEFAULT (BIT(18) | BIT(21))
#define XTP_LN_TX_LCTXC0_SW2_PRE0_DEFAULT GENMASK(29, 29)
#define DRIVING_PARAM_4_DEFAULT (XTP_LN_TX_LCTXC0_SW1_PRE0_DEFAULT | \
XTP_LN_TX_LCTXC0_SW1_PRE1_DEFAULT | \
XTP_LN_TX_LCTXC0_SW1_PRE2_DEFAULT | \
XTP_LN_TX_LCTXC0_SW2_PRE0_DEFAULT)
#define XTP_LN_TX_LCTXC0_SW2_PRE1_DEFAULT (BIT(3) | BIT(5))
#define XTP_LN_TX_LCTXC0_SW3_PRE0_DEFAULT GENMASK(13, 12)
#define DRIVING_PARAM_5_DEFAULT (XTP_LN_TX_LCTXC0_SW2_PRE1_DEFAULT | \
XTP_LN_TX_LCTXC0_SW3_PRE0_DEFAULT)
#define XTP_LN_TX_LCTXCP1_SW0_PRE0_DEFAULT 0
#define XTP_LN_TX_LCTXCP1_SW0_PRE1_DEFAULT GENMASK(10, 10)
#define XTP_LN_TX_LCTXCP1_SW0_PRE2_DEFAULT GENMASK(19, 19)
#define XTP_LN_TX_LCTXCP1_SW0_PRE3_DEFAULT GENMASK(28, 28)
#define DRIVING_PARAM_6_DEFAULT (XTP_LN_TX_LCTXCP1_SW0_PRE0_DEFAULT | \
XTP_LN_TX_LCTXCP1_SW0_PRE1_DEFAULT | \
XTP_LN_TX_LCTXCP1_SW0_PRE2_DEFAULT | \
XTP_LN_TX_LCTXCP1_SW0_PRE3_DEFAULT)
#define XTP_LN_TX_LCTXCP1_SW1_PRE0_DEFAULT 0
#define XTP_LN_TX_LCTXCP1_SW1_PRE1_DEFAULT GENMASK(10, 9)
#define XTP_LN_TX_LCTXCP1_SW1_PRE2_DEFAULT GENMASK(19, 18)
#define XTP_LN_TX_LCTXCP1_SW2_PRE0_DEFAULT 0
#define DRIVING_PARAM_7_DEFAULT (XTP_LN_TX_LCTXCP1_SW1_PRE0_DEFAULT | \
XTP_LN_TX_LCTXCP1_SW1_PRE1_DEFAULT | \
XTP_LN_TX_LCTXCP1_SW1_PRE2_DEFAULT | \
XTP_LN_TX_LCTXCP1_SW2_PRE0_DEFAULT)
#define XTP_LN_TX_LCTXCP1_SW2_PRE1_DEFAULT GENMASK(3, 3)
#define XTP_LN_TX_LCTXCP1_SW3_PRE0_DEFAULT 0
#define DRIVING_PARAM_8_DEFAULT (XTP_LN_TX_LCTXCP1_SW2_PRE1_DEFAULT | \
XTP_LN_TX_LCTXCP1_SW3_PRE0_DEFAULT)
struct mtk_dp_phy {
struct regmap *regs;
};
static int mtk_dp_phy_init(struct phy *phy)
{
struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
static const u32 driving_params[] = {
DRIVING_PARAM_3_DEFAULT,
DRIVING_PARAM_4_DEFAULT,
DRIVING_PARAM_5_DEFAULT,
DRIVING_PARAM_6_DEFAULT,
DRIVING_PARAM_7_DEFAULT,
DRIVING_PARAM_8_DEFAULT
};
regmap_bulk_write(dp_phy->regs, MTK_DP_LANE0_DRIVING_PARAM_3,
driving_params, ARRAY_SIZE(driving_params));
regmap_bulk_write(dp_phy->regs, MTK_DP_LANE1_DRIVING_PARAM_3,
driving_params, ARRAY_SIZE(driving_params));
regmap_bulk_write(dp_phy->regs, MTK_DP_LANE2_DRIVING_PARAM_3,
driving_params, ARRAY_SIZE(driving_params));
regmap_bulk_write(dp_phy->regs, MTK_DP_LANE3_DRIVING_PARAM_3,
driving_params, ARRAY_SIZE(driving_params));
return 0;
}
static int mtk_dp_phy_configure(struct phy *phy, union phy_configure_opts *opts)
{
struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
u32 val;
if (opts->dp.set_rate) {
switch (opts->dp.link_rate) {
default:
dev_err(&phy->dev,
"Implementation error, unknown linkrate %x\n",
opts->dp.link_rate);
return -EINVAL;
case 1620:
val = BIT_RATE_RBR;
break;
case 2700:
val = BIT_RATE_HBR;
break;
case 5400:
val = BIT_RATE_HBR2;
break;
case 8100:
val = BIT_RATE_HBR3;
break;
}
regmap_write(dp_phy->regs, MTK_DP_PHY_DIG_BIT_RATE, val);
}
regmap_update_bits(dp_phy->regs, MTK_DP_PHY_DIG_PLL_CTL_1,
TPLL_SSC_EN, opts->dp.ssc ? TPLL_SSC_EN : 0);
return 0;
}
static int mtk_dp_phy_reset(struct phy *phy)
{
struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
regmap_update_bits(dp_phy->regs, MTK_DP_PHY_DIG_SW_RST,
DP_GLB_SW_RST_PHYD, 0);
usleep_range(50, 200);
regmap_update_bits(dp_phy->regs, MTK_DP_PHY_DIG_SW_RST,
DP_GLB_SW_RST_PHYD, 1);
return 0;
}
static const struct phy_ops mtk_dp_phy_dev_ops = {
.init = mtk_dp_phy_init,
.configure = mtk_dp_phy_configure,
.reset = mtk_dp_phy_reset,
.owner = THIS_MODULE,
};
static int mtk_dp_phy_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct mtk_dp_phy *dp_phy;
struct phy *phy;
struct regmap *regs;
regs = *(struct regmap **)dev->platform_data;
if (!regs)
return dev_err_probe(dev, -EINVAL,
"No data passed, requires struct regmap**\n");
dp_phy = devm_kzalloc(dev, sizeof(*dp_phy), GFP_KERNEL);
if (!dp_phy)
return -ENOMEM;
dp_phy->regs = regs;
phy = devm_phy_create(dev, NULL, &mtk_dp_phy_dev_ops);
if (IS_ERR(phy))
return dev_err_probe(dev, PTR_ERR(phy),
"Failed to create DP PHY\n");
phy_set_drvdata(phy, dp_phy);
if (!dev->of_node)
phy_create_lookup(phy, "dp", dev_name(dev));
return 0;
}
static struct platform_driver mtk_dp_phy_driver = {
.probe = mtk_dp_phy_probe,
.driver = {
.name = "mediatek-dp-phy",
},
};
module_platform_driver(mtk_dp_phy_driver);
MODULE_AUTHOR("Markus Schneider-Pargmann <msp@baylibre.com>");
MODULE_DESCRIPTION("MediaTek DP PHY Driver");
MODULE_LICENSE("GPL");
|