1*9e7dfa4bSSriNavmani A // SPDX-License-Identifier: GPL-2.0-or-later 2*9e7dfa4bSSriNavmani A /* 3*9e7dfa4bSSriNavmani A * Axiado eMMC PHY driver 4*9e7dfa4bSSriNavmani A * 5*9e7dfa4bSSriNavmani A * Copyright (C) 2017 Arasan Chip Systems Inc. 6*9e7dfa4bSSriNavmani A * Copyright (C) 2022-2026 Axiado Corporation (or its affiliates). 7*9e7dfa4bSSriNavmani A * 8*9e7dfa4bSSriNavmani A * Based on Arasan Driver (sdhci-pci-arasan.c) 9*9e7dfa4bSSriNavmani A * sdhci-pci-arasan.c - Driver for Arasan PCI Controller with integrated phy. 10*9e7dfa4bSSriNavmani A */ 11*9e7dfa4bSSriNavmani A #include <linux/bitfield.h> 12*9e7dfa4bSSriNavmani A #include <linux/delay.h> 13*9e7dfa4bSSriNavmani A #include <linux/io.h> 14*9e7dfa4bSSriNavmani A #include <linux/iopoll.h> 15*9e7dfa4bSSriNavmani A #include <linux/module.h> 16*9e7dfa4bSSriNavmani A #include <linux/of.h> 17*9e7dfa4bSSriNavmani A #include <linux/phy/phy.h> 18*9e7dfa4bSSriNavmani A #include <linux/platform_device.h> 19*9e7dfa4bSSriNavmani A 20*9e7dfa4bSSriNavmani A /* Arasan eMMC 5.1 - PHY configuration registers */ 21*9e7dfa4bSSriNavmani A #define CAP_REG_IN_S1_MSB 0x04 22*9e7dfa4bSSriNavmani A #define PHY_CTRL_1 0x38 23*9e7dfa4bSSriNavmani A #define PHY_CTRL_2 0x3c 24*9e7dfa4bSSriNavmani A #define PHY_CTRL_3 0x40 25*9e7dfa4bSSriNavmani A #define STATUS 0x50 26*9e7dfa4bSSriNavmani A 27*9e7dfa4bSSriNavmani A #define DLL_ENBL BIT(26) 28*9e7dfa4bSSriNavmani A #define RTRIM_EN BIT(21) 29*9e7dfa4bSSriNavmani A #define PDB_ENBL BIT(23) 30*9e7dfa4bSSriNavmani A #define RETB_ENBL BIT(1) 31*9e7dfa4bSSriNavmani A 32*9e7dfa4bSSriNavmani A #define REN_STRB BIT(27) 33*9e7dfa4bSSriNavmani A #define REN_CMD_EN GENMASK(20, 12) 34*9e7dfa4bSSriNavmani A 35*9e7dfa4bSSriNavmani A /* Pull-UP Enable on CMD Line */ 36*9e7dfa4bSSriNavmani A #define PU_CMD_EN GENMASK(11, 3) 37*9e7dfa4bSSriNavmani A 38*9e7dfa4bSSriNavmani A /* Selection value for the optimum delay from 1-32 output tap lines */ 39*9e7dfa4bSSriNavmani A #define OTAP_DLY 0x02 40*9e7dfa4bSSriNavmani A /* DLL charge pump current trim default [1000] */ 41*9e7dfa4bSSriNavmani A #define DLL_TRM_ICP 0x08 42*9e7dfa4bSSriNavmani A /* Select the frequency range of DLL Operation */ 43*9e7dfa4bSSriNavmani A #define FRQ_SEL 0x01 44*9e7dfa4bSSriNavmani A 45*9e7dfa4bSSriNavmani A #define OTAP_SEL_MASK GENMASK(10, 7) 46*9e7dfa4bSSriNavmani A #define DLL_TRM_MASK GENMASK(25, 22) 47*9e7dfa4bSSriNavmani A #define DLL_FRQSEL_MASK GENMASK(27, 25) 48*9e7dfa4bSSriNavmani A 49*9e7dfa4bSSriNavmani A #define OTAP_SEL(x) (FIELD_PREP(OTAP_SEL_MASK, x) | OTAPDLY_EN) 50*9e7dfa4bSSriNavmani A #define DLL_TRM(x) (FIELD_PREP(DLL_TRM_MASK, x) | DLL_ENBL) 51*9e7dfa4bSSriNavmani A #define DLL_FRQSEL(x) FIELD_PREP(DLL_FRQSEL_MASK, x) 52*9e7dfa4bSSriNavmani A 53*9e7dfa4bSSriNavmani A #define OTAPDLY_EN BIT(11) 54*9e7dfa4bSSriNavmani A 55*9e7dfa4bSSriNavmani A #define SEL_DLY_RXCLK BIT(18) 56*9e7dfa4bSSriNavmani A #define SEL_DLY_TXCLK BIT(19) 57*9e7dfa4bSSriNavmani A 58*9e7dfa4bSSriNavmani A #define CALDONE_MASK 0x40 59*9e7dfa4bSSriNavmani A #define DLL_RDY_MASK 0x1 60*9e7dfa4bSSriNavmani A #define MAX_CLK_BUF0 BIT(20) 61*9e7dfa4bSSriNavmani A #define MAX_CLK_BUF1 BIT(21) 62*9e7dfa4bSSriNavmani A #define MAX_CLK_BUF2 BIT(22) 63*9e7dfa4bSSriNavmani A 64*9e7dfa4bSSriNavmani A #define CLK_MULTIPLIER 0xc008e 65*9e7dfa4bSSriNavmani A #define POLL_TIMEOUT_MS 3000 66*9e7dfa4bSSriNavmani A #define POLL_DELAY_US 100 67*9e7dfa4bSSriNavmani A 68*9e7dfa4bSSriNavmani A struct axiado_emmc_phy { 69*9e7dfa4bSSriNavmani A void __iomem *reg_base; 70*9e7dfa4bSSriNavmani A struct device *dev; 71*9e7dfa4bSSriNavmani A }; 72*9e7dfa4bSSriNavmani A 73*9e7dfa4bSSriNavmani A static int axiado_emmc_phy_init(struct phy *phy) 74*9e7dfa4bSSriNavmani A { 75*9e7dfa4bSSriNavmani A struct axiado_emmc_phy *ax_phy = phy_get_drvdata(phy); 76*9e7dfa4bSSriNavmani A struct device *dev = ax_phy->dev; 77*9e7dfa4bSSriNavmani A u32 val; 78*9e7dfa4bSSriNavmani A int ret; 79*9e7dfa4bSSriNavmani A 80*9e7dfa4bSSriNavmani A val = readl(ax_phy->reg_base + PHY_CTRL_1); 81*9e7dfa4bSSriNavmani A writel(val | RETB_ENBL | RTRIM_EN, ax_phy->reg_base + PHY_CTRL_1); 82*9e7dfa4bSSriNavmani A 83*9e7dfa4bSSriNavmani A val = readl(ax_phy->reg_base + PHY_CTRL_3); 84*9e7dfa4bSSriNavmani A writel(val | PDB_ENBL, ax_phy->reg_base + PHY_CTRL_3); 85*9e7dfa4bSSriNavmani A 86*9e7dfa4bSSriNavmani A ret = readl_poll_timeout(ax_phy->reg_base + STATUS, val, 87*9e7dfa4bSSriNavmani A val & CALDONE_MASK, POLL_DELAY_US, 88*9e7dfa4bSSriNavmani A POLL_TIMEOUT_MS * 1000); 89*9e7dfa4bSSriNavmani A if (ret) { 90*9e7dfa4bSSriNavmani A dev_err(dev, "PHY calibration timeout\n"); 91*9e7dfa4bSSriNavmani A return ret; 92*9e7dfa4bSSriNavmani A } 93*9e7dfa4bSSriNavmani A 94*9e7dfa4bSSriNavmani A val = readl(ax_phy->reg_base + PHY_CTRL_1); 95*9e7dfa4bSSriNavmani A writel(val | REN_CMD_EN | PU_CMD_EN, ax_phy->reg_base + PHY_CTRL_1); 96*9e7dfa4bSSriNavmani A 97*9e7dfa4bSSriNavmani A val = readl(ax_phy->reg_base + PHY_CTRL_2); 98*9e7dfa4bSSriNavmani A writel(val | REN_STRB, ax_phy->reg_base + PHY_CTRL_2); 99*9e7dfa4bSSriNavmani A 100*9e7dfa4bSSriNavmani A val = readl(ax_phy->reg_base + PHY_CTRL_3); 101*9e7dfa4bSSriNavmani A writel(val | MAX_CLK_BUF0 | MAX_CLK_BUF1 | MAX_CLK_BUF2, 102*9e7dfa4bSSriNavmani A ax_phy->reg_base + PHY_CTRL_3); 103*9e7dfa4bSSriNavmani A 104*9e7dfa4bSSriNavmani A writel(CLK_MULTIPLIER, ax_phy->reg_base + CAP_REG_IN_S1_MSB); 105*9e7dfa4bSSriNavmani A 106*9e7dfa4bSSriNavmani A val = readl(ax_phy->reg_base + PHY_CTRL_3); 107*9e7dfa4bSSriNavmani A writel(val | SEL_DLY_RXCLK | SEL_DLY_TXCLK, 108*9e7dfa4bSSriNavmani A ax_phy->reg_base + PHY_CTRL_3); 109*9e7dfa4bSSriNavmani A 110*9e7dfa4bSSriNavmani A return 0; 111*9e7dfa4bSSriNavmani A } 112*9e7dfa4bSSriNavmani A 113*9e7dfa4bSSriNavmani A static int axiado_emmc_phy_power_on(struct phy *phy) 114*9e7dfa4bSSriNavmani A { 115*9e7dfa4bSSriNavmani A struct axiado_emmc_phy *ax_phy = phy_get_drvdata(phy); 116*9e7dfa4bSSriNavmani A struct device *dev = ax_phy->dev; 117*9e7dfa4bSSriNavmani A u32 val; 118*9e7dfa4bSSriNavmani A int ret; 119*9e7dfa4bSSriNavmani A 120*9e7dfa4bSSriNavmani A val = readl(ax_phy->reg_base + PHY_CTRL_1); 121*9e7dfa4bSSriNavmani A writel(val | RETB_ENBL, ax_phy->reg_base + PHY_CTRL_1); 122*9e7dfa4bSSriNavmani A 123*9e7dfa4bSSriNavmani A val = readl(ax_phy->reg_base + PHY_CTRL_3); 124*9e7dfa4bSSriNavmani A writel(val | PDB_ENBL, ax_phy->reg_base + PHY_CTRL_3); 125*9e7dfa4bSSriNavmani A 126*9e7dfa4bSSriNavmani A val = readl(ax_phy->reg_base + PHY_CTRL_2); 127*9e7dfa4bSSriNavmani A writel(val | OTAP_SEL(OTAP_DLY), ax_phy->reg_base + PHY_CTRL_2); 128*9e7dfa4bSSriNavmani A 129*9e7dfa4bSSriNavmani A val = readl(ax_phy->reg_base + PHY_CTRL_1); 130*9e7dfa4bSSriNavmani A writel(val | DLL_TRM(DLL_TRM_ICP), ax_phy->reg_base + PHY_CTRL_1); 131*9e7dfa4bSSriNavmani A 132*9e7dfa4bSSriNavmani A val = readl(ax_phy->reg_base + PHY_CTRL_3); 133*9e7dfa4bSSriNavmani A writel(val | DLL_FRQSEL(FRQ_SEL), ax_phy->reg_base + PHY_CTRL_3); 134*9e7dfa4bSSriNavmani A 135*9e7dfa4bSSriNavmani A ret = read_poll_timeout(readl, val, val & DLL_RDY_MASK, POLL_DELAY_US, 136*9e7dfa4bSSriNavmani A POLL_TIMEOUT_MS * 1000, false, 137*9e7dfa4bSSriNavmani A ax_phy->reg_base + STATUS); 138*9e7dfa4bSSriNavmani A if (ret) { 139*9e7dfa4bSSriNavmani A dev_err(dev, "DLL ready timeout\n"); 140*9e7dfa4bSSriNavmani A return ret; 141*9e7dfa4bSSriNavmani A } 142*9e7dfa4bSSriNavmani A 143*9e7dfa4bSSriNavmani A return 0; 144*9e7dfa4bSSriNavmani A } 145*9e7dfa4bSSriNavmani A 146*9e7dfa4bSSriNavmani A static int axiado_emmc_phy_power_off(struct phy *phy) 147*9e7dfa4bSSriNavmani A { 148*9e7dfa4bSSriNavmani A struct axiado_emmc_phy *ax_phy = phy_get_drvdata(phy); 149*9e7dfa4bSSriNavmani A u32 val; 150*9e7dfa4bSSriNavmani A 151*9e7dfa4bSSriNavmani A val = readl(ax_phy->reg_base + PHY_CTRL_1); 152*9e7dfa4bSSriNavmani A val &= ~(DLL_TRM_MASK | DLL_ENBL); 153*9e7dfa4bSSriNavmani A writel(val, ax_phy->reg_base + PHY_CTRL_1); 154*9e7dfa4bSSriNavmani A 155*9e7dfa4bSSriNavmani A val = readl(ax_phy->reg_base + PHY_CTRL_3); 156*9e7dfa4bSSriNavmani A val &= ~(DLL_FRQSEL_MASK | PDB_ENBL); 157*9e7dfa4bSSriNavmani A writel(val, ax_phy->reg_base + PHY_CTRL_3); 158*9e7dfa4bSSriNavmani A 159*9e7dfa4bSSriNavmani A return 0; 160*9e7dfa4bSSriNavmani A } 161*9e7dfa4bSSriNavmani A 162*9e7dfa4bSSriNavmani A static const struct phy_ops axiado_emmc_phy_ops = { 163*9e7dfa4bSSriNavmani A .init = axiado_emmc_phy_init, 164*9e7dfa4bSSriNavmani A .power_on = axiado_emmc_phy_power_on, 165*9e7dfa4bSSriNavmani A .power_off = axiado_emmc_phy_power_off, 166*9e7dfa4bSSriNavmani A .owner = THIS_MODULE, 167*9e7dfa4bSSriNavmani A }; 168*9e7dfa4bSSriNavmani A 169*9e7dfa4bSSriNavmani A static const struct of_device_id axiado_emmc_phy_of_match[] = { 170*9e7dfa4bSSriNavmani A { .compatible = "axiado,ax3000-emmc-phy" }, 171*9e7dfa4bSSriNavmani A { /* sentinel */ }, 172*9e7dfa4bSSriNavmani A }; 173*9e7dfa4bSSriNavmani A MODULE_DEVICE_TABLE(of, axiado_emmc_phy_of_match); 174*9e7dfa4bSSriNavmani A 175*9e7dfa4bSSriNavmani A static int axiado_emmc_phy_probe(struct platform_device *pdev) 176*9e7dfa4bSSriNavmani A { 177*9e7dfa4bSSriNavmani A struct axiado_emmc_phy *ax_phy; 178*9e7dfa4bSSriNavmani A struct phy_provider *phy_provider; 179*9e7dfa4bSSriNavmani A struct device *dev = &pdev->dev; 180*9e7dfa4bSSriNavmani A struct phy *generic_phy; 181*9e7dfa4bSSriNavmani A 182*9e7dfa4bSSriNavmani A if (!dev->of_node) 183*9e7dfa4bSSriNavmani A return -ENODEV; 184*9e7dfa4bSSriNavmani A 185*9e7dfa4bSSriNavmani A ax_phy = devm_kzalloc(dev, sizeof(*ax_phy), GFP_KERNEL); 186*9e7dfa4bSSriNavmani A if (!ax_phy) 187*9e7dfa4bSSriNavmani A return -ENOMEM; 188*9e7dfa4bSSriNavmani A 189*9e7dfa4bSSriNavmani A ax_phy->reg_base = devm_platform_ioremap_resource(pdev, 0); 190*9e7dfa4bSSriNavmani A if (IS_ERR(ax_phy->reg_base)) 191*9e7dfa4bSSriNavmani A return PTR_ERR(ax_phy->reg_base); 192*9e7dfa4bSSriNavmani A 193*9e7dfa4bSSriNavmani A ax_phy->dev = dev; 194*9e7dfa4bSSriNavmani A 195*9e7dfa4bSSriNavmani A generic_phy = devm_phy_create(dev, dev->of_node, &axiado_emmc_phy_ops); 196*9e7dfa4bSSriNavmani A if (IS_ERR(generic_phy)) 197*9e7dfa4bSSriNavmani A return dev_err_probe(dev, PTR_ERR(generic_phy), 198*9e7dfa4bSSriNavmani A "failed to create PHY\n"); 199*9e7dfa4bSSriNavmani A 200*9e7dfa4bSSriNavmani A phy_set_drvdata(generic_phy, ax_phy); 201*9e7dfa4bSSriNavmani A phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); 202*9e7dfa4bSSriNavmani A 203*9e7dfa4bSSriNavmani A return PTR_ERR_OR_ZERO(phy_provider); 204*9e7dfa4bSSriNavmani A } 205*9e7dfa4bSSriNavmani A 206*9e7dfa4bSSriNavmani A static struct platform_driver axiado_emmc_phy_driver = { 207*9e7dfa4bSSriNavmani A .probe = axiado_emmc_phy_probe, 208*9e7dfa4bSSriNavmani A .driver = { 209*9e7dfa4bSSriNavmani A .name = "axiado-emmc-phy", 210*9e7dfa4bSSriNavmani A .of_match_table = axiado_emmc_phy_of_match, 211*9e7dfa4bSSriNavmani A }, 212*9e7dfa4bSSriNavmani A }; 213*9e7dfa4bSSriNavmani A module_platform_driver(axiado_emmc_phy_driver); 214*9e7dfa4bSSriNavmani A 215*9e7dfa4bSSriNavmani A MODULE_DESCRIPTION("AX3000 eMMC PHY Driver"); 216*9e7dfa4bSSriNavmani A MODULE_AUTHOR("Axiado Corporation"); 217*9e7dfa4bSSriNavmani A MODULE_LICENSE("GPL"); 218