Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (c) 2015 MediaTek Inc.
0004  */
0005 
0006 #include "phy-mtk-mipi-dsi.h"
0007 
0008 inline struct mtk_mipi_tx *mtk_mipi_tx_from_clk_hw(struct clk_hw *hw)
0009 {
0010     return container_of(hw, struct mtk_mipi_tx, pll_hw);
0011 }
0012 
0013 void mtk_mipi_tx_clear_bits(struct mtk_mipi_tx *mipi_tx, u32 offset,
0014                 u32 bits)
0015 {
0016     u32 temp = readl(mipi_tx->regs + offset);
0017 
0018     writel(temp & ~bits, mipi_tx->regs + offset);
0019 }
0020 
0021 void mtk_mipi_tx_set_bits(struct mtk_mipi_tx *mipi_tx, u32 offset,
0022               u32 bits)
0023 {
0024     u32 temp = readl(mipi_tx->regs + offset);
0025 
0026     writel(temp | bits, mipi_tx->regs + offset);
0027 }
0028 
0029 void mtk_mipi_tx_update_bits(struct mtk_mipi_tx *mipi_tx, u32 offset,
0030                  u32 mask, u32 data)
0031 {
0032     u32 temp = readl(mipi_tx->regs + offset);
0033 
0034     writel((temp & ~mask) | (data & mask), mipi_tx->regs + offset);
0035 }
0036 
0037 int mtk_mipi_tx_pll_set_rate(struct clk_hw *hw, unsigned long rate,
0038                  unsigned long parent_rate)
0039 {
0040     struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw);
0041 
0042     dev_dbg(mipi_tx->dev, "set rate: %lu Hz\n", rate);
0043 
0044     mipi_tx->data_rate = rate;
0045 
0046     return 0;
0047 }
0048 
0049 unsigned long mtk_mipi_tx_pll_recalc_rate(struct clk_hw *hw,
0050                       unsigned long parent_rate)
0051 {
0052     struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw);
0053 
0054     return mipi_tx->data_rate;
0055 }
0056 
0057 static int mtk_mipi_tx_power_on(struct phy *phy)
0058 {
0059     struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy);
0060     int ret;
0061 
0062     /* Power up core and enable PLL */
0063     ret = clk_prepare_enable(mipi_tx->pll);
0064     if (ret < 0)
0065         return ret;
0066 
0067     /* Enable DSI Lane LDO outputs, disable pad tie low */
0068     mipi_tx->driver_data->mipi_tx_enable_signal(phy);
0069     return 0;
0070 }
0071 
0072 static int mtk_mipi_tx_power_off(struct phy *phy)
0073 {
0074     struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy);
0075 
0076     /* Enable pad tie low, disable DSI Lane LDO outputs */
0077     mipi_tx->driver_data->mipi_tx_disable_signal(phy);
0078 
0079     /* Disable PLL and power down core */
0080     clk_disable_unprepare(mipi_tx->pll);
0081 
0082     return 0;
0083 }
0084 
0085 static const struct phy_ops mtk_mipi_tx_ops = {
0086     .power_on = mtk_mipi_tx_power_on,
0087     .power_off = mtk_mipi_tx_power_off,
0088     .owner = THIS_MODULE,
0089 };
0090 
0091 static void mtk_mipi_tx_get_calibration_datal(struct mtk_mipi_tx *mipi_tx)
0092 {
0093     struct nvmem_cell *cell;
0094     size_t len;
0095     u32 *buf;
0096 
0097     cell = nvmem_cell_get(mipi_tx->dev, "calibration-data");
0098     if (IS_ERR(cell)) {
0099         dev_info(mipi_tx->dev, "can't get nvmem_cell_get, ignore it\n");
0100         return;
0101     }
0102     buf = (u32 *)nvmem_cell_read(cell, &len);
0103     nvmem_cell_put(cell);
0104 
0105     if (IS_ERR(buf)) {
0106         dev_info(mipi_tx->dev, "can't get data, ignore it\n");
0107         return;
0108     }
0109 
0110     if (len < 3 * sizeof(u32)) {
0111         dev_info(mipi_tx->dev, "invalid calibration data\n");
0112         kfree(buf);
0113         return;
0114     }
0115 
0116     mipi_tx->rt_code[0] = ((buf[0] >> 6 & 0x1f) << 5) |
0117                    (buf[0] >> 11 & 0x1f);
0118     mipi_tx->rt_code[1] = ((buf[1] >> 27 & 0x1f) << 5) |
0119                    (buf[0] >> 1 & 0x1f);
0120     mipi_tx->rt_code[2] = ((buf[1] >> 17 & 0x1f) << 5) |
0121                    (buf[1] >> 22 & 0x1f);
0122     mipi_tx->rt_code[3] = ((buf[1] >> 7 & 0x1f) << 5) |
0123                    (buf[1] >> 12 & 0x1f);
0124     mipi_tx->rt_code[4] = ((buf[2] >> 27 & 0x1f) << 5) |
0125                    (buf[1] >> 2 & 0x1f);
0126     kfree(buf);
0127 }
0128 
0129 static int mtk_mipi_tx_probe(struct platform_device *pdev)
0130 {
0131     struct device *dev = &pdev->dev;
0132     struct mtk_mipi_tx *mipi_tx;
0133     const char *ref_clk_name;
0134     struct clk *ref_clk;
0135     struct clk_init_data clk_init = {
0136         .num_parents = 1,
0137         .parent_names = (const char * const *)&ref_clk_name,
0138         .flags = CLK_SET_RATE_GATE,
0139     };
0140     struct phy *phy;
0141     struct phy_provider *phy_provider;
0142     int ret;
0143 
0144     mipi_tx = devm_kzalloc(dev, sizeof(*mipi_tx), GFP_KERNEL);
0145     if (!mipi_tx)
0146         return -ENOMEM;
0147 
0148     mipi_tx->driver_data = of_device_get_match_data(dev);
0149     if (!mipi_tx->driver_data)
0150         return -ENODEV;
0151 
0152     mipi_tx->regs = devm_platform_ioremap_resource(pdev, 0);
0153     if (IS_ERR(mipi_tx->regs))
0154         return PTR_ERR(mipi_tx->regs);
0155 
0156     ref_clk = devm_clk_get(dev, NULL);
0157     if (IS_ERR(ref_clk))
0158         return dev_err_probe(dev, PTR_ERR(ref_clk),
0159                      "Failed to get reference clock\n");
0160 
0161     ret = of_property_read_u32(dev->of_node, "drive-strength-microamp",
0162                    &mipi_tx->mipitx_drive);
0163     /* If can't get the "mipi_tx->mipitx_drive", set it default 0x8 */
0164     if (ret < 0)
0165         mipi_tx->mipitx_drive = 4600;
0166 
0167     /* check the mipitx_drive valid */
0168     if (mipi_tx->mipitx_drive > 6000 || mipi_tx->mipitx_drive < 3000) {
0169         dev_warn(dev, "drive-strength-microamp is invalid %d, not in 3000 ~ 6000\n",
0170              mipi_tx->mipitx_drive);
0171         mipi_tx->mipitx_drive = clamp_val(mipi_tx->mipitx_drive, 3000,
0172                           6000);
0173     }
0174 
0175     ref_clk_name = __clk_get_name(ref_clk);
0176 
0177     ret = of_property_read_string(dev->of_node, "clock-output-names",
0178                       &clk_init.name);
0179     if (ret < 0)
0180         return dev_err_probe(dev, ret, "Failed to read clock-output-names\n");
0181 
0182     clk_init.ops = mipi_tx->driver_data->mipi_tx_clk_ops;
0183 
0184     mipi_tx->pll_hw.init = &clk_init;
0185     mipi_tx->pll = devm_clk_register(dev, &mipi_tx->pll_hw);
0186     if (IS_ERR(mipi_tx->pll))
0187         return dev_err_probe(dev, PTR_ERR(mipi_tx->pll), "Failed to register PLL\n");
0188 
0189     phy = devm_phy_create(dev, NULL, &mtk_mipi_tx_ops);
0190     if (IS_ERR(phy))
0191         return dev_err_probe(dev, PTR_ERR(phy), "Failed to create MIPI D-PHY\n");
0192 
0193     phy_set_drvdata(phy, mipi_tx);
0194 
0195     phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
0196     if (IS_ERR(phy_provider))
0197         return PTR_ERR(phy_provider);
0198 
0199     mipi_tx->dev = dev;
0200 
0201     mtk_mipi_tx_get_calibration_datal(mipi_tx);
0202 
0203     return of_clk_add_provider(dev->of_node, of_clk_src_simple_get,
0204                    mipi_tx->pll);
0205 }
0206 
0207 static int mtk_mipi_tx_remove(struct platform_device *pdev)
0208 {
0209     of_clk_del_provider(pdev->dev.of_node);
0210     return 0;
0211 }
0212 
0213 static const struct of_device_id mtk_mipi_tx_match[] = {
0214     { .compatible = "mediatek,mt2701-mipi-tx",
0215       .data = &mt2701_mipitx_data },
0216     { .compatible = "mediatek,mt8173-mipi-tx",
0217       .data = &mt8173_mipitx_data },
0218     { .compatible = "mediatek,mt8183-mipi-tx",
0219       .data = &mt8183_mipitx_data },
0220     { },
0221 };
0222 MODULE_DEVICE_TABLE(of, mtk_mipi_tx_match);
0223 
0224 static struct platform_driver mtk_mipi_tx_driver = {
0225     .probe = mtk_mipi_tx_probe,
0226     .remove = mtk_mipi_tx_remove,
0227     .driver = {
0228         .name = "mediatek-mipi-tx",
0229         .of_match_table = mtk_mipi_tx_match,
0230     },
0231 };
0232 module_platform_driver(mtk_mipi_tx_driver);
0233 
0234 MODULE_DESCRIPTION("MediaTek MIPI TX Driver");
0235 MODULE_LICENSE("GPL v2");