| @@ -1,17 +1,9 @@ |
| | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 1 | /* | 2 | /* |
| 2 | * Copyright (C) 2009 Felix Fietkau <nbd@nbd.name> | 3 | * Copyright (C) 2009 Felix Fietkau <nbd@nbd.name> |
| 3 | * Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org> | 4 | * Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org> |
| 4 | * Copyright (c) 2015, The Linux Foundation. All rights reserved. | 5 | * Copyright (c) 2015, The Linux Foundation. All rights reserved. |
| 5 | * Copyright (c) 2016 John Crispin <john@phrozen.org> | 6 | * Copyright (c) 2016 John Crispin <john@phrozen.org> |
| 6 | * | | |
| 7 | * This program is free software; you can redistribute it and/or modify | | |
| 8 | * it under the terms of the GNU General Public License version 2 and | | |
| 9 | * only version 2 as published by the Free Software Foundation. | | |
| 10 | * | | |
| 11 | * This program is distributed in the hope that it will be useful, | | |
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | | |
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | |
| 14 | * GNU General Public License for more details. | | |
| 15 | */ | 7 | */ |
| 16 | | 8 | |
| 17 | #include <linux/module.h> | 9 | #include <linux/module.h> |
| @@ -473,10 +465,10 @@ qca8k_set_pad_ctrl(struct qca8k_priv *priv, int port, int mode) · 455 unmodified lines |
| 473 | static void | 465 | static void |
| 474 | qca8k_port_set_status(struct qca8k_priv *priv, int port, int enable) | 466 | qca8k_port_set_status(struct qca8k_priv *priv, int port, int enable) |
| 475 | { | 467 | { |
| 476 | u32 mask = QCA8K_PORT_STATUS_TXMAC; | 468 | u32 mask = QCA8K_PORT_STATUS_TXMAC | QCA8K_PORT_STATUS_RXMAC; |
| 477 | | 469 | |
| 478 | /* Port 0 and 6 have no internal PHY */ | 470 | /* Port 0 and 6 have no internal PHY */ |
| 479 | if ((port > 0) && (port < 6)) | 471 | if (port > 0 && port < 6) |
| 480 | mask |= QCA8K_PORT_STATUS_LINK_AUTO; | 472 | mask |= QCA8K_PORT_STATUS_LINK_AUTO; |
| 481 | | 473 | |
| 482 | if (enable) | 474 | if (enable) |
| @@ -490,6 +482,7 @@ qca8k_setup(struct dsa_switch *ds) · 7 unmodified lines |
| 490 | { | 482 | { |
| 491 | struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; | 483 | struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; |
| 492 | int ret, i, phy_mode = -1; | 484 | int ret, i, phy_mode = -1; |
| | 485 | u32 mask; |
| 493 | | 486 | |
| 494 | /* Make sure that port 0 is the cpu port */ | 487 | /* Make sure that port 0 is the cpu port */ |
| 495 | if (!dsa_is_cpu_port(ds, 0)) { | 488 | if (!dsa_is_cpu_port(ds, 0)) { |
| @@ -515,7 +508,10 @@ qca8k_setup(struct dsa_switch *ds) · 19 unmodified lines |
| 515 | if (ret < 0) | 508 | if (ret < 0) |
| 516 | return ret; | 509 | return ret; |
| 517 | | 510 | |
| 518 | /* Enable CPU Port */ | 511 | /* Enable CPU Port, force it to maximum bandwidth and full-duplex */ |
| | 512 | mask = QCA8K_PORT_STATUS_SPEED_1000 | QCA8K_PORT_STATUS_TXFLOW | |
| | 513 | QCA8K_PORT_STATUS_RXFLOW | QCA8K_PORT_STATUS_DUPLEX; |
| | 514 | qca8k_write(priv, QCA8K_REG_PORT_STATUS(QCA8K_CPU_PORT), mask); |
| 519 | qca8k_reg_set(priv, QCA8K_REG_GLOBAL_FW_CTRL0, | 515 | qca8k_reg_set(priv, QCA8K_REG_GLOBAL_FW_CTRL0, |
| 520 | QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN); | 516 | QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN); |
| 521 | qca8k_port_set_status(priv, QCA8K_CPU_PORT, 1); | 517 | qca8k_port_set_status(priv, QCA8K_CPU_PORT, 1); |
| @@ -583,6 +579,47 @@ qca8k_setup(struct dsa_switch *ds) · 61 unmodified lines |
| 583 | return 0; | 579 | return 0; |
| 584 | } | 580 | } |
| 585 | | 581 | |
| | 582 | static void |
| | 583 | qca8k_adjust_link(struct dsa_switch *ds, int port, struct phy_device *phy) |
| | 584 | { |
| | 585 | struct qca8k_priv *priv = ds->priv; |
| | 586 | u32 reg; |
| | 587 | |
| | 588 | /* Force fixed-link setting for CPU port, skip others. */ |
| | 589 | if (!phy_is_pseudo_fixed_link(phy)) |
| | 590 | return; |
| | 591 | |
| | 592 | /* Set port speed */ |
| | 593 | switch (phy->speed) { |
| | 594 | case 10: |
| | 595 | reg = QCA8K_PORT_STATUS_SPEED_10; |
| | 596 | break; |
| | 597 | case 100: |
| | 598 | reg = QCA8K_PORT_STATUS_SPEED_100; |
| | 599 | break; |
| | 600 | case 1000: |
| | 601 | reg = QCA8K_PORT_STATUS_SPEED_1000; |
| | 602 | break; |
| | 603 | default: |
| | 604 | dev_dbg(priv->dev, "port%d link speed %dMbps not supported.\n", |
| | 605 | port, phy->speed); |
| | 606 | return; |
| | 607 | } |
| | 608 | |
| | 609 | /* Set duplex mode */ |
| | 610 | if (phy->duplex == DUPLEX_FULL) |
| | 611 | reg |= QCA8K_PORT_STATUS_DUPLEX; |
| | 612 | |
| | 613 | /* Force flow control */ |
| | 614 | if (dsa_is_cpu_port(ds, port)) |
| | 615 | reg |= QCA8K_PORT_STATUS_RXFLOW | QCA8K_PORT_STATUS_TXFLOW; |
| | 616 | |
| | 617 | /* Force link down before changing MAC options */ |
| | 618 | qca8k_port_set_status(priv, port, 0); |
| | 619 | qca8k_write(priv, QCA8K_REG_PORT_STATUS(port), reg); |
| | 620 | qca8k_port_set_status(priv, port, 1); |
| | 621 | } |
| | 622 | |
| 586 | static int | 623 | static int |
| 587 | qca8k_phy_read(struct dsa_switch *ds, int phy, int regnum) | 624 | qca8k_phy_read(struct dsa_switch *ds, int phy, int regnum) |
| 588 | { | 625 | { |
| @@ -837,6 +874,7 @@ qca8k_get_tag_protocol(struct dsa_switch *ds, int port) · 248 unmodified lines |
| 837 | static const struct dsa_switch_ops qca8k_switch_ops = { | 874 | static const struct dsa_switch_ops qca8k_switch_ops = { |
| 838 | .get_tag_protocol = qca8k_get_tag_protocol, | 875 | .get_tag_protocol = qca8k_get_tag_protocol, |
| 839 | .setup = qca8k_setup, | 876 | .setup = qca8k_setup, |
| | 877 | .adjust_link = qca8k_adjust_link, |
| 840 | .get_strings = qca8k_get_strings, | 878 | .get_strings = qca8k_get_strings, |
| 841 | .phy_read = qca8k_phy_read, | 879 | .phy_read = qca8k_phy_read, |
| 842 | .phy_write = qca8k_phy_write, | 880 | .phy_write = qca8k_phy_write, |
| @@ -868,6 +906,7 @@ qca8k_sw_probe(struct mdio_device *mdiodev) · 25 unmodified lines |
| 868 | return -ENOMEM; | 906 | return -ENOMEM; |
| 869 | | 907 | |
| 870 | priv->bus = mdiodev->bus; | 908 | priv->bus = mdiodev->bus; |
| | 909 | priv->dev = &mdiodev->dev; |
| 871 | | 910 | |
| 872 | /* read the switches ID register */ | 911 | /* read the switches ID register */ |
| 873 | id = qca8k_read(priv, QCA8K_REG_MASK_CTRL); | 912 | id = qca8k_read(priv, QCA8K_REG_MASK_CTRL); |
| @@ -939,6 +978,7 @@ static SIMPLE_DEV_PM_OPS(qca8k_pm_ops, · 65 unmodified lines |
| 939 | qca8k_suspend, qca8k_resume); | 978 | qca8k_suspend, qca8k_resume); |
| 940 | | 979 | |
| 941 | static const struct of_device_id qca8k_of_match[] = { | 980 | static const struct of_device_id qca8k_of_match[] = { |
| | 981 | { .compatible = "qca,qca8334" }, |
| 942 | { .compatible = "qca,qca8337" }, | 982 | { .compatible = "qca,qca8337" }, |
| 943 | { /* sentinel */ }, | 983 | { /* sentinel */ }, |
| 944 | }; | 984 | }; |