Commit 6ca5f482a38ce227a25ccc2da4403705245250af

Authored by Mugunthan V N
Committed by Lokesh Vutla
1 parent e7eb8f9387

driver: net: cpsw: add support for RGMII id mode support and RMII clock source selection

cpsw driver supports only selection of phy mode in control module
but control module has more setting like RGMII ID mode selection,
RMII clock source selection. So ported to cpsw-phy-sel driver
from kernel to u-boot.

Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>

Showing 2 changed files with 138 additions and 15 deletions Side-by-side Diff

... ... @@ -224,6 +224,18 @@
224 224 void *hdp, *cp, *rxfree;
225 225 };
226 226  
  227 +/* AM33xx SoC specific definitions for the CONTROL port */
  228 +#define AM33XX_GMII_SEL_MODE_MII 0
  229 +#define AM33XX_GMII_SEL_MODE_RMII 1
  230 +#define AM33XX_GMII_SEL_MODE_RGMII 2
  231 +
  232 +#define AM33XX_GMII_SEL_RGMII1_IDMODE BIT(4)
  233 +#define AM33XX_GMII_SEL_RGMII2_IDMODE BIT(5)
  234 +#define AM33XX_GMII_SEL_RMII1_IO_CLK_EN BIT(6)
  235 +#define AM33XX_GMII_SEL_RMII2_IO_CLK_EN BIT(7)
  236 +
  237 +#define GMII_SEL_MODE_MASK 0x3
  238 +
227 239 #define desc_write(desc, fld, val) __raw_writel((u32)(val), &(desc)->fld)
228 240 #define desc_read(desc, fld) __raw_readl(&(desc)->fld)
229 241 #define desc_read_ptr(desc, fld) ((void *)__raw_readl(&(desc)->fld))
230 242  
... ... @@ -1148,11 +1160,126 @@
1148 1160 return fdtdec_get_addr_size_auto_noparent(fdt, node, "reg", 0, NULL);
1149 1161 }
1150 1162  
  1163 +static void cpsw_gmii_sel_am3352(struct cpsw_priv *priv,
  1164 + phy_interface_t phy_mode)
  1165 +{
  1166 + u32 reg;
  1167 + u32 mask;
  1168 + u32 mode = 0;
  1169 + bool rgmii_id = false;
  1170 + int slave = priv->data.active_slave;
  1171 +
  1172 + reg = readl(priv->data.gmii_sel);
  1173 +
  1174 + switch (phy_mode) {
  1175 + case PHY_INTERFACE_MODE_RMII:
  1176 + mode = AM33XX_GMII_SEL_MODE_RMII;
  1177 + break;
  1178 +
  1179 + case PHY_INTERFACE_MODE_RGMII:
  1180 + mode = AM33XX_GMII_SEL_MODE_RGMII;
  1181 + break;
  1182 + case PHY_INTERFACE_MODE_RGMII_ID:
  1183 + case PHY_INTERFACE_MODE_RGMII_RXID:
  1184 + case PHY_INTERFACE_MODE_RGMII_TXID:
  1185 + mode = AM33XX_GMII_SEL_MODE_RGMII;
  1186 + rgmii_id = true;
  1187 + break;
  1188 +
  1189 + case PHY_INTERFACE_MODE_MII:
  1190 + default:
  1191 + mode = AM33XX_GMII_SEL_MODE_MII;
  1192 + break;
  1193 + };
  1194 +
  1195 + mask = GMII_SEL_MODE_MASK << (slave * 2) | BIT(slave + 6);
  1196 + mode <<= slave * 2;
  1197 +
  1198 + if (priv->data.rmii_clock_external) {
  1199 + if (slave == 0)
  1200 + mode |= AM33XX_GMII_SEL_RMII1_IO_CLK_EN;
  1201 + else
  1202 + mode |= AM33XX_GMII_SEL_RMII2_IO_CLK_EN;
  1203 + }
  1204 +
  1205 + if (rgmii_id) {
  1206 + if (slave == 0)
  1207 + mode |= AM33XX_GMII_SEL_RGMII1_IDMODE;
  1208 + else
  1209 + mode |= AM33XX_GMII_SEL_RGMII2_IDMODE;
  1210 + }
  1211 +
  1212 + reg &= ~mask;
  1213 + reg |= mode;
  1214 +
  1215 + writel(reg, priv->data.gmii_sel);
  1216 +}
  1217 +
  1218 +static void cpsw_gmii_sel_dra7xx(struct cpsw_priv *priv,
  1219 + phy_interface_t phy_mode)
  1220 +{
  1221 + u32 reg;
  1222 + u32 mask;
  1223 + u32 mode = 0;
  1224 + int slave = priv->data.active_slave;
  1225 +
  1226 + reg = readl(priv->data.gmii_sel);
  1227 +
  1228 + switch (phy_mode) {
  1229 + case PHY_INTERFACE_MODE_RMII:
  1230 + mode = AM33XX_GMII_SEL_MODE_RMII;
  1231 + break;
  1232 +
  1233 + case PHY_INTERFACE_MODE_RGMII:
  1234 + case PHY_INTERFACE_MODE_RGMII_ID:
  1235 + case PHY_INTERFACE_MODE_RGMII_RXID:
  1236 + case PHY_INTERFACE_MODE_RGMII_TXID:
  1237 + mode = AM33XX_GMII_SEL_MODE_RGMII;
  1238 + break;
  1239 +
  1240 + case PHY_INTERFACE_MODE_MII:
  1241 + default:
  1242 + mode = AM33XX_GMII_SEL_MODE_MII;
  1243 + break;
  1244 + };
  1245 +
  1246 + switch (slave) {
  1247 + case 0:
  1248 + mask = GMII_SEL_MODE_MASK;
  1249 + break;
  1250 + case 1:
  1251 + mask = GMII_SEL_MODE_MASK << 4;
  1252 + mode <<= 4;
  1253 + break;
  1254 + default:
  1255 + dev_err(priv->dev, "invalid slave number...\n");
  1256 + return;
  1257 + }
  1258 +
  1259 + if (priv->data.rmii_clock_external)
  1260 + dev_err(priv->dev, "RMII External clock is not supported\n");
  1261 +
  1262 + reg &= ~mask;
  1263 + reg |= mode;
  1264 +
  1265 + writel(reg, priv->data.gmii_sel);
  1266 +}
  1267 +
  1268 +static void cpsw_phy_sel(struct cpsw_priv *priv, const char *compat,
  1269 + phy_interface_t phy_mode)
  1270 +{
  1271 + if (!strcmp(compat, "ti,am3352-cpsw-phy-sel"))
  1272 + cpsw_gmii_sel_am3352(priv, phy_mode);
  1273 + else if (!strcmp(compat, "ti,dra7xx-cpsw-phy-sel"))
  1274 + cpsw_gmii_sel_dra7xx(priv, phy_mode);
  1275 +}
  1276 +
