[PATCH V4 6/8] phy: st-miphy-40lp: Add SPEAr1310 and SPEAr1340 PCIe phy support

From: Pratyush Anand
Date: Wed Feb 05 2014 - 23:46:06 EST


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

Signed-off-by: Pratyush Anand <pratyush.anand@xxxxxx>
Tested-by: Mohit Kumar <mohit.kumar@xxxxxx>
Cc: Arnd Bergmann <arnd@xxxxxxxx>
Cc: Kishon Vijay Abraham I <kishon@xxxxxx>
Cc: spear-devel@xxxxxxxxxxx
Cc: linux-arm-kernel@xxxxxxxxxxxxxxxxxxx
Cc: linux-kernel@xxxxxxxxxxxxxxx
---
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 majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/