|
@@ -225,6 +225,18 @@ struct cpdma_chan {
|
|
|
void *hdp, *cp, *rxfree;
|
|
|
};
|
|
|
|
|
|
+/* AM33xx SoC specific definitions for the CONTROL port */
|
|
|
+#define AM33XX_GMII_SEL_MODE_MII 0
|
|
|
+#define AM33XX_GMII_SEL_MODE_RMII 1
|
|
|
+#define AM33XX_GMII_SEL_MODE_RGMII 2
|
|
|
+
|
|
|
+#define AM33XX_GMII_SEL_RGMII1_IDMODE BIT(4)
|
|
|
+#define AM33XX_GMII_SEL_RGMII2_IDMODE BIT(5)
|
|
|
+#define AM33XX_GMII_SEL_RMII1_IO_CLK_EN BIT(6)
|
|
|
+#define AM33XX_GMII_SEL_RMII2_IO_CLK_EN BIT(7)
|
|
|
+
|
|
|
+#define GMII_SEL_MODE_MASK 0x3
|
|
|
+
|
|
|
#define desc_write(desc, fld, val) __raw_writel((u32)(val), &(desc)->fld)
|
|
|
#define desc_read(desc, fld) __raw_readl(&(desc)->fld)
|
|
|
#define desc_read_ptr(desc, fld) ((void *)__raw_readl(&(desc)->fld))
|
|
@@ -1150,12 +1162,129 @@ static inline fdt_addr_t cpsw_get_addr_by_node(const void *fdt, int node)
|
|
|
false);
|
|
|
}
|
|
|
|
|
|
+static void cpsw_gmii_sel_am3352(struct cpsw_priv *priv,
|
|
|
+ phy_interface_t phy_mode)
|
|
|
+{
|
|
|
+ u32 reg;
|
|
|
+ u32 mask;
|
|
|
+ u32 mode = 0;
|
|
|
+ bool rgmii_id = false;
|
|
|
+ int slave = priv->data.active_slave;
|
|
|
+
|
|
|
+ reg = readl(priv->data.gmii_sel);
|
|
|
+
|
|
|
+ switch (phy_mode) {
|
|
|
+ case PHY_INTERFACE_MODE_RMII:
|
|
|
+ mode = AM33XX_GMII_SEL_MODE_RMII;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case PHY_INTERFACE_MODE_RGMII:
|
|
|
+ mode = AM33XX_GMII_SEL_MODE_RGMII;
|
|
|
+ break;
|
|
|
+ case PHY_INTERFACE_MODE_RGMII_ID:
|
|
|
+ case PHY_INTERFACE_MODE_RGMII_RXID:
|
|
|
+ case PHY_INTERFACE_MODE_RGMII_TXID:
|
|
|
+ mode = AM33XX_GMII_SEL_MODE_RGMII;
|
|
|
+ rgmii_id = true;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case PHY_INTERFACE_MODE_MII:
|
|
|
+ default:
|
|
|
+ mode = AM33XX_GMII_SEL_MODE_MII;
|
|
|
+ break;
|
|
|
+ };
|
|
|
+
|
|
|
+ mask = GMII_SEL_MODE_MASK << (slave * 2) | BIT(slave + 6);
|
|
|
+ mode <<= slave * 2;
|
|
|
+
|
|
|
+ if (priv->data.rmii_clock_external) {
|
|
|
+ if (slave == 0)
|
|
|
+ mode |= AM33XX_GMII_SEL_RMII1_IO_CLK_EN;
|
|
|
+ else
|
|
|
+ mode |= AM33XX_GMII_SEL_RMII2_IO_CLK_EN;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (rgmii_id) {
|
|
|
+ if (slave == 0)
|
|
|
+ mode |= AM33XX_GMII_SEL_RGMII1_IDMODE;
|
|
|
+ else
|
|
|
+ mode |= AM33XX_GMII_SEL_RGMII2_IDMODE;
|
|
|
+ }
|
|
|
+
|
|
|
+ reg &= ~mask;
|
|
|
+ reg |= mode;
|
|
|
+
|
|
|
+ writel(reg, priv->data.gmii_sel);
|
|
|
+}
|
|
|
+
|
|
|
+static void cpsw_gmii_sel_dra7xx(struct cpsw_priv *priv,
|
|
|
+ phy_interface_t phy_mode)
|
|
|
+{
|
|
|
+ u32 reg;
|
|
|
+ u32 mask;
|
|
|
+ u32 mode = 0;
|
|
|
+ int slave = priv->data.active_slave;
|
|
|
+
|
|
|
+ reg = readl(priv->data.gmii_sel);
|
|
|
+
|
|
|
+ switch (phy_mode) {
|
|
|
+ case PHY_INTERFACE_MODE_RMII:
|
|
|
+ mode = AM33XX_GMII_SEL_MODE_RMII;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case PHY_INTERFACE_MODE_RGMII:
|
|
|
+ case PHY_INTERFACE_MODE_RGMII_ID:
|
|
|
+ case PHY_INTERFACE_MODE_RGMII_RXID:
|
|
|
+ case PHY_INTERFACE_MODE_RGMII_TXID:
|
|
|
+ mode = AM33XX_GMII_SEL_MODE_RGMII;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case PHY_INTERFACE_MODE_MII:
|
|
|
+ default:
|
|
|
+ mode = AM33XX_GMII_SEL_MODE_MII;
|
|
|
+ break;
|
|
|
+ };
|
|
|
+
|
|
|
+ switch (slave) {
|
|
|
+ case 0:
|
|
|
+ mask = GMII_SEL_MODE_MASK;
|
|
|
+ break;
|
|
|
+ case 1:
|
|
|
+ mask = GMII_SEL_MODE_MASK << 4;
|
|
|
+ mode <<= 4;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ dev_err(priv->dev, "invalid slave number...\n");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (priv->data.rmii_clock_external)
|
|
|
+ dev_err(priv->dev, "RMII External clock is not supported\n");
|
|
|
+
|
|
|
+ reg &= ~mask;
|
|
|
+ reg |= mode;
|
|
|
+
|
|
|
+ writel(reg, priv->data.gmii_sel);
|
|
|
+}
|
|
|
+
|
|
|
+static void cpsw_phy_sel(struct cpsw_priv *priv, const char *compat,
|
|
|
+ phy_interface_t phy_mode)
|
|
|
+{
|
|
|
+ if (!strcmp(compat, "ti,am3352-cpsw-phy-sel"))
|
|
|
+ cpsw_gmii_sel_am3352(priv, phy_mode);
|
|
|
+ if (!strcmp(compat, "ti,am43xx-cpsw-phy-sel"))
|
|
|
+ cpsw_gmii_sel_am3352(priv, phy_mode);
|
|
|
+ else if (!strcmp(compat, "ti,dra7xx-cpsw-phy-sel"))
|
|
|
+ cpsw_gmii_sel_dra7xx(priv, phy_mode);
|
|
|
+}
|
|
|
+
|
|
|
static int cpsw_eth_ofdata_to_platdata(struct udevice *dev)
|
|
|
{
|
|
|
struct eth_pdata *pdata = dev_get_platdata(dev);
|
|
|
struct cpsw_priv *priv = dev_get_priv(dev);
|
|
|
struct gpio_desc *mode_gpios;
|
|
|
const char *phy_mode;
|
|
|
+ const char *phy_sel_compat = NULL;
|
|
|
const void *fdt = gd->fdt_blob;
|
|
|
int node = dev->of_offset;
|
|
|
int subnode;
|
|
@@ -1271,6 +1400,17 @@ static int cpsw_eth_ofdata_to_platdata(struct udevice *dev)
|
|
|
error("Not able to get gmii_sel reg address\n");
|
|
|
return -ENOENT;
|
|
|
}
|
|
|
+
|
|
|
+ if (fdt_get_property(fdt, subnode, "rmii-clock-ext",
|
|
|
+ NULL))
|
|
|
+ priv->data.rmii_clock_external = true;
|
|
|
+
|
|
|
+ phy_sel_compat = fdt_getprop(fdt, subnode, "compatible",
|
|
|
+ NULL);
|
|
|
+ if (!phy_sel_compat) {
|
|
|
+ error("Not able to get gmii_sel compatible\n");
|
|
|
+ return -ENOENT;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1293,20 +1433,9 @@ static int cpsw_eth_ofdata_to_platdata(struct udevice *dev)
|
|
|
debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode);
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
- switch (pdata->phy_interface) {
|
|
|
- case PHY_INTERFACE_MODE_MII:
|
|
|
- writel(MII_MODE_ENABLE, priv->data.gmii_sel);
|
|
|
- break;
|
|
|
- case PHY_INTERFACE_MODE_RMII:
|
|
|
- writel(RMII_MODE_ENABLE, priv->data.gmii_sel);
|
|
|
- break;
|
|
|
- case PHY_INTERFACE_MODE_RGMII:
|
|
|
- case PHY_INTERFACE_MODE_RGMII_ID:
|
|
|
- case PHY_INTERFACE_MODE_RGMII_RXID:
|
|
|
- case PHY_INTERFACE_MODE_RGMII_TXID:
|
|
|
- writel(RGMII_MODE_ENABLE, priv->data.gmii_sel);
|
|
|
- break;
|
|
|
- }
|
|
|
+
|
|
|
+ /* Select phy interface in control module */
|
|
|
+ cpsw_phy_sel(priv, phy_sel_compat, pdata->phy_interface);
|
|
|
|
|
|
return 0;
|
|
|
}
|