NVMe: Only release requested regions
[linux-2.6-block.git] / drivers / phy / phy-brcm-sata.c
CommitLineData
0d486806
BN
1/*
2 * Broadcom SATA3 AHCI Controller PHY Driver
3 *
037c4189 4 * Copyright (C) 2016 Broadcom
0d486806
BN
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
4faee9a4 17#include <linux/delay.h>
0d486806
BN
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
4faee9a4
AP
28#define SATA_PCB_BANK_OFFSET 0x23c
29#define SATA_PCB_REG_OFFSET(ofs) ((ofs) * 4)
0d486806
BN
30
31#define MAX_PORTS 2
32
33/* Register offset between PHYs in PCB space */
4faee9a4 34#define SATA_PCB_REG_28NM_SPACE_SIZE 0x1000
810c6f16 35
c1602a1a
JS
36/* The older SATA PHY registers duplicated per port registers within the map,
37 * rather than having a separate map per port.
38 */
4faee9a4
AP
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
c1602a1a 43
810c6f16 44enum brcm_sata_phy_version {
4faee9a4
AP
45 BRCM_SATA_PHY_STB_28NM,
46 BRCM_SATA_PHY_STB_40NM,
47 BRCM_SATA_PHY_IPROC_NS2,
810c6f16 48};
0d486806
BN
49
50struct brcm_sata_port {
51 int portnum;
52 struct phy *phy;
53 struct brcm_sata_phy *phy_priv;
54 bool ssc_en;
55};
56
57struct brcm_sata_phy {
58 struct device *dev;
59 void __iomem *phy_base;
4faee9a4 60 void __iomem *ctrl_base;
810c6f16 61 enum brcm_sata_phy_version version;
0d486806
BN
62
63 struct brcm_sata_port phys[MAX_PORTS];
64};
65
4faee9a4
AP
66enum sata_phy_regs {
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,
0d486806
BN
75 PLL_REG_BANK_0_PLLCONTROL_0 = 0x81,
76
4faee9a4
AP
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
0d486806
BN
102 TXPMD_REG_BANK = 0x1a0,
103 TXPMD_CONTROL1 = 0x81,
104 TXPMD_CONTROL1_TX_SSC_EN_FRC = BIT(0),
105 TXPMD_CONTROL1_TX_SSC_EN_FRC_VAL = BIT(1),
106 TXPMD_TX_FREQ_CTRL_CONTROL1 = 0x82,
107 TXPMD_TX_FREQ_CTRL_CONTROL2 = 0x83,
108 TXPMD_TX_FREQ_CTRL_CONTROL2_FMIN_MASK = 0x3ff,
109 TXPMD_TX_FREQ_CTRL_CONTROL3 = 0x84,
110 TXPMD_TX_FREQ_CTRL_CONTROL3_FMAX_MASK = 0x3ff,
111};
112
4faee9a4
AP
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)
0d486806
BN
119{
120 struct brcm_sata_phy *priv = port->phy_priv;
4faee9a4
AP
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 };
0d486806 135
4faee9a4
AP
136 return priv->phy_base + (port->portnum * size);
137}
138
139static inline void __iomem *brcm_sata_ctrl_base(struct brcm_sata_port *port)
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:
c1602a1a 149 dev_err(priv->dev, "invalid phy version\n");
4faee9a4
AP
150 break;
151 };
810c6f16 152
4faee9a4 153 return priv->ctrl_base + (port->portnum * size);
0d486806
BN
154}
155
4faee9a4
AP
156static void brcm_sata_phy_wr(void __iomem *pcb_base, u32 bank,
157 u32 ofs, u32 msk, u32 value)
0d486806
BN
158{
159 u32 tmp;
160
4faee9a4
AP
161 writel(bank, pcb_base + SATA_PCB_BANK_OFFSET);
162 tmp = readl(pcb_base + SATA_PCB_REG_OFFSET(ofs));
0d486806 163 tmp = (tmp & msk) | value;
4faee9a4
AP
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));
0d486806
BN
171}
172
173/* These defaults were characterized by H/W group */
4faee9a4
AP
174#define STB_FMIN_VAL_DEFAULT 0x3df
175#define STB_FMAX_VAL_DEFAULT 0x3df
176#define STB_FMAX_VAL_SSC 0x83
0d486806 177
4faee9a4 178static int brcm_stb_sata_init(struct brcm_sata_port *port)
0d486806 179{
4faee9a4 180 void __iomem *base = brcm_sata_pcb_base(port);
0d486806
BN
181 struct brcm_sata_phy *priv = port->phy_priv;
182 u32 tmp;
183
184 /* override the TX spread spectrum setting */
185 tmp = TXPMD_CONTROL1_TX_SSC_EN_FRC_VAL | TXPMD_CONTROL1_TX_SSC_EN_FRC;
4faee9a4 186 brcm_sata_phy_wr(base, TXPMD_REG_BANK, TXPMD_CONTROL1, ~tmp, tmp);
0d486806
BN
187
188 /* set fixed min freq */
4faee9a4
AP
189 brcm_sata_phy_wr(base, TXPMD_REG_BANK, TXPMD_TX_FREQ_CTRL_CONTROL2,
190 ~TXPMD_TX_FREQ_CTRL_CONTROL2_FMIN_MASK,
191 STB_FMIN_VAL_DEFAULT);
0d486806
BN
192
193 /* set fixed max freq depending on SSC config */
194 if (port->ssc_en) {
4faee9a4
AP
195 dev_info(priv->dev, "enabling SSC on port%d\n", port->portnum);
196 tmp = STB_FMAX_VAL_SSC;
0d486806 197 } else {
4faee9a4 198 tmp = STB_FMAX_VAL_DEFAULT;
0d486806
BN
199 }
200
4faee9a4 201 brcm_sata_phy_wr(base, TXPMD_REG_BANK, TXPMD_TX_FREQ_CTRL_CONTROL3,
0d486806 202 ~TXPMD_TX_FREQ_CTRL_CONTROL3_FMAX_MASK, tmp);
4faee9a4
AP
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;
0d486806
BN
272}
273
274static int brcm_sata_phy_init(struct phy *phy)
275{
4faee9a4 276 int rc;
0d486806
BN
277 struct brcm_sata_port *port = phy_get_drvdata(phy);
278
4faee9a4
AP
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 };
0d486806
BN
290
291 return 0;
292}
293
c1602a1a 294static const struct phy_ops phy_ops = {
0d486806
BN
295 .init = brcm_sata_phy_init,
296 .owner = THIS_MODULE,
297};
298
299static const struct of_device_id brcm_sata_phy_of_match[] = {
810c6f16 300 { .compatible = "brcm,bcm7445-sata-phy",
4faee9a4 301 .data = (void *)BRCM_SATA_PHY_STB_28NM },
c1602a1a 302 { .compatible = "brcm,bcm7425-sata-phy",
4faee9a4
AP
303 .data = (void *)BRCM_SATA_PHY_STB_40NM },
304 { .compatible = "brcm,iproc-ns2-sata-phy",
305 .data = (void *)BRCM_SATA_PHY_IPROC_NS2 },
0d486806
BN
306 {},
307};
308MODULE_DEVICE_TABLE(of, brcm_sata_phy_of_match);
309
310static int brcm_sata_phy_probe(struct platform_device *pdev)
311{
312 struct device *dev = &pdev->dev;
313 struct device_node *dn = dev->of_node, *child;
810c6f16 314 const struct of_device_id *of_id;
0d486806
BN
315 struct brcm_sata_phy *priv;
316 struct resource *res;
317 struct phy_provider *provider;
0b25ff86 318 int ret, count = 0;
0d486806
BN
319
320 if (of_get_child_count(dn) == 0)
321 return -ENODEV;
322
323 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
324 if (!priv)
325 return -ENOMEM;
326 dev_set_drvdata(dev, priv);
327 priv->dev = dev;
328
329 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy");
330 priv->phy_base = devm_ioremap_resource(dev, res);
331 if (IS_ERR(priv->phy_base))
332 return PTR_ERR(priv->phy_base);
333
810c6f16
JS
334 of_id = of_match_node(brcm_sata_phy_of_match, dn);
335 if (of_id)
336 priv->version = (enum brcm_sata_phy_version)of_id->data;
337 else
4faee9a4
AP
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 }
810c6f16 347
0d486806
BN
348 for_each_available_child_of_node(dn, child) {
349 unsigned int id;
350 struct brcm_sata_port *port;
351
352 if (of_property_read_u32(child, "reg", &id)) {
353 dev_err(dev, "missing reg property in node %s\n",
354 child->name);
0b25ff86
JL
355 ret = -EINVAL;
356 goto put_child;
0d486806
BN
357 }
358
359 if (id >= MAX_PORTS) {
360 dev_err(dev, "invalid reg: %u\n", id);
0b25ff86
JL
361 ret = -EINVAL;
362 goto put_child;
0d486806
BN
363 }
364 if (priv->phys[id].phy) {
365 dev_err(dev, "already registered port %u\n", id);
0b25ff86
JL
366 ret = -EINVAL;
367 goto put_child;
0d486806
BN
368 }
369
370 port = &priv->phys[id];
371 port->portnum = id;
372 port->phy_priv = priv;
c1602a1a 373 port->phy = devm_phy_create(dev, child, &phy_ops);
0d486806
BN
374 port->ssc_en = of_property_read_bool(child, "brcm,enable-ssc");
375 if (IS_ERR(port->phy)) {
376 dev_err(dev, "failed to create PHY\n");
0b25ff86
JL
377 ret = PTR_ERR(port->phy);
378 goto put_child;
0d486806
BN
379 }
380
381 phy_set_drvdata(port->phy, port);
382 count++;
383 }
384
385 provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
386 if (IS_ERR(provider)) {
387 dev_err(dev, "could not register PHY provider\n");
388 return PTR_ERR(provider);
389 }
390
391 dev_info(dev, "registered %d port(s)\n", count);
392
393 return 0;
0b25ff86
JL
394put_child:
395 of_node_put(child);
396 return ret;
0d486806
BN
397}
398
399static struct platform_driver brcm_sata_phy_driver = {
400 .probe = brcm_sata_phy_probe,
401 .driver = {
402 .of_match_table = brcm_sata_phy_of_match,
037c4189 403 .name = "brcm-sata-phy",
0d486806
BN
404 }
405};
406module_platform_driver(brcm_sata_phy_driver);
407
037c4189 408MODULE_DESCRIPTION("Broadcom SATA PHY driver");
0d486806
BN
409MODULE_LICENSE("GPL");
410MODULE_AUTHOR("Marc Carino");
411MODULE_AUTHOR("Brian Norris");
037c4189 412MODULE_ALIAS("platform:phy-brcm-sata");