root/drivers/phy/samsung/phy-exynos5250-sata.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. wait_for_reg_status
  2. exynos_sata_phy_power_on
  3. exynos_sata_phy_power_off
  4. exynos_sata_phy_init
  5. exynos_sata_phy_probe

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Samsung SATA SerDes(PHY) driver
   4  *
   5  * Copyright (C) 2013 Samsung Electronics Co., Ltd.
   6  * Authors: Girish K S <ks.giri@samsung.com>
   7  *         Yuvaraj Kumar C D <yuvaraj.cd@samsung.com>
   8  */
   9 
  10 #include <linux/clk.h>
  11 #include <linux/delay.h>
  12 #include <linux/io.h>
  13 #include <linux/i2c.h>
  14 #include <linux/kernel.h>
  15 #include <linux/module.h>
  16 #include <linux/of.h>
  17 #include <linux/of_address.h>
  18 #include <linux/phy/phy.h>
  19 #include <linux/platform_device.h>
  20 #include <linux/regmap.h>
  21 #include <linux/spinlock.h>
  22 #include <linux/mfd/syscon.h>
  23 
  24 #define SATAPHY_CONTROL_OFFSET          0x0724
  25 #define EXYNOS5_SATAPHY_PMU_ENABLE      BIT(0)
  26 #define EXYNOS5_SATA_RESET              0x4
  27 #define RESET_GLOBAL_RST_N              BIT(0)
  28 #define RESET_CMN_RST_N                 BIT(1)
  29 #define RESET_CMN_BLOCK_RST_N           BIT(2)
  30 #define RESET_CMN_I2C_RST_N             BIT(3)
  31 #define RESET_TX_RX_PIPE_RST_N          BIT(4)
  32 #define RESET_TX_RX_BLOCK_RST_N         BIT(5)
  33 #define RESET_TX_RX_I2C_RST_N           (BIT(6) | BIT(7))
  34 #define LINK_RESET                      0xf0000
  35 #define EXYNOS5_SATA_MODE0              0x10
  36 #define SATA_SPD_GEN3                   BIT(1)
  37 #define EXYNOS5_SATA_CTRL0              0x14
  38 #define CTRL0_P0_PHY_CALIBRATED_SEL     BIT(9)
  39 #define CTRL0_P0_PHY_CALIBRATED         BIT(8)
  40 #define EXYNOS5_SATA_PHSATA_CTRLM       0xe0
  41 #define PHCTRLM_REF_RATE                BIT(1)
  42 #define PHCTRLM_HIGH_SPEED              BIT(0)
  43 #define EXYNOS5_SATA_PHSATA_STATM       0xf0
  44 #define PHSTATM_PLL_LOCKED              BIT(0)
  45 
  46 #define PHY_PLL_TIMEOUT (usecs_to_jiffies(1000))
  47 
  48 struct exynos_sata_phy {
  49         struct phy *phy;
  50         struct clk *phyclk;
  51         void __iomem *regs;
  52         struct regmap *pmureg;
  53         struct i2c_client *client;
  54 };
  55 
  56 static int wait_for_reg_status(void __iomem *base, u32 reg, u32 checkbit,
  57                                 u32 status)
  58 {
  59         unsigned long timeout = jiffies + PHY_PLL_TIMEOUT;
  60 
  61         while (time_before(jiffies, timeout)) {
  62                 if ((readl(base + reg) & checkbit) == status)
  63                         return 0;
  64         }
  65 
  66         return -EFAULT;
  67 }
  68 
  69 static int exynos_sata_phy_power_on(struct phy *phy)
  70 {
  71         struct exynos_sata_phy *sata_phy = phy_get_drvdata(phy);
  72 
  73         return regmap_update_bits(sata_phy->pmureg, SATAPHY_CONTROL_OFFSET,
  74                         EXYNOS5_SATAPHY_PMU_ENABLE, true);
  75 
  76 }
  77 
  78 static int exynos_sata_phy_power_off(struct phy *phy)
  79 {
  80         struct exynos_sata_phy *sata_phy = phy_get_drvdata(phy);
  81 
  82         return regmap_update_bits(sata_phy->pmureg, SATAPHY_CONTROL_OFFSET,
  83                         EXYNOS5_SATAPHY_PMU_ENABLE, false);
  84 
  85 }
  86 
  87 static int exynos_sata_phy_init(struct phy *phy)
  88 {
  89         u32 val = 0;
  90         int ret = 0;
  91         u8 buf[] = { 0x3a, 0x0b };
  92         struct exynos_sata_phy *sata_phy = phy_get_drvdata(phy);
  93 
  94         ret = regmap_update_bits(sata_phy->pmureg, SATAPHY_CONTROL_OFFSET,
  95                         EXYNOS5_SATAPHY_PMU_ENABLE, true);
  96         if (ret != 0)
  97                 dev_err(&sata_phy->phy->dev, "phy init failed\n");
  98 
  99         writel(val, sata_phy->regs + EXYNOS5_SATA_RESET);
 100 
 101         val = readl(sata_phy->regs + EXYNOS5_SATA_RESET);
 102         val |= RESET_GLOBAL_RST_N | RESET_CMN_RST_N | RESET_CMN_BLOCK_RST_N
 103                 | RESET_CMN_I2C_RST_N | RESET_TX_RX_PIPE_RST_N
 104                 | RESET_TX_RX_BLOCK_RST_N | RESET_TX_RX_I2C_RST_N;
 105         writel(val, sata_phy->regs + EXYNOS5_SATA_RESET);
 106 
 107         val = readl(sata_phy->regs + EXYNOS5_SATA_RESET);
 108         val |= LINK_RESET;
 109         writel(val, sata_phy->regs + EXYNOS5_SATA_RESET);
 110 
 111         val = readl(sata_phy->regs + EXYNOS5_SATA_RESET);
 112         val |= RESET_CMN_RST_N;
 113         writel(val, sata_phy->regs + EXYNOS5_SATA_RESET);
 114 
 115         val = readl(sata_phy->regs + EXYNOS5_SATA_PHSATA_CTRLM);
 116         val &= ~PHCTRLM_REF_RATE;
 117         writel(val, sata_phy->regs + EXYNOS5_SATA_PHSATA_CTRLM);
 118 
 119         /* High speed enable for Gen3 */
 120         val = readl(sata_phy->regs + EXYNOS5_SATA_PHSATA_CTRLM);
 121         val |= PHCTRLM_HIGH_SPEED;
 122         writel(val, sata_phy->regs + EXYNOS5_SATA_PHSATA_CTRLM);
 123 
 124         val = readl(sata_phy->regs + EXYNOS5_SATA_CTRL0);
 125         val |= CTRL0_P0_PHY_CALIBRATED_SEL | CTRL0_P0_PHY_CALIBRATED;
 126         writel(val, sata_phy->regs + EXYNOS5_SATA_CTRL0);
 127 
 128         val = readl(sata_phy->regs + EXYNOS5_SATA_MODE0);
 129         val |= SATA_SPD_GEN3;
 130         writel(val, sata_phy->regs + EXYNOS5_SATA_MODE0);
 131 
 132         ret = i2c_master_send(sata_phy->client, buf, sizeof(buf));
 133         if (ret < 0)
 134                 return ret;
 135 
 136         /* release cmu reset */
 137         val = readl(sata_phy->regs + EXYNOS5_SATA_RESET);
 138         val &= ~RESET_CMN_RST_N;
 139         writel(val, sata_phy->regs + EXYNOS5_SATA_RESET);
 140 
 141         val = readl(sata_phy->regs + EXYNOS5_SATA_RESET);
 142         val |= RESET_CMN_RST_N;
 143         writel(val, sata_phy->regs + EXYNOS5_SATA_RESET);
 144 
 145         ret = wait_for_reg_status(sata_phy->regs,
 146                                 EXYNOS5_SATA_PHSATA_STATM,
 147                                 PHSTATM_PLL_LOCKED, 1);
 148         if (ret < 0)
 149                 dev_err(&sata_phy->phy->dev,
 150                         "PHY PLL locking failed\n");
 151         return ret;
 152 }
 153 
 154 static const struct phy_ops exynos_sata_phy_ops = {
 155         .init           = exynos_sata_phy_init,
 156         .power_on       = exynos_sata_phy_power_on,
 157         .power_off      = exynos_sata_phy_power_off,
 158         .owner          = THIS_MODULE,
 159 };
 160 
 161 static int exynos_sata_phy_probe(struct platform_device *pdev)
 162 {
 163         struct exynos_sata_phy *sata_phy;
 164         struct device *dev = &pdev->dev;
 165         struct resource *res;
 166         struct phy_provider *phy_provider;
 167         struct device_node *node;
 168         int ret = 0;
 169 
 170         sata_phy = devm_kzalloc(dev, sizeof(*sata_phy), GFP_KERNEL);
 171         if (!sata_phy)
 172                 return -ENOMEM;
 173 
 174         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 175 
 176         sata_phy->regs = devm_ioremap_resource(dev, res);
 177         if (IS_ERR(sata_phy->regs))
 178                 return PTR_ERR(sata_phy->regs);
 179 
 180         sata_phy->pmureg = syscon_regmap_lookup_by_phandle(dev->of_node,
 181                                         "samsung,syscon-phandle");
 182         if (IS_ERR(sata_phy->pmureg)) {
 183                 dev_err(dev, "syscon regmap lookup failed.\n");
 184                 return PTR_ERR(sata_phy->pmureg);
 185         }
 186 
 187         node = of_parse_phandle(dev->of_node,
 188                         "samsung,exynos-sataphy-i2c-phandle", 0);
 189         if (!node)
 190                 return -EINVAL;
 191 
 192         sata_phy->client = of_find_i2c_device_by_node(node);
 193         if (!sata_phy->client)
 194                 return -EPROBE_DEFER;
 195 
 196         dev_set_drvdata(dev, sata_phy);
 197 
 198         sata_phy->phyclk = devm_clk_get(dev, "sata_phyctrl");
 199         if (IS_ERR(sata_phy->phyclk)) {
 200                 dev_err(dev, "failed to get clk for PHY\n");
 201                 return PTR_ERR(sata_phy->phyclk);
 202         }
 203 
 204         ret = clk_prepare_enable(sata_phy->phyclk);
 205         if (ret < 0) {
 206                 dev_err(dev, "failed to enable source clk\n");
 207                 return ret;
 208         }
 209 
 210         sata_phy->phy = devm_phy_create(dev, NULL, &exynos_sata_phy_ops);
 211         if (IS_ERR(sata_phy->phy)) {
 212                 clk_disable_unprepare(sata_phy->phyclk);
 213                 dev_err(dev, "failed to create PHY\n");
 214                 return PTR_ERR(sata_phy->phy);
 215         }
 216 
 217         phy_set_drvdata(sata_phy->phy, sata_phy);
 218 
 219         phy_provider = devm_of_phy_provider_register(dev,
 220                                         of_phy_simple_xlate);
 221         if (IS_ERR(phy_provider)) {
 222                 clk_disable_unprepare(sata_phy->phyclk);
 223                 return PTR_ERR(phy_provider);
 224         }
 225 
 226         return 0;
 227 }
 228 
 229 static const struct of_device_id exynos_sata_phy_of_match[] = {
 230         { .compatible = "samsung,exynos5250-sata-phy" },
 231         { },
 232 };
 233 MODULE_DEVICE_TABLE(of, exynos_sata_phy_of_match);
 234 
 235 static struct platform_driver exynos_sata_phy_driver = {
 236         .probe  = exynos_sata_phy_probe,
 237         .driver = {
 238                 .of_match_table = exynos_sata_phy_of_match,
 239                 .name  = "samsung,sata-phy",
 240                 .suppress_bind_attrs = true,
 241         }
 242 };
 243 module_platform_driver(exynos_sata_phy_driver);
 244 
 245 MODULE_DESCRIPTION("Samsung SerDes PHY driver");
 246 MODULE_LICENSE("GPL v2");
 247 MODULE_AUTHOR("Girish K S <ks.giri@samsung.com>");
 248 MODULE_AUTHOR("Yuvaraj C D <yuvaraj.cd@samsung.com>");

/* [<][>][^][v][top][bottom][index][help] */