cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

phy-mtk-ufs.c (5521B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (C) 2019 MediaTek Inc.
      4 * Author: Stanley Chu <stanley.chu@mediatek.com>
      5 */
      6
      7#include <linux/clk.h>
      8#include <linux/delay.h>
      9#include <linux/io.h>
     10#include <linux/module.h>
     11#include <linux/phy/phy.h>
     12#include <linux/platform_device.h>
     13
     14/* mphy register and offsets */
     15#define MP_GLB_DIG_8C               0x008C
     16#define FRC_PLL_ISO_EN              BIT(8)
     17#define PLL_ISO_EN                  BIT(9)
     18#define FRC_FRC_PWR_ON              BIT(10)
     19#define PLL_PWR_ON                  BIT(11)
     20
     21#define MP_LN_DIG_RX_9C             0xA09C
     22#define FSM_DIFZ_FRC                BIT(18)
     23
     24#define MP_LN_DIG_RX_AC             0xA0AC
     25#define FRC_RX_SQ_EN                BIT(0)
     26#define RX_SQ_EN                    BIT(1)
     27
     28#define MP_LN_RX_44                 0xB044
     29#define FRC_CDR_PWR_ON              BIT(17)
     30#define CDR_PWR_ON                  BIT(18)
     31#define FRC_CDR_ISO_EN              BIT(19)
     32#define CDR_ISO_EN                  BIT(20)
     33
     34#define UFSPHY_CLKS_CNT    2
     35
     36struct ufs_mtk_phy {
     37	struct device *dev;
     38	void __iomem *mmio;
     39	struct clk_bulk_data clks[UFSPHY_CLKS_CNT];
     40};
     41
     42static inline u32 mphy_readl(struct ufs_mtk_phy *phy, u32 reg)
     43{
     44	return readl(phy->mmio + reg);
     45}
     46
     47static inline void mphy_writel(struct ufs_mtk_phy *phy, u32 val, u32 reg)
     48{
     49	writel(val, phy->mmio + reg);
     50}
     51
     52static void mphy_set_bit(struct ufs_mtk_phy *phy, u32 reg, u32 bit)
     53{
     54	u32 val;
     55
     56	val = mphy_readl(phy, reg);
     57	val |= bit;
     58	mphy_writel(phy, val, reg);
     59}
     60
     61static void mphy_clr_bit(struct ufs_mtk_phy *phy, u32 reg, u32 bit)
     62{
     63	u32 val;
     64
     65	val = mphy_readl(phy, reg);
     66	val &= ~bit;
     67	mphy_writel(phy, val, reg);
     68}
     69
     70static struct ufs_mtk_phy *get_ufs_mtk_phy(struct phy *generic_phy)
     71{
     72	return (struct ufs_mtk_phy *)phy_get_drvdata(generic_phy);
     73}
     74
     75static int ufs_mtk_phy_clk_init(struct ufs_mtk_phy *phy)
     76{
     77	struct device *dev = phy->dev;
     78	struct clk_bulk_data *clks = phy->clks;
     79
     80	clks[0].id = "unipro";
     81	clks[1].id = "mp";
     82	return devm_clk_bulk_get(dev, UFSPHY_CLKS_CNT, clks);
     83}
     84
     85static void ufs_mtk_phy_set_active(struct ufs_mtk_phy *phy)
     86{
     87	/* release DA_MP_PLL_PWR_ON */
     88	mphy_set_bit(phy, MP_GLB_DIG_8C, PLL_PWR_ON);
     89	mphy_clr_bit(phy, MP_GLB_DIG_8C, FRC_FRC_PWR_ON);
     90
     91	/* release DA_MP_PLL_ISO_EN */
     92	mphy_clr_bit(phy, MP_GLB_DIG_8C, PLL_ISO_EN);
     93	mphy_clr_bit(phy, MP_GLB_DIG_8C, FRC_PLL_ISO_EN);
     94
     95	/* release DA_MP_CDR_PWR_ON */
     96	mphy_set_bit(phy, MP_LN_RX_44, CDR_PWR_ON);
     97	mphy_clr_bit(phy, MP_LN_RX_44, FRC_CDR_PWR_ON);
     98
     99	/* release DA_MP_CDR_ISO_EN */
    100	mphy_clr_bit(phy, MP_LN_RX_44, CDR_ISO_EN);
    101	mphy_clr_bit(phy, MP_LN_RX_44, FRC_CDR_ISO_EN);
    102
    103	/* release DA_MP_RX0_SQ_EN */
    104	mphy_set_bit(phy, MP_LN_DIG_RX_AC, RX_SQ_EN);
    105	mphy_clr_bit(phy, MP_LN_DIG_RX_AC, FRC_RX_SQ_EN);
    106
    107	/* delay 1us to wait DIFZ stable */
    108	udelay(1);
    109
    110	/* release DIFZ */
    111	mphy_clr_bit(phy, MP_LN_DIG_RX_9C, FSM_DIFZ_FRC);
    112}
    113
    114static void ufs_mtk_phy_set_deep_hibern(struct ufs_mtk_phy *phy)
    115{
    116	/* force DIFZ */
    117	mphy_set_bit(phy, MP_LN_DIG_RX_9C, FSM_DIFZ_FRC);
    118
    119	/* force DA_MP_RX0_SQ_EN */
    120	mphy_set_bit(phy, MP_LN_DIG_RX_AC, FRC_RX_SQ_EN);
    121	mphy_clr_bit(phy, MP_LN_DIG_RX_AC, RX_SQ_EN);
    122
    123	/* force DA_MP_CDR_ISO_EN */
    124	mphy_set_bit(phy, MP_LN_RX_44, FRC_CDR_ISO_EN);
    125	mphy_set_bit(phy, MP_LN_RX_44, CDR_ISO_EN);
    126
    127	/* force DA_MP_CDR_PWR_ON */
    128	mphy_set_bit(phy, MP_LN_RX_44, FRC_CDR_PWR_ON);
    129	mphy_clr_bit(phy, MP_LN_RX_44, CDR_PWR_ON);
    130
    131	/* force DA_MP_PLL_ISO_EN */
    132	mphy_set_bit(phy, MP_GLB_DIG_8C, FRC_PLL_ISO_EN);
    133	mphy_set_bit(phy, MP_GLB_DIG_8C, PLL_ISO_EN);
    134
    135	/* force DA_MP_PLL_PWR_ON */
    136	mphy_set_bit(phy, MP_GLB_DIG_8C, FRC_FRC_PWR_ON);
    137	mphy_clr_bit(phy, MP_GLB_DIG_8C, PLL_PWR_ON);
    138}
    139
    140static int ufs_mtk_phy_power_on(struct phy *generic_phy)
    141{
    142	struct ufs_mtk_phy *phy = get_ufs_mtk_phy(generic_phy);
    143	int ret;
    144
    145	ret = clk_bulk_prepare_enable(UFSPHY_CLKS_CNT, phy->clks);
    146	if (ret)
    147		return ret;
    148
    149	ufs_mtk_phy_set_active(phy);
    150
    151	return 0;
    152}
    153
    154static int ufs_mtk_phy_power_off(struct phy *generic_phy)
    155{
    156	struct ufs_mtk_phy *phy = get_ufs_mtk_phy(generic_phy);
    157
    158	ufs_mtk_phy_set_deep_hibern(phy);
    159
    160	clk_bulk_disable_unprepare(UFSPHY_CLKS_CNT, phy->clks);
    161
    162	return 0;
    163}
    164
    165static const struct phy_ops ufs_mtk_phy_ops = {
    166	.power_on       = ufs_mtk_phy_power_on,
    167	.power_off      = ufs_mtk_phy_power_off,
    168	.owner          = THIS_MODULE,
    169};
    170
    171static int ufs_mtk_phy_probe(struct platform_device *pdev)
    172{
    173	struct device *dev = &pdev->dev;
    174	struct phy *generic_phy;
    175	struct phy_provider *phy_provider;
    176	struct ufs_mtk_phy *phy;
    177	int ret;
    178
    179	phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
    180	if (!phy)
    181		return -ENOMEM;
    182
    183	phy->mmio = devm_platform_ioremap_resource(pdev, 0);
    184	if (IS_ERR(phy->mmio))
    185		return PTR_ERR(phy->mmio);
    186
    187	phy->dev = dev;
    188
    189	ret = ufs_mtk_phy_clk_init(phy);
    190	if (ret)
    191		return ret;
    192
    193	generic_phy = devm_phy_create(dev, NULL, &ufs_mtk_phy_ops);
    194	if (IS_ERR(generic_phy))
    195		return PTR_ERR(generic_phy);
    196
    197	phy_set_drvdata(generic_phy, phy);
    198
    199	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
    200
    201	return PTR_ERR_OR_ZERO(phy_provider);
    202}
    203
    204static const struct of_device_id ufs_mtk_phy_of_match[] = {
    205	{.compatible = "mediatek,mt8183-ufsphy"},
    206	{},
    207};
    208MODULE_DEVICE_TABLE(of, ufs_mtk_phy_of_match);
    209
    210static struct platform_driver ufs_mtk_phy_driver = {
    211	.probe = ufs_mtk_phy_probe,
    212	.driver = {
    213		.of_match_table = ufs_mtk_phy_of_match,
    214		.name = "ufs_mtk_phy",
    215	},
    216};
    217module_platform_driver(ufs_mtk_phy_driver);
    218
    219MODULE_DESCRIPTION("Universal Flash Storage (UFS) MediaTek MPHY");
    220MODULE_AUTHOR("Stanley Chu <stanley.chu@mediatek.com>");
    221MODULE_LICENSE("GPL v2");