]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/phy/phy-brcm-sata.c
Merge branch 'hash' of git://ftp.sciencehorizons.net/linux
[karo-tx-linux.git] / drivers / phy / phy-brcm-sata.c
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 };
49
50 struct brcm_sata_port {
51         int portnum;
52         struct phy *phy;
53         struct brcm_sata_phy *phy_priv;
54         bool ssc_en;
55 };
56
57 struct brcm_sata_phy {
58         struct device *dev;
59         void __iomem *phy_base;
60         void __iomem *ctrl_base;
61         enum brcm_sata_phy_version version;
62
63         struct brcm_sata_port phys[MAX_PORTS];
64 };
65
66 enum 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,
75         PLL_REG_BANK_0_PLLCONTROL_0             = 0x81,
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
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
113 enum sata_phy_ctrl_regs {
114         PHY_CTRL_1                              = 0x0,
115         PHY_CTRL_1_RESET                        = BIT(0),
116 };
117
118 static inline void __iomem *brcm_sata_pcb_base(struct brcm_sata_port *port)
119 {
120         struct brcm_sata_phy *priv = port->phy_priv;
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         };
135
136         return priv->phy_base + (port->portnum * size);
137 }
138
139 static 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:
149                 dev_err(priv->dev, "invalid phy version\n");
150                 break;
151         };
152
153         return priv->ctrl_base + (port->portnum * size);
154 }
155
156 static void brcm_sata_phy_wr(void __iomem *pcb_base, u32 bank,
157                              u32 ofs, u32 msk, u32 value)
158 {
159         u32 tmp;
160
161         writel(bank, pcb_base + SATA_PCB_BANK_OFFSET);
162         tmp = readl(pcb_base + SATA_PCB_REG_OFFSET(ofs));
163         tmp = (tmp & msk) | value;
164         writel(tmp, pcb_base + SATA_PCB_REG_OFFSET(ofs));
165 }
166
167 static 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));
171 }
172
173 /* These defaults were characterized by H/W group */
174 #define STB_FMIN_VAL_DEFAULT    0x3df
175 #define STB_FMAX_VAL_DEFAULT    0x3df
176 #define STB_FMAX_VAL_SSC        0x83
177
178 static int brcm_stb_sata_init(struct brcm_sata_port *port)
179 {
180         void __iomem *base = brcm_sata_pcb_base(port);
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;
186         brcm_sata_phy_wr(base, TXPMD_REG_BANK, TXPMD_CONTROL1, ~tmp, tmp);
187
188         /* set fixed min freq */
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);
192
193         /* set fixed max freq depending on SSC config */
194         if (port->ssc_en) {
195                 dev_info(priv->dev, "enabling SSC on port%d\n", port->portnum);
196                 tmp = STB_FMAX_VAL_SSC;
197         } else {
198                 tmp = STB_FMAX_VAL_DEFAULT;
199         }
200
201         brcm_sata_phy_wr(base, TXPMD_REG_BANK, TXPMD_TX_FREQ_CTRL_CONTROL3,
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
212 static 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;
272 }
273
274 static int brcm_sata_phy_init(struct phy *phy)
275 {
276         int rc;
277         struct brcm_sata_port *port = phy_get_drvdata(phy);
278
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         };
290
291         return 0;
292 }
293
294 static const struct phy_ops phy_ops = {
295         .init           = brcm_sata_phy_init,
296         .owner          = THIS_MODULE,
297 };
298
299 static const struct of_device_id brcm_sata_phy_of_match[] = {
300         { .compatible   = "brcm,bcm7445-sata-phy",
301           .data = (void *)BRCM_SATA_PHY_STB_28NM },
302         { .compatible   = "brcm,bcm7425-sata-phy",
303           .data = (void *)BRCM_SATA_PHY_STB_40NM },
304         { .compatible   = "brcm,iproc-ns2-sata-phy",
305           .data = (void *)BRCM_SATA_PHY_IPROC_NS2 },
306         {},
307 };
308 MODULE_DEVICE_TABLE(of, brcm_sata_phy_of_match);
309
310 static 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;
314         const struct of_device_id *of_id;
315         struct brcm_sata_phy *priv;
316         struct resource *res;
317         struct phy_provider *provider;
318         int ret, count = 0;
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
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
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         }
347
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);
355                         ret = -EINVAL;
356                         goto put_child;
357                 }
358
359                 if (id >= MAX_PORTS) {
360                         dev_err(dev, "invalid reg: %u\n", id);
361                         ret = -EINVAL;
362                         goto put_child;
363                 }
364                 if (priv->phys[id].phy) {
365                         dev_err(dev, "already registered port %u\n", id);
366                         ret = -EINVAL;
367                         goto put_child;
368                 }
369
370                 port = &priv->phys[id];
371                 port->portnum = id;
372                 port->phy_priv = priv;
373                 port->phy = devm_phy_create(dev, child, &phy_ops);
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");
377                         ret = PTR_ERR(port->phy);
378                         goto put_child;
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;
394 put_child:
395         of_node_put(child);
396         return ret;
397 }
398
399 static struct platform_driver brcm_sata_phy_driver = {
400         .probe  = brcm_sata_phy_probe,
401         .driver = {
402                 .of_match_table = brcm_sata_phy_of_match,
403                 .name           = "brcm-sata-phy",
404         }
405 };
406 module_platform_driver(brcm_sata_phy_driver);
407
408 MODULE_DESCRIPTION("Broadcom SATA PHY driver");
409 MODULE_LICENSE("GPL");
410 MODULE_AUTHOR("Marc Carino");
411 MODULE_AUTHOR("Brian Norris");
412 MODULE_ALIAS("platform:phy-brcm-sata");