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