SPEAr1310 and SPEAr1340 uses miphy40lp phy for PCIe. This driver adds
support for the same.

Signed-off-by: Pratyush Anand <pratyush.an...@st.com>
Tested-by: Mohit Kumar <mohit.ku...@st.com>
Cc: Arnd Bergmann <a...@arndb.de>
Cc: Kishon Vijay Abraham I <kis...@ti.com>
Cc: spear-de...@list.st.com
Cc: linux-arm-ker...@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/phy/phy-miphy40lp.c | 178 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 178 insertions(+)

diff --git a/drivers/phy/phy-miphy40lp.c b/drivers/phy/phy-miphy40lp.c
index cc7f45d..61e94be 100644
--- a/drivers/phy/phy-miphy40lp.c
+++ b/drivers/phy/phy-miphy40lp.c
@@ -9,6 +9,7 @@
  * published by the Free Software Foundation.
  *
  * 04/02/2014: Adding support of SATA mode for SPEAr1340.
+ * 04/02/2014: Adding support of PCIe mode for SPEAr1340 and SPEAr1310
  */
 
 #include <linux/delay.h>
@@ -73,6 +74,80 @@
        #define SPEAR1340_PCIE_SATA_MIPHY_CFG_PCIE \
                        (SPEAR1340_MIPHY_OSC_BYPASS_EXT | \
                        SPEAR1340_MIPHY_PLL_RATIO_TOP(25))
