aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/net/cpsw.txt104
-rw-r--r--drivers/net/ethernet/ti/cpsw.c174
2 files changed, 272 insertions, 6 deletions
diff --git a/Documentation/devicetree/bindings/net/cpsw.txt b/Documentation/devicetree/bindings/net/cpsw.txt
new file mode 100644
index 000000000000..acca48c4246d
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/cpsw.txt
@@ -0,0 +1,104 @@
1TI SoC Ethernet Switch Controller Device Tree Bindings
2------------------------------------------------------
3
4Required properties:
5- compatible : Should be "ti,cpsw"
6- reg : physical base address and size of the cpsw
7 registers map
8- interrupts : property with a value describing the interrupt
9 number
10- interrupt-parent : The parent interrupt controller
11- cpdma_channels : Specifies number of channels in CPDMA
12- host_port_no : Specifies host port shift
13- cpdma_reg_ofs : Specifies CPDMA submodule register offset
14- ale_reg_ofs : Specifies ALE submodule register offset
15- ale_entries : Specifies No of entries ALE can hold
16- host_port_reg_ofs : Specifies host port register offset
17- hw_stats_reg_ofs : Specifies hardware statistics register offset
18- bd_ram_ofs : Specifies internal desciptor RAM offset
19- bd_ram_size : Specifies internal descriptor RAM size
20- rx_descs : Specifies number of Rx descriptors
21- mac_control : Specifies Default MAC control register content
22 for the specific platform
23- slaves : Specifies number for slaves
24- slave_reg_ofs : Specifies slave register offset
25- sliver_reg_ofs : Specifies slave sliver register offset
26- phy_id : Specifies slave phy id
27- mac-address : Specifies slave MAC address
28
29Optional properties:
30- ti,hwmods : Must be "cpgmac0"
31- no_bd_ram : Must be 0 or 1
32
33Note: "ti,hwmods" field is used to fetch the base address and irq
34resources from TI, omap hwmod data base during device registration.
35Future plan is to migrate hwmod data base contents into device tree
36blob so that, all the required data will be used from device tree dts
37file.
38
39Examples:
40
41 mac: ethernet@4A100000 {
42 compatible = "ti,cpsw";
43 reg = <0x4A100000 0x1000>;
44 interrupts = <55 0x4>;
45 interrupt-parent = <&intc>;
46 cpdma_channels = 8;
47 host_port_no = 0;
48 cpdma_reg_ofs = 0x800;
49 ale_reg_ofs = 0xd00;
50 ale_entries = 1024;
51 host_port_reg_ofs = 0x108;
52 hw_stats_reg_ofs = 0x900;
53 bd_ram_ofs = 0x2000;
54 bd_ram_size = 0x2000;
55 no_bd_ram = 0;
56 rx_descs = 64;
57 mac_control = 0x20;
58 slaves = 2;
59 slave@0 {
60 slave_reg_ofs = 0x208;
61 sliver_reg_ofs = 0xd80;
62 phy_id = "davinci_mdio-0:00"
63 mac-address = [00 04 9F 01 1B B8];
64 };
65 slave@1 {
66 slave_reg_ofs = 0x208;
67 sliver_reg_ofs = 0xd80;
68 phy_id = "davinci_mdio-0:01"
69 mac-address = [00 04 9F 01 1B B9];
70 };
71 };
72
73(or)
74
75 mac: ethernet@4A100000 {
76 compatible = "ti,cpsw";
77 ti,hwmods = "cpgmac0";
78 cpdma_channels = 8;
79 host_port_no = 0;
80 cpdma_reg_ofs = 0x800;
81 ale_reg_ofs = 0xd00;
82 ale_entries = 1024;
83 host_port_reg_ofs = 0x108;
84 hw_stats_reg_ofs = 0x900;
85 bd_ram_ofs = 0x2000;
86 bd_ram_size = 0x2000;
87 no_bd_ram = 0;
88 rx_descs = 64;
89 mac_control = 0x20;
90 slaves = 2;
91 slave@0 {
92 slave_reg_ofs = 0x208;
93 sliver_reg_ofs = 0xd80;
94 phy_id = "davinci_mdio-0:00"
95 mac-address = [00 04 9F 01 1B B8];
96 };
97 slave@1 {
98 slave_reg_ofs = 0x208;
99 sliver_reg_ofs = 0xd80;
100 phy_id = "davinci_mdio-0:01"
101 mac-address = [00 04 9F 01 1B B9];
102 };
103
104 };
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 1e5d85b06e71..0cbc0e59252c 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -28,6 +28,9 @@
28#include <linux/workqueue.h> 28#include <linux/workqueue.h>
29#include <linux/delay.h> 29#include <linux/delay.h>
30#include <linux/pm_runtime.h> 30#include <linux/pm_runtime.h>
31#include <linux/of.h>
32#include <linux/of_net.h>
33#include <linux/of_device.h>
31 34
32#include <linux/platform_data/cpsw.h> 35#include <linux/platform_data/cpsw.h>
33 36
@@ -709,6 +712,158 @@ static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_priv *priv)
709 slave->sliver = regs + data->sliver_reg_ofs; 712 slave->sliver = regs + data->sliver_reg_ofs;
710} 713}
711 714
715static int cpsw_probe_dt(struct cpsw_platform_data *data,
716 struct platform_device *pdev)
717{
718 struct device_node *node = pdev->dev.of_node;
719 struct device_node *slave_node;
720 int i = 0, ret;
721 u32 prop;
722
723 if (!node)
724 return -EINVAL;
725
726 if (of_property_read_u32(node, "slaves", &prop)) {
727 pr_err("Missing slaves property in the DT.\n");
728 return -EINVAL;
729 }
730 data->slaves = prop;
731
732 data->slave_data = kzalloc(sizeof(struct cpsw_slave_data) *
733 data->slaves, GFP_KERNEL);
734 if (!data->slave_data) {
735 pr_err("Could not allocate slave memory.\n");
736 return -EINVAL;
737 }
738
739 data->no_bd_ram = of_property_read_bool(node, "no_bd_ram");
740
741 if (of_property_read_u32(node, "cpdma_channels", &prop)) {
742 pr_err("Missing cpdma_channels property in the DT.\n");
743 ret = -EINVAL;
744 goto error_ret;
745 }
746 data->channels = prop;
747
748 if (of_property_read_u32(node, "host_port_no", &prop)) {
749 pr_err("Missing host_port_no property in the DT.\n");
750 ret = -EINVAL;
751 goto error_ret;
752 }
753 data->host_port_num = prop;
754
755 if (of_property_read_u32(node, "cpdma_reg_ofs", &prop)) {
756 pr_err("Missing cpdma_reg_ofs property in the DT.\n");
757 ret = -EINVAL;
758 goto error_ret;
759 }
760 data->cpdma_reg_ofs = prop;
761
762 if (of_property_read_u32(node, "cpdma_sram_ofs", &prop)) {
763 pr_err("Missing cpdma_sram_ofs property in the DT.\n");
764 ret = -EINVAL;
765 goto error_ret;
766 }
767 data->cpdma_sram_ofs = prop;
768
769 if (of_property_read_u32(node, "ale_reg_ofs", &prop)) {
770 pr_err("Missing ale_reg_ofs property in the DT.\n");
771 ret = -EINVAL;
772 goto error_ret;
773 }
774 data->ale_reg_ofs = prop;
775
776 if (of_property_read_u32(node, "ale_entries", &prop)) {
777 pr_err("Missing ale_entries property in the DT.\n");
778 ret = -EINVAL;
779 goto error_ret;
780 }
781 data->ale_entries = prop;
782
783 if (of_property_read_u32(node, "host_port_reg_ofs", &prop)) {
784 pr_err("Missing host_port_reg_ofs property in the DT.\n");
785 ret = -EINVAL;
786 goto error_ret;
787 }
788 data->host_port_reg_ofs = prop;
789
790 if (of_property_read_u32(node, "hw_stats_reg_ofs", &prop)) {
791 pr_err("Missing hw_stats_reg_ofs property in the DT.\n");
792 ret = -EINVAL;
793 goto error_ret;
794 }
795 data->hw_stats_reg_ofs = prop;
796
797 if (of_property_read_u32(node, "bd_ram_ofs", &prop)) {
798 pr_err("Missing bd_ram_ofs property in the DT.\n");
799 ret = -EINVAL;
800 goto error_ret;
801 }
802 data->bd_ram_ofs = prop;
803
804 if (of_property_read_u32(node, "bd_ram_size", &prop)) {
805 pr_err("Missing bd_ram_size property in the DT.\n");
806 ret = -EINVAL;
807 goto error_ret;
808 }
809 data->bd_ram_size = prop;
810
811 if (of_property_read_u32(node, "rx_descs", &prop)) {
812 pr_err("Missing rx_descs property in the DT.\n");
813 ret = -EINVAL;
814 goto error_ret;
815 }
816 data->rx_descs = prop;
817
818 if (of_property_read_u32(node, "mac_control", &prop)) {
819 pr_err("Missing mac_control property in the DT.\n");
820 ret = -EINVAL;
821 goto error_ret;
822 }
823 data->mac_control = prop;
824
825 for_each_child_of_node(node, slave_node) {
826 struct cpsw_slave_data *slave_data = data->slave_data + i;
827 const char *phy_id = NULL;
828 const void *mac_addr = NULL;
829
830 if (of_property_read_string(slave_node, "phy_id", &phy_id)) {
831 pr_err("Missing slave[%d] phy_id property\n", i);
832 ret = -EINVAL;
833 goto error_ret;
834 }
835 slave_data->phy_id = phy_id;
836
837 if (of_property_read_u32(slave_node, "slave_reg_ofs", &prop)) {
838 pr_err("Missing slave[%d] slave_reg_ofs property\n", i);
839 ret = -EINVAL;
840 goto error_ret;
841 }
842 slave_data->slave_reg_ofs = prop;
843
844 if (of_property_read_u32(slave_node, "sliver_reg_ofs",
845 &prop)) {
846 pr_err("Missing slave[%d] sliver_reg_ofs property\n",
847 i);
848 ret = -EINVAL;
849 goto error_ret;
850 }
851 slave_data->sliver_reg_ofs = prop;
852
853 mac_addr = of_get_mac_address(slave_node);
854 if (mac_addr)
855 memcpy(slave_data->mac_addr, mac_addr, ETH_ALEN);
856
857 i++;
858 }
859
860 return 0;
861
862error_ret:
863 kfree(data->slave_data);
864 return ret;
865}
866
712static int __devinit cpsw_probe(struct platform_device *pdev) 867static int __devinit cpsw_probe(struct platform_device *pdev)
713{ 868{
714 struct cpsw_platform_data *data = pdev->dev.platform_data; 869 struct cpsw_platform_data *data = pdev->dev.platform_data;
@@ -720,11 +875,6 @@ static int __devinit cpsw_probe(struct platform_device *pdev)
720 struct resource *res; 875 struct resource *res;
721 int ret = 0, i, k = 0; 876 int ret = 0, i, k = 0;
722 877
723 if (!data) {
724 pr_err("platform data missing\n");
725 return -ENODEV;
726 }
727
728 ndev = alloc_etherdev(sizeof(struct cpsw_priv)); 878 ndev = alloc_etherdev(sizeof(struct cpsw_priv));
729 if (!ndev) { 879 if (!ndev) {
730 pr_err("error allocating net_device\n"); 880 pr_err("error allocating net_device\n");
@@ -734,13 +884,19 @@ static int __devinit cpsw_probe(struct platform_device *pdev)
734 platform_set_drvdata(pdev, ndev); 884 platform_set_drvdata(pdev, ndev);
735 priv = netdev_priv(ndev); 885 priv = netdev_priv(ndev);
736 spin_lock_init(&priv->lock); 886 spin_lock_init(&priv->lock);
737 priv->data = *data;
738 priv->pdev = pdev; 887 priv->pdev = pdev;
739 priv->ndev = ndev; 888 priv->ndev = ndev;
740 priv->dev = &ndev->dev; 889 priv->dev = &ndev->dev;
741 priv->msg_enable = netif_msg_init(debug_level, CPSW_DEBUG); 890 priv->msg_enable = netif_msg_init(debug_level, CPSW_DEBUG);
742 priv->rx_packet_max = max(rx_packet_max, 128); 891 priv->rx_packet_max = max(rx_packet_max, 128);
743 892
893 if (cpsw_probe_dt(&priv->data, pdev)) {
894 pr_err("cpsw: platform data missing\n");
895 ret = -ENODEV;
896 goto clean_ndev_ret;
897 }
898 data = &priv->data;
899
744 if (is_valid_ether_addr(data->slave_data[0].mac_addr)) { 900 if (is_valid_ether_addr(data->slave_data[0].mac_addr)) {
745 memcpy(priv->mac_addr, data->slave_data[0].mac_addr, ETH_ALEN); 901 memcpy(priv->mac_addr, data->slave_data[0].mac_addr, ETH_ALEN);
746 pr_info("Detected MACID = %pM", priv->mac_addr); 902 pr_info("Detected MACID = %pM", priv->mac_addr);
@@ -996,11 +1152,17 @@ static const struct dev_pm_ops cpsw_pm_ops = {
996 .resume = cpsw_resume, 1152 .resume = cpsw_resume,
997}; 1153};
998 1154
1155static const struct of_device_id cpsw_of_mtable[] = {
1156 { .compatible = "ti,cpsw", },
1157 { /* sentinel */ },
1158};
1159
999static struct platform_driver cpsw_driver = { 1160static struct platform_driver cpsw_driver = {
1000 .driver = { 1161 .driver = {
1001 .name = "cpsw", 1162 .name = "cpsw",
1002 .owner = THIS_MODULE, 1163 .owner = THIS_MODULE,
1003 .pm = &cpsw_pm_ops, 1164 .pm = &cpsw_pm_ops,
1165 .of_match_table = of_match_ptr(cpsw_of_mtable),
1004 }, 1166 },
1005 .probe = cpsw_probe, 1167 .probe = cpsw_probe,
1006 .remove = __devexit_p(cpsw_remove), 1168 .remove = __devexit_p(cpsw_remove),