1/*
2 * Marvell Berlin SATA PHY driver
3 *
4 * Copyright (C) 2014 Marvell Technology Group Ltd.
5 *
6 * Antoine Ténart <antoine.tenart@free-electrons.com>
7 *
8 * This file is licensed under the terms of the GNU General Public
9 * License version 2. This program is licensed "as is" without any
10 * warranty of any kind, whether express or implied.
11 */
12
13#include <linux/clk.h>
14#include <linux/module.h>
15#include <linux/phy/phy.h>
16#include <linux/io.h>
17#include <linux/platform_device.h>
18
19#define HOST_VSA_ADDR		0x0
20#define HOST_VSA_DATA		0x4
21#define PORT_SCR_CTL		0x2c
22#define PORT_VSR_ADDR		0x78
23#define PORT_VSR_DATA		0x7c
24
25#define CONTROL_REGISTER	0x0
26#define MBUS_SIZE_CONTROL	0x4
27
28#define POWER_DOWN_PHY0			BIT(6)
29#define POWER_DOWN_PHY1			BIT(14)
30#define MBUS_WRITE_REQUEST_SIZE_128	(BIT(2) << 16)
31#define MBUS_READ_REQUEST_SIZE_128	(BIT(2) << 19)
32
33#define BG2_PHY_BASE		0x080
34#define BG2Q_PHY_BASE		0x200
35
36/* register 0x01 */
37#define REF_FREF_SEL_25		BIT(0)
38#define PHY_MODE_SATA		(0x0 << 5)
39
40/* register 0x02 */
41#define USE_MAX_PLL_RATE	BIT(12)
42
43/* register 0x23 */
44#define DATA_BIT_WIDTH_10	(0x0 << 10)
45#define DATA_BIT_WIDTH_20	(0x1 << 10)
46#define DATA_BIT_WIDTH_40	(0x2 << 10)
47
48/* register 0x25 */
49#define PHY_GEN_MAX_1_5		(0x0 << 10)
50#define PHY_GEN_MAX_3_0		(0x1 << 10)
51#define PHY_GEN_MAX_6_0		(0x2 << 10)
52
53struct phy_berlin_desc {
54	struct phy	*phy;
55	u32		power_bit;
56	unsigned	index;
57};
58
59struct phy_berlin_priv {
60	void __iomem		*base;
61	spinlock_t		lock;
62	struct clk		*clk;
63	struct phy_berlin_desc	**phys;
64	unsigned		nphys;
65	u32			phy_base;
66};
67
68static inline void phy_berlin_sata_reg_setbits(void __iomem *ctrl_reg,
69			       u32 phy_base, u32 reg, u32 mask, u32 val)
70{
71	u32 regval;
72
73	/* select register */
74	writel(phy_base + reg, ctrl_reg + PORT_VSR_ADDR);
75
76	/* set bits */
77	regval = readl(ctrl_reg + PORT_VSR_DATA);
78	regval &= ~mask;
79	regval |= val;
80	writel(regval, ctrl_reg + PORT_VSR_DATA);
81}
82
83static int phy_berlin_sata_power_on(struct phy *phy)
84{
85	struct phy_berlin_desc *desc = phy_get_drvdata(phy);
86	struct phy_berlin_priv *priv = dev_get_drvdata(phy->dev.parent);
87	void __iomem *ctrl_reg = priv->base + 0x60 + (desc->index * 0x80);
88	int ret = 0;
89	u32 regval;
90
91	clk_prepare_enable(priv->clk);
92
93	spin_lock(&priv->lock);
94
95	/* Power on PHY */
96	writel(CONTROL_REGISTER, priv->base + HOST_VSA_ADDR);
97	regval = readl(priv->base + HOST_VSA_DATA);
98	regval &= ~desc->power_bit;
99	writel(regval, priv->base + HOST_VSA_DATA);
100
101	/* Configure MBus */
102	writel(MBUS_SIZE_CONTROL, priv->base + HOST_VSA_ADDR);
103	regval = readl(priv->base + HOST_VSA_DATA);
104	regval |= MBUS_WRITE_REQUEST_SIZE_128 | MBUS_READ_REQUEST_SIZE_128;
105	writel(regval, priv->base + HOST_VSA_DATA);
106
107	/* set PHY mode and ref freq to 25 MHz */
108	phy_berlin_sata_reg_setbits(ctrl_reg, priv->phy_base, 0x01,
109				    0x00ff, REF_FREF_SEL_25 | PHY_MODE_SATA);
110
111	/* set PHY up to 6 Gbps */
112	phy_berlin_sata_reg_setbits(ctrl_reg, priv->phy_base, 0x25,
113				    0x0c00, PHY_GEN_MAX_6_0);
114
115	/* set 40 bits width */
116	phy_berlin_sata_reg_setbits(ctrl_reg, priv->phy_base, 0x23,
117				    0x0c00, DATA_BIT_WIDTH_40);
118
119	/* use max pll rate */
120	phy_berlin_sata_reg_setbits(ctrl_reg, priv->phy_base, 0x02,
121				    0x0000, USE_MAX_PLL_RATE);
122
123	/* set Gen3 controller speed */
124	regval = readl(ctrl_reg + PORT_SCR_CTL);
125	regval &= ~GENMASK(7, 4);
126	regval |= 0x30;
127	writel(regval, ctrl_reg + PORT_SCR_CTL);
128
129	spin_unlock(&priv->lock);
130
131	clk_disable_unprepare(priv->clk);
132
133	return ret;
134}
135
136static int phy_berlin_sata_power_off(struct phy *phy)
137{
138	struct phy_berlin_desc *desc = phy_get_drvdata(phy);
139	struct phy_berlin_priv *priv = dev_get_drvdata(phy->dev.parent);
140	u32 regval;
141
142	clk_prepare_enable(priv->clk);
143
144	spin_lock(&priv->lock);
145
146	/* Power down PHY */
147	writel(CONTROL_REGISTER, priv->base + HOST_VSA_ADDR);
148	regval = readl(priv->base + HOST_VSA_DATA);
149	regval |= desc->power_bit;
150	writel(regval, priv->base + HOST_VSA_DATA);
151
152	spin_unlock(&priv->lock);
153
154	clk_disable_unprepare(priv->clk);
155
156	return 0;
157}
158
159static struct phy *phy_berlin_sata_phy_xlate(struct device *dev,
160					     struct of_phandle_args *args)
161{
162	struct phy_berlin_priv *priv = dev_get_drvdata(dev);
163	int i;
164
165	if (WARN_ON(args->args[0] >= priv->nphys))
166		return ERR_PTR(-ENODEV);
167
168	for (i = 0; i < priv->nphys; i++) {
169		if (priv->phys[i]->index == args->args[0])
170			break;
171	}
172
173	if (i == priv->nphys)
174		return ERR_PTR(-ENODEV);
175
176	return priv->phys[i]->phy;
177}
178
179static struct phy_ops phy_berlin_sata_ops = {
180	.power_on	= phy_berlin_sata_power_on,
181	.power_off	= phy_berlin_sata_power_off,
182	.owner		= THIS_MODULE,
183};
184
185static u32 phy_berlin_power_down_bits[] = {
186	POWER_DOWN_PHY0,
187	POWER_DOWN_PHY1,
188};
189
190static int phy_berlin_sata_probe(struct platform_device *pdev)
191{
192	struct device *dev = &pdev->dev;
193	struct device_node *child;
194	struct phy *phy;
195	struct phy_provider *phy_provider;
196	struct phy_berlin_priv *priv;
197	struct resource *res;
198	int i = 0;
199	u32 phy_id;
200
201	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
202	if (!priv)
203		return -ENOMEM;
204
205	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
206	if (!res)
207		return -EINVAL;
208
209	priv->base = devm_ioremap(dev, res->start, resource_size(res));
210	if (!priv->base)
211		return -ENOMEM;
212
213	priv->clk = devm_clk_get(dev, NULL);
214	if (IS_ERR(priv->clk))
215		return PTR_ERR(priv->clk);
216
217	priv->nphys = of_get_child_count(dev->of_node);
218	if (priv->nphys == 0)
219		return -ENODEV;
220
221	priv->phys = devm_kcalloc(dev, priv->nphys, sizeof(*priv->phys),
222				  GFP_KERNEL);
223	if (!priv->phys)
224		return -ENOMEM;
225
226	if (of_device_is_compatible(dev->of_node, "marvell,berlin2-sata-phy"))
227		priv->phy_base = BG2_PHY_BASE;
228	else
229		priv->phy_base = BG2Q_PHY_BASE;
230
231	dev_set_drvdata(dev, priv);
232	spin_lock_init(&priv->lock);
233
234	for_each_available_child_of_node(dev->of_node, child) {
235		struct phy_berlin_desc *phy_desc;
236
237		if (of_property_read_u32(child, "reg", &phy_id)) {
238			dev_err(dev, "missing reg property in node %s\n",
239				child->name);
240			return -EINVAL;
241		}
242
243		if (phy_id >= ARRAY_SIZE(phy_berlin_power_down_bits)) {
244			dev_err(dev, "invalid reg in node %s\n", child->name);
245			return -EINVAL;
246		}
247
248		phy_desc = devm_kzalloc(dev, sizeof(*phy_desc), GFP_KERNEL);
249		if (!phy_desc)
250			return -ENOMEM;
251
252		phy = devm_phy_create(dev, NULL, &phy_berlin_sata_ops);
253		if (IS_ERR(phy)) {
254			dev_err(dev, "failed to create PHY %d\n", phy_id);
255			return PTR_ERR(phy);
256		}
257
258		phy_desc->phy = phy;
259		phy_desc->power_bit = phy_berlin_power_down_bits[phy_id];
260		phy_desc->index = phy_id;
261		phy_set_drvdata(phy, phy_desc);
262
263		priv->phys[i++] = phy_desc;
264
265		/* Make sure the PHY is off */
266		phy_berlin_sata_power_off(phy);
267	}
268
269	phy_provider =
270		devm_of_phy_provider_register(dev, phy_berlin_sata_phy_xlate);
271	return PTR_ERR_OR_ZERO(phy_provider);
272}
273
274static const struct of_device_id phy_berlin_sata_of_match[] = {
275	{ .compatible = "marvell,berlin2-sata-phy" },
276	{ .compatible = "marvell,berlin2q-sata-phy" },
277	{ },
278};
279
280static struct platform_driver phy_berlin_sata_driver = {
281	.probe	= phy_berlin_sata_probe,
282	.driver	= {
283		.name		= "phy-berlin-sata",
284		.of_match_table	= phy_berlin_sata_of_match,
285	},
286};
287module_platform_driver(phy_berlin_sata_driver);
288
289MODULE_DESCRIPTION("Marvell Berlin SATA PHY driver");
290MODULE_AUTHOR("Antoine Ténart <antoine.tenart@free-electrons.com>");
291MODULE_LICENSE("GPL v2");
292