1151 1277 static int cpsw_eth_ofdata_to_platdata(struct udevice *dev)
1152 1278 {
1153 1279 struct eth_pdata *pdata = dev_get_platdata(dev);
1154 1280 struct cpsw_priv *priv = dev_get_priv(dev);
1155 1281 const char *phy_mode;
  1282 + const char *phy_sel_compat = NULL;
1156 1283 const void *fdt = gd->fdt_blob;
1157 1284 int node = dev->of_offset;
1158 1285 int subnode;
... ... @@ -1255,6 +1382,13 @@
1255 1382 error("Not able to get gmii_sel reg address\n");
1256 1383 return -ENOENT;
1257 1384 }
  1385 +
  1386 + phy_sel_compat = fdt_getprop(fdt, subnode, "compatible",
  1387 + NULL);
  1388 + if (!phy_sel_compat) {
  1389 + error("Not able to get gmii_sel compatible\n");
  1390 + return -ENOENT;
  1391 + }
1258 1392 }
1259 1393 }
1260 1394  
... ... @@ -1277,21 +1411,9 @@
1277 1411 debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode);
1278 1412 return -EINVAL;
1279 1413 }
1280   - switch (pdata->phy_interface) {
1281   - case PHY_INTERFACE_MODE_MII:
1282   - writel(MII_MODE_ENABLE, priv->data.gmii_sel);
1283   - break;
1284   - case PHY_INTERFACE_MODE_RMII:
1285   - writel(RMII_MODE_ENABLE | RMII_CHIPCKL_ENABLE,
1286   - priv->data.gmii_sel);
1287   - break;
1288   - case PHY_INTERFACE_MODE_RGMII:
1289   - case PHY_INTERFACE_MODE_RGMII_ID:
1290   - case PHY_INTERFACE_MODE_RGMII_RXID:
1291   - case PHY_INTERFACE_MODE_RGMII_TXID:
1292   - writel(RGMII_MODE_ENABLE, priv->data.gmii_sel);
1293   - break;
1294   - }
  1414 +
  1415 + /* Select phy interface in control module */
  1416 + cpsw_phy_sel(priv, phy_sel_compat, pdata->phy_interface);
1295 1417  
1296 1418 return 0;
1297 1419 }
... ... @@ -48,6 +48,7 @@
48 48 void (*control)(int enabled);
49 49 u32 host_port_num;
50 50 u32 active_slave;
  51 + bool rmii_clock_external;
51 52 u8 version;
52 53 };
53 54