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