ASoC: dwc: Disallow building designware_pcm as a module
[sfrench/cifs-2.6.git] / drivers / phy / phy-bcm-nsp-usb3.c
1 /*
2  * Copyright (C) 2016 Broadcom
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation version 2.
7  *
8  * This program is distributed "as is" WITHOUT ANY WARRANTY of any
9  * kind, whether express or implied; without even the implied warranty
10  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  */
13
14 #include <linux/delay.h>
15 #include <linux/io.h>
16 #include <linux/kernel.h>
17 #include <linux/mfd/syscon.h>
18 #include <linux/mdio.h>
19 #include <linux/module.h>
20 #include <linux/of.h>
21 #include <linux/of_address.h>
22 #include <linux/phy/phy.h>
23 #include <linux/regmap.h>
24
25 #define NSP_USB3_RST_CTRL_OFFSET        0x3f8
26
27 /* mdio reg access */
28 #define NSP_USB3_PHY_BASE_ADDR_REG      0x1f
29
30 #define NSP_USB3_PHY_PLL30_BLOCK        0x8000
31 #define NSP_USB3_PLL_CONTROL            0x01
32 #define NSP_USB3_PLLA_CONTROL0          0x0a
33 #define NSP_USB3_PLLA_CONTROL1          0x0b
34
35 #define NSP_USB3_PHY_TX_PMD_BLOCK       0x8040
36 #define NSP_USB3_TX_PMD_CONTROL1        0x01
37
38 #define NSP_USB3_PHY_PIPE_BLOCK         0x8060
39 #define NSP_USB3_LFPS_CMP               0x02
40 #define NSP_USB3_LFPS_DEGLITCH          0x03
41
42 struct nsp_usb3_phy {
43         struct regmap *usb3_ctrl;
44         struct phy *phy;
45         struct mdio_device *mdiodev;
46 };
47
48 static int nsp_usb3_phy_init(struct phy *phy)
49 {
50         struct nsp_usb3_phy *iphy = phy_get_drvdata(phy);
51         struct mii_bus *bus = iphy->mdiodev->bus;
52         int addr = iphy->mdiodev->addr;
53         u32 data;
54         int rc;
55
56         rc = regmap_read(iphy->usb3_ctrl, 0, &data);
57         if (rc)
58                 return rc;
59         data |= 1;
60         rc = regmap_write(iphy->usb3_ctrl, 0, data);
61         if (rc)
62                 return rc;
63
64         rc = regmap_write(iphy->usb3_ctrl, NSP_USB3_RST_CTRL_OFFSET, 1);
65         if (rc)
66                 return rc;
67
68         rc = mdiobus_write(bus, addr, NSP_USB3_PHY_BASE_ADDR_REG,
69                            NSP_USB3_PHY_PLL30_BLOCK);
70         if (rc)
71                 return rc;
72
73         rc = mdiobus_write(bus, addr, NSP_USB3_PLL_CONTROL, 0x1000);
74         if (rc)
75                 return rc;
76
77         rc = mdiobus_write(bus, addr, NSP_USB3_PLLA_CONTROL0, 0x6400);
78         if (rc)
79                 return rc;
80
81         rc = mdiobus_write(bus, addr, NSP_USB3_PLLA_CONTROL1, 0xc000);
82         if (rc)
83                 return rc;
84
85         rc = mdiobus_write(bus, addr, NSP_USB3_PLLA_CONTROL1, 0x8000);
86         if (rc)
87                 return rc;
88
89         rc = regmap_write(iphy->usb3_ctrl, NSP_USB3_RST_CTRL_OFFSET, 0);
90         if (rc)
91                 return rc;
92
93         rc = mdiobus_write(bus, addr, NSP_USB3_PLL_CONTROL, 0x9000);
94         if (rc)
95                 return rc;
96
97         rc = mdiobus_write(bus, addr, NSP_USB3_PHY_BASE_ADDR_REG,
98                            NSP_USB3_PHY_PIPE_BLOCK);
99         if (rc)
100                 return rc;
101
102         rc = mdiobus_write(bus, addr, NSP_USB3_LFPS_CMP, 0xf30d);
103         if (rc)
104                 return rc;
105
106         rc = mdiobus_write(bus, addr, NSP_USB3_LFPS_DEGLITCH, 0x6302);
107         if (rc)
108                 return rc;
109
110         rc = mdiobus_write(bus, addr, NSP_USB3_PHY_BASE_ADDR_REG,
111                            NSP_USB3_PHY_TX_PMD_BLOCK);
112         if (rc)
113                 return rc;
114
115         rc = mdiobus_write(bus, addr, NSP_USB3_TX_PMD_CONTROL1, 0x1003);
116
117         return rc;
118 }
119
120 static struct phy_ops nsp_usb3_phy_ops = {
121         .init   = nsp_usb3_phy_init,
122         .owner  = THIS_MODULE,
123 };
124
125 static int nsp_usb3_phy_probe(struct mdio_device *mdiodev)
126 {
127         struct device *dev = &mdiodev->dev;
128         struct phy_provider *provider;
129         struct nsp_usb3_phy *iphy;
130
131         iphy = devm_kzalloc(dev, sizeof(*iphy), GFP_KERNEL);
132         if (!iphy)
133                 return -ENOMEM;
134         iphy->mdiodev = mdiodev;
135
136         iphy->usb3_ctrl = syscon_regmap_lookup_by_phandle(dev->of_node,
137                                                  "usb3-ctrl-syscon");
138         if (IS_ERR(iphy->usb3_ctrl))
139                 return PTR_ERR(iphy->usb3_ctrl);
140
141         iphy->phy = devm_phy_create(dev, dev->of_node, &nsp_usb3_phy_ops);
142         if (IS_ERR(iphy->phy)) {
143                 dev_err(dev, "failed to create PHY\n");
144                 return PTR_ERR(iphy->phy);
145         }
146
147         phy_set_drvdata(iphy->phy, iphy);
148
149         provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
150         if (IS_ERR(provider)) {
151                 dev_err(dev, "could not register PHY provider\n");
152                 return PTR_ERR(provider);
153         }
154
155         return 0;
156 }
157
158 static const struct of_device_id nsp_usb3_phy_of_match[] = {
159         {.compatible = "brcm,nsp-usb3-phy",},
160         { /* sentinel */ }
161 };
162
163 static struct mdio_driver nsp_usb3_phy_driver = {
164         .mdiodrv = {
165                 .driver = {
166                         .name = "nsp-usb3-phy",
167                         .of_match_table = nsp_usb3_phy_of_match,
168                 },
169         },
170         .probe = nsp_usb3_phy_probe,
171 };
172
173 mdio_module_driver(nsp_usb3_phy_driver);
174
175 MODULE_DESCRIPTION("Broadcom NSP USB3 PHY driver");
176 MODULE_LICENSE("GPL v2");
177 MODULE_AUTHOR("Yendapally Reddy Dhananjaya Reddy <yendapally.reddy@broadcom.com");