Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

phy: Add support for NS2 SATA3 PHY in Broadcom SATA3 PHY driver

This patch adds support for Broadcom NS2 SATA3 PHY in existing
Broadcom SATA3 PHY driver.

Signed-off-by: Anup Patel <anup.patel@broadcom.com>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>

authored by

Anup Patel and committed by
Kishon Vijay Abraham I
4faee9a4 037c4189

+211 -48
+10 -9
drivers/phy/Kconfig
··· 403 403 help 404 404 Support for TI TUSB1210 USB ULPI PHY. 405 405 406 - config PHY_CYGNUS_PCIE 407 - tristate "Broadcom Cygnus PCIe PHY driver" 408 - depends on OF && (ARCH_BCM_CYGNUS || COMPILE_TEST) 409 - select GENERIC_PHY 410 - default ARCH_BCM_CYGNUS 411 - help 412 - Enable this to support the Broadcom Cygnus PCIe PHY. 413 - If unsure, say N. 414 - 415 406 config PHY_BRCM_SATA 416 407 tristate "Broadcom SATA PHY driver" 417 408 depends on ARCH_BRCMSTB || ARCH_BCM_IPROC || BMIPS_GENERIC || COMPILE_TEST ··· 412 421 help 413 422 Enable this to support the Broadcom SATA PHY. 414 423 If unsure, say N. 424 + 425 + config PHY_CYGNUS_PCIE 426 + tristate "Broadcom Cygnus PCIe PHY driver" 427 + depends on OF && (ARCH_BCM_CYGNUS || COMPILE_TEST) 428 + select GENERIC_PHY 429 + default ARCH_BCM_CYGNUS 430 + help 431 + Enable this to support the Broadcom Cygnus PCIe PHY. 432 + If unsure, say N. 433 + 415 434 endmenu
+1 -1
drivers/phy/Makefile
··· 49 49 obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-20nm.o 50 50 obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-14nm.o 51 51 obj-$(CONFIG_PHY_TUSB1210) += phy-tusb1210.o 52 + obj-$(CONFIG_PHY_BRCM_SATA) += phy-brcm-sata.o 52 53 obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o 53 54 obj-$(CONFIG_PHY_CYGNUS_PCIE) += phy-bcm-cygnus-pcie.o 54 - obj-$(CONFIG_PHY_BRCM_SATA) += phy-brcm-sata.o
+200 -38
drivers/phy/phy-brcm-sata.c
··· 14 14 * GNU General Public License for more details. 15 15 */ 16 16 17 + #include <linux/delay.h> 17 18 #include <linux/device.h> 18 19 #include <linux/init.h> 19 20 #include <linux/interrupt.h> ··· 25 24 #include <linux/phy/phy.h> 26 25 #include <linux/platform_device.h> 27 26 28 - #define SATA_MDIO_BANK_OFFSET 0x23c 29 - #define SATA_MDIO_REG_OFFSET(ofs) ((ofs) * 4) 27 + #define SATA_PCB_BANK_OFFSET 0x23c 28 + #define SATA_PCB_REG_OFFSET(ofs) ((ofs) * 4) 30 29 31 30 #define MAX_PORTS 2 32 31 33 32 /* Register offset between PHYs in PCB space */ 34 - #define SATA_MDIO_REG_28NM_SPACE_SIZE 0x1000 33 + #define SATA_PCB_REG_28NM_SPACE_SIZE 0x1000 35 34 36 35 /* The older SATA PHY registers duplicated per port registers within the map, 37 36 * rather than having a separate map per port. 38 37 */ 39 - #define SATA_MDIO_REG_40NM_SPACE_SIZE 0x10 38 + #define SATA_PCB_REG_40NM_SPACE_SIZE 0x10 39 + 40 + /* Register offset between PHYs in PHY control space */ 41 + #define SATA_PHY_CTRL_REG_28NM_SPACE_SIZE 0x8 40 42 41 43 enum brcm_sata_phy_version { 42 - BRCM_SATA_PHY_28NM, 43 - BRCM_SATA_PHY_40NM, 44 + BRCM_SATA_PHY_STB_28NM, 45 + BRCM_SATA_PHY_STB_40NM, 46 + BRCM_SATA_PHY_IPROC_NS2, 44 47 }; 45 48 46 49 struct brcm_sata_port { ··· 57 52 struct brcm_sata_phy { 58 53 struct device *dev; 59 54 void __iomem *phy_base; 55 + void __iomem *ctrl_base; 60 56 enum brcm_sata_phy_version version; 61 57 62 58 struct brcm_sata_port phys[MAX_PORTS]; 63 59 }; 64 60 65 - enum sata_mdio_phy_regs { 66 - PLL_REG_BANK_0 = 0x50, 61 + enum sata_phy_regs { 62 + BLOCK0_REG_BANK = 0x000, 63 + BLOCK0_XGXSSTATUS = 0x81, 64 + BLOCK0_XGXSSTATUS_PLL_LOCK = BIT(12), 65 + BLOCK0_SPARE = 0x8d, 66 + BLOCK0_SPARE_OOB_CLK_SEL_MASK = 0x3, 67 + BLOCK0_SPARE_OOB_CLK_SEL_REFBY2 = 0x1, 68 + 69 + PLL_REG_BANK_0 = 0x050, 67 70 PLL_REG_BANK_0_PLLCONTROL_0 = 0x81, 71 + 72 + PLL1_REG_BANK = 0x060, 73 + PLL1_ACTRL2 = 0x82, 74 + PLL1_ACTRL3 = 0x83, 75 + PLL1_ACTRL4 = 0x84, 76 + 77 + OOB_REG_BANK = 0x150, 78 + OOB_CTRL1 = 0x80, 79 + OOB_CTRL1_BURST_MAX_MASK = 0xf, 80 + OOB_CTRL1_BURST_MAX_SHIFT = 12, 81 + OOB_CTRL1_BURST_MIN_MASK = 0xf, 82 + OOB_CTRL1_BURST_MIN_SHIFT = 8, 83 + OOB_CTRL1_WAKE_IDLE_MAX_MASK = 0xf, 84 + OOB_CTRL1_WAKE_IDLE_MAX_SHIFT = 4, 85 + OOB_CTRL1_WAKE_IDLE_MIN_MASK = 0xf, 86 + OOB_CTRL1_WAKE_IDLE_MIN_SHIFT = 0, 87 + OOB_CTRL2 = 0x81, 88 + OOB_CTRL2_SEL_ENA_SHIFT = 15, 89 + OOB_CTRL2_SEL_ENA_RC_SHIFT = 14, 90 + OOB_CTRL2_RESET_IDLE_MAX_MASK = 0x3f, 91 + OOB_CTRL2_RESET_IDLE_MAX_SHIFT = 8, 92 + OOB_CTRL2_BURST_CNT_MASK = 0x3, 93 + OOB_CTRL2_BURST_CNT_SHIFT = 6, 94 + OOB_CTRL2_RESET_IDLE_MIN_MASK = 0x3f, 95 + OOB_CTRL2_RESET_IDLE_MIN_SHIFT = 0, 68 96 69 97 TXPMD_REG_BANK = 0x1a0, 70 98 TXPMD_CONTROL1 = 0x81, ··· 110 72 TXPMD_TX_FREQ_CTRL_CONTROL3_FMAX_MASK = 0x3ff, 111 73 }; 112 74 113 - static inline void __iomem *brcm_sata_phy_base(struct brcm_sata_port *port) 75 + enum sata_phy_ctrl_regs { 76 + PHY_CTRL_1 = 0x0, 77 + PHY_CTRL_1_RESET = BIT(0), 78 + }; 79 + 80 + static inline void __iomem *brcm_sata_pcb_base(struct brcm_sata_port *port) 114 81 { 115 82 struct brcm_sata_phy *priv = port->phy_priv; 116 - u32 offset = 0; 83 + u32 size = 0; 117 84 118 - if (priv->version == BRCM_SATA_PHY_28NM) 119 - offset = SATA_MDIO_REG_28NM_SPACE_SIZE; 120 - else if (priv->version == BRCM_SATA_PHY_40NM) 121 - offset = SATA_MDIO_REG_40NM_SPACE_SIZE; 122 - else 85 + switch (priv->version) { 86 + case BRCM_SATA_PHY_STB_28NM: 87 + case BRCM_SATA_PHY_IPROC_NS2: 88 + size = SATA_PCB_REG_28NM_SPACE_SIZE; 89 + break; 90 + case BRCM_SATA_PHY_STB_40NM: 91 + size = SATA_PCB_REG_40NM_SPACE_SIZE; 92 + break; 93 + default: 123 94 dev_err(priv->dev, "invalid phy version\n"); 95 + break; 96 + }; 124 97 125 - return priv->phy_base + (port->portnum * offset); 98 + return priv->phy_base + (port->portnum * size); 126 99 } 127 100 128 - static void brcm_sata_mdio_wr(void __iomem *addr, u32 bank, u32 ofs, 129 - u32 msk, u32 value) 101 + static inline void __iomem *brcm_sata_ctrl_base(struct brcm_sata_port *port) 102 + { 103 + struct brcm_sata_phy *priv = port->phy_priv; 104 + u32 size = 0; 105 + 106 + switch (priv->version) { 107 + case BRCM_SATA_PHY_IPROC_NS2: 108 + size = SATA_PHY_CTRL_REG_28NM_SPACE_SIZE; 109 + break; 110 + default: 111 + dev_err(priv->dev, "invalid phy version\n"); 112 + break; 113 + }; 114 + 115 + return priv->ctrl_base + (port->portnum * size); 116 + } 117 + 118 + static void brcm_sata_phy_wr(void __iomem *pcb_base, u32 bank, 119 + u32 ofs, u32 msk, u32 value) 130 120 { 131 121 u32 tmp; 132 122 133 - writel(bank, addr + SATA_MDIO_BANK_OFFSET); 134 - tmp = readl(addr + SATA_MDIO_REG_OFFSET(ofs)); 123 + writel(bank, pcb_base + SATA_PCB_BANK_OFFSET); 124 + tmp = readl(pcb_base + SATA_PCB_REG_OFFSET(ofs)); 135 125 tmp = (tmp & msk) | value; 136 - writel(tmp, addr + SATA_MDIO_REG_OFFSET(ofs)); 126 + writel(tmp, pcb_base + SATA_PCB_REG_OFFSET(ofs)); 127 + } 128 + 129 + static u32 brcm_sata_phy_rd(void __iomem *pcb_base, u32 bank, u32 ofs) 130 + { 131 + writel(bank, pcb_base + SATA_PCB_BANK_OFFSET); 132 + return readl(pcb_base + SATA_PCB_REG_OFFSET(ofs)); 137 133 } 138 134 139 135 /* These defaults were characterized by H/W group */ 140 - #define FMIN_VAL_DEFAULT 0x3df 141 - #define FMAX_VAL_DEFAULT 0x3df 142 - #define FMAX_VAL_SSC 0x83 136 + #define STB_FMIN_VAL_DEFAULT 0x3df 137 + #define STB_FMAX_VAL_DEFAULT 0x3df 138 + #define STB_FMAX_VAL_SSC 0x83 143 139 144 - static void brcm_sata_cfg_ssc(struct brcm_sata_port *port) 140 + static int brcm_stb_sata_init(struct brcm_sata_port *port) 145 141 { 146 - void __iomem *base = brcm_sata_phy_base(port); 142 + void __iomem *base = brcm_sata_pcb_base(port); 147 143 struct brcm_sata_phy *priv = port->phy_priv; 148 144 u32 tmp; 149 145 150 146 /* override the TX spread spectrum setting */ 151 147 tmp = TXPMD_CONTROL1_TX_SSC_EN_FRC_VAL | TXPMD_CONTROL1_TX_SSC_EN_FRC; 152 - brcm_sata_mdio_wr(base, TXPMD_REG_BANK, TXPMD_CONTROL1, ~tmp, tmp); 148 + brcm_sata_phy_wr(base, TXPMD_REG_BANK, TXPMD_CONTROL1, ~tmp, tmp); 153 149 154 150 /* set fixed min freq */ 155 - brcm_sata_mdio_wr(base, TXPMD_REG_BANK, TXPMD_TX_FREQ_CTRL_CONTROL2, 156 - ~TXPMD_TX_FREQ_CTRL_CONTROL2_FMIN_MASK, 157 - FMIN_VAL_DEFAULT); 151 + brcm_sata_phy_wr(base, TXPMD_REG_BANK, TXPMD_TX_FREQ_CTRL_CONTROL2, 152 + ~TXPMD_TX_FREQ_CTRL_CONTROL2_FMIN_MASK, 153 + STB_FMIN_VAL_DEFAULT); 158 154 159 155 /* set fixed max freq depending on SSC config */ 160 156 if (port->ssc_en) { 161 - dev_info(priv->dev, "enabling SSC on port %d\n", port->portnum); 162 - tmp = FMAX_VAL_SSC; 157 + dev_info(priv->dev, "enabling SSC on port%d\n", port->portnum); 158 + tmp = STB_FMAX_VAL_SSC; 163 159 } else { 164 - tmp = FMAX_VAL_DEFAULT; 160 + tmp = STB_FMAX_VAL_DEFAULT; 165 161 } 166 162 167 - brcm_sata_mdio_wr(base, TXPMD_REG_BANK, TXPMD_TX_FREQ_CTRL_CONTROL3, 163 + brcm_sata_phy_wr(base, TXPMD_REG_BANK, TXPMD_TX_FREQ_CTRL_CONTROL3, 168 164 ~TXPMD_TX_FREQ_CTRL_CONTROL3_FMAX_MASK, tmp); 165 + 166 + return 0; 167 + } 168 + 169 + /* NS2 SATA PLL1 defaults were characterized by H/W group */ 170 + #define NS2_PLL1_ACTRL2_MAGIC 0x1df8 171 + #define NS2_PLL1_ACTRL3_MAGIC 0x2b00 172 + #define NS2_PLL1_ACTRL4_MAGIC 0x8824 173 + 174 + static int brcm_ns2_sata_init(struct brcm_sata_port *port) 175 + { 176 + int try; 177 + unsigned int val; 178 + void __iomem *base = brcm_sata_pcb_base(port); 179 + void __iomem *ctrl_base = brcm_sata_ctrl_base(port); 180 + struct device *dev = port->phy_priv->dev; 181 + 182 + /* Configure OOB control */ 183 + val = 0x0; 184 + val |= (0xc << OOB_CTRL1_BURST_MAX_SHIFT); 185 + val |= (0x4 << OOB_CTRL1_BURST_MIN_SHIFT); 186 + val |= (0x9 << OOB_CTRL1_WAKE_IDLE_MAX_SHIFT); 187 + val |= (0x3 << OOB_CTRL1_WAKE_IDLE_MIN_SHIFT); 188 + brcm_sata_phy_wr(base, OOB_REG_BANK, OOB_CTRL1, 0x0, val); 189 + val = 0x0; 190 + val |= (0x1b << OOB_CTRL2_RESET_IDLE_MAX_SHIFT); 191 + val |= (0x2 << OOB_CTRL2_BURST_CNT_SHIFT); 192 + val |= (0x9 << OOB_CTRL2_RESET_IDLE_MIN_SHIFT); 193 + brcm_sata_phy_wr(base, OOB_REG_BANK, OOB_CTRL2, 0x0, val); 194 + 195 + /* Configure PHY PLL register bank 1 */ 196 + val = NS2_PLL1_ACTRL2_MAGIC; 197 + brcm_sata_phy_wr(base, PLL1_REG_BANK, PLL1_ACTRL2, 0x0, val); 198 + val = NS2_PLL1_ACTRL3_MAGIC; 199 + brcm_sata_phy_wr(base, PLL1_REG_BANK, PLL1_ACTRL3, 0x0, val); 200 + val = NS2_PLL1_ACTRL4_MAGIC; 201 + brcm_sata_phy_wr(base, PLL1_REG_BANK, PLL1_ACTRL4, 0x0, val); 202 + 203 + /* Configure PHY BLOCK0 register bank */ 204 + /* Set oob_clk_sel to refclk/2 */ 205 + brcm_sata_phy_wr(base, BLOCK0_REG_BANK, BLOCK0_SPARE, 206 + ~BLOCK0_SPARE_OOB_CLK_SEL_MASK, 207 + BLOCK0_SPARE_OOB_CLK_SEL_REFBY2); 208 + 209 + /* Strobe PHY reset using PHY control register */ 210 + writel(PHY_CTRL_1_RESET, ctrl_base + PHY_CTRL_1); 211 + mdelay(1); 212 + writel(0x0, ctrl_base + PHY_CTRL_1); 213 + mdelay(1); 214 + 215 + /* Wait for PHY PLL lock by polling pll_lock bit */ 216 + try = 50; 217 + while (try) { 218 + val = brcm_sata_phy_rd(base, BLOCK0_REG_BANK, 219 + BLOCK0_XGXSSTATUS); 220 + if (val & BLOCK0_XGXSSTATUS_PLL_LOCK) 221 + break; 222 + msleep(20); 223 + try--; 224 + } 225 + if (!try) { 226 + /* PLL did not lock; give up */ 227 + dev_err(dev, "port%d PLL did not lock\n", port->portnum); 228 + return -ETIMEDOUT; 229 + } 230 + 231 + dev_dbg(dev, "port%d initialized\n", port->portnum); 232 + 233 + return 0; 169 234 } 170 235 171 236 static int brcm_sata_phy_init(struct phy *phy) 172 237 { 238 + int rc; 173 239 struct brcm_sata_port *port = phy_get_drvdata(phy); 174 240 175 - brcm_sata_cfg_ssc(port); 241 + switch (port->phy_priv->version) { 242 + case BRCM_SATA_PHY_STB_28NM: 243 + case BRCM_SATA_PHY_STB_40NM: 244 + rc = brcm_stb_sata_init(port); 245 + break; 246 + case BRCM_SATA_PHY_IPROC_NS2: 247 + rc = brcm_ns2_sata_init(port); 248 + break; 249 + default: 250 + rc = -ENODEV; 251 + }; 176 252 177 253 return 0; 178 254 } ··· 298 146 299 147 static const struct of_device_id brcm_sata_phy_of_match[] = { 300 148 { .compatible = "brcm,bcm7445-sata-phy", 301 - .data = (void *)BRCM_SATA_PHY_28NM }, 149 + .data = (void *)BRCM_SATA_PHY_STB_28NM }, 302 150 { .compatible = "brcm,bcm7425-sata-phy", 303 - .data = (void *)BRCM_SATA_PHY_40NM }, 151 + .data = (void *)BRCM_SATA_PHY_STB_40NM }, 152 + { .compatible = "brcm,iproc-ns2-sata-phy", 153 + .data = (void *)BRCM_SATA_PHY_IPROC_NS2 }, 304 154 {}, 305 155 }; 306 156 MODULE_DEVICE_TABLE(of, brcm_sata_phy_of_match); ··· 335 181 if (of_id) 336 182 priv->version = (enum brcm_sata_phy_version)of_id->data; 337 183 else 338 - priv->version = BRCM_SATA_PHY_28NM; 184 + priv->version = BRCM_SATA_PHY_STB_28NM; 185 + 186 + if (priv->version == BRCM_SATA_PHY_IPROC_NS2) { 187 + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, 188 + "phy-ctrl"); 189 + priv->ctrl_base = devm_ioremap_resource(dev, res); 190 + if (IS_ERR(priv->ctrl_base)) 191 + return PTR_ERR(priv->ctrl_base); 192 + } 339 193 340 194 for_each_available_child_of_node(dn, child) { 341 195 unsigned int id;