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