• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Broadcom SATA3 AHCI Controller PHY Driver
3  *
4  * Copyright (C) 2016 Broadcom
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  */
16 
17 #include <linux/delay.h>
18 #include <linux/device.h>
19 #include <linux/init.h>
20 #include <linux/interrupt.h>
21 #include <linux/io.h>
22 #include <linux/kernel.h>
23 #include <linux/module.h>
24 #include <linux/of.h>
25 #include <linux/phy/phy.h>
26 #include <linux/platform_device.h>
27 
28 #define SATA_PCB_BANK_OFFSET				0x23c
29 #define SATA_PCB_REG_OFFSET(ofs)			((ofs) * 4)
30 
31 #define MAX_PORTS					2
32 
33 /* Register offset between PHYs in PCB space */
34 #define SATA_PCB_REG_28NM_SPACE_SIZE			0x1000
35 
36 /* The older SATA PHY registers duplicated per port registers within the map,
37  * rather than having a separate map per port.
38  */
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
43 
44 enum brcm_sata_phy_version {
45 	BRCM_SATA_PHY_STB_28NM,
46 	BRCM_SATA_PHY_STB_40NM,
47 	BRCM_SATA_PHY_IPROC_NS2,
48 	BRCM_SATA_PHY_IPROC_NSP,
49 };
50 
51 struct brcm_sata_port {
52 	int portnum;
53 	struct phy *phy;
54 	struct brcm_sata_phy *phy_priv;
55 	bool ssc_en;
56 };
57 
58 struct brcm_sata_phy {
59 	struct device *dev;
60 	void __iomem *phy_base;
61 	void __iomem *ctrl_base;
62 	enum brcm_sata_phy_version version;
63 
64 	struct brcm_sata_port phys[MAX_PORTS];
65 };
66 
67 enum sata_phy_regs {
68 	BLOCK0_REG_BANK				= 0x000,
69 	BLOCK0_XGXSSTATUS			= 0x81,
70 	BLOCK0_XGXSSTATUS_PLL_LOCK		= BIT(12),
71 	BLOCK0_SPARE				= 0x8d,
72 	BLOCK0_SPARE_OOB_CLK_SEL_MASK		= 0x3,
73 	BLOCK0_SPARE_OOB_CLK_SEL_REFBY2		= 0x1,
74 
75 	PLL_REG_BANK_0				= 0x050,
76 	PLL_REG_BANK_0_PLLCONTROL_0		= 0x81,
77 	PLLCONTROL_0_FREQ_DET_RESTART		= BIT(13),
78 	PLLCONTROL_0_FREQ_MONITOR		= BIT(12),
79 	PLLCONTROL_0_SEQ_START			= BIT(15),
80 	PLL_CAP_CONTROL				= 0x85,
81 	PLL_ACTRL2				= 0x8b,
82 	PLL_ACTRL2_SELDIV_MASK			= 0x1f,
83 	PLL_ACTRL2_SELDIV_SHIFT			= 9,
84 
85 	PLL1_REG_BANK				= 0x060,
86 	PLL1_ACTRL2				= 0x82,
87 	PLL1_ACTRL3				= 0x83,
88 	PLL1_ACTRL4				= 0x84,
89 
90 	OOB_REG_BANK				= 0x150,
91 	OOB1_REG_BANK				= 0x160,
92 	OOB_CTRL1				= 0x80,
93 	OOB_CTRL1_BURST_MAX_MASK		= 0xf,
94 	OOB_CTRL1_BURST_MAX_SHIFT		= 12,
95 	OOB_CTRL1_BURST_MIN_MASK		= 0xf,
96 	OOB_CTRL1_BURST_MIN_SHIFT		= 8,
97 	OOB_CTRL1_WAKE_IDLE_MAX_MASK		= 0xf,
98 	OOB_CTRL1_WAKE_IDLE_MAX_SHIFT		= 4,
99 	OOB_CTRL1_WAKE_IDLE_MIN_MASK		= 0xf,
100 	OOB_CTRL1_WAKE_IDLE_MIN_SHIFT		= 0,
101 	OOB_CTRL2				= 0x81,
102 	OOB_CTRL2_SEL_ENA_SHIFT			= 15,
103 	OOB_CTRL2_SEL_ENA_RC_SHIFT		= 14,
104 	OOB_CTRL2_RESET_IDLE_MAX_MASK		= 0x3f,
105 	OOB_CTRL2_RESET_IDLE_MAX_SHIFT		= 8,
106 	OOB_CTRL2_BURST_CNT_MASK		= 0x3,
107 	OOB_CTRL2_BURST_CNT_SHIFT		= 6,
108 	OOB_CTRL2_RESET_IDLE_MIN_MASK		= 0x3f,
109 	OOB_CTRL2_RESET_IDLE_MIN_SHIFT		= 0,
110 
111 	TXPMD_REG_BANK				= 0x1a0,
112 	TXPMD_CONTROL1				= 0x81,
113 	TXPMD_CONTROL1_TX_SSC_EN_FRC		= BIT(0),
114 	TXPMD_CONTROL1_TX_SSC_EN_FRC_VAL	= BIT(1),
115 	TXPMD_TX_FREQ_CTRL_CONTROL1		= 0x82,
116 	TXPMD_TX_FREQ_CTRL_CONTROL2		= 0x83,
117 	TXPMD_TX_FREQ_CTRL_CONTROL2_FMIN_MASK	= 0x3ff,
118 	TXPMD_TX_FREQ_CTRL_CONTROL3		= 0x84,
119 	TXPMD_TX_FREQ_CTRL_CONTROL3_FMAX_MASK	= 0x3ff,
120 };
121 
122 enum sata_phy_ctrl_regs {
123 	PHY_CTRL_1				= 0x0,
124 	PHY_CTRL_1_RESET			= BIT(0),
125 };
126 
brcm_sata_pcb_base(struct brcm_sata_port * port)127 static inline void __iomem *brcm_sata_pcb_base(struct brcm_sata_port *port)
128 {
129 	struct brcm_sata_phy *priv = port->phy_priv;
130 	u32 size = 0;
131 
132 	switch (priv->version) {
133 	case BRCM_SATA_PHY_STB_28NM:
134 	case BRCM_SATA_PHY_IPROC_NS2:
135 		size = SATA_PCB_REG_28NM_SPACE_SIZE;
136 		break;
137 	case BRCM_SATA_PHY_STB_40NM:
138 		size = SATA_PCB_REG_40NM_SPACE_SIZE;
139 		break;
140 	default:
141 		dev_err(priv->dev, "invalid phy version\n");
142 		break;
143 	};
144 
145 	return priv->phy_base + (port->portnum * size);
146 }
147 
brcm_sata_ctrl_base(struct brcm_sata_port * port)148 static inline void __iomem *brcm_sata_ctrl_base(struct brcm_sata_port *port)
149 {
150 	struct brcm_sata_phy *priv = port->phy_priv;
151 	u32 size = 0;
152 
153 	switch (priv->version) {
154 	case BRCM_SATA_PHY_IPROC_NS2:
155 		size = SATA_PHY_CTRL_REG_28NM_SPACE_SIZE;
156 		break;
157 	default:
158 		dev_err(priv->dev, "invalid phy version\n");
159 		break;
160 	};
161 
162 	return priv->ctrl_base + (port->portnum * size);
163 }
164 
brcm_sata_phy_wr(void __iomem * pcb_base,u32 bank,u32 ofs,u32 msk,u32 value)165 static void brcm_sata_phy_wr(void __iomem *pcb_base, u32 bank,
166 			     u32 ofs, u32 msk, u32 value)
167 {
168 	u32 tmp;
169 
170 	writel(bank, pcb_base + SATA_PCB_BANK_OFFSET);
171 	tmp = readl(pcb_base + SATA_PCB_REG_OFFSET(ofs));
172 	tmp = (tmp & msk) | value;
173 	writel(tmp, pcb_base + SATA_PCB_REG_OFFSET(ofs));
174 }
175 
brcm_sata_phy_rd(void __iomem * pcb_base,u32 bank,u32 ofs)176 static u32 brcm_sata_phy_rd(void __iomem *pcb_base, u32 bank, u32 ofs)
177 {
178 	writel(bank, pcb_base + SATA_PCB_BANK_OFFSET);
179 	return readl(pcb_base + SATA_PCB_REG_OFFSET(ofs));
180 }
181 
182 /* These defaults were characterized by H/W group */
183 #define STB_FMIN_VAL_DEFAULT	0x3df
184 #define STB_FMAX_VAL_DEFAULT	0x3df
185 #define STB_FMAX_VAL_SSC	0x83
186 
brcm_stb_sata_init(struct brcm_sata_port * port)187 static int brcm_stb_sata_init(struct brcm_sata_port *port)
188 {
189 	void __iomem *base = brcm_sata_pcb_base(port);
190 	struct brcm_sata_phy *priv = port->phy_priv;
191 	u32 tmp;
192 
193 	/* override the TX spread spectrum setting */
194 	tmp = TXPMD_CONTROL1_TX_SSC_EN_FRC_VAL | TXPMD_CONTROL1_TX_SSC_EN_FRC;
195 	brcm_sata_phy_wr(base, TXPMD_REG_BANK, TXPMD_CONTROL1, ~tmp, tmp);
196 
197 	/* set fixed min freq */
198 	brcm_sata_phy_wr(base, TXPMD_REG_BANK, TXPMD_TX_FREQ_CTRL_CONTROL2,
199 			 ~TXPMD_TX_FREQ_CTRL_CONTROL2_FMIN_MASK,
200 			 STB_FMIN_VAL_DEFAULT);
201 
202 	/* set fixed max freq depending on SSC config */
203 	if (port->ssc_en) {
204 		dev_info(priv->dev, "enabling SSC on port%d\n", port->portnum);
205 		tmp = STB_FMAX_VAL_SSC;
206 	} else {
207 		tmp = STB_FMAX_VAL_DEFAULT;
208 	}
209 
210 	brcm_sata_phy_wr(base, TXPMD_REG_BANK, TXPMD_TX_FREQ_CTRL_CONTROL3,
211 			  ~TXPMD_TX_FREQ_CTRL_CONTROL3_FMAX_MASK, tmp);
212 
213 	return 0;
214 }
215 
216 /* NS2 SATA PLL1 defaults were characterized by H/W group */
217 #define NS2_PLL1_ACTRL2_MAGIC	0x1df8
218 #define NS2_PLL1_ACTRL3_MAGIC	0x2b00
219 #define NS2_PLL1_ACTRL4_MAGIC	0x8824
220 
brcm_ns2_sata_init(struct brcm_sata_port * port)221 static int brcm_ns2_sata_init(struct brcm_sata_port *port)
222 {
223 	int try;
224 	unsigned int val;
225 	void __iomem *base = brcm_sata_pcb_base(port);
226 	void __iomem *ctrl_base = brcm_sata_ctrl_base(port);
227 	struct device *dev = port->phy_priv->dev;
228 
229 	/* Configure OOB control */
230 	val = 0x0;
231 	val |= (0xc << OOB_CTRL1_BURST_MAX_SHIFT);
232 	val |= (0x4 << OOB_CTRL1_BURST_MIN_SHIFT);
233 	val |= (0x9 << OOB_CTRL1_WAKE_IDLE_MAX_SHIFT);
234 	val |= (0x3 << OOB_CTRL1_WAKE_IDLE_MIN_SHIFT);
235 	brcm_sata_phy_wr(base, OOB_REG_BANK, OOB_CTRL1, 0x0, val);
236 	val = 0x0;
237 	val |= (0x1b << OOB_CTRL2_RESET_IDLE_MAX_SHIFT);
238 	val |= (0x2 << OOB_CTRL2_BURST_CNT_SHIFT);
239 	val |= (0x9 << OOB_CTRL2_RESET_IDLE_MIN_SHIFT);
240 	brcm_sata_phy_wr(base, OOB_REG_BANK, OOB_CTRL2, 0x0, val);
241 
242 	/* Configure PHY PLL register bank 1 */
243 	val = NS2_PLL1_ACTRL2_MAGIC;
244 	brcm_sata_phy_wr(base, PLL1_REG_BANK, PLL1_ACTRL2, 0x0, val);
245 	val = NS2_PLL1_ACTRL3_MAGIC;
246 	brcm_sata_phy_wr(base, PLL1_REG_BANK, PLL1_ACTRL3, 0x0, val);
247 	val = NS2_PLL1_ACTRL4_MAGIC;
248 	brcm_sata_phy_wr(base, PLL1_REG_BANK, PLL1_ACTRL4, 0x0, val);
249 
250 	/* Configure PHY BLOCK0 register bank */
251 	/* Set oob_clk_sel to refclk/2 */
252 	brcm_sata_phy_wr(base, BLOCK0_REG_BANK, BLOCK0_SPARE,
253 			 ~BLOCK0_SPARE_OOB_CLK_SEL_MASK,
254 			 BLOCK0_SPARE_OOB_CLK_SEL_REFBY2);
255 
256 	/* Strobe PHY reset using PHY control register */
257 	writel(PHY_CTRL_1_RESET, ctrl_base + PHY_CTRL_1);
258 	mdelay(1);
259 	writel(0x0, ctrl_base + PHY_CTRL_1);
260 	mdelay(1);
261 
262 	/* Wait for PHY PLL lock by polling pll_lock bit */
263 	try = 50;
264 	while (try) {
265 		val = brcm_sata_phy_rd(base, BLOCK0_REG_BANK,
266 					BLOCK0_XGXSSTATUS);
267 		if (val & BLOCK0_XGXSSTATUS_PLL_LOCK)
268 			break;
269 		msleep(20);
270 		try--;
271 	}
272 	if (!try) {
273 		/* PLL did not lock; give up */
274 		dev_err(dev, "port%d PLL did not lock\n", port->portnum);
275 		return -ETIMEDOUT;
276 	}
277 
278 	dev_dbg(dev, "port%d initialized\n", port->portnum);
279 
280 	return 0;
281 }
282 
brcm_nsp_sata_init(struct brcm_sata_port * port)283 static int brcm_nsp_sata_init(struct brcm_sata_port *port)
284 {
285 	struct brcm_sata_phy *priv = port->phy_priv;
286 	struct device *dev = port->phy_priv->dev;
287 	void __iomem *base = priv->phy_base;
288 	unsigned int oob_bank;
289 	unsigned int val, try;
290 
291 	/* Configure OOB control */
292 	if (port->portnum == 0)
293 		oob_bank = OOB_REG_BANK;
294 	else if (port->portnum == 1)
295 		oob_bank = OOB1_REG_BANK;
296 	else
297 		return -EINVAL;
298 
299 	val = 0x0;
300 	val |= (0x0f << OOB_CTRL1_BURST_MAX_SHIFT);
301 	val |= (0x06 << OOB_CTRL1_BURST_MIN_SHIFT);
302 	val |= (0x0f << OOB_CTRL1_WAKE_IDLE_MAX_SHIFT);
303 	val |= (0x06 << OOB_CTRL1_WAKE_IDLE_MIN_SHIFT);
304 	brcm_sata_phy_wr(base, oob_bank, OOB_CTRL1, 0x0, val);
305 
306 	val = 0x0;
307 	val |= (0x2e << OOB_CTRL2_RESET_IDLE_MAX_SHIFT);
308 	val |= (0x02 << OOB_CTRL2_BURST_CNT_SHIFT);
309 	val |= (0x16 << OOB_CTRL2_RESET_IDLE_MIN_SHIFT);
310 	brcm_sata_phy_wr(base, oob_bank, OOB_CTRL2, 0x0, val);
311 
312 
313 	brcm_sata_phy_wr(base, PLL_REG_BANK_0, PLL_ACTRL2,
314 		~(PLL_ACTRL2_SELDIV_MASK << PLL_ACTRL2_SELDIV_SHIFT),
315 		0x0c << PLL_ACTRL2_SELDIV_SHIFT);
316 
317 	brcm_sata_phy_wr(base, PLL_REG_BANK_0, PLL_CAP_CONTROL,
318 						0xff0, 0x4f0);
319 
320 	val = PLLCONTROL_0_FREQ_DET_RESTART | PLLCONTROL_0_FREQ_MONITOR;
321 	brcm_sata_phy_wr(base, PLL_REG_BANK_0, PLL_REG_BANK_0_PLLCONTROL_0,
322 								~val, val);
323 	val = PLLCONTROL_0_SEQ_START;
324 	brcm_sata_phy_wr(base, PLL_REG_BANK_0, PLL_REG_BANK_0_PLLCONTROL_0,
325 								~val, 0);
326 	mdelay(10);
327 	brcm_sata_phy_wr(base, PLL_REG_BANK_0, PLL_REG_BANK_0_PLLCONTROL_0,
328 								~val, val);
329 
330 	/* Wait for pll_seq_done bit */
331 	try = 50;
332 	while (try--) {
333 		val = brcm_sata_phy_rd(base, BLOCK0_REG_BANK,
334 					BLOCK0_XGXSSTATUS);
335 		if (val & BLOCK0_XGXSSTATUS_PLL_LOCK)
336 			break;
337 		msleep(20);
338 	}
339 	if (!try) {
340 		/* PLL did not lock; give up */
341 		dev_err(dev, "port%d PLL did not lock\n", port->portnum);
342 		return -ETIMEDOUT;
343 	}
344 
345 	dev_dbg(dev, "port%d initialized\n", port->portnum);
346 
347 	return 0;
348 }
349 
brcm_sata_phy_init(struct phy * phy)350 static int brcm_sata_phy_init(struct phy *phy)
351 {
352 	int rc;
353 	struct brcm_sata_port *port = phy_get_drvdata(phy);
354 
355 	switch (port->phy_priv->version) {
356 	case BRCM_SATA_PHY_STB_28NM:
357 	case BRCM_SATA_PHY_STB_40NM:
358 		rc = brcm_stb_sata_init(port);
359 		break;
360 	case BRCM_SATA_PHY_IPROC_NS2:
361 		rc = brcm_ns2_sata_init(port);
362 		break;
363 	case BRCM_SATA_PHY_IPROC_NSP:
364 		rc = brcm_nsp_sata_init(port);
365 		break;
366 	default:
367 		rc = -ENODEV;
368 	};
369 
370 	return rc;
371 }
372 
373 static const struct phy_ops phy_ops = {
374 	.init		= brcm_sata_phy_init,
375 	.owner		= THIS_MODULE,
376 };
377 
378 static const struct of_device_id brcm_sata_phy_of_match[] = {
379 	{ .compatible	= "brcm,bcm7445-sata-phy",
380 	  .data = (void *)BRCM_SATA_PHY_STB_28NM },
381 	{ .compatible	= "brcm,bcm7425-sata-phy",
382 	  .data = (void *)BRCM_SATA_PHY_STB_40NM },
383 	{ .compatible	= "brcm,iproc-ns2-sata-phy",
384 	  .data = (void *)BRCM_SATA_PHY_IPROC_NS2 },
385 	{ .compatible = "brcm,iproc-nsp-sata-phy",
386 	  .data = (void *)BRCM_SATA_PHY_IPROC_NSP },
387 	{},
388 };
389 MODULE_DEVICE_TABLE(of, brcm_sata_phy_of_match);
390 
brcm_sata_phy_probe(struct platform_device * pdev)391 static int brcm_sata_phy_probe(struct platform_device *pdev)
392 {
393 	struct device *dev = &pdev->dev;
394 	struct device_node *dn = dev->of_node, *child;
395 	const struct of_device_id *of_id;
396 	struct brcm_sata_phy *priv;
397 	struct resource *res;
398 	struct phy_provider *provider;
399 	int ret, count = 0;
400 
401 	if (of_get_child_count(dn) == 0)
402 		return -ENODEV;
403 
404 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
405 	if (!priv)
406 		return -ENOMEM;
407 	dev_set_drvdata(dev, priv);
408 	priv->dev = dev;
409 
410 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy");
411 	priv->phy_base = devm_ioremap_resource(dev, res);
412 	if (IS_ERR(priv->phy_base))
413 		return PTR_ERR(priv->phy_base);
414 
415 	of_id = of_match_node(brcm_sata_phy_of_match, dn);
416 	if (of_id)
417 		priv->version = (enum brcm_sata_phy_version)of_id->data;
418 	else
419 		priv->version = BRCM_SATA_PHY_STB_28NM;
420 
421 	if (priv->version == BRCM_SATA_PHY_IPROC_NS2) {
422 		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
423 						   "phy-ctrl");
424 		priv->ctrl_base = devm_ioremap_resource(dev, res);
425 		if (IS_ERR(priv->ctrl_base))
426 			return PTR_ERR(priv->ctrl_base);
427 	}
428 
429 	for_each_available_child_of_node(dn, child) {
430 		unsigned int id;
431 		struct brcm_sata_port *port;
432 
433 		if (of_property_read_u32(child, "reg", &id)) {
434 			dev_err(dev, "missing reg property in node %s\n",
435 					child->name);
436 			ret = -EINVAL;
437 			goto put_child;
438 		}
439 
440 		if (id >= MAX_PORTS) {
441 			dev_err(dev, "invalid reg: %u\n", id);
442 			ret = -EINVAL;
443 			goto put_child;
444 		}
445 		if (priv->phys[id].phy) {
446 			dev_err(dev, "already registered port %u\n", id);
447 			ret = -EINVAL;
448 			goto put_child;
449 		}
450 
451 		port = &priv->phys[id];
452 		port->portnum = id;
453 		port->phy_priv = priv;
454 		port->phy = devm_phy_create(dev, child, &phy_ops);
455 		port->ssc_en = of_property_read_bool(child, "brcm,enable-ssc");
456 		if (IS_ERR(port->phy)) {
457 			dev_err(dev, "failed to create PHY\n");
458 			ret = PTR_ERR(port->phy);
459 			goto put_child;
460 		}
461 
462 		phy_set_drvdata(port->phy, port);
463 		count++;
464 	}
465 
466 	provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
467 	if (IS_ERR(provider)) {
468 		dev_err(dev, "could not register PHY provider\n");
469 		return PTR_ERR(provider);
470 	}
471 
472 	dev_info(dev, "registered %d port(s)\n", count);
473 
474 	return 0;
475 put_child:
476 	of_node_put(child);
477 	return ret;
478 }
479 
480 static struct platform_driver brcm_sata_phy_driver = {
481 	.probe	= brcm_sata_phy_probe,
482 	.driver	= {
483 		.of_match_table	= brcm_sata_phy_of_match,
484 		.name		= "brcm-sata-phy",
485 	}
486 };
487 module_platform_driver(brcm_sata_phy_driver);
488 
489 MODULE_DESCRIPTION("Broadcom SATA PHY driver");
490 MODULE_LICENSE("GPL");
491 MODULE_AUTHOR("Marc Carino");
492 MODULE_AUTHOR("Brian Norris");
493 MODULE_ALIAS("platform:phy-brcm-sata");
494