linux/drivers/phy/ralink/phy-mt7621-pci.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Mediatek MT7621 PCI PHY Driver
   4 * Author: Sergio Paracuellos <sergio.paracuellos@gmail.com>
   5 */
   6
   7#include <dt-bindings/phy/phy.h>
   8#include <linux/clk.h>
   9#include <linux/bitfield.h>
  10#include <linux/bitops.h>
  11#include <linux/module.h>
  12#include <linux/of_address.h>
  13#include <linux/of_device.h>
  14#include <linux/phy/phy.h>
  15#include <linux/platform_device.h>
  16#include <linux/regmap.h>
  17#include <linux/sys_soc.h>
  18
  19#define RG_PE1_PIPE_REG                         0x02c
  20#define RG_PE1_PIPE_RST                         BIT(12)
  21#define RG_PE1_PIPE_CMD_FRC                     BIT(4)
  22
  23#define RG_P0_TO_P1_WIDTH                       0x100
  24#define RG_PE1_H_LCDDS_REG                      0x49c
  25#define RG_PE1_H_LCDDS_PCW                      GENMASK(30, 0)
  26
  27#define RG_PE1_FRC_H_XTAL_REG                   0x400
  28#define RG_PE1_FRC_H_XTAL_TYPE                  BIT(8)
  29#define RG_PE1_H_XTAL_TYPE                      GENMASK(10, 9)
  30
  31#define RG_PE1_FRC_PHY_REG                      0x000
  32#define RG_PE1_FRC_PHY_EN                       BIT(4)
  33#define RG_PE1_PHY_EN                           BIT(5)
  34
  35#define RG_PE1_H_PLL_REG                        0x490
  36#define RG_PE1_H_PLL_BC                         GENMASK(23, 22)
  37#define RG_PE1_H_PLL_BP                         GENMASK(21, 18)
  38#define RG_PE1_H_PLL_IR                         GENMASK(15, 12)
  39#define RG_PE1_H_PLL_IC                         GENMASK(11, 8)
  40#define RG_PE1_H_PLL_PREDIV                     GENMASK(7, 6)
  41#define RG_PE1_PLL_DIVEN                        GENMASK(3, 1)
  42
  43#define RG_PE1_H_PLL_FBKSEL_REG                 0x4bc
  44#define RG_PE1_H_PLL_FBKSEL                     GENMASK(5, 4)
  45
  46#define RG_PE1_H_LCDDS_SSC_PRD_REG              0x4a4
  47#define RG_PE1_H_LCDDS_SSC_PRD                  GENMASK(15, 0)
  48
  49#define RG_PE1_H_LCDDS_SSC_DELTA_REG            0x4a8
  50#define RG_PE1_H_LCDDS_SSC_DELTA                GENMASK(11, 0)
  51#define RG_PE1_H_LCDDS_SSC_DELTA1               GENMASK(27, 16)
  52
  53#define RG_PE1_LCDDS_CLK_PH_INV_REG             0x4a0
  54#define RG_PE1_LCDDS_CLK_PH_INV                 BIT(5)
  55
  56#define RG_PE1_H_PLL_BR_REG                     0x4ac
  57#define RG_PE1_H_PLL_BR                         GENMASK(18, 16)
  58
  59#define RG_PE1_MSTCKDIV_REG                     0x414
  60#define RG_PE1_MSTCKDIV                         GENMASK(7, 6)
  61
  62#define RG_PE1_FRC_MSTCKDIV                     BIT(5)
  63
  64#define MAX_PHYS        2
  65
  66/**
  67 * struct mt7621_pci_phy - Mt7621 Pcie PHY core
  68 * @dev: pointer to device
  69 * @regmap: kernel regmap pointer
  70 * @phy: pointer to the kernel PHY device
  71 * @sys_clk: pointer to the system XTAL clock
  72 * @port_base: base register
  73 * @has_dual_port: if the phy has dual ports.
  74 * @bypass_pipe_rst: mark if 'mt7621_bypass_pipe_rst'
  75 * needs to be executed. Depends on chip revision.
  76 */
  77struct mt7621_pci_phy {
  78        struct device *dev;
  79        struct regmap *regmap;
  80        struct phy *phy;
  81        struct clk *sys_clk;
  82        void __iomem *port_base;
  83        bool has_dual_port;
  84        bool bypass_pipe_rst;
  85};
  86
  87static inline void mt7621_phy_rmw(struct mt7621_pci_phy *phy,
  88                                  u32 reg, u32 clr, u32 set)
  89{
  90        u32 val;
  91
  92        /*
  93         * We cannot use 'regmap_write_bits' here because internally
  94         * 'set' is masked before is set to the value that will be
  95         * written to the register. That way results in no reliable
  96         * pci setup. Avoid to mask 'set' before set value to 'val'
  97         * completely avoid the problem.
  98         */
  99        regmap_read(phy->regmap, reg, &val);
 100        val &= ~clr;
 101        val |= set;
 102        regmap_write(phy->regmap, reg, val);
 103}
 104
 105static void mt7621_bypass_pipe_rst(struct mt7621_pci_phy *phy)
 106{
 107        mt7621_phy_rmw(phy, RG_PE1_PIPE_REG, 0, RG_PE1_PIPE_RST);
 108        mt7621_phy_rmw(phy, RG_PE1_PIPE_REG, 0, RG_PE1_PIPE_CMD_FRC);
 109
 110        if (phy->has_dual_port) {
 111                mt7621_phy_rmw(phy, RG_PE1_PIPE_REG + RG_P0_TO_P1_WIDTH,
 112                               0, RG_PE1_PIPE_RST);
 113                mt7621_phy_rmw(phy, RG_PE1_PIPE_REG + RG_P0_TO_P1_WIDTH,
 114                               0, RG_PE1_PIPE_CMD_FRC);
 115        }
 116}
 117
 118static int mt7621_set_phy_for_ssc(struct mt7621_pci_phy *phy)
 119{
 120        struct device *dev = phy->dev;
 121        unsigned long clk_rate;
 122
 123        clk_rate = clk_get_rate(phy->sys_clk);
 124        if (!clk_rate)
 125                return -EINVAL;
 126
 127        /* Set PCIe Port PHY to disable SSC */
 128        /* Debug Xtal Type */
 129        mt7621_phy_rmw(phy, RG_PE1_FRC_H_XTAL_REG,
 130                       RG_PE1_FRC_H_XTAL_TYPE | RG_PE1_H_XTAL_TYPE,
 131                       RG_PE1_FRC_H_XTAL_TYPE |
 132                       FIELD_PREP(RG_PE1_H_XTAL_TYPE, 0x00));
 133
 134        /* disable port */
 135        mt7621_phy_rmw(phy, RG_PE1_FRC_PHY_REG, RG_PE1_PHY_EN,
 136                       RG_PE1_FRC_PHY_EN);
 137
 138        if (phy->has_dual_port) {
 139                mt7621_phy_rmw(phy, RG_PE1_FRC_PHY_REG + RG_P0_TO_P1_WIDTH,
 140                               RG_PE1_PHY_EN, RG_PE1_FRC_PHY_EN);
 141        }
 142
 143        if (clk_rate == 40000000) { /* 40MHz Xtal */
 144                /* Set Pre-divider ratio (for host mode) */
 145                mt7621_phy_rmw(phy, RG_PE1_H_PLL_REG, RG_PE1_H_PLL_PREDIV,
 146                               FIELD_PREP(RG_PE1_H_PLL_PREDIV, 0x01));
 147
 148                dev_dbg(dev, "Xtal is 40MHz\n");
 149        } else if (clk_rate == 25000000) { /* 25MHz Xal */
 150                mt7621_phy_rmw(phy, RG_PE1_H_PLL_REG, RG_PE1_H_PLL_PREDIV,
 151                               FIELD_PREP(RG_PE1_H_PLL_PREDIV, 0x00));
 152
 153                /* Select feedback clock */
 154                mt7621_phy_rmw(phy, RG_PE1_H_PLL_FBKSEL_REG,
 155                               RG_PE1_H_PLL_FBKSEL,
 156                               FIELD_PREP(RG_PE1_H_PLL_FBKSEL, 0x01));
 157
 158                /* DDS NCPO PCW (for host mode) */
 159                mt7621_phy_rmw(phy, RG_PE1_H_LCDDS_SSC_PRD_REG,
 160                               RG_PE1_H_LCDDS_SSC_PRD,
 161                               FIELD_PREP(RG_PE1_H_LCDDS_SSC_PRD, 0x00));
 162
 163                /* DDS SSC dither period control */
 164                mt7621_phy_rmw(phy, RG_PE1_H_LCDDS_SSC_PRD_REG,
 165                               RG_PE1_H_LCDDS_SSC_PRD,
 166                               FIELD_PREP(RG_PE1_H_LCDDS_SSC_PRD, 0x18d));
 167
 168                /* DDS SSC dither amplitude control */
 169                mt7621_phy_rmw(phy, RG_PE1_H_LCDDS_SSC_DELTA_REG,
 170                               RG_PE1_H_LCDDS_SSC_DELTA |
 171                               RG_PE1_H_LCDDS_SSC_DELTA1,
 172                               FIELD_PREP(RG_PE1_H_LCDDS_SSC_DELTA, 0x4a) |
 173                               FIELD_PREP(RG_PE1_H_LCDDS_SSC_DELTA1, 0x4a));
 174
 175                dev_dbg(dev, "Xtal is 25MHz\n");
 176        } else { /* 20MHz Xtal */
 177                mt7621_phy_rmw(phy, RG_PE1_H_PLL_REG, RG_PE1_H_PLL_PREDIV,
 178                               FIELD_PREP(RG_PE1_H_PLL_PREDIV, 0x00));
 179
 180                dev_dbg(dev, "Xtal is 20MHz\n");
 181        }
 182
 183        /* DDS clock inversion */
 184        mt7621_phy_rmw(phy, RG_PE1_LCDDS_CLK_PH_INV_REG,
 185                       RG_PE1_LCDDS_CLK_PH_INV, RG_PE1_LCDDS_CLK_PH_INV);
 186
 187        /* Set PLL bits */
 188        mt7621_phy_rmw(phy, RG_PE1_H_PLL_REG,
 189                       RG_PE1_H_PLL_BC | RG_PE1_H_PLL_BP | RG_PE1_H_PLL_IR |
 190                       RG_PE1_H_PLL_IC | RG_PE1_PLL_DIVEN,
 191                       FIELD_PREP(RG_PE1_H_PLL_BC, 0x02) |
 192                       FIELD_PREP(RG_PE1_H_PLL_BP, 0x06) |
 193                       FIELD_PREP(RG_PE1_H_PLL_IR, 0x02) |
 194                       FIELD_PREP(RG_PE1_H_PLL_IC, 0x01) |
 195                       FIELD_PREP(RG_PE1_PLL_DIVEN, 0x02));
 196
 197        mt7621_phy_rmw(phy, RG_PE1_H_PLL_BR_REG, RG_PE1_H_PLL_BR,
 198                       FIELD_PREP(RG_PE1_H_PLL_BR, 0x00));
 199
 200        if (clk_rate == 40000000) { /* 40MHz Xtal */
 201                /* set force mode enable of da_pe1_mstckdiv */
 202                mt7621_phy_rmw(phy, RG_PE1_MSTCKDIV_REG,
 203                               RG_PE1_MSTCKDIV | RG_PE1_FRC_MSTCKDIV,
 204                               FIELD_PREP(RG_PE1_MSTCKDIV, 0x01) |
 205                               RG_PE1_FRC_MSTCKDIV);
 206        }
 207
 208        return 0;
 209}
 210
 211static int mt7621_pci_phy_init(struct phy *phy)
 212{
 213        struct mt7621_pci_phy *mphy = phy_get_drvdata(phy);
 214
 215        if (mphy->bypass_pipe_rst)
 216                mt7621_bypass_pipe_rst(mphy);
 217
 218        return mt7621_set_phy_for_ssc(mphy);
 219}
 220
 221static int mt7621_pci_phy_power_on(struct phy *phy)
 222{
 223        struct mt7621_pci_phy *mphy = phy_get_drvdata(phy);
 224
 225        /* Enable PHY and disable force mode */
 226        mt7621_phy_rmw(mphy, RG_PE1_FRC_PHY_REG,
 227                       RG_PE1_FRC_PHY_EN, RG_PE1_PHY_EN);
 228
 229        if (mphy->has_dual_port) {
 230                mt7621_phy_rmw(mphy, RG_PE1_FRC_PHY_REG + RG_P0_TO_P1_WIDTH,
 231                               RG_PE1_FRC_PHY_EN, RG_PE1_PHY_EN);
 232        }
 233
 234        return 0;
 235}
 236
 237static int mt7621_pci_phy_power_off(struct phy *phy)
 238{
 239        struct mt7621_pci_phy *mphy = phy_get_drvdata(phy);
 240
 241        /* Disable PHY */
 242        mt7621_phy_rmw(mphy, RG_PE1_FRC_PHY_REG,
 243                       RG_PE1_PHY_EN, RG_PE1_FRC_PHY_EN);
 244
 245        if (mphy->has_dual_port) {
 246                mt7621_phy_rmw(mphy, RG_PE1_FRC_PHY_REG + RG_P0_TO_P1_WIDTH,
 247                               RG_PE1_PHY_EN, RG_PE1_FRC_PHY_EN);
 248        }
 249
 250        return 0;
 251}
 252
 253static int mt7621_pci_phy_exit(struct phy *phy)
 254{
 255        return 0;
 256}
 257
 258static const struct phy_ops mt7621_pci_phy_ops = {
 259        .init           = mt7621_pci_phy_init,
 260        .exit           = mt7621_pci_phy_exit,
 261        .power_on       = mt7621_pci_phy_power_on,
 262        .power_off      = mt7621_pci_phy_power_off,
 263        .owner          = THIS_MODULE,
 264};
 265
 266static struct phy *mt7621_pcie_phy_of_xlate(struct device *dev,
 267                                            struct of_phandle_args *args)
 268{
 269        struct mt7621_pci_phy *mt7621_phy = dev_get_drvdata(dev);
 270
 271        if (WARN_ON(args->args[0] >= MAX_PHYS))
 272                return ERR_PTR(-ENODEV);
 273
 274        mt7621_phy->has_dual_port = args->args[0];
 275
 276        dev_dbg(dev, "PHY for 0x%px (dual port = %d)\n",
 277                mt7621_phy->port_base, mt7621_phy->has_dual_port);
 278
 279        return mt7621_phy->phy;
 280}
 281
 282static const struct soc_device_attribute mt7621_pci_quirks_match[] = {
 283        { .soc_id = "mt7621", .revision = "E2" }
 284};
 285
 286static const struct regmap_config mt7621_pci_phy_regmap_config = {
 287        .reg_bits = 32,
 288        .val_bits = 32,
 289        .reg_stride = 4,
 290        .max_register = 0x700,
 291};
 292
 293static int mt7621_pci_phy_probe(struct platform_device *pdev)
 294{
 295        struct device *dev = &pdev->dev;
 296        const struct soc_device_attribute *attr;
 297        struct phy_provider *provider;
 298        struct mt7621_pci_phy *phy;
 299
 300        phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
 301        if (!phy)
 302                return -ENOMEM;
 303
 304        attr = soc_device_match(mt7621_pci_quirks_match);
 305        if (attr)
 306                phy->bypass_pipe_rst = true;
 307
 308        phy->dev = dev;
 309        platform_set_drvdata(pdev, phy);
 310
 311        phy->port_base = devm_platform_ioremap_resource(pdev, 0);
 312        if (IS_ERR(phy->port_base)) {
 313                dev_err(dev, "failed to remap phy regs\n");
 314                return PTR_ERR(phy->port_base);
 315        }
 316
 317        phy->regmap = devm_regmap_init_mmio(phy->dev, phy->port_base,
 318                                            &mt7621_pci_phy_regmap_config);
 319        if (IS_ERR(phy->regmap))
 320                return PTR_ERR(phy->regmap);
 321
 322        phy->phy = devm_phy_create(dev, dev->of_node, &mt7621_pci_phy_ops);
 323        if (IS_ERR(phy->phy)) {
 324                dev_err(dev, "failed to create phy\n");
 325                return PTR_ERR(phy->phy);
 326        }
 327
 328        phy->sys_clk = devm_clk_get(dev, NULL);
 329        if (IS_ERR(phy->sys_clk)) {
 330                dev_err(dev, "failed to get phy clock\n");
 331                return PTR_ERR(phy->sys_clk);
 332        }
 333
 334        phy_set_drvdata(phy->phy, phy);
 335
 336        provider = devm_of_phy_provider_register(dev, mt7621_pcie_phy_of_xlate);
 337
 338        return PTR_ERR_OR_ZERO(provider);
 339}
 340
 341static const struct of_device_id mt7621_pci_phy_ids[] = {
 342        { .compatible = "mediatek,mt7621-pci-phy" },
 343        {},
 344};
 345MODULE_DEVICE_TABLE(of, mt7621_pci_phy_ids);
 346
 347static struct platform_driver mt7621_pci_phy_driver = {
 348        .probe = mt7621_pci_phy_probe,
 349        .driver = {
 350                .name = "mt7621-pci-phy",
 351                .of_match_table = mt7621_pci_phy_ids,
 352        },
 353};
 354
 355builtin_platform_driver(mt7621_pci_phy_driver);
 356
 357MODULE_AUTHOR("Sergio Paracuellos <sergio.paracuellos@gmail.com>");
 358MODULE_DESCRIPTION("MediaTek MT7621 PCIe PHY driver");
 359MODULE_LICENSE("GPL v2");
 360