diff options
author | Roland Stigge <stigge@antcom.de> | 2012-04-22 06:01:19 -0400 |
---|---|---|
committer | Roland Stigge <stigge@antcom.de> | 2012-04-22 06:01:19 -0400 |
commit | 4de02e4a280678224bd12ec3b182e369c87c8fc5 (patch) | |
tree | 455634803a31baa98276ab8d98c37863eb184256 /drivers/net/ethernet/nxp | |
parent | b41a216dafe4dd23c95cb4203de288f773a097a6 (diff) |
net: Add device tree support to LPC32xx
This patch adds device tree support for lpc_eth.c.
The runtime option for MII/RMII is solved via the "phy-mode" property, SRAM
("IRAM") usage for DMA can be chosen via "use-iram".
Signed-off-by: Roland Stigge <stigge@antcom.de>
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/nxp')
-rw-r--r-- | drivers/net/ethernet/nxp/lpc_eth.c | 71 |
1 files changed, 50 insertions, 21 deletions
diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c index 6dfc26d85e47..52deec0b22ea 100644 --- a/drivers/net/ethernet/nxp/lpc_eth.c +++ b/drivers/net/ethernet/nxp/lpc_eth.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <linux/skbuff.h> | 40 | #include <linux/skbuff.h> |
41 | #include <linux/phy.h> | 41 | #include <linux/phy.h> |
42 | #include <linux/dma-mapping.h> | 42 | #include <linux/dma-mapping.h> |
43 | #include <linux/of.h> | ||
43 | #include <linux/of_net.h> | 44 | #include <linux/of_net.h> |
44 | #include <linux/types.h> | 45 | #include <linux/types.h> |
45 | 46 | ||
@@ -340,13 +341,17 @@ | |||
340 | */ | 341 | */ |
341 | #define LPC_POWERDOWN_MACAHB (1 << 31) | 342 | #define LPC_POWERDOWN_MACAHB (1 << 31) |
342 | 343 | ||
343 | /* Upon the upcoming introduction of device tree usage in LPC32xx, | 344 | static phy_interface_t lpc_phy_interface_mode(struct device *dev) |
344 | * lpc_phy_interface_mode() and use_iram_for_net() will be extended with a | ||
345 | * device parameter for access to device tree information at runtime, instead | ||
346 | * of defining the values at compile time | ||
347 | */ | ||
348 | static inline phy_interface_t lpc_phy_interface_mode(void) | ||
349 | { | 345 | { |
346 | if (dev && dev->of_node) { | ||
347 | const char *mode = of_get_property(dev->of_node, | ||
348 | "phy-mode", NULL); | ||
349 | if (mode && !strcmp(mode, "mii")) | ||
350 | return PHY_INTERFACE_MODE_MII; | ||
351 | return PHY_INTERFACE_MODE_RMII; | ||
352 | } | ||
353 | |||
354 | /* non-DT */ | ||
350 | #ifdef CONFIG_ARCH_LPC32XX_MII_SUPPORT | 355 | #ifdef CONFIG_ARCH_LPC32XX_MII_SUPPORT |
351 | return PHY_INTERFACE_MODE_MII; | 356 | return PHY_INTERFACE_MODE_MII; |
352 | #else | 357 | #else |
@@ -354,12 +359,16 @@ static inline phy_interface_t lpc_phy_interface_mode(void) | |||
354 | #endif | 359 | #endif |
355 | } | 360 | } |
356 | 361 | ||
357 | static inline int use_iram_for_net(void) | 362 | static bool use_iram_for_net(struct device *dev) |
358 | { | 363 | { |
364 | if (dev && dev->of_node) | ||
365 | return of_property_read_bool(dev->of_node, "use-iram"); | ||
366 | |||
367 | /* non-DT */ | ||
359 | #ifdef CONFIG_ARCH_LPC32XX_IRAM_FOR_NET | 368 | #ifdef CONFIG_ARCH_LPC32XX_IRAM_FOR_NET |
360 | return 1; | 369 | return true; |
361 | #else | 370 | #else |
362 | return 0; | 371 | return false; |
363 | #endif | 372 | #endif |
364 | } | 373 | } |
365 | 374 | ||
@@ -664,7 +673,7 @@ static void __lpc_eth_init(struct netdata_local *pldat) | |||
664 | LPC_ENET_CLRT(pldat->net_base)); | 673 | LPC_ENET_CLRT(pldat->net_base)); |
665 | writel(LPC_IPGR_LOAD_PART2(0x12), LPC_ENET_IPGR(pldat->net_base)); | 674 | writel(LPC_IPGR_LOAD_PART2(0x12), LPC_ENET_IPGR(pldat->net_base)); |
666 | 675 | ||
667 | if (lpc_phy_interface_mode() == PHY_INTERFACE_MODE_MII) | 676 | if (lpc_phy_interface_mode(&pldat->pdev->dev) == PHY_INTERFACE_MODE_MII) |
668 | writel(LPC_COMMAND_PASSRUNTFRAME, | 677 | writel(LPC_COMMAND_PASSRUNTFRAME, |
669 | LPC_ENET_COMMAND(pldat->net_base)); | 678 | LPC_ENET_COMMAND(pldat->net_base)); |
670 | else { | 679 | else { |
@@ -804,12 +813,13 @@ static int lpc_mii_probe(struct net_device *ndev) | |||
804 | } | 813 | } |
805 | 814 | ||
806 | /* Attach to the PHY */ | 815 | /* Attach to the PHY */ |
807 | if (lpc_phy_interface_mode() == PHY_INTERFACE_MODE_MII) | 816 | if (lpc_phy_interface_mode(&pldat->pdev->dev) == PHY_INTERFACE_MODE_MII) |
808 | netdev_info(ndev, "using MII interface\n"); | 817 | netdev_info(ndev, "using MII interface\n"); |
809 | else | 818 | else |
810 | netdev_info(ndev, "using RMII interface\n"); | 819 | netdev_info(ndev, "using RMII interface\n"); |
811 | phydev = phy_connect(ndev, dev_name(&phydev->dev), | 820 | phydev = phy_connect(ndev, dev_name(&phydev->dev), |
812 | &lpc_handle_link_change, 0, lpc_phy_interface_mode()); | 821 | &lpc_handle_link_change, 0, |
822 | lpc_phy_interface_mode(&pldat->pdev->dev)); | ||
813 | 823 | ||
814 | if (IS_ERR(phydev)) { | 824 | if (IS_ERR(phydev)) { |
815 | netdev_err(ndev, "Could not attach to PHY\n"); | 825 | netdev_err(ndev, "Could not attach to PHY\n"); |
@@ -843,7 +853,7 @@ static int lpc_mii_init(struct netdata_local *pldat) | |||
843 | } | 853 | } |
844 | 854 | ||
845 | /* Setup MII mode */ | 855 | /* Setup MII mode */ |
846 | if (lpc_phy_interface_mode() == PHY_INTERFACE_MODE_MII) | 856 | if (lpc_phy_interface_mode(&pldat->pdev->dev) == PHY_INTERFACE_MODE_MII) |
847 | writel(LPC_COMMAND_PASSRUNTFRAME, | 857 | writel(LPC_COMMAND_PASSRUNTFRAME, |
848 | LPC_ENET_COMMAND(pldat->net_base)); | 858 | LPC_ENET_COMMAND(pldat->net_base)); |
849 | else { | 859 | else { |
@@ -1315,18 +1325,26 @@ static const struct net_device_ops lpc_netdev_ops = { | |||
1315 | static int lpc_eth_drv_probe(struct platform_device *pdev) | 1325 | static int lpc_eth_drv_probe(struct platform_device *pdev) |
1316 | { | 1326 | { |
1317 | struct resource *res; | 1327 | struct resource *res; |
1318 | struct resource *dma_res; | ||
1319 | struct net_device *ndev; | 1328 | struct net_device *ndev; |
1320 | struct netdata_local *pldat; | 1329 | struct netdata_local *pldat; |
1321 | struct phy_device *phydev; | 1330 | struct phy_device *phydev; |
1322 | dma_addr_t dma_handle; | 1331 | dma_addr_t dma_handle; |
1323 | int irq, ret; | 1332 | int irq, ret; |
1333 | u32 tmp; | ||
1334 | |||
1335 | /* Setup network interface for RMII or MII mode */ | ||
1336 | tmp = __raw_readl(LPC32XX_CLKPWR_MACCLK_CTRL); | ||
1337 | tmp &= ~LPC32XX_CLKPWR_MACCTRL_PINS_MSK; | ||
1338 | if (lpc_phy_interface_mode(&pdev->dev) == PHY_INTERFACE_MODE_MII) | ||
1339 | tmp |= LPC32XX_CLKPWR_MACCTRL_USE_MII_PINS; | ||
1340 | else | ||
1341 | tmp |= LPC32XX_CLKPWR_MACCTRL_USE_RMII_PINS; | ||
1342 | __raw_writel(tmp, LPC32XX_CLKPWR_MACCLK_CTRL); | ||
1324 | 1343 | ||
1325 | /* Get platform resources */ | 1344 | /* Get platform resources */ |
1326 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1345 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1327 | dma_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
1328 | irq = platform_get_irq(pdev, 0); | 1346 | irq = platform_get_irq(pdev, 0); |
1329 | if ((!res) || (!dma_res) || (irq < 0) || (irq >= NR_IRQS)) { | 1347 | if ((!res) || (irq < 0) || (irq >= NR_IRQS)) { |
1330 | dev_err(&pdev->dev, "error getting resources.\n"); | 1348 | dev_err(&pdev->dev, "error getting resources.\n"); |
1331 | ret = -ENXIO; | 1349 | ret = -ENXIO; |
1332 | goto err_exit; | 1350 | goto err_exit; |
@@ -1389,17 +1407,19 @@ static int lpc_eth_drv_probe(struct platform_device *pdev) | |||
1389 | sizeof(struct txrx_desc_t) + sizeof(struct rx_status_t)); | 1407 | sizeof(struct txrx_desc_t) + sizeof(struct rx_status_t)); |
1390 | pldat->dma_buff_base_v = 0; | 1408 | pldat->dma_buff_base_v = 0; |
1391 | 1409 | ||
1392 | if (use_iram_for_net()) { | 1410 | if (use_iram_for_net(&pldat->pdev->dev)) { |
1393 | dma_handle = dma_res->start; | 1411 | dma_handle = LPC32XX_IRAM_BASE; |
1394 | if (pldat->dma_buff_size <= lpc32xx_return_iram_size()) | 1412 | if (pldat->dma_buff_size <= lpc32xx_return_iram_size()) |
1395 | pldat->dma_buff_base_v = | 1413 | pldat->dma_buff_base_v = |
1396 | io_p2v(dma_res->start); | 1414 | io_p2v(LPC32XX_IRAM_BASE); |
1397 | else | 1415 | else |
1398 | netdev_err(ndev, | 1416 | netdev_err(ndev, |
1399 | "IRAM not big enough for net buffers, using SDRAM instead.\n"); | 1417 | "IRAM not big enough for net buffers, using SDRAM instead.\n"); |
1400 | } | 1418 | } |
1401 | 1419 | ||
1402 | if (pldat->dma_buff_base_v == 0) { | 1420 | if (pldat->dma_buff_base_v == 0) { |
1421 | pldat->pdev->dev.coherent_dma_mask = 0xFFFFFFFF; | ||
1422 | pldat->pdev->dev.dma_mask = &pldat->pdev->dev.coherent_dma_mask; | ||
1403 | pldat->dma_buff_size = PAGE_ALIGN(pldat->dma_buff_size); | 1423 | pldat->dma_buff_size = PAGE_ALIGN(pldat->dma_buff_size); |
1404 | 1424 | ||
1405 | /* Allocate a chunk of memory for the DMA ethernet buffers | 1425 | /* Allocate a chunk of memory for the DMA ethernet buffers |
@@ -1488,7 +1508,7 @@ err_out_unregister_netdev: | |||
1488 | platform_set_drvdata(pdev, NULL); | 1508 | platform_set_drvdata(pdev, NULL); |
1489 | unregister_netdev(ndev); | 1509 | unregister_netdev(ndev); |
1490 | err_out_dma_unmap: | 1510 | err_out_dma_unmap: |
1491 | if (!use_iram_for_net() || | 1511 | if (!use_iram_for_net(&pldat->pdev->dev) || |
1492 | pldat->dma_buff_size > lpc32xx_return_iram_size()) | 1512 | pldat->dma_buff_size > lpc32xx_return_iram_size()) |
1493 | dma_free_coherent(&pldat->pdev->dev, pldat->dma_buff_size, | 1513 | dma_free_coherent(&pldat->pdev->dev, pldat->dma_buff_size, |
1494 | pldat->dma_buff_base_v, | 1514 | pldat->dma_buff_base_v, |
@@ -1515,7 +1535,7 @@ static int lpc_eth_drv_remove(struct platform_device *pdev) | |||
1515 | unregister_netdev(ndev); | 1535 | unregister_netdev(ndev); |
1516 | platform_set_drvdata(pdev, NULL); | 1536 | platform_set_drvdata(pdev, NULL); |
1517 | 1537 | ||
1518 | if (!use_iram_for_net() || | 1538 | if (!use_iram_for_net(&pldat->pdev->dev) || |
1519 | pldat->dma_buff_size > lpc32xx_return_iram_size()) | 1539 | pldat->dma_buff_size > lpc32xx_return_iram_size()) |
1520 | dma_free_coherent(&pldat->pdev->dev, pldat->dma_buff_size, | 1540 | dma_free_coherent(&pldat->pdev->dev, pldat->dma_buff_size, |
1521 | pldat->dma_buff_base_v, | 1541 | pldat->dma_buff_base_v, |
@@ -1584,6 +1604,14 @@ static int lpc_eth_drv_resume(struct platform_device *pdev) | |||
1584 | } | 1604 | } |
1585 | #endif | 1605 | #endif |
1586 | 1606 | ||
1607 | #ifdef CONFIG_OF | ||
1608 | static const struct of_device_id lpc_eth_match[] = { | ||
1609 | { .compatible = "nxp,lpc-eth" }, | ||
1610 | { } | ||
1611 | }; | ||
1612 | MODULE_DEVICE_TABLE(of, lpc_eth_match); | ||
1613 | #endif | ||
1614 | |||
1587 | static struct platform_driver lpc_eth_driver = { | 1615 | static struct platform_driver lpc_eth_driver = { |
1588 | .probe = lpc_eth_drv_probe, | 1616 | .probe = lpc_eth_drv_probe, |
1589 | .remove = __devexit_p(lpc_eth_drv_remove), | 1617 | .remove = __devexit_p(lpc_eth_drv_remove), |
@@ -1593,6 +1621,7 @@ static struct platform_driver lpc_eth_driver = { | |||
1593 | #endif | 1621 | #endif |
1594 | .driver = { | 1622 | .driver = { |
1595 | .name = MODNAME, | 1623 | .name = MODNAME, |
1624 | .of_match_table = of_match_ptr(lpc_eth_match), | ||
1596 | }, | 1625 | }, |
1597 | }; | 1626 | }; |
1598 | 1627 | ||