1a1bf1c60SKunihiko Hayashi // SPDX-License-Identifier: GPL-2.0 2a1bf1c60SKunihiko Hayashi /* 3a1bf1c60SKunihiko Hayashi * phy-uniphier-ahci.c - PHY driver for UniPhier AHCI controller 4a1bf1c60SKunihiko Hayashi * Copyright 2016-2020, Socionext Inc. 5a1bf1c60SKunihiko Hayashi * Author: Kunihiko Hayashi <hayashi.kunihiko@socionext.com> 6a1bf1c60SKunihiko Hayashi */ 7a1bf1c60SKunihiko Hayashi 8a1bf1c60SKunihiko Hayashi #include <linux/bitfield.h> 9a1bf1c60SKunihiko Hayashi #include <linux/bitops.h> 10a1bf1c60SKunihiko Hayashi #include <linux/clk.h> 11a1bf1c60SKunihiko Hayashi #include <linux/iopoll.h> 12a1bf1c60SKunihiko Hayashi #include <linux/module.h> 13a1bf1c60SKunihiko Hayashi #include <linux/of.h> 14a1bf1c60SKunihiko Hayashi #include <linux/of_platform.h> 15a1bf1c60SKunihiko Hayashi #include <linux/phy/phy.h> 16a1bf1c60SKunihiko Hayashi #include <linux/platform_device.h> 17a1bf1c60SKunihiko Hayashi #include <linux/reset.h> 18a1bf1c60SKunihiko Hayashi 19a1bf1c60SKunihiko Hayashi struct uniphier_ahciphy_priv { 20a1bf1c60SKunihiko Hayashi struct device *dev; 21a1bf1c60SKunihiko Hayashi void __iomem *base; 22*b1f9f454SKunihiko Hayashi struct clk *clk, *clk_parent, *clk_parent_gio; 23*b1f9f454SKunihiko Hayashi struct reset_control *rst, *rst_parent, *rst_parent_gio; 24*b1f9f454SKunihiko Hayashi struct reset_control *rst_pm, *rst_tx, *rst_rx; 25a1bf1c60SKunihiko Hayashi const struct uniphier_ahciphy_soc_data *data; 26a1bf1c60SKunihiko Hayashi }; 27a1bf1c60SKunihiko Hayashi 28a1bf1c60SKunihiko Hayashi struct uniphier_ahciphy_soc_data { 29a1bf1c60SKunihiko Hayashi int (*init)(struct uniphier_ahciphy_priv *priv); 30a1bf1c60SKunihiko Hayashi int (*power_on)(struct uniphier_ahciphy_priv *priv); 31a1bf1c60SKunihiko Hayashi int (*power_off)(struct uniphier_ahciphy_priv *priv); 32*b1f9f454SKunihiko Hayashi bool is_legacy; 33a1bf1c60SKunihiko Hayashi bool is_ready_high; 34a1bf1c60SKunihiko Hayashi bool is_phy_clk; 35a1bf1c60SKunihiko Hayashi }; 36a1bf1c60SKunihiko Hayashi 37*b1f9f454SKunihiko Hayashi /* for Pro4 */ 38*b1f9f454SKunihiko Hayashi #define CKCTRL0 0x0 39*b1f9f454SKunihiko Hayashi #define CKCTRL0_CK_OFF BIT(9) 40*b1f9f454SKunihiko Hayashi #define CKCTRL0_NCY_MASK GENMASK(8, 4) 41*b1f9f454SKunihiko Hayashi #define CKCTRL0_NCY5_MASK GENMASK(3, 2) 42*b1f9f454SKunihiko Hayashi #define CKCTRL0_PRESCALE_MASK GENMASK(1, 0) 43*b1f9f454SKunihiko Hayashi #define CKCTRL1 0x4 44*b1f9f454SKunihiko Hayashi #define CKCTRL1_LOS_LVL_MASK GENMASK(20, 16) 45*b1f9f454SKunihiko Hayashi #define CKCTRL1_TX_LVL_MASK GENMASK(12, 8) 46*b1f9f454SKunihiko Hayashi #define RXTXCTRL 0x8 47*b1f9f454SKunihiko Hayashi #define RXTXCTRL_RX_EQ_VALL_MASK GENMASK(31, 29) 48*b1f9f454SKunihiko Hayashi #define RXTXCTRL_RX_DPLL_MODE_MASK GENMASK(28, 26) 49*b1f9f454SKunihiko Hayashi #define RXTXCTRL_TX_ATTEN_MASK GENMASK(14, 12) 50*b1f9f454SKunihiko Hayashi #define RXTXCTRL_TX_BOOST_MASK GENMASK(11, 8) 51*b1f9f454SKunihiko Hayashi #define RXTXCTRL_TX_EDGERATE_MASK GENMASK(3, 2) 52*b1f9f454SKunihiko Hayashi #define RXTXCTRL_TX_CKO_EN BIT(0) 53*b1f9f454SKunihiko Hayashi #define RSTPWR 0x30 54*b1f9f454SKunihiko Hayashi #define RSTPWR_RX_EN_VAL BIT(18) 55*b1f9f454SKunihiko Hayashi 56a1bf1c60SKunihiko Hayashi /* for PXs2/PXs3 */ 57a1bf1c60SKunihiko Hayashi #define CKCTRL 0x0 58a1bf1c60SKunihiko Hayashi #define CKCTRL_P0_READY BIT(15) 59a1bf1c60SKunihiko Hayashi #define CKCTRL_P0_RESET BIT(10) 60a1bf1c60SKunihiko Hayashi #define CKCTRL_REF_SSP_EN BIT(9) 61a1bf1c60SKunihiko Hayashi #define TXCTRL0 0x4 62a1bf1c60SKunihiko Hayashi #define TXCTRL0_AMP_G3_MASK GENMASK(22, 16) 63a1bf1c60SKunihiko Hayashi #define TXCTRL0_AMP_G2_MASK GENMASK(14, 8) 64a1bf1c60SKunihiko Hayashi #define TXCTRL0_AMP_G1_MASK GENMASK(6, 0) 65a1bf1c60SKunihiko Hayashi #define TXCTRL1 0x8 66a1bf1c60SKunihiko Hayashi #define TXCTRL1_DEEMPH_G3_MASK GENMASK(21, 16) 67a1bf1c60SKunihiko Hayashi #define TXCTRL1_DEEMPH_G2_MASK GENMASK(13, 8) 68a1bf1c60SKunihiko Hayashi #define TXCTRL1_DEEMPH_G1_MASK GENMASK(5, 0) 69a1bf1c60SKunihiko Hayashi #define RXCTRL 0xc 70a1bf1c60SKunihiko Hayashi #define RXCTRL_LOS_LVL_MASK GENMASK(20, 16) 71a1bf1c60SKunihiko Hayashi #define RXCTRL_LOS_BIAS_MASK GENMASK(10, 8) 72a1bf1c60SKunihiko Hayashi #define RXCTRL_RX_EQ_MASK GENMASK(2, 0) 73a1bf1c60SKunihiko Hayashi 74*b1f9f454SKunihiko Hayashi static int uniphier_ahciphy_pro4_init(struct uniphier_ahciphy_priv *priv) 75*b1f9f454SKunihiko Hayashi { 76*b1f9f454SKunihiko Hayashi u32 val; 77*b1f9f454SKunihiko Hayashi 78*b1f9f454SKunihiko Hayashi /* set phy MPLL parameters */ 79*b1f9f454SKunihiko Hayashi val = readl(priv->base + CKCTRL0); 80*b1f9f454SKunihiko Hayashi val &= ~CKCTRL0_NCY_MASK; 81*b1f9f454SKunihiko Hayashi val |= FIELD_PREP(CKCTRL0_NCY_MASK, 0x6); 82*b1f9f454SKunihiko Hayashi val &= ~CKCTRL0_NCY5_MASK; 83*b1f9f454SKunihiko Hayashi val |= FIELD_PREP(CKCTRL0_NCY5_MASK, 0x2); 84*b1f9f454SKunihiko Hayashi val &= ~CKCTRL0_PRESCALE_MASK; 85*b1f9f454SKunihiko Hayashi val |= FIELD_PREP(CKCTRL0_PRESCALE_MASK, 0x1); 86*b1f9f454SKunihiko Hayashi writel(val, priv->base + CKCTRL0); 87*b1f9f454SKunihiko Hayashi 88*b1f9f454SKunihiko Hayashi /* setup phy control parameters */ 89*b1f9f454SKunihiko Hayashi val = readl(priv->base + CKCTRL1); 90*b1f9f454SKunihiko Hayashi val &= ~CKCTRL1_LOS_LVL_MASK; 91*b1f9f454SKunihiko Hayashi val |= FIELD_PREP(CKCTRL1_LOS_LVL_MASK, 0x10); 92*b1f9f454SKunihiko Hayashi val &= ~CKCTRL1_TX_LVL_MASK; 93*b1f9f454SKunihiko Hayashi val |= FIELD_PREP(CKCTRL1_TX_LVL_MASK, 0x06); 94*b1f9f454SKunihiko Hayashi writel(val, priv->base + CKCTRL1); 95*b1f9f454SKunihiko Hayashi 96*b1f9f454SKunihiko Hayashi val = readl(priv->base + RXTXCTRL); 97*b1f9f454SKunihiko Hayashi val &= ~RXTXCTRL_RX_EQ_VALL_MASK; 98*b1f9f454SKunihiko Hayashi val |= FIELD_PREP(RXTXCTRL_RX_EQ_VALL_MASK, 0x6); 99*b1f9f454SKunihiko Hayashi val &= ~RXTXCTRL_RX_DPLL_MODE_MASK; 100*b1f9f454SKunihiko Hayashi val |= FIELD_PREP(RXTXCTRL_RX_DPLL_MODE_MASK, 0x3); 101*b1f9f454SKunihiko Hayashi val &= ~RXTXCTRL_TX_ATTEN_MASK; 102*b1f9f454SKunihiko Hayashi val |= FIELD_PREP(RXTXCTRL_TX_ATTEN_MASK, 0x3); 103*b1f9f454SKunihiko Hayashi val &= ~RXTXCTRL_TX_BOOST_MASK; 104*b1f9f454SKunihiko Hayashi val |= FIELD_PREP(RXTXCTRL_TX_BOOST_MASK, 0x5); 105*b1f9f454SKunihiko Hayashi val &= ~RXTXCTRL_TX_EDGERATE_MASK; 106*b1f9f454SKunihiko Hayashi val |= FIELD_PREP(RXTXCTRL_TX_EDGERATE_MASK, 0x0); 107*b1f9f454SKunihiko Hayashi writel(val, priv->base + RXTXCTRL); 108*b1f9f454SKunihiko Hayashi 109*b1f9f454SKunihiko Hayashi return 0; 110*b1f9f454SKunihiko Hayashi } 111*b1f9f454SKunihiko Hayashi 112*b1f9f454SKunihiko Hayashi static int uniphier_ahciphy_pro4_power_on(struct uniphier_ahciphy_priv *priv) 113*b1f9f454SKunihiko Hayashi { 114*b1f9f454SKunihiko Hayashi u32 val; 115*b1f9f454SKunihiko Hayashi int ret; 116*b1f9f454SKunihiko Hayashi 117*b1f9f454SKunihiko Hayashi /* enable reference clock for phy */ 118*b1f9f454SKunihiko Hayashi val = readl(priv->base + CKCTRL0); 119*b1f9f454SKunihiko Hayashi val &= ~CKCTRL0_CK_OFF; 120*b1f9f454SKunihiko Hayashi writel(val, priv->base + CKCTRL0); 121*b1f9f454SKunihiko Hayashi 122*b1f9f454SKunihiko Hayashi /* enable TX clock */ 123*b1f9f454SKunihiko Hayashi val = readl(priv->base + RXTXCTRL); 124*b1f9f454SKunihiko Hayashi val |= RXTXCTRL_TX_CKO_EN; 125*b1f9f454SKunihiko Hayashi writel(val, priv->base + RXTXCTRL); 126*b1f9f454SKunihiko Hayashi 127*b1f9f454SKunihiko Hayashi /* wait until RX is ready */ 128*b1f9f454SKunihiko Hayashi ret = readl_poll_timeout(priv->base + RSTPWR, val, 129*b1f9f454SKunihiko Hayashi !(val & RSTPWR_RX_EN_VAL), 200, 2000); 130*b1f9f454SKunihiko Hayashi if (ret) { 131*b1f9f454SKunihiko Hayashi dev_err(priv->dev, "Failed to check whether Rx is ready\n"); 132*b1f9f454SKunihiko Hayashi goto out_disable_clock; 133*b1f9f454SKunihiko Hayashi } 134*b1f9f454SKunihiko Hayashi 135*b1f9f454SKunihiko Hayashi /* release all reset */ 136*b1f9f454SKunihiko Hayashi ret = reset_control_deassert(priv->rst_pm); 137*b1f9f454SKunihiko Hayashi if (ret) { 138*b1f9f454SKunihiko Hayashi dev_err(priv->dev, "Failed to release PM reset\n"); 139*b1f9f454SKunihiko Hayashi goto out_disable_clock; 140*b1f9f454SKunihiko Hayashi } 141*b1f9f454SKunihiko Hayashi 142*b1f9f454SKunihiko Hayashi ret = reset_control_deassert(priv->rst_tx); 143*b1f9f454SKunihiko Hayashi if (ret) { 144*b1f9f454SKunihiko Hayashi dev_err(priv->dev, "Failed to release Tx reset\n"); 145*b1f9f454SKunihiko Hayashi goto out_reset_pm_assert; 146*b1f9f454SKunihiko Hayashi } 147*b1f9f454SKunihiko Hayashi 148*b1f9f454SKunihiko Hayashi ret = reset_control_deassert(priv->rst_rx); 149*b1f9f454SKunihiko Hayashi if (ret) { 150*b1f9f454SKunihiko Hayashi dev_err(priv->dev, "Failed to release Rx reset\n"); 151*b1f9f454SKunihiko Hayashi goto out_reset_tx_assert; 152*b1f9f454SKunihiko Hayashi } 153*b1f9f454SKunihiko Hayashi 154*b1f9f454SKunihiko Hayashi return 0; 155*b1f9f454SKunihiko Hayashi 156*b1f9f454SKunihiko Hayashi out_reset_tx_assert: 157*b1f9f454SKunihiko Hayashi reset_control_assert(priv->rst_tx); 158*b1f9f454SKunihiko Hayashi out_reset_pm_assert: 159*b1f9f454SKunihiko Hayashi reset_control_assert(priv->rst_pm); 160*b1f9f454SKunihiko Hayashi 161*b1f9f454SKunihiko Hayashi out_disable_clock: 162*b1f9f454SKunihiko Hayashi /* disable TX clock */ 163*b1f9f454SKunihiko Hayashi val = readl(priv->base + RXTXCTRL); 164*b1f9f454SKunihiko Hayashi val &= ~RXTXCTRL_TX_CKO_EN; 165*b1f9f454SKunihiko Hayashi writel(val, priv->base + RXTXCTRL); 166*b1f9f454SKunihiko Hayashi 167*b1f9f454SKunihiko Hayashi /* disable reference clock for phy */ 168*b1f9f454SKunihiko Hayashi val = readl(priv->base + CKCTRL0); 169*b1f9f454SKunihiko Hayashi val |= CKCTRL0_CK_OFF; 170*b1f9f454SKunihiko Hayashi writel(val, priv->base + CKCTRL0); 171*b1f9f454SKunihiko Hayashi 172*b1f9f454SKunihiko Hayashi return ret; 173*b1f9f454SKunihiko Hayashi } 174*b1f9f454SKunihiko Hayashi 175*b1f9f454SKunihiko Hayashi static int uniphier_ahciphy_pro4_power_off(struct uniphier_ahciphy_priv *priv) 176*b1f9f454SKunihiko Hayashi { 177*b1f9f454SKunihiko Hayashi u32 val; 178*b1f9f454SKunihiko Hayashi 179*b1f9f454SKunihiko Hayashi reset_control_assert(priv->rst_rx); 180*b1f9f454SKunihiko Hayashi reset_control_assert(priv->rst_tx); 181*b1f9f454SKunihiko Hayashi reset_control_assert(priv->rst_pm); 182*b1f9f454SKunihiko Hayashi 183*b1f9f454SKunihiko Hayashi /* disable TX clock */ 184*b1f9f454SKunihiko Hayashi val = readl(priv->base + RXTXCTRL); 185*b1f9f454SKunihiko Hayashi val &= ~RXTXCTRL_TX_CKO_EN; 186*b1f9f454SKunihiko Hayashi writel(val, priv->base + RXTXCTRL); 187*b1f9f454SKunihiko Hayashi 188*b1f9f454SKunihiko Hayashi /* disable reference clock for phy */ 189*b1f9f454SKunihiko Hayashi val = readl(priv->base + CKCTRL0); 190*b1f9f454SKunihiko Hayashi val |= CKCTRL0_CK_OFF; 191*b1f9f454SKunihiko Hayashi writel(val, priv->base + CKCTRL0); 192*b1f9f454SKunihiko Hayashi 193*b1f9f454SKunihiko Hayashi return 0; 194*b1f9f454SKunihiko Hayashi } 195*b1f9f454SKunihiko Hayashi 196a1bf1c60SKunihiko Hayashi static void uniphier_ahciphy_pxs2_enable(struct uniphier_ahciphy_priv *priv, 197a1bf1c60SKunihiko Hayashi bool enable) 198a1bf1c60SKunihiko Hayashi { 199a1bf1c60SKunihiko Hayashi u32 val; 200a1bf1c60SKunihiko Hayashi 201a1bf1c60SKunihiko Hayashi val = readl(priv->base + CKCTRL); 202a1bf1c60SKunihiko Hayashi 203a1bf1c60SKunihiko Hayashi if (enable) { 204a1bf1c60SKunihiko Hayashi val |= CKCTRL_REF_SSP_EN; 205a1bf1c60SKunihiko Hayashi writel(val, priv->base + CKCTRL); 206a1bf1c60SKunihiko Hayashi val &= ~CKCTRL_P0_RESET; 207a1bf1c60SKunihiko Hayashi writel(val, priv->base + CKCTRL); 208a1bf1c60SKunihiko Hayashi } else { 209a1bf1c60SKunihiko Hayashi val |= CKCTRL_P0_RESET; 210a1bf1c60SKunihiko Hayashi writel(val, priv->base + CKCTRL); 211a1bf1c60SKunihiko Hayashi val &= ~CKCTRL_REF_SSP_EN; 212a1bf1c60SKunihiko Hayashi writel(val, priv->base + CKCTRL); 213a1bf1c60SKunihiko Hayashi } 214a1bf1c60SKunihiko Hayashi } 215a1bf1c60SKunihiko Hayashi 216a1bf1c60SKunihiko Hayashi static int uniphier_ahciphy_pxs2_power_on(struct uniphier_ahciphy_priv *priv) 217a1bf1c60SKunihiko Hayashi { 218a1bf1c60SKunihiko Hayashi int ret; 219a1bf1c60SKunihiko Hayashi u32 val; 220a1bf1c60SKunihiko Hayashi 221a1bf1c60SKunihiko Hayashi uniphier_ahciphy_pxs2_enable(priv, true); 222a1bf1c60SKunihiko Hayashi 223a1bf1c60SKunihiko Hayashi /* wait until PLL is ready */ 224a1bf1c60SKunihiko Hayashi if (priv->data->is_ready_high) 225a1bf1c60SKunihiko Hayashi ret = readl_poll_timeout(priv->base + CKCTRL, val, 226a1bf1c60SKunihiko Hayashi (val & CKCTRL_P0_READY), 200, 400); 227a1bf1c60SKunihiko Hayashi else 228a1bf1c60SKunihiko Hayashi ret = readl_poll_timeout(priv->base + CKCTRL, val, 229a1bf1c60SKunihiko Hayashi !(val & CKCTRL_P0_READY), 200, 400); 230a1bf1c60SKunihiko Hayashi if (ret) { 231a1bf1c60SKunihiko Hayashi dev_err(priv->dev, "Failed to check whether PHY PLL is ready\n"); 232a1bf1c60SKunihiko Hayashi uniphier_ahciphy_pxs2_enable(priv, false); 233a1bf1c60SKunihiko Hayashi } 234a1bf1c60SKunihiko Hayashi 235a1bf1c60SKunihiko Hayashi return ret; 236a1bf1c60SKunihiko Hayashi } 237a1bf1c60SKunihiko Hayashi 238a1bf1c60SKunihiko Hayashi static int uniphier_ahciphy_pxs2_power_off(struct uniphier_ahciphy_priv *priv) 239a1bf1c60SKunihiko Hayashi { 240a1bf1c60SKunihiko Hayashi uniphier_ahciphy_pxs2_enable(priv, false); 241a1bf1c60SKunihiko Hayashi 242a1bf1c60SKunihiko Hayashi return 0; 243a1bf1c60SKunihiko Hayashi } 244a1bf1c60SKunihiko Hayashi 245a1bf1c60SKunihiko Hayashi static int uniphier_ahciphy_pxs3_init(struct uniphier_ahciphy_priv *priv) 246a1bf1c60SKunihiko Hayashi { 247a1bf1c60SKunihiko Hayashi int i; 248a1bf1c60SKunihiko Hayashi u32 val; 249a1bf1c60SKunihiko Hayashi 250a1bf1c60SKunihiko Hayashi /* setup port parameter */ 251a1bf1c60SKunihiko Hayashi val = readl(priv->base + TXCTRL0); 252a1bf1c60SKunihiko Hayashi val &= ~TXCTRL0_AMP_G3_MASK; 253a1bf1c60SKunihiko Hayashi val |= FIELD_PREP(TXCTRL0_AMP_G3_MASK, 0x73); 254a1bf1c60SKunihiko Hayashi val &= ~TXCTRL0_AMP_G2_MASK; 255a1bf1c60SKunihiko Hayashi val |= FIELD_PREP(TXCTRL0_AMP_G2_MASK, 0x46); 256a1bf1c60SKunihiko Hayashi val &= ~TXCTRL0_AMP_G1_MASK; 257a1bf1c60SKunihiko Hayashi val |= FIELD_PREP(TXCTRL0_AMP_G1_MASK, 0x42); 258a1bf1c60SKunihiko Hayashi writel(val, priv->base + TXCTRL0); 259a1bf1c60SKunihiko Hayashi 260a1bf1c60SKunihiko Hayashi val = readl(priv->base + TXCTRL1); 261a1bf1c60SKunihiko Hayashi val &= ~TXCTRL1_DEEMPH_G3_MASK; 262a1bf1c60SKunihiko Hayashi val |= FIELD_PREP(TXCTRL1_DEEMPH_G3_MASK, 0x23); 263a1bf1c60SKunihiko Hayashi val &= ~TXCTRL1_DEEMPH_G2_MASK; 264a1bf1c60SKunihiko Hayashi val |= FIELD_PREP(TXCTRL1_DEEMPH_G2_MASK, 0x05); 265a1bf1c60SKunihiko Hayashi val &= ~TXCTRL1_DEEMPH_G1_MASK; 266a1bf1c60SKunihiko Hayashi val |= FIELD_PREP(TXCTRL1_DEEMPH_G1_MASK, 0x05); 267a1bf1c60SKunihiko Hayashi 268a1bf1c60SKunihiko Hayashi val = readl(priv->base + RXCTRL); 269a1bf1c60SKunihiko Hayashi val &= ~RXCTRL_LOS_LVL_MASK; 270a1bf1c60SKunihiko Hayashi val |= FIELD_PREP(RXCTRL_LOS_LVL_MASK, 0x9); 271a1bf1c60SKunihiko Hayashi val &= ~RXCTRL_LOS_BIAS_MASK; 272a1bf1c60SKunihiko Hayashi val |= FIELD_PREP(RXCTRL_LOS_BIAS_MASK, 0x2); 273a1bf1c60SKunihiko Hayashi val &= ~RXCTRL_RX_EQ_MASK; 274a1bf1c60SKunihiko Hayashi val |= FIELD_PREP(RXCTRL_RX_EQ_MASK, 0x1); 275a1bf1c60SKunihiko Hayashi 276a1bf1c60SKunihiko Hayashi /* dummy read 25 times to make a wait time for the phy to stabilize */ 277a1bf1c60SKunihiko Hayashi for (i = 0; i < 25; i++) 278a1bf1c60SKunihiko Hayashi readl(priv->base + CKCTRL); 279a1bf1c60SKunihiko Hayashi 280a1bf1c60SKunihiko Hayashi return 0; 281a1bf1c60SKunihiko Hayashi } 282a1bf1c60SKunihiko Hayashi 283a1bf1c60SKunihiko Hayashi static int uniphier_ahciphy_init(struct phy *phy) 284a1bf1c60SKunihiko Hayashi { 285a1bf1c60SKunihiko Hayashi struct uniphier_ahciphy_priv *priv = phy_get_drvdata(phy); 286a1bf1c60SKunihiko Hayashi int ret; 287a1bf1c60SKunihiko Hayashi 288*b1f9f454SKunihiko Hayashi ret = clk_prepare_enable(priv->clk_parent_gio); 289a1bf1c60SKunihiko Hayashi if (ret) 290a1bf1c60SKunihiko Hayashi return ret; 291a1bf1c60SKunihiko Hayashi 292*b1f9f454SKunihiko Hayashi ret = clk_prepare_enable(priv->clk_parent); 293*b1f9f454SKunihiko Hayashi if (ret) 294*b1f9f454SKunihiko Hayashi goto out_clk_gio_disable; 295*b1f9f454SKunihiko Hayashi 296*b1f9f454SKunihiko Hayashi ret = reset_control_deassert(priv->rst_parent_gio); 297a1bf1c60SKunihiko Hayashi if (ret) 298a1bf1c60SKunihiko Hayashi goto out_clk_disable; 299a1bf1c60SKunihiko Hayashi 300*b1f9f454SKunihiko Hayashi ret = reset_control_deassert(priv->rst_parent); 301*b1f9f454SKunihiko Hayashi if (ret) 302*b1f9f454SKunihiko Hayashi goto out_rst_gio_assert; 303*b1f9f454SKunihiko Hayashi 304a1bf1c60SKunihiko Hayashi if (priv->data->init) { 305a1bf1c60SKunihiko Hayashi ret = priv->data->init(priv); 306a1bf1c60SKunihiko Hayashi if (ret) 307a1bf1c60SKunihiko Hayashi goto out_rst_assert; 308a1bf1c60SKunihiko Hayashi } 309a1bf1c60SKunihiko Hayashi 310a1bf1c60SKunihiko Hayashi return 0; 311a1bf1c60SKunihiko Hayashi 312a1bf1c60SKunihiko Hayashi out_rst_assert: 313a1bf1c60SKunihiko Hayashi reset_control_assert(priv->rst_parent); 314*b1f9f454SKunihiko Hayashi out_rst_gio_assert: 315*b1f9f454SKunihiko Hayashi reset_control_assert(priv->rst_parent_gio); 316a1bf1c60SKunihiko Hayashi out_clk_disable: 317a1bf1c60SKunihiko Hayashi clk_disable_unprepare(priv->clk_parent); 318*b1f9f454SKunihiko Hayashi out_clk_gio_disable: 319*b1f9f454SKunihiko Hayashi clk_disable_unprepare(priv->clk_parent_gio); 320a1bf1c60SKunihiko Hayashi 321a1bf1c60SKunihiko Hayashi return ret; 322a1bf1c60SKunihiko Hayashi } 323a1bf1c60SKunihiko Hayashi 324a1bf1c60SKunihiko Hayashi static int uniphier_ahciphy_exit(struct phy *phy) 325a1bf1c60SKunihiko Hayashi { 326a1bf1c60SKunihiko Hayashi struct uniphier_ahciphy_priv *priv = phy_get_drvdata(phy); 327a1bf1c60SKunihiko Hayashi 328a1bf1c60SKunihiko Hayashi reset_control_assert(priv->rst_parent); 329*b1f9f454SKunihiko Hayashi reset_control_assert(priv->rst_parent_gio); 330a1bf1c60SKunihiko Hayashi clk_disable_unprepare(priv->clk_parent); 331*b1f9f454SKunihiko Hayashi clk_disable_unprepare(priv->clk_parent_gio); 332a1bf1c60SKunihiko Hayashi 333a1bf1c60SKunihiko Hayashi return 0; 334a1bf1c60SKunihiko Hayashi } 335a1bf1c60SKunihiko Hayashi 336a1bf1c60SKunihiko Hayashi static int uniphier_ahciphy_power_on(struct phy *phy) 337a1bf1c60SKunihiko Hayashi { 338a1bf1c60SKunihiko Hayashi struct uniphier_ahciphy_priv *priv = phy_get_drvdata(phy); 339a1bf1c60SKunihiko Hayashi int ret = 0; 340a1bf1c60SKunihiko Hayashi 341a1bf1c60SKunihiko Hayashi ret = clk_prepare_enable(priv->clk); 342a1bf1c60SKunihiko Hayashi if (ret) 343a1bf1c60SKunihiko Hayashi return ret; 344a1bf1c60SKunihiko Hayashi 345a1bf1c60SKunihiko Hayashi ret = reset_control_deassert(priv->rst); 346a1bf1c60SKunihiko Hayashi if (ret) 347a1bf1c60SKunihiko Hayashi goto out_clk_disable; 348a1bf1c60SKunihiko Hayashi 349a1bf1c60SKunihiko Hayashi if (priv->data->power_on) { 350a1bf1c60SKunihiko Hayashi ret = priv->data->power_on(priv); 351a1bf1c60SKunihiko Hayashi if (ret) 352a1bf1c60SKunihiko Hayashi goto out_reset_assert; 353a1bf1c60SKunihiko Hayashi } 354a1bf1c60SKunihiko Hayashi 355a1bf1c60SKunihiko Hayashi return 0; 356a1bf1c60SKunihiko Hayashi 357a1bf1c60SKunihiko Hayashi out_reset_assert: 358a1bf1c60SKunihiko Hayashi reset_control_assert(priv->rst); 359a1bf1c60SKunihiko Hayashi out_clk_disable: 360a1bf1c60SKunihiko Hayashi clk_disable_unprepare(priv->clk); 361a1bf1c60SKunihiko Hayashi 362a1bf1c60SKunihiko Hayashi return ret; 363a1bf1c60SKunihiko Hayashi } 364a1bf1c60SKunihiko Hayashi 365a1bf1c60SKunihiko Hayashi static int uniphier_ahciphy_power_off(struct phy *phy) 366a1bf1c60SKunihiko Hayashi { 367a1bf1c60SKunihiko Hayashi struct uniphier_ahciphy_priv *priv = phy_get_drvdata(phy); 368a1bf1c60SKunihiko Hayashi int ret = 0; 369a1bf1c60SKunihiko Hayashi 370a1bf1c60SKunihiko Hayashi if (priv->data->power_off) 371a1bf1c60SKunihiko Hayashi ret = priv->data->power_off(priv); 372a1bf1c60SKunihiko Hayashi 373a1bf1c60SKunihiko Hayashi reset_control_assert(priv->rst); 374a1bf1c60SKunihiko Hayashi clk_disable_unprepare(priv->clk); 375a1bf1c60SKunihiko Hayashi 376a1bf1c60SKunihiko Hayashi return ret; 377a1bf1c60SKunihiko Hayashi } 378a1bf1c60SKunihiko Hayashi 379a1bf1c60SKunihiko Hayashi static const struct phy_ops uniphier_ahciphy_ops = { 380a1bf1c60SKunihiko Hayashi .init = uniphier_ahciphy_init, 381a1bf1c60SKunihiko Hayashi .exit = uniphier_ahciphy_exit, 382a1bf1c60SKunihiko Hayashi .power_on = uniphier_ahciphy_power_on, 383a1bf1c60SKunihiko Hayashi .power_off = uniphier_ahciphy_power_off, 384a1bf1c60SKunihiko Hayashi .owner = THIS_MODULE, 385a1bf1c60SKunihiko Hayashi }; 386a1bf1c60SKunihiko Hayashi 387a1bf1c60SKunihiko Hayashi static int uniphier_ahciphy_probe(struct platform_device *pdev) 388a1bf1c60SKunihiko Hayashi { 389a1bf1c60SKunihiko Hayashi struct device *dev = &pdev->dev; 390a1bf1c60SKunihiko Hayashi struct uniphier_ahciphy_priv *priv; 391a1bf1c60SKunihiko Hayashi struct phy *phy; 392a1bf1c60SKunihiko Hayashi struct phy_provider *phy_provider; 393a1bf1c60SKunihiko Hayashi 394a1bf1c60SKunihiko Hayashi priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 395a1bf1c60SKunihiko Hayashi if (!priv) 396a1bf1c60SKunihiko Hayashi return -ENOMEM; 397a1bf1c60SKunihiko Hayashi 398a1bf1c60SKunihiko Hayashi priv->dev = dev; 399a1bf1c60SKunihiko Hayashi priv->data = of_device_get_match_data(dev); 400a1bf1c60SKunihiko Hayashi if (WARN_ON(!priv->data)) 401a1bf1c60SKunihiko Hayashi return -EINVAL; 402a1bf1c60SKunihiko Hayashi 403a1bf1c60SKunihiko Hayashi priv->base = devm_platform_ioremap_resource(pdev, 0); 404a1bf1c60SKunihiko Hayashi if (IS_ERR(priv->base)) 405a1bf1c60SKunihiko Hayashi return PTR_ERR(priv->base); 406a1bf1c60SKunihiko Hayashi 407a1bf1c60SKunihiko Hayashi priv->clk_parent = devm_clk_get(dev, "link"); 408a1bf1c60SKunihiko Hayashi if (IS_ERR(priv->clk_parent)) 409a1bf1c60SKunihiko Hayashi return PTR_ERR(priv->clk_parent); 410a1bf1c60SKunihiko Hayashi 411a1bf1c60SKunihiko Hayashi if (priv->data->is_phy_clk) { 412a1bf1c60SKunihiko Hayashi priv->clk = devm_clk_get(dev, "phy"); 413a1bf1c60SKunihiko Hayashi if (IS_ERR(priv->clk)) 414a1bf1c60SKunihiko Hayashi return PTR_ERR(priv->clk); 415a1bf1c60SKunihiko Hayashi } 416a1bf1c60SKunihiko Hayashi 417a1bf1c60SKunihiko Hayashi priv->rst_parent = devm_reset_control_get_shared(dev, "link"); 418a1bf1c60SKunihiko Hayashi if (IS_ERR(priv->rst_parent)) 419a1bf1c60SKunihiko Hayashi return PTR_ERR(priv->rst_parent); 420a1bf1c60SKunihiko Hayashi 421a1bf1c60SKunihiko Hayashi priv->rst = devm_reset_control_get_shared(dev, "phy"); 422a1bf1c60SKunihiko Hayashi if (IS_ERR(priv->rst)) 423a1bf1c60SKunihiko Hayashi return PTR_ERR(priv->rst); 424a1bf1c60SKunihiko Hayashi 425*b1f9f454SKunihiko Hayashi if (priv->data->is_legacy) { 426*b1f9f454SKunihiko Hayashi priv->clk_parent_gio = devm_clk_get(dev, "gio"); 427*b1f9f454SKunihiko Hayashi if (IS_ERR(priv->clk_parent_gio)) 428*b1f9f454SKunihiko Hayashi return PTR_ERR(priv->clk_parent_gio); 429*b1f9f454SKunihiko Hayashi priv->rst_parent_gio = 430*b1f9f454SKunihiko Hayashi devm_reset_control_get_shared(dev, "gio"); 431*b1f9f454SKunihiko Hayashi if (IS_ERR(priv->rst_parent_gio)) 432*b1f9f454SKunihiko Hayashi return PTR_ERR(priv->rst_parent_gio); 433*b1f9f454SKunihiko Hayashi 434*b1f9f454SKunihiko Hayashi priv->rst_pm = devm_reset_control_get_shared(dev, "pm"); 435*b1f9f454SKunihiko Hayashi if (IS_ERR(priv->rst_pm)) 436*b1f9f454SKunihiko Hayashi return PTR_ERR(priv->rst_pm); 437*b1f9f454SKunihiko Hayashi 438*b1f9f454SKunihiko Hayashi priv->rst_tx = devm_reset_control_get_shared(dev, "tx"); 439*b1f9f454SKunihiko Hayashi if (IS_ERR(priv->rst_tx)) 440*b1f9f454SKunihiko Hayashi return PTR_ERR(priv->rst_tx); 441*b1f9f454SKunihiko Hayashi 442*b1f9f454SKunihiko Hayashi priv->rst_rx = devm_reset_control_get_shared(dev, "rx"); 443*b1f9f454SKunihiko Hayashi if (IS_ERR(priv->rst_rx)) 444*b1f9f454SKunihiko Hayashi return PTR_ERR(priv->rst_rx); 445*b1f9f454SKunihiko Hayashi } 446*b1f9f454SKunihiko Hayashi 447a1bf1c60SKunihiko Hayashi phy = devm_phy_create(dev, dev->of_node, &uniphier_ahciphy_ops); 448a1bf1c60SKunihiko Hayashi if (IS_ERR(phy)) { 449a1bf1c60SKunihiko Hayashi dev_err(dev, "failed to create phy\n"); 450a1bf1c60SKunihiko Hayashi return PTR_ERR(phy); 451a1bf1c60SKunihiko Hayashi } 452a1bf1c60SKunihiko Hayashi 453a1bf1c60SKunihiko Hayashi phy_set_drvdata(phy, priv); 454a1bf1c60SKunihiko Hayashi phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); 455a1bf1c60SKunihiko Hayashi if (IS_ERR(phy_provider)) 456a1bf1c60SKunihiko Hayashi return PTR_ERR(phy_provider); 457a1bf1c60SKunihiko Hayashi 458a1bf1c60SKunihiko Hayashi return 0; 459a1bf1c60SKunihiko Hayashi } 460a1bf1c60SKunihiko Hayashi 461*b1f9f454SKunihiko Hayashi static const struct uniphier_ahciphy_soc_data uniphier_pro4_data = { 462*b1f9f454SKunihiko Hayashi .init = uniphier_ahciphy_pro4_init, 463*b1f9f454SKunihiko Hayashi .power_on = uniphier_ahciphy_pro4_power_on, 464*b1f9f454SKunihiko Hayashi .power_off = uniphier_ahciphy_pro4_power_off, 465*b1f9f454SKunihiko Hayashi .is_legacy = true, 466*b1f9f454SKunihiko Hayashi .is_phy_clk = false, 467*b1f9f454SKunihiko Hayashi }; 468*b1f9f454SKunihiko Hayashi 469a1bf1c60SKunihiko Hayashi static const struct uniphier_ahciphy_soc_data uniphier_pxs2_data = { 470a1bf1c60SKunihiko Hayashi .power_on = uniphier_ahciphy_pxs2_power_on, 471a1bf1c60SKunihiko Hayashi .power_off = uniphier_ahciphy_pxs2_power_off, 472*b1f9f454SKunihiko Hayashi .is_legacy = false, 473a1bf1c60SKunihiko Hayashi .is_ready_high = false, 474a1bf1c60SKunihiko Hayashi .is_phy_clk = false, 475a1bf1c60SKunihiko Hayashi }; 476a1bf1c60SKunihiko Hayashi 477a1bf1c60SKunihiko Hayashi static const struct uniphier_ahciphy_soc_data uniphier_pxs3_data = { 478a1bf1c60SKunihiko Hayashi .init = uniphier_ahciphy_pxs3_init, 479a1bf1c60SKunihiko Hayashi .power_on = uniphier_ahciphy_pxs2_power_on, 480a1bf1c60SKunihiko Hayashi .power_off = uniphier_ahciphy_pxs2_power_off, 481*b1f9f454SKunihiko Hayashi .is_legacy = false, 482a1bf1c60SKunihiko Hayashi .is_ready_high = true, 483a1bf1c60SKunihiko Hayashi .is_phy_clk = true, 484a1bf1c60SKunihiko Hayashi }; 485a1bf1c60SKunihiko Hayashi 486a1bf1c60SKunihiko Hayashi static const struct of_device_id uniphier_ahciphy_match[] = { 487a1bf1c60SKunihiko Hayashi { 488*b1f9f454SKunihiko Hayashi .compatible = "socionext,uniphier-pro4-ahci-phy", 489*b1f9f454SKunihiko Hayashi .data = &uniphier_pro4_data, 490*b1f9f454SKunihiko Hayashi }, 491*b1f9f454SKunihiko Hayashi { 492a1bf1c60SKunihiko Hayashi .compatible = "socionext,uniphier-pxs2-ahci-phy", 493a1bf1c60SKunihiko Hayashi .data = &uniphier_pxs2_data, 494a1bf1c60SKunihiko Hayashi }, 495a1bf1c60SKunihiko Hayashi { 496a1bf1c60SKunihiko Hayashi .compatible = "socionext,uniphier-pxs3-ahci-phy", 497a1bf1c60SKunihiko Hayashi .data = &uniphier_pxs3_data, 498a1bf1c60SKunihiko Hayashi }, 499a1bf1c60SKunihiko Hayashi { /* Sentinel */ }, 500a1bf1c60SKunihiko Hayashi }; 501a1bf1c60SKunihiko Hayashi MODULE_DEVICE_TABLE(of, uniphier_ahciphy_match); 502a1bf1c60SKunihiko Hayashi 503a1bf1c60SKunihiko Hayashi static struct platform_driver uniphier_ahciphy_driver = { 504a1bf1c60SKunihiko Hayashi .probe = uniphier_ahciphy_probe, 505a1bf1c60SKunihiko Hayashi .driver = { 506a1bf1c60SKunihiko Hayashi .name = "uniphier-ahci-phy", 507a1bf1c60SKunihiko Hayashi .of_match_table = uniphier_ahciphy_match, 508a1bf1c60SKunihiko Hayashi }, 509a1bf1c60SKunihiko Hayashi }; 510a1bf1c60SKunihiko Hayashi module_platform_driver(uniphier_ahciphy_driver); 511a1bf1c60SKunihiko Hayashi 512a1bf1c60SKunihiko Hayashi MODULE_AUTHOR("Kunihiko Hayashi <hayashi.kunihiko@socionext.com>"); 513a1bf1c60SKunihiko Hayashi MODULE_DESCRIPTION("UniPhier PHY driver for AHCI controller"); 514a1bf1c60SKunihiko Hayashi MODULE_LICENSE("GPL v2"); 515