6060#include <linux/types.h>
6161#include <linux/slab.h>
6262#include <linux/clk.h>
63+ #include <linux/of.h>
64+ #include <linux/of_irq.h>
65+ #include <linux/of_net.h>
6366#include <linux/of_mdio.h>
6467
6568static char mv643xx_eth_driver_name [] = "mv643xx_eth" ;
@@ -2453,13 +2456,148 @@ static void infer_hw_params(struct mv643xx_eth_shared_private *msp)
24532456 }
24542457}
24552458
2459+ #if defined(CONFIG_OF )
2460+ static const struct of_device_id mv643xx_eth_shared_ids [] = {
2461+ { .compatible = "marvell,orion-eth" , },
2462+ { .compatible = "marvell,kirkwood-eth" , },
2463+ { }
2464+ };
2465+ MODULE_DEVICE_TABLE (of , mv643xx_eth_shared_ids );
2466+ #endif
2467+
2468+ #if defined(CONFIG_OF ) && !defined(CONFIG_MV64X60 )
2469+ #define mv643xx_eth_property (_np , _name , _v ) \
2470+ do { \
2471+ u32 tmp; \
2472+ if (!of_property_read_u32(_np, "marvell," _name, &tmp)) \
2473+ _v = tmp; \
2474+ } while (0)
2475+
2476+ static struct platform_device * port_platdev [3 ];
2477+
2478+ static int mv643xx_eth_shared_of_add_port (struct platform_device * pdev ,
2479+ struct device_node * pnp )
2480+ {
2481+ struct platform_device * ppdev ;
2482+ struct mv643xx_eth_platform_data ppd ;
2483+ struct resource res ;
2484+ const char * mac_addr ;
2485+ int ret ;
2486+
2487+ memset (& ppd , 0 , sizeof (ppd ));
2488+ ppd .shared = pdev ;
2489+
2490+ memset (& res , 0 , sizeof (res ));
2491+ if (!of_irq_to_resource (pnp , 0 , & res )) {
2492+ dev_err (& pdev -> dev , "missing interrupt on %s\n" , pnp -> name );
2493+ return - EINVAL ;
2494+ }
2495+
2496+ if (of_property_read_u32 (pnp , "reg" , & ppd .port_number )) {
2497+ dev_err (& pdev -> dev , "missing reg property on %s\n" , pnp -> name );
2498+ return - EINVAL ;
2499+ }
2500+
2501+ if (ppd .port_number >= 3 ) {
2502+ dev_err (& pdev -> dev , "invalid reg property on %s\n" , pnp -> name );
2503+ return - EINVAL ;
2504+ }
2505+
2506+ mac_addr = of_get_mac_address (pnp );
2507+ if (mac_addr )
2508+ memcpy (ppd .mac_addr , mac_addr , 6 );
2509+
2510+ mv643xx_eth_property (pnp , "tx-queue-size" , ppd .tx_queue_size );
2511+ mv643xx_eth_property (pnp , "tx-sram-addr" , ppd .tx_sram_addr );
2512+ mv643xx_eth_property (pnp , "tx-sram-size" , ppd .tx_sram_size );
2513+ mv643xx_eth_property (pnp , "rx-queue-size" , ppd .rx_queue_size );
2514+ mv643xx_eth_property (pnp , "rx-sram-addr" , ppd .rx_sram_addr );
2515+ mv643xx_eth_property (pnp , "rx-sram-size" , ppd .rx_sram_size );
2516+
2517+ ppd .phy_node = of_parse_phandle (pnp , "phy-handle" , 0 );
2518+ if (!ppd .phy_node ) {
2519+ ppd .phy_addr = MV643XX_ETH_PHY_NONE ;
2520+ of_property_read_u32 (pnp , "speed" , & ppd .speed );
2521+ of_property_read_u32 (pnp , "duplex" , & ppd .duplex );
2522+ }
2523+
2524+ ppdev = platform_device_alloc (MV643XX_ETH_NAME , ppd .port_number );
2525+ if (!ppdev )
2526+ return - ENOMEM ;
2527+ ppdev -> dev .coherent_dma_mask = DMA_BIT_MASK (32 );
2528+
2529+ ret = platform_device_add_resources (ppdev , & res , 1 );
2530+ if (ret )
2531+ goto port_err ;
2532+
2533+ ret = platform_device_add_data (ppdev , & ppd , sizeof (ppd ));
2534+ if (ret )
2535+ goto port_err ;
2536+
2537+ ret = platform_device_add (ppdev );
2538+ if (ret )
2539+ goto port_err ;
2540+
2541+ port_platdev [ppd .port_number ] = ppdev ;
2542+
2543+ return 0 ;
2544+
2545+ port_err :
2546+ platform_device_put (ppdev );
2547+ return ret ;
2548+ }
2549+
2550+ static int mv643xx_eth_shared_of_probe (struct platform_device * pdev )
2551+ {
2552+ struct mv643xx_eth_shared_platform_data * pd ;
2553+ struct device_node * pnp , * np = pdev -> dev .of_node ;
2554+ int ret ;
2555+
2556+ /* bail out if not registered from DT */
2557+ if (!np )
2558+ return 0 ;
2559+
2560+ pd = devm_kzalloc (& pdev -> dev , sizeof (* pd ), GFP_KERNEL );
2561+ if (!pd )
2562+ return - ENOMEM ;
2563+ pdev -> dev .platform_data = pd ;
2564+
2565+ mv643xx_eth_property (np , "tx-checksum-limit" , pd -> tx_csum_limit );
2566+
2567+ for_each_available_child_of_node (np , pnp ) {
2568+ ret = mv643xx_eth_shared_of_add_port (pdev , pnp );
2569+ if (ret )
2570+ return ret ;
2571+ }
2572+ return 0 ;
2573+ }
2574+
2575+ static void mv643xx_eth_shared_of_remove (void )
2576+ {
2577+ int n ;
2578+
2579+ for (n = 0 ; n < 3 ; n ++ ) {
2580+ platform_device_del (port_platdev [n ]);
2581+ port_platdev [n ] = NULL ;
2582+ }
2583+ }
2584+ #else
2585+ static int mv643xx_eth_shared_of_probe (struct platform_device * pdev )
2586+ {
2587+ return 0
2588+ }
2589+
2590+ #define mv643xx_eth_shared_of_remove ()
2591+ #endif
2592+
24562593static int mv643xx_eth_shared_probe (struct platform_device * pdev )
24572594{
24582595 static int mv643xx_eth_version_printed ;
2459- struct mv643xx_eth_shared_platform_data * pd = pdev -> dev . platform_data ;
2596+ struct mv643xx_eth_shared_platform_data * pd ;
24602597 struct mv643xx_eth_shared_private * msp ;
24612598 const struct mbus_dram_target_info * dram ;
24622599 struct resource * res ;
2600+ int ret ;
24632601
24642602 if (!mv643xx_eth_version_printed ++ )
24652603 pr_notice ("MV-643xx 10/100/1000 ethernet driver version %s\n" ,
@@ -2472,6 +2610,7 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
24722610 msp = devm_kzalloc (& pdev -> dev , sizeof (* msp ), GFP_KERNEL );
24732611 if (msp == NULL )
24742612 return - ENOMEM ;
2613+ platform_set_drvdata (pdev , msp );
24752614
24762615 msp -> base = devm_ioremap (& pdev -> dev , res -> start , resource_size (res ));
24772616 if (msp -> base == NULL )
@@ -2488,22 +2627,25 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
24882627 if (dram )
24892628 mv643xx_eth_conf_mbus_windows (msp , dram );
24902629
2630+ ret = mv643xx_eth_shared_of_probe (pdev );
2631+ if (ret )
2632+ return ret ;
2633+ pd = pdev -> dev .platform_data ;
2634+
24912635 msp -> tx_csum_limit = (pd != NULL && pd -> tx_csum_limit ) ?
24922636 pd -> tx_csum_limit : 9 * 1024 ;
24932637 infer_hw_params (msp );
24942638
2495- platform_set_drvdata (pdev , msp );
2496-
24972639 return 0 ;
24982640}
24992641
25002642static int mv643xx_eth_shared_remove (struct platform_device * pdev )
25012643{
25022644 struct mv643xx_eth_shared_private * msp = platform_get_drvdata (pdev );
25032645
2646+ mv643xx_eth_shared_of_remove ();
25042647 if (!IS_ERR (msp -> clk ))
25052648 clk_disable_unprepare (msp -> clk );
2506-
25072649 return 0 ;
25082650}
25092651
@@ -2513,6 +2655,7 @@ static struct platform_driver mv643xx_eth_shared_driver = {
25132655 .driver = {
25142656 .name = MV643XX_ETH_SHARED_NAME ,
25152657 .owner = THIS_MODULE ,
2658+ .of_match_table = of_match_ptr (mv643xx_eth_shared_ids ),
25162659 },
25172660};
25182661
@@ -2721,6 +2864,8 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
27212864 if (!IS_ERR (mp -> clk )) {
27222865 clk_prepare_enable (mp -> clk );
27232866 mp -> t_clk = clk_get_rate (mp -> clk );
2867+ } else if (!IS_ERR (mp -> shared -> clk )) {
2868+ mp -> t_clk = clk_get_rate (mp -> shared -> clk );
27242869 }
27252870
27262871 set_params (mp , pd );
0 commit comments