0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/platform_device.h>
0011 #include <linux/init.h>
0012 #include <linux/netdevice.h>
0013 #include <linux/phy.h>
0014 #include <linux/of.h>
0015 #include <linux/of_device.h>
0016
0017 #include "cpsw.h"
0018
0019
0020 #define AM33XX_GMII_SEL_MODE_MII 0
0021 #define AM33XX_GMII_SEL_MODE_RMII 1
0022 #define AM33XX_GMII_SEL_MODE_RGMII 2
0023
0024 #define AM33XX_GMII_SEL_RMII2_IO_CLK_EN BIT(7)
0025 #define AM33XX_GMII_SEL_RMII1_IO_CLK_EN BIT(6)
0026 #define AM33XX_GMII_SEL_RGMII2_IDMODE BIT(5)
0027 #define AM33XX_GMII_SEL_RGMII1_IDMODE BIT(4)
0028
0029 #define GMII_SEL_MODE_MASK 0x3
0030
0031 struct cpsw_phy_sel_priv {
0032 struct device *dev;
0033 u32 __iomem *gmii_sel;
0034 bool rmii_clock_external;
0035 void (*cpsw_phy_sel)(struct cpsw_phy_sel_priv *priv,
0036 phy_interface_t phy_mode, int slave);
0037 };
0038
0039
0040 static void cpsw_gmii_sel_am3352(struct cpsw_phy_sel_priv *priv,
0041 phy_interface_t phy_mode, int slave)
0042 {
0043 u32 reg;
0044 u32 mask;
0045 u32 mode = 0;
0046 bool rgmii_id = false;
0047
0048 reg = readl(priv->gmii_sel);
0049
0050 switch (phy_mode) {
0051 case PHY_INTERFACE_MODE_RMII:
0052 mode = AM33XX_GMII_SEL_MODE_RMII;
0053 break;
0054
0055 case PHY_INTERFACE_MODE_RGMII:
0056 mode = AM33XX_GMII_SEL_MODE_RGMII;
0057 break;
0058
0059 case PHY_INTERFACE_MODE_RGMII_ID:
0060 case PHY_INTERFACE_MODE_RGMII_RXID:
0061 case PHY_INTERFACE_MODE_RGMII_TXID:
0062 mode = AM33XX_GMII_SEL_MODE_RGMII;
0063 rgmii_id = true;
0064 break;
0065
0066 default:
0067 dev_warn(priv->dev,
0068 "Unsupported PHY mode: \"%s\". Defaulting to MII.\n",
0069 phy_modes(phy_mode));
0070 fallthrough;
0071 case PHY_INTERFACE_MODE_MII:
0072 mode = AM33XX_GMII_SEL_MODE_MII;
0073 break;
0074 }
0075
0076 mask = GMII_SEL_MODE_MASK << (slave * 2) | BIT(slave + 6);
0077 mask |= BIT(slave + 4);
0078 mode <<= slave * 2;
0079
0080 if (priv->rmii_clock_external) {
0081 if (slave == 0)
0082 mode |= AM33XX_GMII_SEL_RMII1_IO_CLK_EN;
0083 else
0084 mode |= AM33XX_GMII_SEL_RMII2_IO_CLK_EN;
0085 }
0086
0087 if (rgmii_id) {
0088 if (slave == 0)
0089 mode |= AM33XX_GMII_SEL_RGMII1_IDMODE;
0090 else
0091 mode |= AM33XX_GMII_SEL_RGMII2_IDMODE;
0092 }
0093
0094 reg &= ~mask;
0095 reg |= mode;
0096
0097 writel(reg, priv->gmii_sel);
0098 }
0099
0100 static void cpsw_gmii_sel_dra7xx(struct cpsw_phy_sel_priv *priv,
0101 phy_interface_t phy_mode, int slave)
0102 {
0103 u32 reg;
0104 u32 mask;
0105 u32 mode = 0;
0106
0107 reg = readl(priv->gmii_sel);
0108
0109 switch (phy_mode) {
0110 case PHY_INTERFACE_MODE_RMII:
0111 mode = AM33XX_GMII_SEL_MODE_RMII;
0112 break;
0113
0114 case PHY_INTERFACE_MODE_RGMII:
0115 case PHY_INTERFACE_MODE_RGMII_ID:
0116 case PHY_INTERFACE_MODE_RGMII_RXID:
0117 case PHY_INTERFACE_MODE_RGMII_TXID:
0118 mode = AM33XX_GMII_SEL_MODE_RGMII;
0119 break;
0120
0121 default:
0122 dev_warn(priv->dev,
0123 "Unsupported PHY mode: \"%s\". Defaulting to MII.\n",
0124 phy_modes(phy_mode));
0125 fallthrough;
0126 case PHY_INTERFACE_MODE_MII:
0127 mode = AM33XX_GMII_SEL_MODE_MII;
0128 break;
0129 }
0130
0131 switch (slave) {
0132 case 0:
0133 mask = GMII_SEL_MODE_MASK;
0134 break;
0135 case 1:
0136 mask = GMII_SEL_MODE_MASK << 4;
0137 mode <<= 4;
0138 break;
0139 default:
0140 dev_err(priv->dev, "invalid slave number...\n");
0141 return;
0142 }
0143
0144 if (priv->rmii_clock_external)
0145 dev_err(priv->dev, "RMII External clock is not supported\n");
0146
0147 reg &= ~mask;
0148 reg |= mode;
0149
0150 writel(reg, priv->gmii_sel);
0151 }
0152
0153 static struct platform_driver cpsw_phy_sel_driver;
0154 static int match(struct device *dev, const void *data)
0155 {
0156 const struct device_node *node = (const struct device_node *)data;
0157 return dev->of_node == node &&
0158 dev->driver == &cpsw_phy_sel_driver.driver;
0159 }
0160
0161 void cpsw_phy_sel(struct device *dev, phy_interface_t phy_mode, int slave)
0162 {
0163 struct device_node *node;
0164 struct cpsw_phy_sel_priv *priv;
0165
0166 node = of_parse_phandle(dev->of_node, "cpsw-phy-sel", 0);
0167 if (!node) {
0168 node = of_get_child_by_name(dev->of_node, "cpsw-phy-sel");
0169 if (!node) {
0170 dev_err(dev, "Phy mode driver DT not found\n");
0171 return;
0172 }
0173 }
0174
0175 dev = bus_find_device(&platform_bus_type, NULL, node, match);
0176 if (!dev) {
0177 dev_err(dev, "unable to find platform device for %pOF\n", node);
0178 goto out;
0179 }
0180
0181 priv = dev_get_drvdata(dev);
0182
0183 priv->cpsw_phy_sel(priv, phy_mode, slave);
0184
0185 put_device(dev);
0186 out:
0187 of_node_put(node);
0188 }
0189 EXPORT_SYMBOL_GPL(cpsw_phy_sel);
0190
0191 static const struct of_device_id cpsw_phy_sel_id_table[] = {
0192 {
0193 .compatible = "ti,am3352-cpsw-phy-sel",
0194 .data = &cpsw_gmii_sel_am3352,
0195 },
0196 {
0197 .compatible = "ti,dra7xx-cpsw-phy-sel",
0198 .data = &cpsw_gmii_sel_dra7xx,
0199 },
0200 {
0201 .compatible = "ti,am43xx-cpsw-phy-sel",
0202 .data = &cpsw_gmii_sel_am3352,
0203 },
0204 {}
0205 };
0206
0207 static int cpsw_phy_sel_probe(struct platform_device *pdev)
0208 {
0209 const struct of_device_id *of_id;
0210 struct cpsw_phy_sel_priv *priv;
0211
0212 of_id = of_match_node(cpsw_phy_sel_id_table, pdev->dev.of_node);
0213 if (!of_id)
0214 return -EINVAL;
0215
0216 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
0217 if (!priv) {
0218 dev_err(&pdev->dev, "unable to alloc memory for cpsw phy sel\n");
0219 return -ENOMEM;
0220 }
0221
0222 priv->dev = &pdev->dev;
0223 priv->cpsw_phy_sel = of_id->data;
0224
0225 priv->gmii_sel = devm_platform_ioremap_resource_byname(pdev, "gmii-sel");
0226 if (IS_ERR(priv->gmii_sel))
0227 return PTR_ERR(priv->gmii_sel);
0228
0229 if (of_find_property(pdev->dev.of_node, "rmii-clock-ext", NULL))
0230 priv->rmii_clock_external = true;
0231
0232 dev_set_drvdata(&pdev->dev, priv);
0233
0234 return 0;
0235 }
0236
0237 static struct platform_driver cpsw_phy_sel_driver = {
0238 .probe = cpsw_phy_sel_probe,
0239 .driver = {
0240 .name = "cpsw-phy-sel",
0241 .of_match_table = cpsw_phy_sel_id_table,
0242 },
0243 };
0244 builtin_platform_driver(cpsw_phy_sel_driver);