root/drivers/phy/cadence/phy-cadence-sierra.c

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

DEFINITIONS

This source file includes following definitions.
  1. cdns_sierra_phy_init
  2. cdns_sierra_phy_on
  3. cdns_sierra_phy_off
  4. cdns_sierra_get_optional
  5. cdns_sierra_phy_probe
  6. cdns_sierra_phy_remove

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Cadence Sierra PHY Driver
   4  *
   5  * Copyright (c) 2018 Cadence Design Systems
   6  * Author: Alan Douglas <adouglas@cadence.com>
   7  *
   8  */
   9 #include <linux/clk.h>
  10 #include <linux/delay.h>
  11 #include <linux/err.h>
  12 #include <linux/io.h>
  13 #include <linux/module.h>
  14 #include <linux/phy/phy.h>
  15 #include <linux/platform_device.h>
  16 #include <linux/pm_runtime.h>
  17 #include <linux/regmap.h>
  18 #include <linux/reset.h>
  19 #include <linux/slab.h>
  20 #include <linux/of.h>
  21 #include <linux/of_platform.h>
  22 #include <dt-bindings/phy/phy.h>
  23 
  24 /* PHY register offsets */
  25 #define SIERRA_PHY_PLL_CFG              (0xc00e << 2)
  26 #define SIERRA_DET_STANDEC_A            (0x4000 << 2)
  27 #define SIERRA_DET_STANDEC_B            (0x4001 << 2)
  28 #define SIERRA_DET_STANDEC_C            (0x4002 << 2)
  29 #define SIERRA_DET_STANDEC_D            (0x4003 << 2)
  30 #define SIERRA_DET_STANDEC_E            (0x4004 << 2)
  31 #define SIERRA_PSM_LANECAL              (0x4008 << 2)
  32 #define SIERRA_PSM_DIAG                 (0x4015 << 2)
  33 #define SIERRA_PSC_TX_A0                (0x4028 << 2)
  34 #define SIERRA_PSC_TX_A1                (0x4029 << 2)
  35 #define SIERRA_PSC_TX_A2                (0x402A << 2)
  36 #define SIERRA_PSC_TX_A3                (0x402B << 2)
  37 #define SIERRA_PSC_RX_A0                (0x4030 << 2)
  38 #define SIERRA_PSC_RX_A1                (0x4031 << 2)
  39 #define SIERRA_PSC_RX_A2                (0x4032 << 2)
  40 #define SIERRA_PSC_RX_A3                (0x4033 << 2)
  41 #define SIERRA_PLLCTRL_SUBRATE          (0x403A << 2)
  42 #define SIERRA_PLLCTRL_GEN_D            (0x403E << 2)
  43 #define SIERRA_DRVCTRL_ATTEN            (0x406A << 2)
  44 #define SIERRA_CLKPATHCTRL_TMR          (0x4081 << 2)
  45 #define SIERRA_RX_CREQ_FLTR_A_MODE1     (0x4087 << 2)
  46 #define SIERRA_RX_CREQ_FLTR_A_MODE0     (0x4088 << 2)
  47 #define SIERRA_CREQ_CCLKDET_MODE01      (0x408E << 2)
  48 #define SIERRA_RX_CTLE_MAINTENANCE      (0x4091 << 2)
  49 #define SIERRA_CREQ_FSMCLK_SEL          (0x4092 << 2)
  50 #define SIERRA_CTLELUT_CTRL             (0x4098 << 2)
  51 #define SIERRA_DFE_ECMP_RATESEL         (0x40C0 << 2)
  52 #define SIERRA_DFE_SMP_RATESEL          (0x40C1 << 2)
  53 #define SIERRA_DEQ_VGATUNE_CTRL         (0x40E1 << 2)
  54 #define SIERRA_TMRVAL_MODE3             (0x416E << 2)
  55 #define SIERRA_TMRVAL_MODE2             (0x416F << 2)
  56 #define SIERRA_TMRVAL_MODE1             (0x4170 << 2)
  57 #define SIERRA_TMRVAL_MODE0             (0x4171 << 2)
  58 #define SIERRA_PICNT_MODE1              (0x4174 << 2)
  59 #define SIERRA_CPI_OUTBUF_RATESEL       (0x417C << 2)
  60 #define SIERRA_LFPSFILT_NS              (0x418A << 2)
  61 #define SIERRA_LFPSFILT_RD              (0x418B << 2)
  62 #define SIERRA_LFPSFILT_MP              (0x418C << 2)
  63 #define SIERRA_SDFILT_H2L_A             (0x4191 << 2)
  64 
  65 #define SIERRA_MACRO_ID                 0x00007364
  66 #define SIERRA_MAX_LANES                4
  67 
  68 struct cdns_sierra_inst {
  69         struct phy *phy;
  70         u32 phy_type;
  71         u32 num_lanes;
  72         u32 mlane;
  73         struct reset_control *lnk_rst;
  74 };
  75 
  76 struct cdns_reg_pairs {
  77         u16 val;
  78         u32 off;
  79 };
  80 
  81 struct cdns_sierra_data {
  82                 u32 id_value;
  83                 u32 pcie_regs;
  84                 u32 usb_regs;
  85                 struct cdns_reg_pairs *pcie_vals;
  86                 struct cdns_reg_pairs  *usb_vals;
  87 };
  88 
  89 struct cdns_sierra_phy {
  90         struct device *dev;
  91         void __iomem *base;
  92         struct cdns_sierra_data *init_data;
  93         struct cdns_sierra_inst phys[SIERRA_MAX_LANES];
  94         struct reset_control *phy_rst;
  95         struct reset_control *apb_rst;
  96         struct clk *clk;
  97         int nsubnodes;
  98         bool autoconf;
  99 };
 100 
 101 static void cdns_sierra_phy_init(struct phy *gphy)
 102 {
 103         struct cdns_sierra_inst *ins = phy_get_drvdata(gphy);
 104         struct cdns_sierra_phy *phy = dev_get_drvdata(gphy->dev.parent);
 105         int i, j;
 106         struct cdns_reg_pairs *vals;
 107         u32 num_regs;
 108 
 109         if (ins->phy_type == PHY_TYPE_PCIE) {
 110                 num_regs = phy->init_data->pcie_regs;
 111                 vals = phy->init_data->pcie_vals;
 112         } else if (ins->phy_type == PHY_TYPE_USB3) {
 113                 num_regs = phy->init_data->usb_regs;
 114                 vals = phy->init_data->usb_vals;
 115         } else {
 116                 return;
 117         }
 118         for (i = 0; i < ins->num_lanes; i++)
 119                 for (j = 0; j < num_regs ; j++)
 120                         writel(vals[j].val, phy->base +
 121                                 vals[j].off + (i + ins->mlane) * 0x800);
 122 }
 123 
 124 static int cdns_sierra_phy_on(struct phy *gphy)
 125 {
 126         struct cdns_sierra_inst *ins = phy_get_drvdata(gphy);
 127 
 128         /* Take the PHY lane group out of reset */
 129         return reset_control_deassert(ins->lnk_rst);
 130 }
 131 
 132 static int cdns_sierra_phy_off(struct phy *gphy)
 133 {
 134         struct cdns_sierra_inst *ins = phy_get_drvdata(gphy);
 135 
 136         return reset_control_assert(ins->lnk_rst);
 137 }
 138 
 139 static const struct phy_ops ops = {
 140         .power_on       = cdns_sierra_phy_on,
 141         .power_off      = cdns_sierra_phy_off,
 142         .owner          = THIS_MODULE,
 143 };
 144 
 145 static int cdns_sierra_get_optional(struct cdns_sierra_inst *inst,
 146                                     struct device_node *child)
 147 {
 148         if (of_property_read_u32(child, "reg", &inst->mlane))
 149                 return -EINVAL;
 150 
 151         if (of_property_read_u32(child, "cdns,num-lanes", &inst->num_lanes))
 152                 return -EINVAL;
 153 
 154         if (of_property_read_u32(child, "cdns,phy-type", &inst->phy_type))
 155                 return -EINVAL;
 156 
 157         return 0;
 158 }
 159 
 160 static const struct of_device_id cdns_sierra_id_table[];
 161 
 162 static int cdns_sierra_phy_probe(struct platform_device *pdev)
 163 {
 164         struct cdns_sierra_phy *sp;
 165         struct phy_provider *phy_provider;
 166         struct device *dev = &pdev->dev;
 167         const struct of_device_id *match;
 168         struct resource *res;
 169         int i, ret, node = 0;
 170         struct device_node *dn = dev->of_node, *child;
 171 
 172         if (of_get_child_count(dn) == 0)
 173                 return -ENODEV;
 174 
 175         sp = devm_kzalloc(dev, sizeof(*sp), GFP_KERNEL);
 176         if (!sp)
 177                 return -ENOMEM;
 178         dev_set_drvdata(dev, sp);
 179         sp->dev = dev;
 180 
 181         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 182         sp->base = devm_ioremap_resource(dev, res);
 183         if (IS_ERR(sp->base)) {
 184                 dev_err(dev, "missing \"reg\"\n");
 185                 return PTR_ERR(sp->base);
 186         }
 187 
 188         /* Get init data for this PHY */
 189         match = of_match_device(cdns_sierra_id_table, dev);
 190         if (!match)
 191                 return -EINVAL;
 192         sp->init_data = (struct cdns_sierra_data *)match->data;
 193 
 194         platform_set_drvdata(pdev, sp);
 195 
 196         sp->clk = devm_clk_get(dev, "phy_clk");
 197         if (IS_ERR(sp->clk)) {
 198                 dev_err(dev, "failed to get clock phy_clk\n");
 199                 return PTR_ERR(sp->clk);
 200         }
 201 
 202         sp->phy_rst = devm_reset_control_get(dev, "sierra_reset");
 203         if (IS_ERR(sp->phy_rst)) {
 204                 dev_err(dev, "failed to get reset\n");
 205                 return PTR_ERR(sp->phy_rst);
 206         }
 207 
 208         sp->apb_rst = devm_reset_control_get(dev, "sierra_apb");
 209         if (IS_ERR(sp->apb_rst)) {
 210                 dev_err(dev, "failed to get apb reset\n");
 211                 return PTR_ERR(sp->apb_rst);
 212         }
 213 
 214         ret = clk_prepare_enable(sp->clk);
 215         if (ret)
 216                 return ret;
 217 
 218         /* Enable APB */
 219         reset_control_deassert(sp->apb_rst);
 220 
 221         /* Check that PHY is present */
 222         if  (sp->init_data->id_value != readl(sp->base)) {
 223                 ret = -EINVAL;
 224                 goto clk_disable;
 225         }
 226 
 227         sp->autoconf = of_property_read_bool(dn, "cdns,autoconf");
 228 
 229         for_each_available_child_of_node(dn, child) {
 230                 struct phy *gphy;
 231 
 232                 sp->phys[node].lnk_rst =
 233                         of_reset_control_get_exclusive_by_index(child, 0);
 234 
 235                 if (IS_ERR(sp->phys[node].lnk_rst)) {
 236                         dev_err(dev, "failed to get reset %s\n",
 237                                 child->full_name);
 238                         ret = PTR_ERR(sp->phys[node].lnk_rst);
 239                         goto put_child2;
 240                 }
 241 
 242                 if (!sp->autoconf) {
 243                         ret = cdns_sierra_get_optional(&sp->phys[node], child);
 244                         if (ret) {
 245                                 dev_err(dev, "missing property in node %s\n",
 246                                         child->name);
 247                                 goto put_child;
 248                         }
 249                 }
 250 
 251                 gphy = devm_phy_create(dev, child, &ops);
 252 
 253                 if (IS_ERR(gphy)) {
 254                         ret = PTR_ERR(gphy);
 255                         goto put_child;
 256                 }
 257                 sp->phys[node].phy = gphy;
 258                 phy_set_drvdata(gphy, &sp->phys[node]);
 259 
 260                 /* Initialise the PHY registers, unless auto configured */
 261                 if (!sp->autoconf)
 262                         cdns_sierra_phy_init(gphy);
 263 
 264                 node++;
 265         }
 266         sp->nsubnodes = node;
 267 
 268         /* If more than one subnode, configure the PHY as multilink */
 269         if (!sp->autoconf && sp->nsubnodes > 1)
 270                 writel(2, sp->base + SIERRA_PHY_PLL_CFG);
 271 
 272         pm_runtime_enable(dev);
 273         phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
 274         reset_control_deassert(sp->phy_rst);
 275         return PTR_ERR_OR_ZERO(phy_provider);
 276 
 277 put_child:
 278         node++;
 279 put_child2:
 280         for (i = 0; i < node; i++)
 281                 reset_control_put(sp->phys[i].lnk_rst);
 282         of_node_put(child);
 283 clk_disable:
 284         clk_disable_unprepare(sp->clk);
 285         reset_control_assert(sp->apb_rst);
 286         return ret;
 287 }
 288 
 289 static int cdns_sierra_phy_remove(struct platform_device *pdev)
 290 {
 291         struct cdns_sierra_phy *phy = dev_get_drvdata(pdev->dev.parent);
 292         int i;
 293 
 294         reset_control_assert(phy->phy_rst);
 295         reset_control_assert(phy->apb_rst);
 296         pm_runtime_disable(&pdev->dev);
 297 
 298         /*
 299          * The device level resets will be put automatically.
 300          * Need to put the subnode resets here though.
 301          */
 302         for (i = 0; i < phy->nsubnodes; i++) {
 303                 reset_control_assert(phy->phys[i].lnk_rst);
 304                 reset_control_put(phy->phys[i].lnk_rst);
 305         }
 306         return 0;
 307 }
 308 
 309 static struct cdns_reg_pairs cdns_usb_regs[] = {
 310         /*
 311          * Write USB configuration parameters to the PHY.
 312          * These values are specific to this specific hardware
 313          * configuration.
 314          */
 315         {0xFE0A, SIERRA_DET_STANDEC_A},
 316         {0x000F, SIERRA_DET_STANDEC_B},
 317         {0x55A5, SIERRA_DET_STANDEC_C},
 318         {0x69AD, SIERRA_DET_STANDEC_D},
 319         {0x0241, SIERRA_DET_STANDEC_E},
 320         {0x0110, SIERRA_PSM_LANECAL},
 321         {0xCF00, SIERRA_PSM_DIAG},
 322         {0x001F, SIERRA_PSC_TX_A0},
 323         {0x0007, SIERRA_PSC_TX_A1},
 324         {0x0003, SIERRA_PSC_TX_A2},
 325         {0x0003, SIERRA_PSC_TX_A3},
 326         {0x0FFF, SIERRA_PSC_RX_A0},
 327         {0x0003, SIERRA_PSC_RX_A1},
 328         {0x0003, SIERRA_PSC_RX_A2},
 329         {0x0001, SIERRA_PSC_RX_A3},
 330         {0x0001, SIERRA_PLLCTRL_SUBRATE},
 331         {0x0406, SIERRA_PLLCTRL_GEN_D},
 332         {0x0000, SIERRA_DRVCTRL_ATTEN},
 333         {0x823E, SIERRA_CLKPATHCTRL_TMR},
 334         {0x078F, SIERRA_RX_CREQ_FLTR_A_MODE1},
 335         {0x078F, SIERRA_RX_CREQ_FLTR_A_MODE0},
 336         {0x7B3C, SIERRA_CREQ_CCLKDET_MODE01},
 337         {0x023C, SIERRA_RX_CTLE_MAINTENANCE},
 338         {0x3232, SIERRA_CREQ_FSMCLK_SEL},
 339         {0x8452, SIERRA_CTLELUT_CTRL},
 340         {0x4121, SIERRA_DFE_ECMP_RATESEL},
 341         {0x4121, SIERRA_DFE_SMP_RATESEL},
 342         {0x9999, SIERRA_DEQ_VGATUNE_CTRL},
 343         {0x0330, SIERRA_TMRVAL_MODE0},
 344         {0x01FF, SIERRA_PICNT_MODE1},
 345         {0x0009, SIERRA_CPI_OUTBUF_RATESEL},
 346         {0x000F, SIERRA_LFPSFILT_NS},
 347         {0x0009, SIERRA_LFPSFILT_RD},
 348         {0x0001, SIERRA_LFPSFILT_MP},
 349         {0x8013, SIERRA_SDFILT_H2L_A},
 350         {0x0400, SIERRA_TMRVAL_MODE1},
 351 };
 352 
 353 static struct cdns_reg_pairs cdns_pcie_regs[] = {
 354         /*
 355          * Write PCIe configuration parameters to the PHY.
 356          * These values are specific to this specific hardware
 357          * configuration.
 358          */
 359         {0x891f, SIERRA_DET_STANDEC_D},
 360         {0x0053, SIERRA_DET_STANDEC_E},
 361         {0x0400, SIERRA_TMRVAL_MODE2},
 362         {0x0200, SIERRA_TMRVAL_MODE3},
 363 };
 364 
 365 static const struct cdns_sierra_data cdns_map_sierra = {
 366         SIERRA_MACRO_ID,
 367         ARRAY_SIZE(cdns_pcie_regs),
 368         ARRAY_SIZE(cdns_usb_regs),
 369         cdns_pcie_regs,
 370         cdns_usb_regs
 371 };
 372 
 373 static const struct of_device_id cdns_sierra_id_table[] = {
 374         {
 375                 .compatible = "cdns,sierra-phy-t0",
 376                 .data = &cdns_map_sierra,
 377         },
 378         {}
 379 };
 380 MODULE_DEVICE_TABLE(of, cdns_sierra_id_table);
 381 
 382 static struct platform_driver cdns_sierra_driver = {
 383         .probe          = cdns_sierra_phy_probe,
 384         .remove         = cdns_sierra_phy_remove,
 385         .driver         = {
 386                 .name   = "cdns-sierra-phy",
 387                 .of_match_table = cdns_sierra_id_table,
 388         },
 389 };
 390 module_platform_driver(cdns_sierra_driver);
 391 
 392 MODULE_ALIAS("platform:cdns_sierra");
 393 MODULE_AUTHOR("Cadence Design Systems");
 394 MODULE_DESCRIPTION("CDNS sierra phy driver");
 395 MODULE_LICENSE("GPL v2");

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