phy-spear1340-miphy.c (8183B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * ST spear1340-miphy driver 4 * 5 * Copyright (C) 2014 ST Microelectronics 6 * Pratyush Anand <pratyush.anand@gmail.com> 7 * Mohit Kumar <mohit.kumar.dhaka@gmail.com> 8 */ 9 10#include <linux/bitops.h> 11#include <linux/delay.h> 12#include <linux/dma-mapping.h> 13#include <linux/kernel.h> 14#include <linux/mfd/syscon.h> 15#include <linux/module.h> 16#include <linux/of_device.h> 17#include <linux/phy/phy.h> 18#include <linux/regmap.h> 19 20/* SPEAr1340 Registers */ 21/* Power Management Registers */ 22#define SPEAR1340_PCM_CFG 0x100 23 #define SPEAR1340_PCM_CFG_SATA_POWER_EN BIT(11) 24#define SPEAR1340_PCM_WKUP_CFG 0x104 25#define SPEAR1340_SWITCH_CTR 0x108 26 27#define SPEAR1340_PERIP1_SW_RST 0x318 28 #define SPEAR1340_PERIP1_SW_RSATA BIT(12) 29#define SPEAR1340_PERIP2_SW_RST 0x31C 30#define SPEAR1340_PERIP3_SW_RST 0x320 31 32/* PCIE - SATA configuration registers */ 33#define SPEAR1340_PCIE_SATA_CFG 0x424 34 /* PCIE CFG MASks */ 35 #define SPEAR1340_PCIE_CFG_DEVICE_PRESENT BIT(11) 36 #define SPEAR1340_PCIE_CFG_POWERUP_RESET BIT(10) 37 #define SPEAR1340_PCIE_CFG_CORE_CLK_EN BIT(9) 38 #define SPEAR1340_PCIE_CFG_AUX_CLK_EN BIT(8) 39 #define SPEAR1340_SATA_CFG_TX_CLK_EN BIT(4) 40 #define SPEAR1340_SATA_CFG_RX_CLK_EN BIT(3) 41 #define SPEAR1340_SATA_CFG_POWERUP_RESET BIT(2) 42 #define SPEAR1340_SATA_CFG_PM_CLK_EN BIT(1) 43 #define SPEAR1340_PCIE_SATA_SEL_PCIE (0) 44 #define SPEAR1340_PCIE_SATA_SEL_SATA (1) 45 #define SPEAR1340_PCIE_SATA_CFG_MASK 0xF1F 46 #define SPEAR1340_PCIE_CFG_VAL (SPEAR1340_PCIE_SATA_SEL_PCIE | \ 47 SPEAR1340_PCIE_CFG_AUX_CLK_EN | \ 48 SPEAR1340_PCIE_CFG_CORE_CLK_EN | \ 49 SPEAR1340_PCIE_CFG_POWERUP_RESET | \ 50 SPEAR1340_PCIE_CFG_DEVICE_PRESENT) 51 #define SPEAR1340_SATA_CFG_VAL (SPEAR1340_PCIE_SATA_SEL_SATA | \ 52 SPEAR1340_SATA_CFG_PM_CLK_EN | \ 53 SPEAR1340_SATA_CFG_POWERUP_RESET | \ 54 SPEAR1340_SATA_CFG_RX_CLK_EN | \ 55 SPEAR1340_SATA_CFG_TX_CLK_EN) 56 57#define SPEAR1340_PCIE_MIPHY_CFG 0x428 58 #define SPEAR1340_MIPHY_OSC_BYPASS_EXT BIT(31) 59 #define SPEAR1340_MIPHY_CLK_REF_DIV2 BIT(27) 60 #define SPEAR1340_MIPHY_CLK_REF_DIV4 (2 << 27) 61 #define SPEAR1340_MIPHY_CLK_REF_DIV8 (3 << 27) 62 #define SPEAR1340_MIPHY_PLL_RATIO_TOP(x) (x << 0) 63 #define SPEAR1340_PCIE_MIPHY_CFG_MASK 0xF80000FF 64 #define SPEAR1340_PCIE_SATA_MIPHY_CFG_SATA \ 65 (SPEAR1340_MIPHY_OSC_BYPASS_EXT | \ 66 SPEAR1340_MIPHY_CLK_REF_DIV2 | \ 67 SPEAR1340_MIPHY_PLL_RATIO_TOP(60)) 68 #define SPEAR1340_PCIE_SATA_MIPHY_CFG_SATA_25M_CRYSTAL_CLK \ 69 (SPEAR1340_MIPHY_PLL_RATIO_TOP(120)) 70 #define SPEAR1340_PCIE_SATA_MIPHY_CFG_PCIE \ 71 (SPEAR1340_MIPHY_OSC_BYPASS_EXT | \ 72 SPEAR1340_MIPHY_PLL_RATIO_TOP(25)) 73 74enum spear1340_miphy_mode { 75 SATA, 76 PCIE, 77}; 78 79struct spear1340_miphy_priv { 80 /* phy mode: 0 for SATA 1 for PCIe */ 81 enum spear1340_miphy_mode mode; 82 /* regmap for any soc specific misc registers */ 83 struct regmap *misc; 84 /* phy struct pointer */ 85 struct phy *phy; 86}; 87 88static int spear1340_miphy_sata_init(struct spear1340_miphy_priv *priv) 89{ 90 regmap_update_bits(priv->misc, SPEAR1340_PCIE_SATA_CFG, 91 SPEAR1340_PCIE_SATA_CFG_MASK, 92 SPEAR1340_SATA_CFG_VAL); 93 regmap_update_bits(priv->misc, SPEAR1340_PCIE_MIPHY_CFG, 94 SPEAR1340_PCIE_MIPHY_CFG_MASK, 95 SPEAR1340_PCIE_SATA_MIPHY_CFG_SATA_25M_CRYSTAL_CLK); 96 /* Switch on sata power domain */ 97 regmap_update_bits(priv->misc, SPEAR1340_PCM_CFG, 98 SPEAR1340_PCM_CFG_SATA_POWER_EN, 99 SPEAR1340_PCM_CFG_SATA_POWER_EN); 100 /* Wait for SATA power domain on */ 101 msleep(20); 102 103 /* Disable PCIE SATA Controller reset */ 104 regmap_update_bits(priv->misc, SPEAR1340_PERIP1_SW_RST, 105 SPEAR1340_PERIP1_SW_RSATA, 0); 106 /* Wait for SATA reset de-assert completion */ 107 msleep(20); 108 109 return 0; 110} 111 112static int spear1340_miphy_sata_exit(struct spear1340_miphy_priv *priv) 113{ 114 regmap_update_bits(priv->misc, SPEAR1340_PCIE_SATA_CFG, 115 SPEAR1340_PCIE_SATA_CFG_MASK, 0); 116 regmap_update_bits(priv->misc, SPEAR1340_PCIE_MIPHY_CFG, 117 SPEAR1340_PCIE_MIPHY_CFG_MASK, 0); 118 119 /* Enable PCIE SATA Controller reset */ 120 regmap_update_bits(priv->misc, SPEAR1340_PERIP1_SW_RST, 121 SPEAR1340_PERIP1_SW_RSATA, 122 SPEAR1340_PERIP1_SW_RSATA); 123 /* Wait for SATA power domain off */ 124 msleep(20); 125 /* Switch off sata power domain */ 126 regmap_update_bits(priv->misc, SPEAR1340_PCM_CFG, 127 SPEAR1340_PCM_CFG_SATA_POWER_EN, 0); 128 /* Wait for SATA reset assert completion */ 129 msleep(20); 130 131 return 0; 132} 133 134static int spear1340_miphy_pcie_init(struct spear1340_miphy_priv *priv) 135{ 136 regmap_update_bits(priv->misc, SPEAR1340_PCIE_MIPHY_CFG, 137 SPEAR1340_PCIE_MIPHY_CFG_MASK, 138 SPEAR1340_PCIE_SATA_MIPHY_CFG_PCIE); 139 regmap_update_bits(priv->misc, SPEAR1340_PCIE_SATA_CFG, 140 SPEAR1340_PCIE_SATA_CFG_MASK, 141 SPEAR1340_PCIE_CFG_VAL); 142 143 return 0; 144} 145 146static int spear1340_miphy_pcie_exit(struct spear1340_miphy_priv *priv) 147{ 148 regmap_update_bits(priv->misc, SPEAR1340_PCIE_MIPHY_CFG, 149 SPEAR1340_PCIE_MIPHY_CFG_MASK, 0); 150 regmap_update_bits(priv->misc, SPEAR1340_PCIE_SATA_CFG, 151 SPEAR1340_PCIE_SATA_CFG_MASK, 0); 152 153 return 0; 154} 155 156static int spear1340_miphy_init(struct phy *phy) 157{ 158 struct spear1340_miphy_priv *priv = phy_get_drvdata(phy); 159 int ret = 0; 160 161 if (priv->mode == SATA) 162 ret = spear1340_miphy_sata_init(priv); 163 else if (priv->mode == PCIE) 164 ret = spear1340_miphy_pcie_init(priv); 165 166 return ret; 167} 168 169static int spear1340_miphy_exit(struct phy *phy) 170{ 171 struct spear1340_miphy_priv *priv = phy_get_drvdata(phy); 172 int ret = 0; 173 174 if (priv->mode == SATA) 175 ret = spear1340_miphy_sata_exit(priv); 176 else if (priv->mode == PCIE) 177 ret = spear1340_miphy_pcie_exit(priv); 178 179 return ret; 180} 181 182static const struct of_device_id spear1340_miphy_of_match[] = { 183 { .compatible = "st,spear1340-miphy" }, 184 { }, 185}; 186MODULE_DEVICE_TABLE(of, spear1340_miphy_of_match); 187 188static const struct phy_ops spear1340_miphy_ops = { 189 .init = spear1340_miphy_init, 190 .exit = spear1340_miphy_exit, 191 .owner = THIS_MODULE, 192}; 193 194#ifdef CONFIG_PM_SLEEP 195static int spear1340_miphy_suspend(struct device *dev) 196{ 197 struct spear1340_miphy_priv *priv = dev_get_drvdata(dev); 198 int ret = 0; 199 200 if (priv->mode == SATA) 201 ret = spear1340_miphy_sata_exit(priv); 202 203 return ret; 204} 205 206static int spear1340_miphy_resume(struct device *dev) 207{ 208 struct spear1340_miphy_priv *priv = dev_get_drvdata(dev); 209 int ret = 0; 210 211 if (priv->mode == SATA) 212 ret = spear1340_miphy_sata_init(priv); 213 214 return ret; 215} 216#endif 217 218static SIMPLE_DEV_PM_OPS(spear1340_miphy_pm_ops, spear1340_miphy_suspend, 219 spear1340_miphy_resume); 220 221static struct phy *spear1340_miphy_xlate(struct device *dev, 222 struct of_phandle_args *args) 223{ 224 struct spear1340_miphy_priv *priv = dev_get_drvdata(dev); 225 226 if (args->args_count < 1) { 227 dev_err(dev, "DT did not pass correct no of args\n"); 228 return ERR_PTR(-ENODEV); 229 } 230 231 priv->mode = args->args[0]; 232 233 if (priv->mode != SATA && priv->mode != PCIE) { 234 dev_err(dev, "DT did not pass correct phy mode\n"); 235 return ERR_PTR(-ENODEV); 236 } 237 238 return priv->phy; 239} 240 241static int spear1340_miphy_probe(struct platform_device *pdev) 242{ 243 struct device *dev = &pdev->dev; 244 struct spear1340_miphy_priv *priv; 245 struct phy_provider *phy_provider; 246 247 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 248 if (!priv) 249 return -ENOMEM; 250 251 priv->misc = 252 syscon_regmap_lookup_by_phandle(dev->of_node, "misc"); 253 if (IS_ERR(priv->misc)) { 254 dev_err(dev, "failed to find misc regmap\n"); 255 return PTR_ERR(priv->misc); 256 } 257 258 priv->phy = devm_phy_create(dev, NULL, &spear1340_miphy_ops); 259 if (IS_ERR(priv->phy)) { 260 dev_err(dev, "failed to create SATA PCIe PHY\n"); 261 return PTR_ERR(priv->phy); 262 } 263 264 dev_set_drvdata(dev, priv); 265 phy_set_drvdata(priv->phy, priv); 266 267 phy_provider = 268 devm_of_phy_provider_register(dev, spear1340_miphy_xlate); 269 if (IS_ERR(phy_provider)) { 270 dev_err(dev, "failed to register phy provider\n"); 271 return PTR_ERR(phy_provider); 272 } 273 274 return 0; 275} 276 277static struct platform_driver spear1340_miphy_driver = { 278 .probe = spear1340_miphy_probe, 279 .driver = { 280 .name = "spear1340-miphy", 281 .pm = &spear1340_miphy_pm_ops, 282 .of_match_table = of_match_ptr(spear1340_miphy_of_match), 283 }, 284}; 285 286module_platform_driver(spear1340_miphy_driver); 287 288MODULE_DESCRIPTION("ST SPEAR1340-MIPHY driver"); 289MODULE_AUTHOR("Pratyush Anand <pratyush.anand@gmail.com>"); 290MODULE_LICENSE("GPL v2");