0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/delay.h>
0009 #include <linux/device.h>
0010 #include <linux/init.h>
0011 #include <linux/interrupt.h>
0012 #include <linux/io.h>
0013 #include <linux/kernel.h>
0014 #include <linux/module.h>
0015 #include <linux/of.h>
0016 #include <linux/phy/phy.h>
0017 #include <linux/platform_device.h>
0018
0019 #define SATA_PCB_BANK_OFFSET 0x23c
0020 #define SATA_PCB_REG_OFFSET(ofs) ((ofs) * 4)
0021
0022 #define MAX_PORTS 2
0023
0024
0025 #define SATA_PCB_REG_28NM_SPACE_SIZE 0x1000
0026
0027
0028
0029
0030 #define SATA_PCB_REG_40NM_SPACE_SIZE 0x10
0031
0032
0033 #define SATA_PHY_CTRL_REG_28NM_SPACE_SIZE 0x8
0034
0035 enum brcm_sata_phy_version {
0036 BRCM_SATA_PHY_STB_16NM,
0037 BRCM_SATA_PHY_STB_28NM,
0038 BRCM_SATA_PHY_STB_40NM,
0039 BRCM_SATA_PHY_IPROC_NS2,
0040 BRCM_SATA_PHY_IPROC_NSP,
0041 BRCM_SATA_PHY_IPROC_SR,
0042 BRCM_SATA_PHY_DSL_28NM,
0043 };
0044
0045 enum brcm_sata_phy_rxaeq_mode {
0046 RXAEQ_MODE_OFF = 0,
0047 RXAEQ_MODE_AUTO,
0048 RXAEQ_MODE_MANUAL,
0049 };
0050
0051 static enum brcm_sata_phy_rxaeq_mode rxaeq_to_val(const char *m)
0052 {
0053 if (!strcmp(m, "auto"))
0054 return RXAEQ_MODE_AUTO;
0055 else if (!strcmp(m, "manual"))
0056 return RXAEQ_MODE_MANUAL;
0057 else
0058 return RXAEQ_MODE_OFF;
0059 }
0060
0061 struct brcm_sata_port {
0062 int portnum;
0063 struct phy *phy;
0064 struct brcm_sata_phy *phy_priv;
0065 bool ssc_en;
0066 enum brcm_sata_phy_rxaeq_mode rxaeq_mode;
0067 u32 rxaeq_val;
0068 u32 tx_amplitude_val;
0069 };
0070
0071 struct brcm_sata_phy {
0072 struct device *dev;
0073 void __iomem *phy_base;
0074 void __iomem *ctrl_base;
0075 enum brcm_sata_phy_version version;
0076
0077 struct brcm_sata_port phys[MAX_PORTS];
0078 };
0079
0080 enum sata_phy_regs {
0081 BLOCK0_REG_BANK = 0x000,
0082 BLOCK0_XGXSSTATUS = 0x81,
0083 BLOCK0_XGXSSTATUS_PLL_LOCK = BIT(12),
0084 BLOCK0_SPARE = 0x8d,
0085 BLOCK0_SPARE_OOB_CLK_SEL_MASK = 0x3,
0086 BLOCK0_SPARE_OOB_CLK_SEL_REFBY2 = 0x1,
0087
0088 BLOCK1_REG_BANK = 0x10,
0089 BLOCK1_TEST_TX = 0x83,
0090 BLOCK1_TEST_TX_AMP_SHIFT = 12,
0091
0092 PLL_REG_BANK_0 = 0x050,
0093 PLL_REG_BANK_0_PLLCONTROL_0 = 0x81,
0094 PLLCONTROL_0_FREQ_DET_RESTART = BIT(13),
0095 PLLCONTROL_0_FREQ_MONITOR = BIT(12),
0096 PLLCONTROL_0_SEQ_START = BIT(15),
0097 PLL_CAP_CHARGE_TIME = 0x83,
0098 PLL_VCO_CAL_THRESH = 0x84,
0099 PLL_CAP_CONTROL = 0x85,
0100 PLL_FREQ_DET_TIME = 0x86,
0101 PLL_ACTRL2 = 0x8b,
0102 PLL_ACTRL2_SELDIV_MASK = 0x1f,
0103 PLL_ACTRL2_SELDIV_SHIFT = 9,
0104 PLL_ACTRL6 = 0x86,
0105
0106 PLL1_REG_BANK = 0x060,
0107 PLL1_ACTRL2 = 0x82,
0108 PLL1_ACTRL3 = 0x83,
0109 PLL1_ACTRL4 = 0x84,
0110 PLL1_ACTRL5 = 0x85,
0111 PLL1_ACTRL6 = 0x86,
0112 PLL1_ACTRL7 = 0x87,
0113 PLL1_ACTRL8 = 0x88,
0114
0115 TX_REG_BANK = 0x070,
0116 TX_ACTRL0 = 0x80,
0117 TX_ACTRL0_TXPOL_FLIP = BIT(6),
0118 TX_ACTRL5 = 0x85,
0119 TX_ACTRL5_SSC_EN = BIT(11),
0120
0121 AEQRX_REG_BANK_0 = 0xd0,
0122 AEQ_CONTROL1 = 0x81,
0123 AEQ_CONTROL1_ENABLE = BIT(2),
0124 AEQ_CONTROL1_FREEZE = BIT(3),
0125 AEQ_FRC_EQ = 0x83,
0126 AEQ_FRC_EQ_FORCE = BIT(0),
0127 AEQ_FRC_EQ_FORCE_VAL = BIT(1),
0128 AEQ_RFZ_FRC_VAL = BIT(8),
0129 AEQRX_REG_BANK_1 = 0xe0,
0130 AEQRX_SLCAL0_CTRL0 = 0x82,
0131 AEQRX_SLCAL1_CTRL0 = 0x86,
0132
0133 OOB_REG_BANK = 0x150,
0134 OOB1_REG_BANK = 0x160,
0135 OOB_CTRL1 = 0x80,
0136 OOB_CTRL1_BURST_MAX_MASK = 0xf,
0137 OOB_CTRL1_BURST_MAX_SHIFT = 12,
0138 OOB_CTRL1_BURST_MIN_MASK = 0xf,
0139 OOB_CTRL1_BURST_MIN_SHIFT = 8,
0140 OOB_CTRL1_WAKE_IDLE_MAX_MASK = 0xf,
0141 OOB_CTRL1_WAKE_IDLE_MAX_SHIFT = 4,
0142 OOB_CTRL1_WAKE_IDLE_MIN_MASK = 0xf,
0143 OOB_CTRL1_WAKE_IDLE_MIN_SHIFT = 0,
0144 OOB_CTRL2 = 0x81,
0145 OOB_CTRL2_SEL_ENA_SHIFT = 15,
0146 OOB_CTRL2_SEL_ENA_RC_SHIFT = 14,
0147 OOB_CTRL2_RESET_IDLE_MAX_MASK = 0x3f,
0148 OOB_CTRL2_RESET_IDLE_MAX_SHIFT = 8,
0149 OOB_CTRL2_BURST_CNT_MASK = 0x3,
0150 OOB_CTRL2_BURST_CNT_SHIFT = 6,
0151 OOB_CTRL2_RESET_IDLE_MIN_MASK = 0x3f,
0152 OOB_CTRL2_RESET_IDLE_MIN_SHIFT = 0,
0153
0154 TXPMD_REG_BANK = 0x1a0,
0155 TXPMD_CONTROL1 = 0x81,
0156 TXPMD_CONTROL1_TX_SSC_EN_FRC = BIT(0),
0157 TXPMD_CONTROL1_TX_SSC_EN_FRC_VAL = BIT(1),
0158 TXPMD_TX_FREQ_CTRL_CONTROL1 = 0x82,
0159 TXPMD_TX_FREQ_CTRL_CONTROL2 = 0x83,
0160 TXPMD_TX_FREQ_CTRL_CONTROL2_FMIN_MASK = 0x3ff,
0161 TXPMD_TX_FREQ_CTRL_CONTROL3 = 0x84,
0162 TXPMD_TX_FREQ_CTRL_CONTROL3_FMAX_MASK = 0x3ff,
0163
0164 RXPMD_REG_BANK = 0x1c0,
0165 RXPMD_RX_CDR_CONTROL1 = 0x81,
0166 RXPMD_RX_PPM_VAL_MASK = 0x1ff,
0167 RXPMD_RXPMD_EN_FRC = BIT(12),
0168 RXPMD_RXPMD_EN_FRC_VAL = BIT(13),
0169 RXPMD_RX_CDR_CDR_PROP_BW = 0x82,
0170 RXPMD_G_CDR_PROP_BW_MASK = 0x7,
0171 RXPMD_G1_CDR_PROP_BW_SHIFT = 0,
0172 RXPMD_G2_CDR_PROP_BW_SHIFT = 3,
0173 RXPMD_G3_CDR_PROB_BW_SHIFT = 6,
0174 RXPMD_RX_CDR_CDR_ACQ_INTEG_BW = 0x83,
0175 RXPMD_G_CDR_ACQ_INT_BW_MASK = 0x7,
0176 RXPMD_G1_CDR_ACQ_INT_BW_SHIFT = 0,
0177 RXPMD_G2_CDR_ACQ_INT_BW_SHIFT = 3,
0178 RXPMD_G3_CDR_ACQ_INT_BW_SHIFT = 6,
0179 RXPMD_RX_CDR_CDR_LOCK_INTEG_BW = 0x84,
0180 RXPMD_G_CDR_LOCK_INT_BW_MASK = 0x7,
0181 RXPMD_G1_CDR_LOCK_INT_BW_SHIFT = 0,
0182 RXPMD_G2_CDR_LOCK_INT_BW_SHIFT = 3,
0183 RXPMD_G3_CDR_LOCK_INT_BW_SHIFT = 6,
0184 RXPMD_RX_FREQ_MON_CONTROL1 = 0x87,
0185 RXPMD_MON_CORRECT_EN = BIT(8),
0186 RXPMD_MON_MARGIN_VAL_MASK = 0xff,
0187 };
0188
0189 enum sata_phy_ctrl_regs {
0190 PHY_CTRL_1 = 0x0,
0191 PHY_CTRL_1_RESET = BIT(0),
0192 };
0193
0194 static inline void __iomem *brcm_sata_ctrl_base(struct brcm_sata_port *port)
0195 {
0196 struct brcm_sata_phy *priv = port->phy_priv;
0197 u32 size = 0;
0198
0199 switch (priv->version) {
0200 case BRCM_SATA_PHY_IPROC_NS2:
0201 size = SATA_PHY_CTRL_REG_28NM_SPACE_SIZE;
0202 break;
0203 default:
0204 dev_err(priv->dev, "invalid phy version\n");
0205 break;
0206 }
0207
0208 return priv->ctrl_base + (port->portnum * size);
0209 }
0210
0211 static void brcm_sata_phy_wr(struct brcm_sata_port *port, u32 bank,
0212 u32 ofs, u32 msk, u32 value)
0213 {
0214 struct brcm_sata_phy *priv = port->phy_priv;
0215 void __iomem *pcb_base = priv->phy_base;
0216 u32 tmp;
0217
0218 if (priv->version == BRCM_SATA_PHY_STB_40NM)
0219 bank += (port->portnum * SATA_PCB_REG_40NM_SPACE_SIZE);
0220 else
0221 pcb_base += (port->portnum * SATA_PCB_REG_28NM_SPACE_SIZE);
0222
0223 writel(bank, pcb_base + SATA_PCB_BANK_OFFSET);
0224 tmp = readl(pcb_base + SATA_PCB_REG_OFFSET(ofs));
0225 tmp = (tmp & msk) | value;
0226 writel(tmp, pcb_base + SATA_PCB_REG_OFFSET(ofs));
0227 }
0228
0229 static u32 brcm_sata_phy_rd(struct brcm_sata_port *port, u32 bank, u32 ofs)
0230 {
0231 struct brcm_sata_phy *priv = port->phy_priv;
0232 void __iomem *pcb_base = priv->phy_base;
0233
0234 if (priv->version == BRCM_SATA_PHY_STB_40NM)
0235 bank += (port->portnum * SATA_PCB_REG_40NM_SPACE_SIZE);
0236 else
0237 pcb_base += (port->portnum * SATA_PCB_REG_28NM_SPACE_SIZE);
0238
0239 writel(bank, pcb_base + SATA_PCB_BANK_OFFSET);
0240 return readl(pcb_base + SATA_PCB_REG_OFFSET(ofs));
0241 }
0242
0243
0244 #define STB_FMIN_VAL_DEFAULT 0x3df
0245 #define STB_FMAX_VAL_DEFAULT 0x3df
0246 #define STB_FMAX_VAL_SSC 0x83
0247
0248 static void brcm_stb_sata_ssc_init(struct brcm_sata_port *port)
0249 {
0250 struct brcm_sata_phy *priv = port->phy_priv;
0251 u32 tmp;
0252
0253
0254 tmp = TXPMD_CONTROL1_TX_SSC_EN_FRC_VAL | TXPMD_CONTROL1_TX_SSC_EN_FRC;
0255 brcm_sata_phy_wr(port, TXPMD_REG_BANK, TXPMD_CONTROL1, ~tmp, tmp);
0256
0257
0258 brcm_sata_phy_wr(port, TXPMD_REG_BANK, TXPMD_TX_FREQ_CTRL_CONTROL2,
0259 ~TXPMD_TX_FREQ_CTRL_CONTROL2_FMIN_MASK,
0260 STB_FMIN_VAL_DEFAULT);
0261
0262
0263 if (port->ssc_en) {
0264 dev_info(priv->dev, "enabling SSC on port%d\n", port->portnum);
0265 tmp = STB_FMAX_VAL_SSC;
0266 } else {
0267 tmp = STB_FMAX_VAL_DEFAULT;
0268 }
0269
0270 brcm_sata_phy_wr(port, TXPMD_REG_BANK, TXPMD_TX_FREQ_CTRL_CONTROL3,
0271 ~TXPMD_TX_FREQ_CTRL_CONTROL3_FMAX_MASK, tmp);
0272 }
0273
0274 #define AEQ_FRC_EQ_VAL_SHIFT 2
0275 #define AEQ_FRC_EQ_VAL_MASK 0x3f
0276
0277 static int brcm_stb_sata_rxaeq_init(struct brcm_sata_port *port)
0278 {
0279 u32 tmp = 0, reg = 0;
0280
0281 switch (port->rxaeq_mode) {
0282 case RXAEQ_MODE_OFF:
0283 return 0;
0284
0285 case RXAEQ_MODE_AUTO:
0286 reg = AEQ_CONTROL1;
0287 tmp = AEQ_CONTROL1_ENABLE | AEQ_CONTROL1_FREEZE;
0288 break;
0289
0290 case RXAEQ_MODE_MANUAL:
0291 reg = AEQ_FRC_EQ;
0292 tmp = AEQ_FRC_EQ_FORCE | AEQ_FRC_EQ_FORCE_VAL;
0293 if (port->rxaeq_val > AEQ_FRC_EQ_VAL_MASK)
0294 return -EINVAL;
0295 tmp |= port->rxaeq_val << AEQ_FRC_EQ_VAL_SHIFT;
0296 break;
0297 }
0298
0299 brcm_sata_phy_wr(port, AEQRX_REG_BANK_0, reg, ~tmp, tmp);
0300 brcm_sata_phy_wr(port, AEQRX_REG_BANK_1, reg, ~tmp, tmp);
0301
0302 return 0;
0303 }
0304
0305 static int brcm_stb_sata_init(struct brcm_sata_port *port)
0306 {
0307 brcm_stb_sata_ssc_init(port);
0308
0309 return brcm_stb_sata_rxaeq_init(port);
0310 }
0311
0312 static int brcm_stb_sata_16nm_ssc_init(struct brcm_sata_port *port)
0313 {
0314 u32 tmp, value;
0315
0316
0317 brcm_sata_phy_wr(port, PLL1_REG_BANK, PLL1_ACTRL6, 0, 0x141);
0318
0319
0320 brcm_sata_phy_wr(port, PLL1_REG_BANK, PLL1_ACTRL8, 0, 0xc006);
0321
0322
0323 tmp = AEQ_FRC_EQ_FORCE_VAL | AEQ_FRC_EQ_FORCE;
0324 brcm_sata_phy_wr(port, AEQRX_REG_BANK_0, AEQ_FRC_EQ,
0325 ~(tmp | AEQ_RFZ_FRC_VAL |
0326 AEQ_FRC_EQ_VAL_MASK << AEQ_FRC_EQ_VAL_SHIFT),
0327 tmp | 32 << AEQ_FRC_EQ_VAL_SHIFT);
0328
0329
0330 if (port->ssc_en)
0331 value = 0x52;
0332 else
0333 value = 0;
0334 brcm_sata_phy_wr(port, RXPMD_REG_BANK, RXPMD_RX_CDR_CONTROL1,
0335 ~RXPMD_RX_PPM_VAL_MASK, value);
0336
0337
0338 tmp = RXPMD_G_CDR_PROP_BW_MASK << RXPMD_G1_CDR_PROP_BW_SHIFT |
0339 RXPMD_G_CDR_PROP_BW_MASK << RXPMD_G2_CDR_PROP_BW_SHIFT |
0340 RXPMD_G_CDR_PROP_BW_MASK << RXPMD_G3_CDR_PROB_BW_SHIFT;
0341 if (port->ssc_en)
0342 value = 2 << RXPMD_G1_CDR_PROP_BW_SHIFT |
0343 2 << RXPMD_G2_CDR_PROP_BW_SHIFT |
0344 2 << RXPMD_G3_CDR_PROB_BW_SHIFT;
0345 else
0346 value = 1 << RXPMD_G1_CDR_PROP_BW_SHIFT |
0347 1 << RXPMD_G2_CDR_PROP_BW_SHIFT |
0348 1 << RXPMD_G3_CDR_PROB_BW_SHIFT;
0349 brcm_sata_phy_wr(port, RXPMD_REG_BANK, RXPMD_RX_CDR_CDR_PROP_BW, ~tmp,
0350 value);
0351
0352
0353 tmp = RXPMD_G_CDR_ACQ_INT_BW_MASK << RXPMD_G1_CDR_ACQ_INT_BW_SHIFT |
0354 RXPMD_G_CDR_ACQ_INT_BW_MASK << RXPMD_G2_CDR_ACQ_INT_BW_SHIFT |
0355 RXPMD_G_CDR_ACQ_INT_BW_MASK << RXPMD_G3_CDR_ACQ_INT_BW_SHIFT;
0356 if (port->ssc_en)
0357 value = 1 << RXPMD_G1_CDR_ACQ_INT_BW_SHIFT |
0358 1 << RXPMD_G2_CDR_ACQ_INT_BW_SHIFT |
0359 1 << RXPMD_G3_CDR_ACQ_INT_BW_SHIFT;
0360 else
0361 value = 0;
0362 brcm_sata_phy_wr(port, RXPMD_REG_BANK, RXPMD_RX_CDR_CDR_ACQ_INTEG_BW,
0363 ~tmp, value);
0364
0365
0366 tmp = RXPMD_G_CDR_LOCK_INT_BW_MASK << RXPMD_G1_CDR_LOCK_INT_BW_SHIFT |
0367 RXPMD_G_CDR_LOCK_INT_BW_MASK << RXPMD_G2_CDR_LOCK_INT_BW_SHIFT |
0368 RXPMD_G_CDR_LOCK_INT_BW_MASK << RXPMD_G3_CDR_LOCK_INT_BW_SHIFT;
0369 if (port->ssc_en)
0370 value = 1 << RXPMD_G1_CDR_LOCK_INT_BW_SHIFT |
0371 1 << RXPMD_G2_CDR_LOCK_INT_BW_SHIFT |
0372 1 << RXPMD_G3_CDR_LOCK_INT_BW_SHIFT;
0373 else
0374 value = 0;
0375 brcm_sata_phy_wr(port, RXPMD_REG_BANK, RXPMD_RX_CDR_CDR_LOCK_INTEG_BW,
0376 ~tmp, value);
0377
0378
0379 tmp = RXPMD_MON_CORRECT_EN | RXPMD_MON_MARGIN_VAL_MASK;
0380 if (port->ssc_en)
0381 value = 0x51;
0382 else
0383 value = 0;
0384 brcm_sata_phy_wr(port, RXPMD_REG_BANK, RXPMD_RX_FREQ_MON_CONTROL1,
0385 ~tmp, RXPMD_MON_CORRECT_EN | value);
0386
0387 tmp = GENMASK(15, 12);
0388 switch (port->tx_amplitude_val) {
0389 case 400:
0390 value = BIT(12) | BIT(13);
0391 break;
0392 case 500:
0393 value = BIT(13);
0394 break;
0395 case 600:
0396 value = BIT(12);
0397 break;
0398 case 800:
0399 value = 0;
0400 break;
0401 default:
0402 value = tmp;
0403 break;
0404 }
0405
0406 if (value != tmp)
0407 brcm_sata_phy_wr(port, BLOCK1_REG_BANK, BLOCK1_TEST_TX, ~tmp,
0408 value);
0409
0410
0411 brcm_sata_phy_wr(port, TX_REG_BANK, TX_ACTRL5, ~TX_ACTRL5_SSC_EN,
0412 port->ssc_en ? TX_ACTRL5_SSC_EN : 0);
0413
0414 return 0;
0415 }
0416
0417 static int brcm_stb_sata_16nm_init(struct brcm_sata_port *port)
0418 {
0419 return brcm_stb_sata_16nm_ssc_init(port);
0420 }
0421
0422
0423 #define NS2_PLL1_ACTRL2_MAGIC 0x1df8
0424 #define NS2_PLL1_ACTRL3_MAGIC 0x2b00
0425 #define NS2_PLL1_ACTRL4_MAGIC 0x8824
0426
0427 static int brcm_ns2_sata_init(struct brcm_sata_port *port)
0428 {
0429 int try;
0430 unsigned int val;
0431 void __iomem *ctrl_base = brcm_sata_ctrl_base(port);
0432 struct device *dev = port->phy_priv->dev;
0433
0434
0435 val = 0x0;
0436 val |= (0xc << OOB_CTRL1_BURST_MAX_SHIFT);
0437 val |= (0x4 << OOB_CTRL1_BURST_MIN_SHIFT);
0438 val |= (0x9 << OOB_CTRL1_WAKE_IDLE_MAX_SHIFT);
0439 val |= (0x3 << OOB_CTRL1_WAKE_IDLE_MIN_SHIFT);
0440 brcm_sata_phy_wr(port, OOB_REG_BANK, OOB_CTRL1, 0x0, val);
0441 val = 0x0;
0442 val |= (0x1b << OOB_CTRL2_RESET_IDLE_MAX_SHIFT);
0443 val |= (0x2 << OOB_CTRL2_BURST_CNT_SHIFT);
0444 val |= (0x9 << OOB_CTRL2_RESET_IDLE_MIN_SHIFT);
0445 brcm_sata_phy_wr(port, OOB_REG_BANK, OOB_CTRL2, 0x0, val);
0446
0447
0448 val = NS2_PLL1_ACTRL2_MAGIC;
0449 brcm_sata_phy_wr(port, PLL1_REG_BANK, PLL1_ACTRL2, 0x0, val);
0450 val = NS2_PLL1_ACTRL3_MAGIC;
0451 brcm_sata_phy_wr(port, PLL1_REG_BANK, PLL1_ACTRL3, 0x0, val);
0452 val = NS2_PLL1_ACTRL4_MAGIC;
0453 brcm_sata_phy_wr(port, PLL1_REG_BANK, PLL1_ACTRL4, 0x0, val);
0454
0455
0456
0457 brcm_sata_phy_wr(port, BLOCK0_REG_BANK, BLOCK0_SPARE,
0458 ~BLOCK0_SPARE_OOB_CLK_SEL_MASK,
0459 BLOCK0_SPARE_OOB_CLK_SEL_REFBY2);
0460
0461
0462 writel(PHY_CTRL_1_RESET, ctrl_base + PHY_CTRL_1);
0463 mdelay(1);
0464 writel(0x0, ctrl_base + PHY_CTRL_1);
0465 mdelay(1);
0466
0467
0468 try = 50;
0469 while (try) {
0470 val = brcm_sata_phy_rd(port, BLOCK0_REG_BANK,
0471 BLOCK0_XGXSSTATUS);
0472 if (val & BLOCK0_XGXSSTATUS_PLL_LOCK)
0473 break;
0474 msleep(20);
0475 try--;
0476 }
0477 if (!try) {
0478
0479 dev_err(dev, "port%d PLL did not lock\n", port->portnum);
0480 return -ETIMEDOUT;
0481 }
0482
0483 dev_dbg(dev, "port%d initialized\n", port->portnum);
0484
0485 return 0;
0486 }
0487
0488 static int brcm_nsp_sata_init(struct brcm_sata_port *port)
0489 {
0490 struct device *dev = port->phy_priv->dev;
0491 unsigned int oob_bank;
0492 unsigned int val, try;
0493
0494
0495 if (port->portnum == 0)
0496 oob_bank = OOB_REG_BANK;
0497 else if (port->portnum == 1)
0498 oob_bank = OOB1_REG_BANK;
0499 else
0500 return -EINVAL;
0501
0502 val = 0x0;
0503 val |= (0x0f << OOB_CTRL1_BURST_MAX_SHIFT);
0504 val |= (0x06 << OOB_CTRL1_BURST_MIN_SHIFT);
0505 val |= (0x0f << OOB_CTRL1_WAKE_IDLE_MAX_SHIFT);
0506 val |= (0x06 << OOB_CTRL1_WAKE_IDLE_MIN_SHIFT);
0507 brcm_sata_phy_wr(port, oob_bank, OOB_CTRL1, 0x0, val);
0508
0509 val = 0x0;
0510 val |= (0x2e << OOB_CTRL2_RESET_IDLE_MAX_SHIFT);
0511 val |= (0x02 << OOB_CTRL2_BURST_CNT_SHIFT);
0512 val |= (0x16 << OOB_CTRL2_RESET_IDLE_MIN_SHIFT);
0513 brcm_sata_phy_wr(port, oob_bank, OOB_CTRL2, 0x0, val);
0514
0515
0516 brcm_sata_phy_wr(port, PLL_REG_BANK_0, PLL_ACTRL2,
0517 ~(PLL_ACTRL2_SELDIV_MASK << PLL_ACTRL2_SELDIV_SHIFT),
0518 0x0c << PLL_ACTRL2_SELDIV_SHIFT);
0519
0520 brcm_sata_phy_wr(port, PLL_REG_BANK_0, PLL_CAP_CONTROL,
0521 0xff0, 0x4f0);
0522
0523 val = PLLCONTROL_0_FREQ_DET_RESTART | PLLCONTROL_0_FREQ_MONITOR;
0524 brcm_sata_phy_wr(port, PLL_REG_BANK_0, PLL_REG_BANK_0_PLLCONTROL_0,
0525 ~val, val);
0526 val = PLLCONTROL_0_SEQ_START;
0527 brcm_sata_phy_wr(port, PLL_REG_BANK_0, PLL_REG_BANK_0_PLLCONTROL_0,
0528 ~val, 0);
0529 mdelay(10);
0530 brcm_sata_phy_wr(port, PLL_REG_BANK_0, PLL_REG_BANK_0_PLLCONTROL_0,
0531 ~val, val);
0532
0533
0534 try = 50;
0535 while (--try) {
0536 val = brcm_sata_phy_rd(port, BLOCK0_REG_BANK,
0537 BLOCK0_XGXSSTATUS);
0538 if (val & BLOCK0_XGXSSTATUS_PLL_LOCK)
0539 break;
0540 msleep(20);
0541 }
0542 if (!try) {
0543
0544 dev_err(dev, "port%d PLL did not lock\n", port->portnum);
0545 return -ETIMEDOUT;
0546 }
0547
0548 dev_dbg(dev, "port%d initialized\n", port->portnum);
0549
0550 return 0;
0551 }
0552
0553
0554 #define SR_PLL0_ACTRL6_MAGIC 0xa
0555
0556
0557 #define SR_PLL1_ACTRL2_MAGIC 0x32
0558 #define SR_PLL1_ACTRL3_MAGIC 0x2
0559 #define SR_PLL1_ACTRL4_MAGIC 0x3e8
0560
0561 static int brcm_sr_sata_init(struct brcm_sata_port *port)
0562 {
0563 struct device *dev = port->phy_priv->dev;
0564 unsigned int val, try;
0565
0566
0567 val = SR_PLL1_ACTRL2_MAGIC;
0568 brcm_sata_phy_wr(port, PLL1_REG_BANK, PLL1_ACTRL2, 0x0, val);
0569 val = SR_PLL1_ACTRL3_MAGIC;
0570 brcm_sata_phy_wr(port, PLL1_REG_BANK, PLL1_ACTRL3, 0x0, val);
0571 val = SR_PLL1_ACTRL4_MAGIC;
0572 brcm_sata_phy_wr(port, PLL1_REG_BANK, PLL1_ACTRL4, 0x0, val);
0573
0574
0575 val = SR_PLL0_ACTRL6_MAGIC;
0576 brcm_sata_phy_wr(port, PLL_REG_BANK_0, PLL_ACTRL6, 0x0, val);
0577
0578
0579 try = 50;
0580 do {
0581 val = brcm_sata_phy_rd(port, BLOCK0_REG_BANK,
0582 BLOCK0_XGXSSTATUS);
0583 if (val & BLOCK0_XGXSSTATUS_PLL_LOCK)
0584 break;
0585 msleep(20);
0586 try--;
0587 } while (try);
0588
0589 if ((val & BLOCK0_XGXSSTATUS_PLL_LOCK) == 0) {
0590
0591 dev_err(dev, "port%d PLL did not lock\n", port->portnum);
0592 return -ETIMEDOUT;
0593 }
0594
0595
0596 brcm_sata_phy_wr(port, TX_REG_BANK, TX_ACTRL0,
0597 ~TX_ACTRL0_TXPOL_FLIP, TX_ACTRL0_TXPOL_FLIP);
0598
0599
0600 val = ((0xc << OOB_CTRL1_BURST_MAX_SHIFT) |
0601 (0x4 << OOB_CTRL1_BURST_MIN_SHIFT) |
0602 (0x8 << OOB_CTRL1_WAKE_IDLE_MAX_SHIFT) |
0603 (0x3 << OOB_CTRL1_WAKE_IDLE_MIN_SHIFT));
0604 brcm_sata_phy_wr(port, OOB_REG_BANK, OOB_CTRL1, 0x0, val);
0605 val = ((0x1b << OOB_CTRL2_RESET_IDLE_MAX_SHIFT) |
0606 (0x2 << OOB_CTRL2_BURST_CNT_SHIFT) |
0607 (0x9 << OOB_CTRL2_RESET_IDLE_MIN_SHIFT));
0608 brcm_sata_phy_wr(port, OOB_REG_BANK, OOB_CTRL2, 0x0, val);
0609
0610 return 0;
0611 }
0612
0613 static int brcm_dsl_sata_init(struct brcm_sata_port *port)
0614 {
0615 struct device *dev = port->phy_priv->dev;
0616 unsigned int try;
0617 u32 tmp;
0618
0619 brcm_sata_phy_wr(port, PLL1_REG_BANK, PLL1_ACTRL7, 0, 0x873);
0620
0621 brcm_sata_phy_wr(port, PLL1_REG_BANK, PLL1_ACTRL6, 0, 0xc000);
0622
0623 brcm_sata_phy_wr(port, PLL_REG_BANK_0, PLL_REG_BANK_0_PLLCONTROL_0,
0624 0, 0x3089);
0625 usleep_range(1000, 2000);
0626
0627 brcm_sata_phy_wr(port, PLL_REG_BANK_0, PLL_REG_BANK_0_PLLCONTROL_0,
0628 0, 0x3088);
0629 usleep_range(1000, 2000);
0630
0631 brcm_sata_phy_wr(port, AEQRX_REG_BANK_1, AEQRX_SLCAL0_CTRL0,
0632 0, 0x3000);
0633
0634 brcm_sata_phy_wr(port, AEQRX_REG_BANK_1, AEQRX_SLCAL1_CTRL0,
0635 0, 0x3000);
0636 usleep_range(1000, 2000);
0637
0638 brcm_sata_phy_wr(port, PLL_REG_BANK_0, PLL_CAP_CHARGE_TIME, 0, 0x32);
0639
0640 brcm_sata_phy_wr(port, PLL_REG_BANK_0, PLL_VCO_CAL_THRESH, 0, 0xa);
0641
0642 brcm_sata_phy_wr(port, PLL_REG_BANK_0, PLL_FREQ_DET_TIME, 0, 0x64);
0643 usleep_range(1000, 2000);
0644
0645
0646 try = 50;
0647 while (try) {
0648 tmp = brcm_sata_phy_rd(port, BLOCK0_REG_BANK,
0649 BLOCK0_XGXSSTATUS);
0650 if (tmp & BLOCK0_XGXSSTATUS_PLL_LOCK)
0651 break;
0652 msleep(20);
0653 try--;
0654 }
0655
0656 if (!try) {
0657
0658 dev_err(dev, "port%d PLL did not lock\n", port->portnum);
0659 return -ETIMEDOUT;
0660 }
0661
0662 dev_dbg(dev, "port%d initialized\n", port->portnum);
0663
0664 return 0;
0665 }
0666
0667 static int brcm_sata_phy_init(struct phy *phy)
0668 {
0669 int rc;
0670 struct brcm_sata_port *port = phy_get_drvdata(phy);
0671
0672 switch (port->phy_priv->version) {
0673 case BRCM_SATA_PHY_STB_16NM:
0674 rc = brcm_stb_sata_16nm_init(port);
0675 break;
0676 case BRCM_SATA_PHY_STB_28NM:
0677 case BRCM_SATA_PHY_STB_40NM:
0678 rc = brcm_stb_sata_init(port);
0679 break;
0680 case BRCM_SATA_PHY_IPROC_NS2:
0681 rc = brcm_ns2_sata_init(port);
0682 break;
0683 case BRCM_SATA_PHY_IPROC_NSP:
0684 rc = brcm_nsp_sata_init(port);
0685 break;
0686 case BRCM_SATA_PHY_IPROC_SR:
0687 rc = brcm_sr_sata_init(port);
0688 break;
0689 case BRCM_SATA_PHY_DSL_28NM:
0690 rc = brcm_dsl_sata_init(port);
0691 break;
0692 default:
0693 rc = -ENODEV;
0694 }
0695
0696 return rc;
0697 }
0698
0699 static void brcm_stb_sata_calibrate(struct brcm_sata_port *port)
0700 {
0701 u32 tmp = BIT(8);
0702
0703 brcm_sata_phy_wr(port, RXPMD_REG_BANK, RXPMD_RX_FREQ_MON_CONTROL1,
0704 ~tmp, tmp);
0705 }
0706
0707 static int brcm_sata_phy_calibrate(struct phy *phy)
0708 {
0709 struct brcm_sata_port *port = phy_get_drvdata(phy);
0710 int rc = -EOPNOTSUPP;
0711
0712 switch (port->phy_priv->version) {
0713 case BRCM_SATA_PHY_STB_28NM:
0714 case BRCM_SATA_PHY_STB_40NM:
0715 brcm_stb_sata_calibrate(port);
0716 rc = 0;
0717 break;
0718 default:
0719 break;
0720 }
0721
0722 return rc;
0723 }
0724
0725 static const struct phy_ops phy_ops = {
0726 .init = brcm_sata_phy_init,
0727 .calibrate = brcm_sata_phy_calibrate,
0728 .owner = THIS_MODULE,
0729 };
0730
0731 static const struct of_device_id brcm_sata_phy_of_match[] = {
0732 { .compatible = "brcm,bcm7216-sata-phy",
0733 .data = (void *)BRCM_SATA_PHY_STB_16NM },
0734 { .compatible = "brcm,bcm7445-sata-phy",
0735 .data = (void *)BRCM_SATA_PHY_STB_28NM },
0736 { .compatible = "brcm,bcm7425-sata-phy",
0737 .data = (void *)BRCM_SATA_PHY_STB_40NM },
0738 { .compatible = "brcm,iproc-ns2-sata-phy",
0739 .data = (void *)BRCM_SATA_PHY_IPROC_NS2 },
0740 { .compatible = "brcm,iproc-nsp-sata-phy",
0741 .data = (void *)BRCM_SATA_PHY_IPROC_NSP },
0742 { .compatible = "brcm,iproc-sr-sata-phy",
0743 .data = (void *)BRCM_SATA_PHY_IPROC_SR },
0744 { .compatible = "brcm,bcm63138-sata-phy",
0745 .data = (void *)BRCM_SATA_PHY_DSL_28NM },
0746 {},
0747 };
0748 MODULE_DEVICE_TABLE(of, brcm_sata_phy_of_match);
0749
0750 static int brcm_sata_phy_probe(struct platform_device *pdev)
0751 {
0752 const char *rxaeq_mode;
0753 struct device *dev = &pdev->dev;
0754 struct device_node *dn = dev->of_node, *child;
0755 const struct of_device_id *of_id;
0756 struct brcm_sata_phy *priv;
0757 struct phy_provider *provider;
0758 int ret, count = 0;
0759
0760 if (of_get_child_count(dn) == 0)
0761 return -ENODEV;
0762
0763 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
0764 if (!priv)
0765 return -ENOMEM;
0766 dev_set_drvdata(dev, priv);
0767 priv->dev = dev;
0768
0769 priv->phy_base = devm_platform_ioremap_resource_byname(pdev, "phy");
0770 if (IS_ERR(priv->phy_base))
0771 return PTR_ERR(priv->phy_base);
0772
0773 of_id = of_match_node(brcm_sata_phy_of_match, dn);
0774 if (of_id)
0775 priv->version = (enum brcm_sata_phy_version)of_id->data;
0776 else
0777 priv->version = BRCM_SATA_PHY_STB_28NM;
0778
0779 if (priv->version == BRCM_SATA_PHY_IPROC_NS2) {
0780 priv->ctrl_base = devm_platform_ioremap_resource_byname(pdev, "phy-ctrl");
0781 if (IS_ERR(priv->ctrl_base))
0782 return PTR_ERR(priv->ctrl_base);
0783 }
0784
0785 for_each_available_child_of_node(dn, child) {
0786 unsigned int id;
0787 struct brcm_sata_port *port;
0788
0789 if (of_property_read_u32(child, "reg", &id)) {
0790 dev_err(dev, "missing reg property in node %pOFn\n",
0791 child);
0792 ret = -EINVAL;
0793 goto put_child;
0794 }
0795
0796 if (id >= MAX_PORTS) {
0797 dev_err(dev, "invalid reg: %u\n", id);
0798 ret = -EINVAL;
0799 goto put_child;
0800 }
0801 if (priv->phys[id].phy) {
0802 dev_err(dev, "already registered port %u\n", id);
0803 ret = -EINVAL;
0804 goto put_child;
0805 }
0806
0807 port = &priv->phys[id];
0808 port->portnum = id;
0809 port->phy_priv = priv;
0810 port->phy = devm_phy_create(dev, child, &phy_ops);
0811 port->rxaeq_mode = RXAEQ_MODE_OFF;
0812 if (!of_property_read_string(child, "brcm,rxaeq-mode",
0813 &rxaeq_mode))
0814 port->rxaeq_mode = rxaeq_to_val(rxaeq_mode);
0815 if (port->rxaeq_mode == RXAEQ_MODE_MANUAL)
0816 of_property_read_u32(child, "brcm,rxaeq-value",
0817 &port->rxaeq_val);
0818
0819 of_property_read_u32(child, "brcm,tx-amplitude-millivolt",
0820 &port->tx_amplitude_val);
0821
0822 port->ssc_en = of_property_read_bool(child, "brcm,enable-ssc");
0823 if (IS_ERR(port->phy)) {
0824 dev_err(dev, "failed to create PHY\n");
0825 ret = PTR_ERR(port->phy);
0826 goto put_child;
0827 }
0828
0829 phy_set_drvdata(port->phy, port);
0830 count++;
0831 }
0832
0833 provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
0834 if (IS_ERR(provider)) {
0835 dev_err(dev, "could not register PHY provider\n");
0836 return PTR_ERR(provider);
0837 }
0838
0839 dev_info(dev, "registered %d port(s)\n", count);
0840
0841 return 0;
0842 put_child:
0843 of_node_put(child);
0844 return ret;
0845 }
0846
0847 static struct platform_driver brcm_sata_phy_driver = {
0848 .probe = brcm_sata_phy_probe,
0849 .driver = {
0850 .of_match_table = brcm_sata_phy_of_match,
0851 .name = "brcm-sata-phy",
0852 }
0853 };
0854 module_platform_driver(brcm_sata_phy_driver);
0855
0856 MODULE_DESCRIPTION("Broadcom SATA PHY driver");
0857 MODULE_LICENSE("GPL");
0858 MODULE_AUTHOR("Marc Carino");
0859 MODULE_AUTHOR("Brian Norris");
0860 MODULE_ALIAS("platform:phy-brcm-sata");