diff options
author | Mark Brown <broonie@kernel.org> | 2015-10-12 13:09:27 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2015-10-12 13:09:27 -0400 |
commit | 79828b4fa835f73cdaf4bffa48696abdcbea9d02 (patch) | |
tree | 5e0fa7156acb75ba603022bc807df8f2fedb97a8 /net/dsa/dsa.c | |
parent | 721b51fcf91898299d96f4b72cb9434cda29dce6 (diff) | |
parent | 8c1a9d6323abf0fb1e5dad96cf3f1c783505ea5a (diff) |
Merge remote-tracking branch 'asoc/fix/rt5645' into asoc-fix-rt5645
Diffstat (limited to 'net/dsa/dsa.c')
-rw-r--r-- | net/dsa/dsa.c | 101 |
1 files changed, 87 insertions, 14 deletions
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c index 392e29a0227d..76e3800765f8 100644 --- a/net/dsa/dsa.c +++ b/net/dsa/dsa.c | |||
@@ -176,6 +176,41 @@ __ATTRIBUTE_GROUPS(dsa_hwmon); | |||
176 | #endif /* CONFIG_NET_DSA_HWMON */ | 176 | #endif /* CONFIG_NET_DSA_HWMON */ |
177 | 177 | ||
178 | /* basic switch operations **************************************************/ | 178 | /* basic switch operations **************************************************/ |
179 | static int dsa_cpu_dsa_setup(struct dsa_switch *ds, struct net_device *master) | ||
180 | { | ||
181 | struct dsa_chip_data *cd = ds->pd; | ||
182 | struct device_node *port_dn; | ||
183 | struct phy_device *phydev; | ||
184 | int ret, port, mode; | ||
185 | |||
186 | for (port = 0; port < DSA_MAX_PORTS; port++) { | ||
187 | if (!(dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port))) | ||
188 | continue; | ||
189 | |||
190 | port_dn = cd->port_dn[port]; | ||
191 | if (of_phy_is_fixed_link(port_dn)) { | ||
192 | ret = of_phy_register_fixed_link(port_dn); | ||
193 | if (ret) { | ||
194 | netdev_err(master, | ||
195 | "failed to register fixed PHY\n"); | ||
196 | return ret; | ||
197 | } | ||
198 | phydev = of_phy_find_device(port_dn); | ||
199 | |||
200 | mode = of_get_phy_mode(port_dn); | ||
201 | if (mode < 0) | ||
202 | mode = PHY_INTERFACE_MODE_NA; | ||
203 | phydev->interface = mode; | ||
204 | |||
205 | genphy_config_init(phydev); | ||
206 | genphy_read_status(phydev); | ||
207 | if (ds->drv->adjust_link) | ||
208 | ds->drv->adjust_link(ds, port, phydev); | ||
209 | } | ||
210 | } | ||
211 | return 0; | ||
212 | } | ||
213 | |||
179 | static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent) | 214 | static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent) |
180 | { | 215 | { |
181 | struct dsa_switch_driver *drv = ds->drv; | 216 | struct dsa_switch_driver *drv = ds->drv; |
@@ -297,6 +332,14 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent) | |||
297 | } | 332 | } |
298 | } | 333 | } |
299 | 334 | ||
335 | /* Perform configuration of the CPU and DSA ports */ | ||
336 | ret = dsa_cpu_dsa_setup(ds, dst->master_netdev); | ||
337 | if (ret < 0) { | ||
338 | netdev_err(dst->master_netdev, "[%d] : can't configure CPU and DSA ports\n", | ||
339 | index); | ||
340 | ret = 0; | ||
341 | } | ||
342 | |||
300 | #ifdef CONFIG_NET_DSA_HWMON | 343 | #ifdef CONFIG_NET_DSA_HWMON |
301 | /* If the switch provides a temperature sensor, | 344 | /* If the switch provides a temperature sensor, |
302 | * register with hardware monitoring subsystem. | 345 | * register with hardware monitoring subsystem. |
@@ -554,6 +597,31 @@ static int dsa_of_setup_routing_table(struct dsa_platform_data *pd, | |||
554 | return 0; | 597 | return 0; |
555 | } | 598 | } |
556 | 599 | ||
600 | static int dsa_of_probe_links(struct dsa_platform_data *pd, | ||
601 | struct dsa_chip_data *cd, | ||
602 | int chip_index, int port_index, | ||
603 | struct device_node *port, | ||
604 | const char *port_name) | ||
605 | { | ||
606 | struct device_node *link; | ||
607 | int link_index; | ||
608 | int ret; | ||
609 | |||
610 | for (link_index = 0;; link_index++) { | ||
611 | link = of_parse_phandle(port, "link", link_index); | ||
612 | if (!link) | ||
613 | break; | ||
614 | |||
615 | if (!strcmp(port_name, "dsa") && pd->nr_chips > 1) { | ||
616 | ret = dsa_of_setup_routing_table(pd, cd, chip_index, | ||
617 | port_index, link); | ||
618 | if (ret) | ||
619 | return ret; | ||
620 | } | ||
621 | } | ||
622 | return 0; | ||
623 | } | ||
624 | |||
557 | static void dsa_of_free_platform_data(struct dsa_platform_data *pd) | 625 | static void dsa_of_free_platform_data(struct dsa_platform_data *pd) |
558 | { | 626 | { |
559 | int i; | 627 | int i; |
@@ -573,8 +641,8 @@ static void dsa_of_free_platform_data(struct dsa_platform_data *pd) | |||
573 | static int dsa_of_probe(struct device *dev) | 641 | static int dsa_of_probe(struct device *dev) |
574 | { | 642 | { |
575 | struct device_node *np = dev->of_node; | 643 | struct device_node *np = dev->of_node; |
576 | struct device_node *child, *mdio, *ethernet, *port, *link; | 644 | struct device_node *child, *mdio, *ethernet, *port; |
577 | struct mii_bus *mdio_bus; | 645 | struct mii_bus *mdio_bus, *mdio_bus_switch; |
578 | struct net_device *ethernet_dev; | 646 | struct net_device *ethernet_dev; |
579 | struct dsa_platform_data *pd; | 647 | struct dsa_platform_data *pd; |
580 | struct dsa_chip_data *cd; | 648 | struct dsa_chip_data *cd; |
@@ -630,18 +698,30 @@ static int dsa_of_probe(struct device *dev) | |||
630 | continue; | 698 | continue; |
631 | 699 | ||
632 | cd->sw_addr = be32_to_cpup(sw_addr); | 700 | cd->sw_addr = be32_to_cpup(sw_addr); |
633 | if (cd->sw_addr > PHY_MAX_ADDR) | 701 | if (cd->sw_addr >= PHY_MAX_ADDR) |
634 | continue; | 702 | continue; |
635 | 703 | ||
636 | if (!of_property_read_u32(child, "eeprom-length", &eeprom_len)) | 704 | if (!of_property_read_u32(child, "eeprom-length", &eeprom_len)) |
637 | cd->eeprom_len = eeprom_len; | 705 | cd->eeprom_len = eeprom_len; |
638 | 706 | ||
707 | mdio = of_parse_phandle(child, "mii-bus", 0); | ||
708 | if (mdio) { | ||
709 | mdio_bus_switch = of_mdio_find_bus(mdio); | ||
710 | if (!mdio_bus_switch) { | ||
711 | ret = -EPROBE_DEFER; | ||
712 | goto out_free_chip; | ||
713 | } | ||
714 | cd->host_dev = &mdio_bus_switch->dev; | ||
715 | } | ||
716 | |||
639 | for_each_available_child_of_node(child, port) { | 717 | for_each_available_child_of_node(child, port) { |
640 | port_reg = of_get_property(port, "reg", NULL); | 718 | port_reg = of_get_property(port, "reg", NULL); |
641 | if (!port_reg) | 719 | if (!port_reg) |
642 | continue; | 720 | continue; |
643 | 721 | ||
644 | port_index = be32_to_cpup(port_reg); | 722 | port_index = be32_to_cpup(port_reg); |
723 | if (port_index >= DSA_MAX_PORTS) | ||
724 | break; | ||
645 | 725 | ||
646 | port_name = of_get_property(port, "label", NULL); | 726 | port_name = of_get_property(port, "label", NULL); |
647 | if (!port_name) | 727 | if (!port_name) |
@@ -656,18 +736,11 @@ static int dsa_of_probe(struct device *dev) | |||
656 | goto out_free_chip; | 736 | goto out_free_chip; |
657 | } | 737 | } |
658 | 738 | ||
659 | link = of_parse_phandle(port, "link", 0); | 739 | ret = dsa_of_probe_links(pd, cd, chip_index, |
660 | 740 | port_index, port, port_name); | |
661 | if (!strcmp(port_name, "dsa") && link && | 741 | if (ret) |
662 | pd->nr_chips > 1) { | 742 | goto out_free_chip; |
663 | ret = dsa_of_setup_routing_table(pd, cd, | ||
664 | chip_index, port_index, link); | ||
665 | if (ret) | ||
666 | goto out_free_chip; | ||
667 | } | ||
668 | 743 | ||
669 | if (port_index == DSA_MAX_PORTS) | ||
670 | break; | ||
671 | } | 744 | } |
672 | } | 745 | } |
673 | 746 | ||