+/* SPEAr1310 Registers */
+#define SPEAR1310_PCIE_SATA_CFG                        0x3A4
+       #define SPEAR1310_PCIE_SATA2_SEL_PCIE           (0 << 31)
+       #define SPEAR1310_PCIE_SATA1_SEL_PCIE           (0 << 30)
+       #define SPEAR1310_PCIE_SATA0_SEL_PCIE           (0 << 29)
+       #define SPEAR1310_PCIE_SATA2_SEL_SATA           (1 << 31)
+       #define SPEAR1310_PCIE_SATA1_SEL_SATA           (1 << 30)
+       #define SPEAR1310_PCIE_SATA0_SEL_SATA           (1 << 29)
+       #define SPEAR1310_SATA2_CFG_TX_CLK_EN           (1 << 27)
+       #define SPEAR1310_SATA2_CFG_RX_CLK_EN           (1 << 26)
+       #define SPEAR1310_SATA2_CFG_POWERUP_RESET       (1 << 25)
+       #define SPEAR1310_SATA2_CFG_PM_CLK_EN           (1 << 24)
+       #define SPEAR1310_SATA1_CFG_TX_CLK_EN           (1 << 23)
+       #define SPEAR1310_SATA1_CFG_RX_CLK_EN           (1 << 22)
+       #define SPEAR1310_SATA1_CFG_POWERUP_RESET       (1 << 21)
+       #define SPEAR1310_SATA1_CFG_PM_CLK_EN           (1 << 20)
+       #define SPEAR1310_SATA0_CFG_TX_CLK_EN           (1 << 19)
+       #define SPEAR1310_SATA0_CFG_RX_CLK_EN           (1 << 18)
+       #define SPEAR1310_SATA0_CFG_POWERUP_RESET       (1 << 17)
+       #define SPEAR1310_SATA0_CFG_PM_CLK_EN           (1 << 16)
+       #define SPEAR1310_PCIE2_CFG_DEVICE_PRESENT      (1 << 11)
+       #define SPEAR1310_PCIE2_CFG_POWERUP_RESET       (1 << 10)
+       #define SPEAR1310_PCIE2_CFG_CORE_CLK_EN         (1 << 9)
+       #define SPEAR1310_PCIE2_CFG_AUX_CLK_EN          (1 << 8)
+       #define SPEAR1310_PCIE1_CFG_DEVICE_PRESENT      (1 << 7)
+       #define SPEAR1310_PCIE1_CFG_POWERUP_RESET       (1 << 6)
+       #define SPEAR1310_PCIE1_CFG_CORE_CLK_EN         (1 << 5)
+       #define SPEAR1310_PCIE1_CFG_AUX_CLK_EN          (1 << 4)
+       #define SPEAR1310_PCIE0_CFG_DEVICE_PRESENT      (1 << 3)
+       #define SPEAR1310_PCIE0_CFG_POWERUP_RESET       (1 << 2)
+       #define SPEAR1310_PCIE0_CFG_CORE_CLK_EN         (1 << 1)
+       #define SPEAR1310_PCIE0_CFG_AUX_CLK_EN          (1 << 0)
+
+       #define SPEAR1310_PCIE_CFG_MASK(x) ((0xF << (x * 4)) | (1 << (x + 29)))
+       #define SPEAR1310_SATA_CFG_MASK(x) ((0xF << (x * 4 + 16)) | \
+                       (1 << (x + 29)))
+       #define SPEAR1310_PCIE_CFG_VAL(x) \
+                       (SPEAR1310_PCIE_SATA##x##_SEL_PCIE | \
+                       SPEAR1310_PCIE##x##_CFG_AUX_CLK_EN | \
+                       SPEAR1310_PCIE##x##_CFG_CORE_CLK_EN | \
+                       SPEAR1310_PCIE##x##_CFG_POWERUP_RESET | \
+                       SPEAR1310_PCIE##x##_CFG_DEVICE_PRESENT)
+       #define SPEAR1310_SATA_CFG_VAL(x) \
+                       (SPEAR1310_PCIE_SATA##x##_SEL_SATA | \
+                       SPEAR1310_SATA##x##_CFG_PM_CLK_EN | \
+                       SPEAR1310_SATA##x##_CFG_POWERUP_RESET | \
+                       SPEAR1310_SATA##x##_CFG_RX_CLK_EN | \
+                       SPEAR1310_SATA##x##_CFG_TX_CLK_EN)
+
+#define SPEAR1310_PCIE_MIPHY_CFG_1             0x3A8
+       #define SPEAR1310_MIPHY_DUAL_OSC_BYPASS_EXT     (1 << 31)
+       #define SPEAR1310_MIPHY_DUAL_CLK_REF_DIV2       (1 << 28)
+       #define SPEAR1310_MIPHY_DUAL_PLL_RATIO_TOP(x)   (x << 16)
+       #define SPEAR1310_MIPHY_SINGLE_OSC_BYPASS_EXT   (1 << 15)
+       #define SPEAR1310_MIPHY_SINGLE_CLK_REF_DIV2     (1 << 12)
+       #define SPEAR1310_MIPHY_SINGLE_PLL_RATIO_TOP(x) (x << 0)
+       #define SPEAR1310_PCIE_SATA_MIPHY_CFG_SATA_MASK (0xFFFF)
+       #define SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE_MASK (0xFFFF << 16)
+       #define SPEAR1310_PCIE_SATA_MIPHY_CFG_SATA \
+                       (SPEAR1310_MIPHY_DUAL_OSC_BYPASS_EXT | \
+                       SPEAR1310_MIPHY_DUAL_CLK_REF_DIV2 | \
+                       SPEAR1310_MIPHY_DUAL_PLL_RATIO_TOP(60) | \
+                       SPEAR1310_MIPHY_SINGLE_OSC_BYPASS_EXT | \
+                       SPEAR1310_MIPHY_SINGLE_CLK_REF_DIV2 | \
+                       SPEAR1310_MIPHY_SINGLE_PLL_RATIO_TOP(60))
+       #define SPEAR1310_PCIE_SATA_MIPHY_CFG_SATA_25M_CRYSTAL_CLK \
+                       (SPEAR1310_MIPHY_SINGLE_PLL_RATIO_TOP(120))
+       #define SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE \
+                       (SPEAR1310_MIPHY_DUAL_OSC_BYPASS_EXT | \
+                       SPEAR1310_MIPHY_DUAL_PLL_RATIO_TOP(25) | \
+                       SPEAR1310_MIPHY_SINGLE_OSC_BYPASS_EXT | \
+                       SPEAR1310_MIPHY_SINGLE_PLL_RATIO_TOP(25))
+
+#define SPEAR1310_PCIE_MIPHY_CFG_2             0x3AC
 
 enum phy_mode {
        SATA,
@@ -181,6 +256,104 @@ static int sata_miphy_resume(struct st_miphy40lp_priv 
*phypriv)
                return -EINVAL;
 }
 
+static int spear1340_pcie_miphy_init(struct st_miphy40lp_priv *phypriv)
+{
+       regmap_update_bits(phypriv->misc, SPEAR1340_PCIE_MIPHY_CFG,
+                       SPEAR1340_PCIE_MIPHY_CFG_MASK,
+                       SPEAR1340_PCIE_SATA_MIPHY_CFG_PCIE);
+       regmap_update_bits(phypriv->misc, SPEAR1340_PCIE_SATA_CFG,
+                       SPEAR1340_PCIE_SATA_CFG_MASK, SPEAR1340_PCIE_CFG_VAL);
+
+       return 0;
+}
+
+static int spear1340_pcie_miphy_exit(struct st_miphy40lp_priv *phypriv)
+{
+       regmap_update_bits(phypriv->misc, SPEAR1340_PCIE_MIPHY_CFG,
+                       SPEAR1340_PCIE_MIPHY_CFG_MASK, 0);
+       regmap_update_bits(phypriv->misc, SPEAR1340_PCIE_SATA_CFG,
+                       SPEAR1340_PCIE_SATA_CFG_MASK, 0);
+
+       return 0;
+}
+
+static int spear1310_pcie_miphy_init(struct st_miphy40lp_priv *phypriv)
+{
+       u32 mask, val;
+
+       regmap_update_bits(phypriv->misc, SPEAR1310_PCIE_MIPHY_CFG_1,
+                       SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE_MASK,
+                       SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE);
+
+       switch (phypriv->id) {
+       case 0:
+               mask = SPEAR1310_PCIE_CFG_MASK(0);
+               val = SPEAR1310_PCIE_CFG_VAL(0);
+               break;
+       case 1:
+               mask = SPEAR1310_PCIE_CFG_MASK(1);
+               val = SPEAR1310_PCIE_CFG_VAL(1);
+               break;
+       case 2:
+               mask = SPEAR1310_PCIE_CFG_MASK(2);
+               val = SPEAR1310_PCIE_CFG_VAL(2);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       regmap_update_bits(phypriv->misc, SPEAR1310_PCIE_SATA_CFG, mask, val);
+
+       return 0;
+}
+
+static int spear1310_pcie_miphy_exit(struct st_miphy40lp_priv *phypriv)
+{
+       u32 mask;
+
+       switch (phypriv->id) {
+       case 0:
+               mask = SPEAR1310_PCIE_CFG_MASK(0);
+               break;
+       case 1:
+               mask = SPEAR1310_PCIE_CFG_MASK(1);
+               break;
+       case 2:
+               mask = SPEAR1310_PCIE_CFG_MASK(2);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       regmap_update_bits(phypriv->misc, SPEAR1310_PCIE_SATA_CFG,
+                       SPEAR1310_PCIE_CFG_MASK(phypriv->id), 0);
+
+       regmap_update_bits(phypriv->misc, SPEAR1310_PCIE_MIPHY_CFG_1,
+                       SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE_MASK, 0);
+
+       return 0;
+}
+
+static int pcie_miphy_init(struct st_miphy40lp_priv *phypriv)
+{
+       if (of_device_is_compatible(phypriv->np, "st,spear1340-miphy"))
+               return spear1340_pcie_miphy_init(phypriv);
+       else if (of_device_is_compatible(phypriv->np, "st,spear1310-miphy"))
+               return spear1310_pcie_miphy_init(phypriv);
+       else
+               return -EINVAL;
+}
+
+static int pcie_miphy_exit(struct st_miphy40lp_priv *phypriv)
+{
+       if (of_device_is_compatible(phypriv->np, "st,spear1340-miphy"))
+               return spear1340_pcie_miphy_exit(phypriv);
+       else if (of_device_is_compatible(phypriv->np, "st,spear1310-miphy"))
+               return spear1310_pcie_miphy_exit(phypriv);
+       else
+               return -EINVAL;
+}
+
 static int miphy40lp_init(struct phy *phy)
 {
        struct st_miphy40lp_priv *phypriv = phy_get_drvdata(phy);
@@ -188,6 +361,8 @@ static int miphy40lp_init(struct phy *phy)
        switch (phypriv->mode) {
        case SATA:
                return sata_miphy_init(phypriv);
+       case PCIE:
+               return pcie_miphy_init(phypriv);
        default:
                return -EINVAL;
        }
@@ -200,6 +375,8 @@ static int miphy40lp_exit(struct phy *phy)
        switch (phypriv->mode) {
        case SATA:
                return sata_miphy_exit(phypriv);
+       case PCIE:
+               return pcie_miphy_exit(phypriv);
        default:
                return -EINVAL;
        }
@@ -232,6 +409,7 @@ static int miphy40lp_power_on(struct phy *phy)
 static const struct of_device_id st_miphy40lp_of_match[] = {
        { .compatible = "st,miphy40lp-phy" },
        { .compatible = "st,spear1340-miphy" },
+       { .compatible = "st,spear1310-miphy" },
        { },
 };
 MODULE_DEVICE_TABLE(of, st_miphy40lp_of_match);
-- 
1.8.1.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to