[ mvebu-dev ] Merge pull request #1745 from armbian/mvebu-dev-cleanup

[ mvebu-dev ] cleanup patches and disable pcie support in kernel config to use pcie
This commit is contained in:
Jannis 2020-01-19 11:21:06 +01:00 committed by GitHub
commit e4c8c0aaa0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 23 additions and 79664 deletions

View File

@ -1,6 +1,6 @@
#
# Automatically generated file; DO NOT EDIT.
# Linux/arm 5.4.7 Kernel Configuration
# Linux/arm 5.4.12 Kernel Configuration
#
#
@ -1626,20 +1626,7 @@ CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
CONFIG_PCI_DOMAINS_GENERIC=y
CONFIG_PCI_SYSCALL=y
CONFIG_PCIEPORTBUS=y
CONFIG_PCIEAER=y
# CONFIG_PCIEAER_INJECT is not set
# CONFIG_PCIE_ECRC is not set
CONFIG_PCIEASPM=y
# CONFIG_PCIEASPM_DEBUG is not set
# CONFIG_PCIEASPM_DEFAULT is not set
# CONFIG_PCIEASPM_POWERSAVE is not set
# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set
CONFIG_PCIEASPM_PERFORMANCE=y
CONFIG_PCIE_PME=y
# CONFIG_PCIE_DPC is not set
# CONFIG_PCIE_PTM is not set
CONFIG_PCIE_BW=y
# CONFIG_PCIEPORTBUS is not set
CONFIG_PCI_MSI=y
CONFIG_PCI_MSI_IRQ_DOMAIN=y
CONFIG_PCI_QUIRKS=y

View File

@ -5,12 +5,9 @@ Subject: sfp: display SFP module information
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
drivers/net/phy/sfp.c | 254 +++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 253 insertions(+), 1 deletion(-)
--- a/drivers/net/phy/sfp.c
+++ b/drivers/net/phy/sfp.c
@@ -247,6 +247,184 @@ static unsigned int sfp_check(void *buf,
@@ -403,6 +403,185 @@ static unsigned int sfp_check(void *buf, size_t len)
return check;
}
@ -24,11 +21,11 @@ Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
+ *buf++ = '>';
+ size -= 1;
+ length -= 1;
+ }
+ }
+
+ length *= multiplier;
+ length *= multiplier;
+
+ if (length >= 1000)
+ if (length >= 1000)
+ snprintf(buf, size, "%u.%0*ukm",
+ length / 1000,
+ multiplier > 100 ? 1 :
@ -185,40 +182,29 @@ Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
+ return "4b5b";
+ case SFP_ENCODING_NRZ:
+ return "NRZ";
+ case SFP_ENCODING_8472_MANCHESTER:
+ case SFP_ENCODING_8472_MANCHESTER:
+ return "MANCHESTER";
+ default:
+ return "unknown";
+ }
+}
+
/* Helpers */
static void sfp_module_tx_disable(struct sfp *sfp)
{
@@ -415,6 +593,7 @@ static int sfp_sm_mod_probe(struct sfp *
char sn[17];
char date[9];
char rev[5];
+
/* hwmon */
#if IS_ENABLED(CONFIG_HWMON)
static umode_t sfp_hwmon_is_visible(const void *data,
@@ -1388,6 +1567,7 @@ static int sfp_sm_mod_probe(struct sfp *sfp)
/* SFP module inserted - read I2C data */
struct sfp_eeprom_id id;
bool cotsworks;
+ char options[80];
u8 check;
int err;
int ret;
@@ -458,10 +637,83 @@ static int sfp_sm_mod_probe(struct sfp *
rev[4] = '\0';
memcpy(sn, sfp->id.ext.vendor_sn, 16);
sn[16] = '\0';
- memcpy(date, sfp->id.ext.datecode, 8);
+ date[0] = sfp->id.ext.datecode[4];
+ date[1] = sfp->id.ext.datecode[5];
+ date[2] = '-';
+ date[3] = sfp->id.ext.datecode[2];
+ date[4] = sfp->id.ext.datecode[3];
+ date[5] = '-';
+ date[6] = sfp->id.ext.datecode[0];
+ date[7] = sfp->id.ext.datecode[1];
date[8] = '\0';
@@ -1450,6 +1630,73 @@ static int sfp_sm_mod_probe(struct sfp *sfp)
(int)sizeof(id.ext.vendor_sn), id.ext.vendor_sn,
(int)sizeof(id.ext.datecode), id.ext.datecode);
dev_info(sfp->dev, "module %s %s rev %s sn %s dc %s\n", vendor, part, rev, sn, date);
+ dev_info(sfp->dev, " %s connector, encoding %s, nominal bitrate %u.%uGbps +%u%% -%u%%\n",
+ sfp_connector(sfp->id.base.connector),
+ sfp_encoding(sfp->id.base.encoding),
@ -285,6 +271,7 @@ Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
+ dev_info(sfp->dev, " Diagnostics: %s\n",
+ sfp_bitfield(options, sizeof(options), diagmon,
+ sfp->id.ext.diagmon));
/* We only support SFP modules, not the legacy GBIC modules. */
if (sfp->id.base.phys_id != SFP_PHYS_ID_SFP ||
+
/* Check whether we support this module */
if (!sfp->type->module_supported(&sfp->id)) {
dev_err(sfp->dev,

View File

@ -1,979 +0,0 @@
From 36f29e6cf8071fed3854d9825217ed2a3c83b990 Mon Sep 17 00:00:00 2001
From: Russell King <rmk+kernel@arm.linux.org.uk>
Date: Wed, 16 Sep 2015 21:27:10 +0100
Subject: net: mvneta: convert to phylink
Convert mvneta to use phylink, which models the MAC to PHY link in
a generic, reusable form.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
- remove unused sync status
---
drivers/net/ethernet/marvell/Kconfig | 2 +-
drivers/net/ethernet/marvell/mvneta.c | 594 ++++++++++++++++++++--------------
2 files changed, 349 insertions(+), 247 deletions(-)
--- a/drivers/net/ethernet/marvell/Kconfig
+++ b/drivers/net/ethernet/marvell/Kconfig
@@ -60,7 +60,7 @@ config MVNETA
depends on ARCH_MVEBU || COMPILE_TEST
depends on HAS_DMA
select MVMDIO
- select FIXED_PHY
+ select PHYLINK
---help---
This driver supports the network interface units in the
Marvell ARMADA XP, ARMADA 370, ARMADA 38x and
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -28,7 +28,7 @@
#include <linux/of_mdio.h>
#include <linux/of_net.h>
#include <linux/phy.h>
-#include <linux/phy_fixed.h>
+#include <linux/phylink.h>
#include <linux/platform_device.h>
#include <linux/skbuff.h>
#include <net/hwbm.h>
@@ -189,6 +189,7 @@
#define MVNETA_GMAC_CTRL_0 0x2c00
#define MVNETA_GMAC_MAX_RX_SIZE_SHIFT 2
#define MVNETA_GMAC_MAX_RX_SIZE_MASK 0x7ffc
+#define MVNETA_GMAC0_PORT_1000BASE_X BIT(1)
#define MVNETA_GMAC0_PORT_ENABLE BIT(0)
#define MVNETA_GMAC_CTRL_2 0x2c08
#define MVNETA_GMAC2_INBAND_AN_ENABLE BIT(0)
@@ -204,13 +205,19 @@
#define MVNETA_GMAC_TX_FLOW_CTRL_ENABLE BIT(5)
#define MVNETA_GMAC_RX_FLOW_CTRL_ACTIVE BIT(6)
#define MVNETA_GMAC_TX_FLOW_CTRL_ACTIVE BIT(7)
+#define MVNETA_GMAC_AN_COMPLETE BIT(11)
+#define MVNETA_GMAC_SYNC_OK BIT(14)
#define MVNETA_GMAC_AUTONEG_CONFIG 0x2c0c
#define MVNETA_GMAC_FORCE_LINK_DOWN BIT(0)
#define MVNETA_GMAC_FORCE_LINK_PASS BIT(1)
#define MVNETA_GMAC_INBAND_AN_ENABLE BIT(2)
+#define MVNETA_GMAC_AN_BYPASS_ENABLE BIT(3)
+#define MVNETA_GMAC_INBAND_RESTART_AN BIT(4)
#define MVNETA_GMAC_CONFIG_MII_SPEED BIT(5)
#define MVNETA_GMAC_CONFIG_GMII_SPEED BIT(6)
#define MVNETA_GMAC_AN_SPEED_EN BIT(7)
+#define MVNETA_GMAC_CONFIG_FLOW_CTRL BIT(8)
+#define MVNETA_GMAC_ADVERT_SYM_FLOW_CTRL BIT(9)
#define MVNETA_GMAC_AN_FLOW_CTRL_EN BIT(11)
#define MVNETA_GMAC_CONFIG_FULL_DUPLEX BIT(12)
#define MVNETA_GMAC_AN_DUPLEX_EN BIT(13)
@@ -237,6 +244,12 @@
#define MVNETA_TXQ_TOKEN_SIZE_REG(q) (0x3e40 + ((q) << 2))
#define MVNETA_TXQ_TOKEN_SIZE_MAX 0x7fffffff
+#define MVNETA_LPI_CTRL_0 0x2cc0
+#define MVNETA_LPI_CTRL_1 0x2cc4
+#define MVNETA_LPI_REQUEST_ENABLE BIT(0)
+#define MVNETA_LPI_CTRL_2 0x2cc8
+#define MVNETA_LPI_STATUS 0x2ccc
+
#define MVNETA_CAUSE_TXQ_SENT_DESC_ALL_MASK 0xff
/* Descriptor ring Macros */
@@ -313,6 +326,11 @@
#define MVNETA_RX_GET_BM_POOL_ID(rxd) \
(((rxd)->status & MVNETA_RXD_BM_POOL_MASK) >> MVNETA_RXD_BM_POOL_SHIFT)
+enum {
+ ETHTOOL_STAT_EEE_WAKEUP,
+ ETHTOOL_MAX_STATS,
+};
+
struct mvneta_statistic {
unsigned short offset;
unsigned short type;
@@ -321,6 +339,7 @@ struct mvneta_statistic {
#define T_REG_32 32
#define T_REG_64 64
+#define T_SW 1
static const struct mvneta_statistic mvneta_statistics[] = {
{ 0x3000, T_REG_64, "good_octets_received", },
@@ -355,6 +374,7 @@ static const struct mvneta_statistic mvn
{ 0x304c, T_REG_32, "broadcast_frames_sent", },
{ 0x3054, T_REG_32, "fc_sent", },
{ 0x300c, T_REG_32, "internal_mac_transmit_err", },
+ { ETHTOOL_STAT_EEE_WAKEUP, T_SW, "eee_wakeup_errors", },
};
struct mvneta_pcpu_stats {
@@ -407,20 +427,19 @@ struct mvneta_port {
u16 tx_ring_size;
u16 rx_ring_size;
- struct mii_bus *mii_bus;
- phy_interface_t phy_interface;
- struct device_node *phy_node;
- unsigned int link;
- unsigned int duplex;
- unsigned int speed;
+ struct device_node *dn;
unsigned int tx_csum_limit;
- unsigned int use_inband_status:1;
+ struct phylink *phylink;
struct mvneta_bm *bm_priv;
struct mvneta_bm_pool *pool_long;
struct mvneta_bm_pool *pool_short;
int bm_win_id;
+ bool eee_enabled;
+ bool eee_active;
+ bool tx_lpi_enabled;
+
u64 ethtool_stats[ARRAY_SIZE(mvneta_statistics)];
u32 indir[MVNETA_RSS_LU_TABLE_SIZE];
@@ -1214,10 +1233,6 @@ static void mvneta_port_disable(struct m
val &= ~MVNETA_GMAC0_PORT_ENABLE;
mvreg_write(pp, MVNETA_GMAC_CTRL_0, val);
- pp->link = 0;
- pp->duplex = -1;
- pp->speed = 0;
-
udelay(200);
}
@@ -1277,44 +1292,6 @@ static void mvneta_set_other_mcast_table
mvreg_write(pp, MVNETA_DA_FILT_OTH_MCAST + offset, val);
}
-static void mvneta_set_autoneg(struct mvneta_port *pp, int enable)
-{
- u32 val;
-
- if (enable) {
- val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG);
- val &= ~(MVNETA_GMAC_FORCE_LINK_PASS |
- MVNETA_GMAC_FORCE_LINK_DOWN |
- MVNETA_GMAC_AN_FLOW_CTRL_EN);
- val |= MVNETA_GMAC_INBAND_AN_ENABLE |
- MVNETA_GMAC_AN_SPEED_EN |
- MVNETA_GMAC_AN_DUPLEX_EN;
- mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val);
-
- val = mvreg_read(pp, MVNETA_GMAC_CLOCK_DIVIDER);
- val |= MVNETA_GMAC_1MS_CLOCK_ENABLE;
- mvreg_write(pp, MVNETA_GMAC_CLOCK_DIVIDER, val);
-
- val = mvreg_read(pp, MVNETA_GMAC_CTRL_2);
- val |= MVNETA_GMAC2_INBAND_AN_ENABLE;
- mvreg_write(pp, MVNETA_GMAC_CTRL_2, val);
- } else {
- val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG);
- val &= ~(MVNETA_GMAC_INBAND_AN_ENABLE |
- MVNETA_GMAC_AN_SPEED_EN |
- MVNETA_GMAC_AN_DUPLEX_EN);
- mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val);
-
- val = mvreg_read(pp, MVNETA_GMAC_CLOCK_DIVIDER);
- val &= ~MVNETA_GMAC_1MS_CLOCK_ENABLE;
- mvreg_write(pp, MVNETA_GMAC_CLOCK_DIVIDER, val);
-
- val = mvreg_read(pp, MVNETA_GMAC_CTRL_2);
- val &= ~MVNETA_GMAC2_INBAND_AN_ENABLE;
- mvreg_write(pp, MVNETA_GMAC_CTRL_2, val);
- }
-}
-
static void mvneta_percpu_unmask_interrupt(void *arg)
{
struct mvneta_port *pp = arg;
@@ -1467,7 +1444,6 @@ static void mvneta_defaults_set(struct m
val &= ~MVNETA_PHY_POLLING_ENABLE;
mvreg_write(pp, MVNETA_UNIT_CONTROL, val);
- mvneta_set_autoneg(pp, pp->use_inband_status);
mvneta_set_ucast_table(pp, -1);
mvneta_set_special_mcast_table(pp, -1);
mvneta_set_other_mcast_table(pp, -1);
@@ -2692,26 +2668,11 @@ static irqreturn_t mvneta_percpu_isr(int
return IRQ_HANDLED;
}
-static int mvneta_fixed_link_update(struct mvneta_port *pp,
- struct phy_device *phy)
+static void mvneta_link_change(struct mvneta_port *pp)
{
- struct fixed_phy_status status;
- struct fixed_phy_status changed = {};
u32 gmac_stat = mvreg_read(pp, MVNETA_GMAC_STATUS);
- status.link = !!(gmac_stat & MVNETA_GMAC_LINK_UP);
- if (gmac_stat & MVNETA_GMAC_SPEED_1000)
- status.speed = SPEED_1000;
- else if (gmac_stat & MVNETA_GMAC_SPEED_100)
- status.speed = SPEED_100;
- else
- status.speed = SPEED_10;
- status.duplex = !!(gmac_stat & MVNETA_GMAC_FULL_DUPLEX);
- changed.link = 1;
- changed.speed = 1;
- changed.duplex = 1;
- fixed_phy_update_state(phy, &status, &changed);
- return 0;
+ phylink_mac_change(pp->phylink, !!(gmac_stat & MVNETA_GMAC_LINK_UP));
}
/* NAPI handler
@@ -2727,7 +2688,6 @@ static int mvneta_poll(struct napi_struc
u32 cause_rx_tx;
int rx_queue;
struct mvneta_port *pp = netdev_priv(napi->dev);
- struct net_device *ndev = pp->dev;
struct mvneta_pcpu_port *port = this_cpu_ptr(pp->ports);
if (!netif_running(pp->dev)) {
@@ -2741,12 +2701,11 @@ static int mvneta_poll(struct napi_struc
u32 cause_misc = mvreg_read(pp, MVNETA_INTR_MISC_CAUSE);
mvreg_write(pp, MVNETA_INTR_MISC_CAUSE, 0);
- if (pp->use_inband_status && (cause_misc &
- (MVNETA_CAUSE_PHY_STATUS_CHANGE |
- MVNETA_CAUSE_LINK_CHANGE |
- MVNETA_CAUSE_PSC_SYNC_CHANGE))) {
- mvneta_fixed_link_update(pp, ndev->phydev);
- }
+
+ if (cause_misc & (MVNETA_CAUSE_PHY_STATUS_CHANGE |
+ MVNETA_CAUSE_LINK_CHANGE |
+ MVNETA_CAUSE_PSC_SYNC_CHANGE))
+ mvneta_link_change(pp);
}
/* Release Tx descriptors */
@@ -3060,7 +3019,6 @@ static int mvneta_setup_txqs(struct mvne
static void mvneta_start_dev(struct mvneta_port *pp)
{
int cpu;
- struct net_device *ndev = pp->dev;
mvneta_max_rx_size_set(pp, pp->pkt_size);
mvneta_txq_max_tx_size_set(pp, pp->pkt_size);
@@ -3088,16 +3046,15 @@ static void mvneta_start_dev(struct mvne
MVNETA_CAUSE_LINK_CHANGE |
MVNETA_CAUSE_PSC_SYNC_CHANGE);
- phy_start(ndev->phydev);
+ phylink_start(pp->phylink);
netif_tx_start_all_queues(pp->dev);
}
static void mvneta_stop_dev(struct mvneta_port *pp)
{
unsigned int cpu;
- struct net_device *ndev = pp->dev;
- phy_stop(ndev->phydev);
+ phylink_stop(pp->phylink);
if (!pp->neta_armada3700) {
for_each_online_cpu(cpu) {
@@ -3251,103 +3208,232 @@ static int mvneta_set_mac_addr(struct ne
return 0;
}
-static void mvneta_adjust_link(struct net_device *ndev)
+static void mvneta_validate(struct net_device *ndev, unsigned long *supported,
+ struct phylink_link_state *state)
+{
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
+
+ /* Allow all the expected bits */
+ phylink_set(mask, Autoneg);
+ phylink_set_port_modes(mask);
+
+ /* Asymmetric pause is unsupported */
+ phylink_set(mask, Pause);
+ /* Half-duplex at speeds higher than 100Mbit is unsupported */
+ phylink_set(mask, 1000baseT_Full);
+ phylink_set(mask, 1000baseX_Full);
+
+ if (state->interface != PHY_INTERFACE_MODE_1000BASEX) {
+ /* 10M and 100M are only supported in non-802.3z mode */
+ phylink_set(mask, 10baseT_Half);
+ phylink_set(mask, 10baseT_Full);
+ phylink_set(mask, 100baseT_Half);
+ phylink_set(mask, 100baseT_Full);
+ }
+
+ bitmap_and(supported, supported, mask,
+ __ETHTOOL_LINK_MODE_MASK_NBITS);
+ bitmap_and(state->advertising, state->advertising, mask,
+ __ETHTOOL_LINK_MODE_MASK_NBITS);
+}
+
+static int mvneta_mac_link_state(struct net_device *ndev,
+ struct phylink_link_state *state)
{
struct mvneta_port *pp = netdev_priv(ndev);
- struct phy_device *phydev = ndev->phydev;
- int status_change = 0;
+ u32 gmac_stat;
- if (phydev->link) {
- if ((pp->speed != phydev->speed) ||
- (pp->duplex != phydev->duplex)) {
- u32 val;
-
- val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG);
- val &= ~(MVNETA_GMAC_CONFIG_MII_SPEED |
- MVNETA_GMAC_CONFIG_GMII_SPEED |
- MVNETA_GMAC_CONFIG_FULL_DUPLEX);
-
- if (phydev->duplex)
- val |= MVNETA_GMAC_CONFIG_FULL_DUPLEX;
-
- if (phydev->speed == SPEED_1000)
- val |= MVNETA_GMAC_CONFIG_GMII_SPEED;
- else if (phydev->speed == SPEED_100)
- val |= MVNETA_GMAC_CONFIG_MII_SPEED;
+ gmac_stat = mvreg_read(pp, MVNETA_GMAC_STATUS);
- mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val);
+ if (gmac_stat & MVNETA_GMAC_SPEED_1000)
+ state->speed = SPEED_1000;
+ else if (gmac_stat & MVNETA_GMAC_SPEED_100)
+ state->speed = SPEED_100;
+ else
+ state->speed = SPEED_10;
- pp->duplex = phydev->duplex;
- pp->speed = phydev->speed;
- }
+ state->an_complete = !!(gmac_stat & MVNETA_GMAC_AN_COMPLETE);
+ state->link = !!(gmac_stat & MVNETA_GMAC_LINK_UP);
+ state->duplex = !!(gmac_stat & MVNETA_GMAC_FULL_DUPLEX);
+
+ state->pause = 0;
+ if (gmac_stat & MVNETA_GMAC_RX_FLOW_CTRL_ENABLE)
+ state->pause |= MLO_PAUSE_RX;
+ if (gmac_stat & MVNETA_GMAC_TX_FLOW_CTRL_ENABLE)
+ state->pause |= MLO_PAUSE_TX;
+
+ return 1;
+}
+
+static void mvneta_mac_an_restart(struct net_device *ndev)
+{
+ struct mvneta_port *pp = netdev_priv(ndev);
+ u32 gmac_an = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG);
+
+ mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG,
+ gmac_an | MVNETA_GMAC_INBAND_RESTART_AN);
+ mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG,
+ gmac_an & ~MVNETA_GMAC_INBAND_RESTART_AN);
+}
+
+static void mvneta_mac_config(struct net_device *ndev, unsigned int mode,
+ const struct phylink_link_state *state)
+{
+ struct mvneta_port *pp = netdev_priv(ndev);
+ u32 new_ctrl0, gmac_ctrl0 = mvreg_read(pp, MVNETA_GMAC_CTRL_0);
+ u32 new_ctrl2, gmac_ctrl2 = mvreg_read(pp, MVNETA_GMAC_CTRL_2);
+ u32 new_clk, gmac_clk = mvreg_read(pp, MVNETA_GMAC_CLOCK_DIVIDER);
+ u32 new_an, gmac_an = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG);
+
+ new_ctrl0 = gmac_ctrl0 & ~MVNETA_GMAC0_PORT_1000BASE_X;
+ new_ctrl2 = gmac_ctrl2 & ~MVNETA_GMAC2_INBAND_AN_ENABLE;
+ new_clk = gmac_clk & ~MVNETA_GMAC_1MS_CLOCK_ENABLE;
+ new_an = gmac_an & ~(MVNETA_GMAC_INBAND_AN_ENABLE |
+ MVNETA_GMAC_INBAND_RESTART_AN |
+ MVNETA_GMAC_CONFIG_MII_SPEED |
+ MVNETA_GMAC_CONFIG_GMII_SPEED |
+ MVNETA_GMAC_AN_SPEED_EN |
+ MVNETA_GMAC_ADVERT_SYM_FLOW_CTRL |
+ MVNETA_GMAC_CONFIG_FLOW_CTRL |
+ MVNETA_GMAC_AN_FLOW_CTRL_EN |
+ MVNETA_GMAC_CONFIG_FULL_DUPLEX |
+ MVNETA_GMAC_AN_DUPLEX_EN);
+
+ if (phylink_test(state->advertising, Pause))
+ new_an |= MVNETA_GMAC_ADVERT_SYM_FLOW_CTRL;
+ if (state->pause & MLO_PAUSE_TXRX_MASK)
+ new_an |= MVNETA_GMAC_CONFIG_FLOW_CTRL;
+
+ if (!phylink_autoneg_inband(mode)) {
+ /* Phy or fixed speed */
+ if (state->duplex)
+ new_an |= MVNETA_GMAC_CONFIG_FULL_DUPLEX;
+
+ if (state->speed == SPEED_1000)
+ new_an |= MVNETA_GMAC_CONFIG_GMII_SPEED;
+ else if (state->speed == SPEED_100)
+ new_an |= MVNETA_GMAC_CONFIG_MII_SPEED;
+ } else if (state->interface == PHY_INTERFACE_MODE_SGMII) {
+ /* SGMII mode receives the state from the PHY */
+ new_ctrl2 |= MVNETA_GMAC2_INBAND_AN_ENABLE;
+ new_clk |= MVNETA_GMAC_1MS_CLOCK_ENABLE;
+ new_an = (new_an & ~(MVNETA_GMAC_FORCE_LINK_DOWN |
+ MVNETA_GMAC_FORCE_LINK_PASS)) |
+ MVNETA_GMAC_INBAND_AN_ENABLE |
+ MVNETA_GMAC_AN_SPEED_EN |
+ MVNETA_GMAC_AN_DUPLEX_EN;
+ } else {
+ /* 802.3z negotiation - only 1000base-X */
+ new_ctrl0 |= MVNETA_GMAC0_PORT_1000BASE_X;
+ new_clk |= MVNETA_GMAC_1MS_CLOCK_ENABLE;
+ new_an = (new_an & ~(MVNETA_GMAC_FORCE_LINK_DOWN |
+ MVNETA_GMAC_FORCE_LINK_PASS)) |
+ MVNETA_GMAC_INBAND_AN_ENABLE |
+ MVNETA_GMAC_CONFIG_GMII_SPEED |
+ /* The MAC only supports FD mode */
+ MVNETA_GMAC_CONFIG_FULL_DUPLEX;
+
+ if (state->pause & MLO_PAUSE_AN && state->an_enabled)
+ new_an |= MVNETA_GMAC_AN_FLOW_CTRL_EN;
+ }
+
+ /* Armada 370 documentation says we can only change the port mode
+ * and in-band enable when the link is down, so force it down
+ * while making these changes. We also do this for GMAC_CTRL2 */
+ if ((new_ctrl0 ^ gmac_ctrl0) & MVNETA_GMAC0_PORT_1000BASE_X ||
+ (new_ctrl2 ^ gmac_ctrl2) & MVNETA_GMAC2_INBAND_AN_ENABLE ||
+ (new_an ^ gmac_an) & MVNETA_GMAC_INBAND_AN_ENABLE) {
+ mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG,
+ (gmac_an & ~MVNETA_GMAC_FORCE_LINK_PASS) |
+ MVNETA_GMAC_FORCE_LINK_DOWN);
+ }
+
+ if (new_ctrl0 != gmac_ctrl0)
+ mvreg_write(pp, MVNETA_GMAC_CTRL_0, new_ctrl0);
+ if (new_ctrl2 != gmac_ctrl2)
+ mvreg_write(pp, MVNETA_GMAC_CTRL_2, new_ctrl2);
+ if (new_clk != gmac_clk)
+ mvreg_write(pp, MVNETA_GMAC_CLOCK_DIVIDER, new_clk);
+ if (new_an != gmac_an)
+ mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, new_an);
+}
+
+static void mvneta_set_eee(struct mvneta_port *pp, bool enable)
+{
+ u32 lpi_ctl1;
+
+ lpi_ctl1 = mvreg_read(pp, MVNETA_LPI_CTRL_1);
+ if (enable)
+ lpi_ctl1 |= MVNETA_LPI_REQUEST_ENABLE;
+ else
+ lpi_ctl1 &= ~MVNETA_LPI_REQUEST_ENABLE;
+ mvreg_write(pp, MVNETA_LPI_CTRL_1, lpi_ctl1);
+}
+
+static void mvneta_mac_link_down(struct net_device *ndev, unsigned int mode)
+{
+ struct mvneta_port *pp = netdev_priv(ndev);
+ u32 val;
+
+ mvneta_port_down(pp);
+
+ if (!phylink_autoneg_inband(mode)) {
+ val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG);
+ val &= ~MVNETA_GMAC_FORCE_LINK_PASS;
+ val |= MVNETA_GMAC_FORCE_LINK_DOWN;
+ mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val);
}
- if (phydev->link != pp->link) {
- if (!phydev->link) {
- pp->duplex = -1;
- pp->speed = 0;
- }
+ pp->eee_active = false;
+ mvneta_set_eee(pp, false);
+}
+
+static void mvneta_mac_link_up(struct net_device *ndev, unsigned int mode,
+ struct phy_device *phy)
+{
+ struct mvneta_port *pp = netdev_priv(ndev);
+ u32 val;
- pp->link = phydev->link;
- status_change = 1;
+ if (!phylink_autoneg_inband(mode)) {
+ val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG);
+ val &= ~MVNETA_GMAC_FORCE_LINK_DOWN;
+ val |= MVNETA_GMAC_FORCE_LINK_PASS;
+ mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val);
}
- if (status_change) {
- if (phydev->link) {
- if (!pp->use_inband_status) {
- u32 val = mvreg_read(pp,
- MVNETA_GMAC_AUTONEG_CONFIG);
- val &= ~MVNETA_GMAC_FORCE_LINK_DOWN;
- val |= MVNETA_GMAC_FORCE_LINK_PASS;
- mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG,
- val);
- }
- mvneta_port_up(pp);
- } else {
- if (!pp->use_inband_status) {
- u32 val = mvreg_read(pp,
- MVNETA_GMAC_AUTONEG_CONFIG);
- val &= ~MVNETA_GMAC_FORCE_LINK_PASS;
- val |= MVNETA_GMAC_FORCE_LINK_DOWN;
- mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG,
- val);
- }
- mvneta_port_down(pp);
- }
- phy_print_status(phydev);
+ mvneta_port_up(pp);
+
+ if (phy && pp->eee_enabled) {
+ pp->eee_active = phy_init_eee(phy, 0) >= 0;
+ mvneta_set_eee(pp, pp->eee_active && pp->tx_lpi_enabled);
}
}
+static const struct phylink_mac_ops mvneta_phylink_ops = {
+ .validate = mvneta_validate,
+ .mac_link_state = mvneta_mac_link_state,
+ .mac_an_restart = mvneta_mac_an_restart,
+ .mac_config = mvneta_mac_config,
+ .mac_link_down = mvneta_mac_link_down,
+ .mac_link_up = mvneta_mac_link_up,
+};
+
static int mvneta_mdio_probe(struct mvneta_port *pp)
{
- struct phy_device *phy_dev;
struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL };
+ int err = phylink_of_phy_connect(pp->phylink, pp->dn);
+ if (err)
+ netdev_err(pp->dev, "could not attach PHY\n");
- phy_dev = of_phy_connect(pp->dev, pp->phy_node, mvneta_adjust_link, 0,
- pp->phy_interface);
- if (!phy_dev) {
- netdev_err(pp->dev, "could not find the PHY\n");
- return -ENODEV;
- }
-
- phy_ethtool_get_wol(phy_dev, &wol);
+ phylink_ethtool_get_wol(pp->phylink, &wol);
device_set_wakeup_capable(&pp->dev->dev, !!wol.supported);
- phy_dev->supported &= PHY_GBIT_FEATURES;
- phy_dev->advertising = phy_dev->supported;
-
- pp->link = 0;
- pp->duplex = 0;
- pp->speed = 0;
-
- return 0;
+ return err;
}
static void mvneta_mdio_remove(struct mvneta_port *pp)
{
- struct net_device *ndev = pp->dev;
-
- phy_disconnect(ndev->phydev);
+ phylink_disconnect_phy(pp->phylink);
}
/* Electing a CPU must be done in an atomic way: it should be done
@@ -3626,10 +3712,9 @@ static int mvneta_stop(struct net_device
static int mvneta_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
- if (!dev->phydev)
- return -ENOTSUPP;
+ struct mvneta_port *pp = netdev_priv(dev);
- return phy_mii_ioctl(dev->phydev, ifr, cmd);
+ return phylink_mii_ioctl(pp->phylink, ifr, cmd);
}
/* Ethtool methods */
@@ -3640,44 +3725,25 @@ mvneta_ethtool_set_link_ksettings(struct
const struct ethtool_link_ksettings *cmd)
{
struct mvneta_port *pp = netdev_priv(ndev);
- struct phy_device *phydev = ndev->phydev;
- if (!phydev)
- return -ENODEV;
-
- if ((cmd->base.autoneg == AUTONEG_ENABLE) != pp->use_inband_status) {
- u32 val;
-
- mvneta_set_autoneg(pp, cmd->base.autoneg == AUTONEG_ENABLE);
-
- if (cmd->base.autoneg == AUTONEG_DISABLE) {
- val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG);
- val &= ~(MVNETA_GMAC_CONFIG_MII_SPEED |
- MVNETA_GMAC_CONFIG_GMII_SPEED |
- MVNETA_GMAC_CONFIG_FULL_DUPLEX);
-
- if (phydev->duplex)
- val |= MVNETA_GMAC_CONFIG_FULL_DUPLEX;
+ return phylink_ethtool_ksettings_set(pp->phylink, cmd);
+}
- if (phydev->speed == SPEED_1000)
- val |= MVNETA_GMAC_CONFIG_GMII_SPEED;
- else if (phydev->speed == SPEED_100)
- val |= MVNETA_GMAC_CONFIG_MII_SPEED;
+/* Get link ksettings for ethtools */
+static int
+mvneta_ethtool_get_link_ksettings(struct net_device *ndev,
+ struct ethtool_link_ksettings *cmd)
+{
+ struct mvneta_port *pp = netdev_priv(ndev);
- mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val);
- }
+ return phylink_ethtool_ksettings_get(pp->phylink, cmd);
+}
- pp->use_inband_status = (cmd->base.autoneg == AUTONEG_ENABLE);
- netdev_info(pp->dev, "autoneg status set to %i\n",
- pp->use_inband_status);
-
- if (netif_running(ndev)) {
- mvneta_port_down(pp);
- mvneta_port_up(pp);
- }
- }
+static int mvneta_ethtool_nway_reset(struct net_device *dev)
+{
+ struct mvneta_port *pp = netdev_priv(dev);
- return phy_ethtool_ksettings_set(ndev->phydev, cmd);
+ return phylink_ethtool_nway_reset(pp->phylink);
}
/* Set interrupt coalescing for ethtools */
@@ -3769,6 +3835,22 @@ static int mvneta_ethtool_set_ringparam(
return 0;
}
+static void mvneta_ethtool_get_pauseparam(struct net_device *dev,
+ struct ethtool_pauseparam *pause)
+{
+ struct mvneta_port *pp = netdev_priv(dev);
+
+ phylink_ethtool_get_pauseparam(pp->phylink, pause);
+}
+
+static int mvneta_ethtool_set_pauseparam(struct net_device *dev,
+ struct ethtool_pauseparam *pause)
+{
+ struct mvneta_port *pp = netdev_priv(dev);
+
+ return phylink_ethtool_set_pauseparam(pp->phylink, pause);
+}
+
static void mvneta_ethtool_get_strings(struct net_device *netdev, u32 sset,
u8 *data)
{
@@ -3785,26 +3867,35 @@ static void mvneta_ethtool_update_stats(
{
const struct mvneta_statistic *s;
void __iomem *base = pp->base;
- u32 high, low, val;
- u64 val64;
+ u32 high, low;
+ u64 val;
int i;
for (i = 0, s = mvneta_statistics;
s < mvneta_statistics + ARRAY_SIZE(mvneta_statistics);
s++, i++) {
+ val = 0;
+
switch (s->type) {
case T_REG_32:
val = readl_relaxed(base + s->offset);
- pp->ethtool_stats[i] += val;
break;
case T_REG_64:
/* Docs say to read low 32-bit then high */
low = readl_relaxed(base + s->offset);
high = readl_relaxed(base + s->offset + 4);
- val64 = (u64)high << 32 | low;
- pp->ethtool_stats[i] += val64;
+ val = (u64)high << 32 | low;
+ break;
+ case T_SW:
+ switch (s->offset) {
+ case ETHTOOL_STAT_EEE_WAKEUP:
+ val = phylink_get_eee_err(pp->phylink);
+ break;
+ }
break;
}
+
+ pp->ethtool_stats[i] += val;
}
}
@@ -3939,28 +4030,65 @@ static int mvneta_ethtool_get_rxfh(struc
static void mvneta_ethtool_get_wol(struct net_device *dev,
struct ethtool_wolinfo *wol)
{
- wol->supported = 0;
- wol->wolopts = 0;
+ struct mvneta_port *pp = netdev_priv(dev);
- if (dev->phydev)
- phy_ethtool_get_wol(dev->phydev, wol);
+ phylink_ethtool_get_wol(pp->phylink, wol);
}
static int mvneta_ethtool_set_wol(struct net_device *dev,
struct ethtool_wolinfo *wol)
{
+ struct mvneta_port *pp = netdev_priv(dev);
int ret;
- if (!dev->phydev)
- return -EOPNOTSUPP;
-
- ret = phy_ethtool_set_wol(dev->phydev, wol);
+ ret = phylink_ethtool_set_wol(pp->phylink, wol);
if (!ret)
device_set_wakeup_enable(&dev->dev, !!wol->wolopts);
return ret;
}
+static int mvneta_ethtool_get_eee(struct net_device *dev,
+ struct ethtool_eee *eee)
+{
+ struct mvneta_port *pp = netdev_priv(dev);
+ u32 lpi_ctl0;
+
+ lpi_ctl0 = mvreg_read(pp, MVNETA_LPI_CTRL_0);
+
+ eee->eee_enabled = pp->eee_enabled;
+ eee->eee_active = pp->eee_active;
+ eee->tx_lpi_enabled = pp->tx_lpi_enabled;
+ eee->tx_lpi_timer = (lpi_ctl0) >> 8; // * scale;
+
+ return phylink_ethtool_get_eee(pp->phylink, eee);
+}
+
+static int mvneta_ethtool_set_eee(struct net_device *dev,
+ struct ethtool_eee *eee)
+{
+ struct mvneta_port *pp = netdev_priv(dev);
+ u32 lpi_ctl0;
+
+ /* The Armada 37x documents do not give limits for this other than
+ * it being an 8-bit register. */
+ if (eee->tx_lpi_enabled &&
+ (eee->tx_lpi_timer < 0 || eee->tx_lpi_timer > 255))
+ return -EINVAL;
+
+ lpi_ctl0 = mvreg_read(pp, MVNETA_LPI_CTRL_0);
+ lpi_ctl0 &= ~(0xff << 8);
+ lpi_ctl0 |= eee->tx_lpi_timer << 8;
+ mvreg_write(pp, MVNETA_LPI_CTRL_0, lpi_ctl0);
+
+ pp->eee_enabled = eee->eee_enabled;
+ pp->tx_lpi_enabled = eee->tx_lpi_enabled;
+
+ mvneta_set_eee(pp, eee->tx_lpi_enabled && eee->eee_enabled);
+
+ return phylink_ethtool_set_eee(pp->phylink, eee);
+}
+
static u16 mvneta_select_queue(struct net_device *dev, struct sk_buff *skb,
void *accel_priv,
select_queue_fallback_t fallback)
@@ -3984,13 +4112,15 @@ static const struct net_device_ops mvnet
};
static const struct ethtool_ops mvneta_eth_tool_ops = {
- .nway_reset = phy_ethtool_nway_reset,
+ .nway_reset = mvneta_ethtool_nway_reset,
.get_link = ethtool_op_get_link,
.set_coalesce = mvneta_ethtool_set_coalesce,
.get_coalesce = mvneta_ethtool_get_coalesce,
.get_drvinfo = mvneta_ethtool_get_drvinfo,
.get_ringparam = mvneta_ethtool_get_ringparam,
.set_ringparam = mvneta_ethtool_set_ringparam,
+ .get_pauseparam = mvneta_ethtool_get_pauseparam,
+ .set_pauseparam = mvneta_ethtool_set_pauseparam,
.get_strings = mvneta_ethtool_get_strings,
.get_ethtool_stats = mvneta_ethtool_get_stats,
.get_sset_count = mvneta_ethtool_get_sset_count,
@@ -3998,10 +4128,12 @@ static const struct ethtool_ops mvneta_e
.get_rxnfc = mvneta_ethtool_get_rxnfc,
.get_rxfh = mvneta_ethtool_get_rxfh,
.set_rxfh = mvneta_ethtool_set_rxfh,
- .get_link_ksettings = phy_ethtool_get_link_ksettings,
+ .get_link_ksettings = mvneta_ethtool_get_link_ksettings,
.set_link_ksettings = mvneta_ethtool_set_link_ksettings,
.get_wol = mvneta_ethtool_get_wol,
.set_wol = mvneta_ethtool_set_wol,
+ .get_eee = mvneta_ethtool_get_eee,
+ .set_eee = mvneta_ethtool_set_eee,
};
/* Initialize hw */
@@ -4146,14 +4278,13 @@ static int mvneta_probe(struct platform_
{
struct resource *res;
struct device_node *dn = pdev->dev.of_node;
- struct device_node *phy_node;
struct device_node *bm_node;
struct mvneta_port *pp;
struct net_device *dev;
+ struct phylink *phylink;
const char *dt_mac_addr;
char hw_mac_addr[ETH_ALEN];
const char *mac_from;
- const char *managed;
int tx_csum_limit;
int phy_mode;
int err;
@@ -4169,31 +4300,11 @@ static int mvneta_probe(struct platform_
goto err_free_netdev;
}
- phy_node = of_parse_phandle(dn, "phy", 0);
- if (!phy_node) {
- if (!of_phy_is_fixed_link(dn)) {
- dev_err(&pdev->dev, "no PHY specified\n");
- err = -ENODEV;
- goto err_free_irq;
- }
-
- err = of_phy_register_fixed_link(dn);
- if (err < 0) {
- dev_err(&pdev->dev, "cannot register fixed PHY\n");
- goto err_free_irq;
- }
-
- /* In the case of a fixed PHY, the DT node associated
- * to the PHY is the Ethernet MAC DT node.
- */
- phy_node = of_node_get(dn);
- }
-
phy_mode = of_get_phy_mode(dn);
if (phy_mode < 0) {
dev_err(&pdev->dev, "incorrect phy-mode\n");
err = -EINVAL;
- goto err_put_phy_node;
+ goto err_free_irq;
}
dev->tx_queue_len = MVNETA_MAX_TXD;
@@ -4204,12 +4315,7 @@ static int mvneta_probe(struct platform_
pp = netdev_priv(dev);
spin_lock_init(&pp->lock);
- pp->phy_node = phy_node;
- pp->phy_interface = phy_mode;
-
- err = of_property_read_string(dn, "managed", &managed);
- pp->use_inband_status = (err == 0 &&
- strcmp(managed, "in-band-status") == 0);
+ pp->dn = dn;
pp->rxq_def = rxq_def;
@@ -4231,7 +4337,7 @@ static int mvneta_probe(struct platform_
pp->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(pp->clk)) {
err = PTR_ERR(pp->clk);
- goto err_put_phy_node;
+ goto err_free_irq;
}
clk_prepare_enable(pp->clk);
@@ -4357,6 +4463,14 @@ static int mvneta_probe(struct platform_
/* 9676 == 9700 - 20 and rounding to 8 */
dev->max_mtu = 9676;
+ phylink = phylink_create(dev, dn, phy_mode, &mvneta_phylink_ops);
+ if (IS_ERR(phylink)) {
+ err = PTR_ERR(phylink);
+ goto err_free_stats;
+ }
+
+ pp->phylink = phylink;
+
err = register_netdev(dev);
if (err < 0) {
dev_err(&pdev->dev, "failed to register\n");
@@ -4368,14 +4482,6 @@ static int mvneta_probe(struct platform_
platform_set_drvdata(pdev, pp->dev);
- if (pp->use_inband_status) {
- struct phy_device *phy = of_phy_find_device(dn);
-
- mvneta_fixed_link_update(pp, phy);
-
- put_device(&phy->mdio.dev);
- }
-
return 0;
err_netdev:
@@ -4386,16 +4492,14 @@ err_netdev:
1 << pp->id);
}
err_free_stats:
+ if (pp->phylink)
+ phylink_destroy(pp->phylink);
free_percpu(pp->stats);
err_free_ports:
free_percpu(pp->ports);
err_clk:
clk_disable_unprepare(pp->clk_bus);
clk_disable_unprepare(pp->clk);
-err_put_phy_node:
- of_node_put(phy_node);
- if (of_phy_is_fixed_link(dn))
- of_phy_deregister_fixed_link(dn);
err_free_irq:
irq_dispose_mapping(dev->irq);
err_free_netdev:
@@ -4407,7 +4511,6 @@ err_free_netdev:
static int mvneta_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
- struct device_node *dn = pdev->dev.of_node;
struct mvneta_port *pp = netdev_priv(dev);
unregister_netdev(dev);
@@ -4415,10 +4518,8 @@ static int mvneta_remove(struct platform
clk_disable_unprepare(pp->clk);
free_percpu(pp->ports);
free_percpu(pp->stats);
- if (of_phy_is_fixed_link(dn))
- of_phy_deregister_fixed_link(dn);
irq_dispose_mapping(dev->irq);
- of_node_put(pp->phy_node);
+ phylink_destroy(pp->phylink);
free_netdev(dev);
if (pp->bm_priv) {
@@ -4470,9 +4571,6 @@ static int mvneta_resume(struct device *
return err;
}
- if (pp->use_inband_status)
- mvneta_fixed_link_update(pp, dev->phydev);
-
netif_device_attach(dev);
if (netif_running(dev)) {
mvneta_open(dev);

View File

@ -1,28 +0,0 @@
From acdfcc7ef78c46baca1439a1cac5b73008abc672 Mon Sep 17 00:00:00 2001
From: Russell King <rmk+kernel@armlinux.org.uk>
Date: Tue, 16 May 2017 11:55:58 +0100
Subject: net: mvneta: hack fix phy_interface
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
drivers/net/ethernet/marvell/mvneta.c | 2 ++
1 file changed, 2 insertions(+)
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -427,6 +427,7 @@ struct mvneta_port {
u16 tx_ring_size;
u16 rx_ring_size;
+ phy_interface_t phy_interface;
struct device_node *dn;
unsigned int tx_csum_limit;
struct phylink *phylink;
@@ -4315,6 +4316,7 @@ static int mvneta_probe(struct platform_
pp = netdev_priv(dev);
spin_lock_init(&pp->lock);
+ pp->phy_interface = phy_mode;
pp->dn = dn;
pp->rxq_def = rxq_def;

View File

@ -1,56 +0,0 @@
From fde9e742a47606110232b7464608b6f9c0510938 Mon Sep 17 00:00:00 2001
From: Russell King <rmk+kernel@armlinux.org.uk>
Date: Sat, 24 Dec 2016 10:27:08 +0000
Subject: net: mvneta: disable MVNETA_CAUSE_PSC_SYNC_CHANGE interrupt
The PSC sync change interrupt can fire multiple times while the link is
down. As this isn't information we make use of, it's pointless having
the interrupt enabled, so let's disable this interrupt.
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
drivers/net/ethernet/marvell/mvneta.c | 12 ++++--------
1 file changed, 4 insertions(+), 8 deletions(-)
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -2704,8 +2704,7 @@ static int mvneta_poll(struct napi_struc
mvreg_write(pp, MVNETA_INTR_MISC_CAUSE, 0);
if (cause_misc & (MVNETA_CAUSE_PHY_STATUS_CHANGE |
- MVNETA_CAUSE_LINK_CHANGE |
- MVNETA_CAUSE_PSC_SYNC_CHANGE))
+ MVNETA_CAUSE_LINK_CHANGE))
mvneta_link_change(pp);
}
@@ -3044,8 +3043,7 @@ static void mvneta_start_dev(struct mvne
mvreg_write(pp, MVNETA_INTR_MISC_MASK,
MVNETA_CAUSE_PHY_STATUS_CHANGE |
- MVNETA_CAUSE_LINK_CHANGE |
- MVNETA_CAUSE_PSC_SYNC_CHANGE);
+ MVNETA_CAUSE_LINK_CHANGE);
phylink_start(pp->phylink);
netif_tx_start_all_queues(pp->dev);
@@ -3542,8 +3540,7 @@ static int mvneta_cpu_online(unsigned in
on_each_cpu(mvneta_percpu_unmask_interrupt, pp, true);
mvreg_write(pp, MVNETA_INTR_MISC_MASK,
MVNETA_CAUSE_PHY_STATUS_CHANGE |
- MVNETA_CAUSE_LINK_CHANGE |
- MVNETA_CAUSE_PSC_SYNC_CHANGE);
+ MVNETA_CAUSE_LINK_CHANGE);
netif_tx_start_all_queues(pp->dev);
spin_unlock(&pp->lock);
return 0;
@@ -3584,8 +3581,7 @@ static int mvneta_cpu_dead(unsigned int
on_each_cpu(mvneta_percpu_unmask_interrupt, pp, true);
mvreg_write(pp, MVNETA_INTR_MISC_MASK,
MVNETA_CAUSE_PHY_STATUS_CHANGE |
- MVNETA_CAUSE_LINK_CHANGE |
- MVNETA_CAUSE_PSC_SYNC_CHANGE);
+ MVNETA_CAUSE_LINK_CHANGE);
netif_tx_start_all_queues(pp->dev);
return 0;
}

View File

@ -1,44 +0,0 @@
From 2ff039aa4462c2104c210b7cf39691c612de8214 Mon Sep 17 00:00:00 2001
From: Russell King <rmk+kernel@arm.linux.org.uk>
Date: Thu, 1 Oct 2015 23:32:39 +0100
Subject: net: mvneta: add module EEPROM reading support
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
drivers/net/ethernet/marvell/mvneta.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -4045,6 +4045,22 @@ static int mvneta_ethtool_set_wol(struct
return ret;
}
+static int mvneta_ethtool_get_module_info(struct net_device *dev,
+ struct ethtool_modinfo *modinfo)
+{
+ struct mvneta_port *pp = netdev_priv(dev);
+
+ return phylink_ethtool_get_module_info(pp->phylink, modinfo);
+}
+
+static int mvneta_ethtool_get_module_eeprom(struct net_device *dev,
+ struct ethtool_eeprom *ee, u8 *buf)
+{
+ struct mvneta_port *pp = netdev_priv(dev);
+
+ return phylink_ethtool_get_module_eeprom(pp->phylink, ee, buf);
+}
+
static int mvneta_ethtool_get_eee(struct net_device *dev,
struct ethtool_eee *eee)
{
@@ -4129,6 +4145,8 @@ static const struct ethtool_ops mvneta_e
.set_link_ksettings = mvneta_ethtool_set_link_ksettings,
.get_wol = mvneta_ethtool_get_wol,
.set_wol = mvneta_ethtool_set_wol,
+ .get_module_info = mvneta_ethtool_get_module_info,
+ .get_module_eeprom = mvneta_ethtool_get_module_eeprom,
.get_eee = mvneta_ethtool_get_eee,
.set_eee = mvneta_ethtool_set_eee,
};

View File

@ -1,80 +0,0 @@
From 774ce2eda0a929f79ee398ba6d2d13fd406f31c4 Mon Sep 17 00:00:00 2001
From: Russell King <rmk+kernel@arm.linux.org.uk>
Date: Fri, 2 Oct 2015 22:46:54 +0100
Subject: phy: fixed-phy: remove fixed_phy_update_state()
mvneta is the only user of fixed_phy_update_state(), which has been
converted to use phylink instead. Remove fixed_phy_update_state().
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
drivers/net/phy/fixed_phy.c | 31 -------------------------------
include/linux/phy_fixed.h | 9 ---------
2 files changed, 40 deletions(-)
--- a/drivers/net/phy/fixed_phy.c
+++ b/drivers/net/phy/fixed_phy.c
@@ -115,37 +115,6 @@ int fixed_phy_set_link_update(struct phy
}
EXPORT_SYMBOL_GPL(fixed_phy_set_link_update);
-int fixed_phy_update_state(struct phy_device *phydev,
- const struct fixed_phy_status *status,
- const struct fixed_phy_status *changed)
-{
- struct fixed_mdio_bus *fmb = &platform_fmb;
- struct fixed_phy *fp;
-
- if (!phydev || phydev->mdio.bus != fmb->mii_bus)
- return -EINVAL;
-
- list_for_each_entry(fp, &fmb->phys, node) {
- if (fp->addr == phydev->mdio.addr) {
- write_seqcount_begin(&fp->seqcount);
-#define _UPD(x) if (changed->x) \
- fp->status.x = status->x
- _UPD(link);
- _UPD(speed);
- _UPD(duplex);
- _UPD(pause);
- _UPD(asym_pause);
-#undef _UPD
- fixed_phy_update(fp);
- write_seqcount_end(&fp->seqcount);
- return 0;
- }
- }
-
- return -ENOENT;
-}
-EXPORT_SYMBOL(fixed_phy_update_state);
-
int fixed_phy_add(unsigned int irq, int phy_addr,
struct fixed_phy_status *status,
int link_gpio)
--- a/include/linux/phy_fixed.h
+++ b/include/linux/phy_fixed.h
@@ -24,9 +24,6 @@ extern void fixed_phy_unregister(struct
extern int fixed_phy_set_link_update(struct phy_device *phydev,
int (*link_update)(struct net_device *,
struct fixed_phy_status *));
-extern int fixed_phy_update_state(struct phy_device *phydev,
- const struct fixed_phy_status *status,
- const struct fixed_phy_status *changed);
#else
static inline int fixed_phy_add(unsigned int irq, int phy_id,
struct fixed_phy_status *status,
@@ -50,12 +47,6 @@ static inline int fixed_phy_set_link_upd
{
return -ENODEV;
}
-static inline int fixed_phy_update_state(struct phy_device *phydev,
- const struct fixed_phy_status *status,
- const struct fixed_phy_status *changed)
-{
- return -ENODEV;
-}
#endif /* CONFIG_FIXED_PHY */
#endif /* __PHY_FIXED_H */

View File

@ -1,181 +0,0 @@
From c47beb7e3f8575dfd7d58240a72c4e4e66ce5449 Mon Sep 17 00:00:00 2001
From: Russell King <rmk+kernel@armlinux.org.uk>
Date: Fri, 14 Apr 2017 15:26:32 +0100
Subject: sfp: move module eeprom ethtool access into netdev core ethtool
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
drivers/net/ethernet/marvell/mvneta.c | 18 ------------------
drivers/net/phy/phylink.c | 28 ----------------------------
drivers/net/phy/sfp-bus.c | 6 ++----
include/linux/netdevice.h | 2 ++
include/linux/phylink.h | 3 ---
net/core/ethtool.c | 7 +++++++
6 files changed, 11 insertions(+), 53 deletions(-)
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -4045,22 +4045,6 @@ static int mvneta_ethtool_set_wol(struct
return ret;
}
-static int mvneta_ethtool_get_module_info(struct net_device *dev,
- struct ethtool_modinfo *modinfo)
-{
- struct mvneta_port *pp = netdev_priv(dev);
-
- return phylink_ethtool_get_module_info(pp->phylink, modinfo);
-}
-
-static int mvneta_ethtool_get_module_eeprom(struct net_device *dev,
- struct ethtool_eeprom *ee, u8 *buf)
-{
- struct mvneta_port *pp = netdev_priv(dev);
-
- return phylink_ethtool_get_module_eeprom(pp->phylink, ee, buf);
-}
-
static int mvneta_ethtool_get_eee(struct net_device *dev,
struct ethtool_eee *eee)
{
@@ -4145,8 +4129,6 @@ static const struct ethtool_ops mvneta_e
.set_link_ksettings = mvneta_ethtool_set_link_ksettings,
.get_wol = mvneta_ethtool_get_wol,
.set_wol = mvneta_ethtool_set_wol,
- .get_module_info = mvneta_ethtool_get_module_info,
- .get_module_eeprom = mvneta_ethtool_get_module_eeprom,
.get_eee = mvneta_ethtool_get_eee,
.set_eee = mvneta_ethtool_set_eee,
};
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -1040,34 +1040,6 @@ int phylink_ethtool_set_pauseparam(struc
}
EXPORT_SYMBOL_GPL(phylink_ethtool_set_pauseparam);
-int phylink_ethtool_get_module_info(struct phylink *pl,
- struct ethtool_modinfo *modinfo)
-{
- int ret = -EOPNOTSUPP;
-
- WARN_ON(!lockdep_rtnl_is_held());
-
- if (pl->sfp_bus)
- ret = sfp_get_module_info(pl->sfp_bus, modinfo);
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(phylink_ethtool_get_module_info);
-
-int phylink_ethtool_get_module_eeprom(struct phylink *pl,
- struct ethtool_eeprom *ee, u8 *buf)
-{
- int ret = -EOPNOTSUPP;
-
- WARN_ON(!lockdep_rtnl_is_held());
-
- if (pl->sfp_bus)
- ret = sfp_get_module_eeprom(pl->sfp_bus, ee, buf);
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(phylink_ethtool_get_module_eeprom);
-
int phylink_init_eee(struct phylink *pl, bool clk_stop_enable)
{
int ret = -EPROTONOSUPPORT;
--- a/drivers/net/phy/sfp-bus.c
+++ b/drivers/net/phy/sfp-bus.c
@@ -278,6 +278,7 @@ static int sfp_register_bus(struct sfp_b
}
if (bus->started)
bus->socket_ops->start(bus->sfp);
+ bus->netdev->sfp_bus = bus;
bus->registered = true;
return 0;
}
@@ -292,14 +293,13 @@ static void sfp_unregister_bus(struct sf
if (bus->phydev && ops && ops->disconnect_phy)
ops->disconnect_phy(bus->upstream);
}
+ bus->netdev->sfp_bus = NULL;
bus->registered = false;
}
int sfp_get_module_info(struct sfp_bus *bus, struct ethtool_modinfo *modinfo)
{
- if (!bus->registered)
- return -ENOIOCTLCMD;
return bus->socket_ops->module_info(bus->sfp, modinfo);
}
EXPORT_SYMBOL_GPL(sfp_get_module_info);
@@ -307,8 +307,6 @@ EXPORT_SYMBOL_GPL(sfp_get_module_info);
int sfp_get_module_eeprom(struct sfp_bus *bus, struct ethtool_eeprom *ee,
u8 *data)
{
- if (!bus->registered)
- return -ENOIOCTLCMD;
return bus->socket_ops->module_eeprom(bus->sfp, ee, data);
}
EXPORT_SYMBOL_GPL(sfp_get_module_eeprom);
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -57,6 +57,7 @@ struct device;
struct phy_device;
struct dsa_switch_tree;
+struct sfp_bus;
/* 802.11 specific */
struct wireless_dev;
/* 802.15.4 specific */
@@ -1932,6 +1933,7 @@ struct net_device {
struct netprio_map __rcu *priomap;
#endif
struct phy_device *phydev;
+ struct sfp_bus *sfp_bus;
struct lock_class_key *qdisc_tx_busylock;
struct lock_class_key *qdisc_running_key;
bool proto_down;
--- a/include/linux/phylink.h
+++ b/include/linux/phylink.h
@@ -125,9 +125,6 @@ void phylink_ethtool_get_pauseparam(stru
struct ethtool_pauseparam *);
int phylink_ethtool_set_pauseparam(struct phylink *,
struct ethtool_pauseparam *);
-int phylink_ethtool_get_module_info(struct phylink *, struct ethtool_modinfo *);
-int phylink_ethtool_get_module_eeprom(struct phylink *,
- struct ethtool_eeprom *, u8 *);
int phylink_init_eee(struct phylink *, bool);
int phylink_get_eee_err(struct phylink *);
int phylink_ethtool_get_eee(struct phylink *, struct ethtool_eee *);
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -22,6 +22,7 @@
#include <linux/bitops.h>
#include <linux/uaccess.h>
#include <linux/vmalloc.h>
+#include <linux/sfp.h>
#include <linux/slab.h>
#include <linux/rtnetlink.h>
#include <linux/sched/signal.h>
@@ -2190,6 +2191,9 @@ static int __ethtool_get_module_info(str
const struct ethtool_ops *ops = dev->ethtool_ops;
struct phy_device *phydev = dev->phydev;
+ if (dev->sfp_bus)
+ return sfp_get_module_info(dev->sfp_bus, modinfo);
+
if (phydev && phydev->drv && phydev->drv->module_info)
return phydev->drv->module_info(phydev, modinfo);
@@ -2224,6 +2228,9 @@ static int __ethtool_get_module_eeprom(s
const struct ethtool_ops *ops = dev->ethtool_ops;
struct phy_device *phydev = dev->phydev;
+ if (dev->sfp_bus)
+ return sfp_get_module_eeprom(dev->sfp_bus, ee, data);
+
if (phydev && phydev->drv && phydev->drv->module_eeprom)
return phydev->drv->module_eeprom(phydev, ee, data);

View File

@ -1,34 +0,0 @@
From 883dc66755313e133a787eba4dfde313fe33525b Mon Sep 17 00:00:00 2001
From: Russell King <rmk+kernel@armlinux.org.uk>
Date: Fri, 14 Apr 2017 16:41:55 +0100
Subject: sfp: use netdev sfp_bus for start/stop
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
drivers/net/phy/phylink.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -755,8 +755,8 @@ void phylink_start(struct phylink *pl)
clear_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state);
phylink_run_resolve(pl);
- if (pl->sfp_bus)
- sfp_upstream_start(pl->sfp_bus);
+ if (pl->netdev->sfp_bus)
+ sfp_upstream_start(pl->netdev->sfp_bus);
if (pl->phydev)
phy_start(pl->phydev);
}
@@ -768,8 +768,8 @@ void phylink_stop(struct phylink *pl)
if (pl->phydev)
phy_stop(pl->phydev);
- if (pl->sfp_bus)
- sfp_upstream_stop(pl->sfp_bus);
+ if (pl->netdev->sfp_bus)
+ sfp_upstream_stop(pl->netdev->sfp_bus);
set_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state);
queue_work(system_power_efficient_wq, &pl->resolve);

View File

@ -1,131 +0,0 @@
From 4a4aca08b11501cb1b2c509113bbb65eb66a1f45 Mon Sep 17 00:00:00 2001
From: Russell King <rmk+kernel@armlinux.org.uk>
Date: Fri, 14 Apr 2017 14:21:25 +0100
Subject: sfp: hack: allow marvell 10G phy support to use SFP
Allow the Marvell 10G PHY to register with the SFP bus, so that SFP+
cages can work. This bypasses phylink, meaning that socket status
is not taken into account for the link state. Also, the tx-disable
signal must be commented out in DT for this to work...
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
drivers/net/phy/marvell10g.c | 54 +++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 53 insertions(+), 1 deletion(-)
--- a/drivers/net/phy/marvell10g.c
+++ b/drivers/net/phy/marvell10g.c
@@ -15,8 +15,10 @@
* If both the fiber and copper ports are connected, the first to gain
* link takes priority and the other port is completely locked out.
*/
+#include <linux/of.h>
#include <linux/phy.h>
#include <linux/marvell_phy.h>
+#include <linux/sfp.h>
enum {
MV_PCS_BASE_T = 0x0000,
@@ -38,6 +40,11 @@ enum {
MV_AN_RESULT_SPD_10000 = BIT(15),
};
+struct mv3310_priv {
+ struct device_node *sfp_node;
+ struct sfp_bus *sfp_bus;
+};
+
static int mv3310_modify(struct phy_device *phydev, int devad, u16 reg,
u16 mask, u16 bits)
{
@@ -56,17 +63,52 @@ static int mv3310_modify(struct phy_devi
return ret < 0 ? ret : 1;
}
+static int mv3310_sfp_insert(void *upstream, const struct sfp_eeprom_id *id)
+{
+ struct phy_device *phydev = upstream;
+ struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
+
+ if (sfp_parse_interface(priv->sfp_bus, id) != PHY_INTERFACE_MODE_10GKR) {
+ dev_err(&phydev->mdio.dev, "incompatible SFP module inserted\n");
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static const struct sfp_upstream_ops mv3310_sfp_ops = {
+ .module_insert = mv3310_sfp_insert,
+};
+
static int mv3310_probe(struct phy_device *phydev)
{
+ struct mv3310_priv *priv;
u32 mmd_mask = MDIO_DEVS_PMAPMD | MDIO_DEVS_AN;
if (!phydev->is_c45 ||
(phydev->c45_ids.devices_in_package & mmd_mask) != mmd_mask)
return -ENODEV;
+ priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ dev_set_drvdata(&phydev->mdio.dev, priv);
+
+ if (phydev->mdio.dev.of_node)
+ priv->sfp_node = of_parse_phandle(phydev->mdio.dev.of_node,
+ "sfp", 0);
+
return 0;
}
+static void mv3310_remove(struct phy_device *phydev)
+{
+ struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
+
+ if (priv->sfp_bus)
+ sfp_unregister_upstream(priv->sfp_bus);
+}
+
/*
* Resetting the MV88X3310 causes it to become non-responsive. Avoid
* setting the reset bit(s).
@@ -78,6 +120,7 @@ static int mv3310_soft_reset(struct phy_
static int mv3310_config_init(struct phy_device *phydev)
{
+ struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
__ETHTOOL_DECLARE_LINK_MODE_MASK(supported) = { 0, };
u32 mask;
int val;
@@ -166,6 +209,14 @@ static int mv3310_config_init(struct phy
phydev->supported &= mask;
phydev->advertising &= phydev->supported;
+ /* Would be nice to do this in the probe function, but unfortunately,
+ * phylib doesn't have phydev->attached_dev set there.
+ */
+ if (priv->sfp_node && !priv->sfp_bus)
+ priv->sfp_bus = sfp_register_upstream(priv->sfp_node,
+ phydev->attached_dev,
+ phydev, &mv3310_sfp_ops);
+
return 0;
}
@@ -349,12 +400,13 @@ static struct phy_driver mv3310_drivers[
SUPPORTED_FIBRE |
SUPPORTED_10000baseT_Full |
SUPPORTED_Backplane,
- .probe = mv3310_probe,
.soft_reset = mv3310_soft_reset,
.config_init = mv3310_config_init,
+ .probe = mv3310_probe,
.config_aneg = mv3310_config_aneg,
.aneg_done = mv3310_aneg_done,
.read_status = mv3310_read_status,
+ .remove = mv3310_remove,
},
};

View File

@ -1,24 +0,0 @@
From 3344f73509a34d2124b716efc79cd9787773018b Mon Sep 17 00:00:00 2001
From: Russell King <rmk+kernel@armlinux.org.uk>
Date: Fri, 14 Apr 2017 20:17:13 +0100
Subject: sfp: add sfp+ compatible
Add a compatible for SFP+ cages. SFP+ cages are backwards compatible,
but the ethernet device behind them may not support the slower speeds
of SFP modules.
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
drivers/net/phy/sfp.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/net/phy/sfp.c
+++ b/drivers/net/phy/sfp.c
@@ -1136,6 +1136,7 @@ static int sfp_remove(struct platform_de
static const struct of_device_id sfp_of_match[] = {
{ .compatible = "sff,sfp", },
+ { .compatible = "sff,sfp+", },
{ },
};
MODULE_DEVICE_TABLE(of, sfp_of_match);

View File

@ -1,305 +0,0 @@
diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c
index ae7532894..a23a5c7f0 100644
--- a/drivers/thermal/armada_thermal.c
+++ b/drivers/thermal/armada_thermal.c
@@ -23,8 +23,7 @@
#include <linux/platform_device.h>
#include <linux/of_device.h>
#include <linux/thermal.h>
-
-#define THERMAL_VALID_MASK 0x1
+#include <linux/iopoll.h>
/* Thermal Manager Control and Status Register */
#define PMU_TDC0_SW_RST_MASK (0x1 << 1)
@@ -39,14 +38,33 @@
#define A375_UNIT_CONTROL_MASK 0x7
#define A375_READOUT_INVERT BIT(15)
#define A375_HW_RESETn BIT(8)
-#define A380_HW_RESET BIT(8)
+
+/* Legacy bindings */
+#define LEGACY_CONTROL_MEM_LEN 0x4
+
+/* Current bindings with the 2 control registers under the same memory area */
+#define LEGACY_CONTROL1_OFFSET 0x0
+#define CONTROL0_OFFSET 0x0
+#define CONTROL1_OFFSET 0x4
+
+/* Errata fields */
+#define CONTROL0_TSEN_TC_TRIM_MASK 0x7
+#define CONTROL0_TSEN_TC_TRIM_VAL 0x3
+
+/* EXT_TSEN refers to the external temperature sensors, out of the AP */
+#define CONTROL1_EXT_TSEN_SW_RESET BIT(7)
+#define CONTROL1_EXT_TSEN_HW_RESETn BIT(8)
+
+#define STATUS_POLL_PERIOD_US 1000
+#define STATUS_POLL_TIMEOUT_US 100000
struct armada_thermal_data;
/* Marvell EBU Thermal Sensor Dev Structure */
struct armada_thermal_priv {
- void __iomem *sensor;
- void __iomem *control;
+ void __iomem *status;
+ void __iomem *control0;
+ void __iomem *control1;
struct armada_thermal_data *data;
};
@@ -58,7 +76,7 @@ struct armada_thermal_data {
/* Test for a valid sensor value (optional) */
bool (*is_valid)(struct armada_thermal_priv *);
- /* Formula coeficients: temp = (b + m * reg) / div */
+ /* Formula coeficients: temp = (b - m * reg) / div */
unsigned long coef_b;
unsigned long coef_m;
unsigned long coef_div;
@@ -67,91 +85,111 @@ struct armada_thermal_data {
/* Register shift and mask to access the sensor temperature */
unsigned int temp_shift;
unsigned int temp_mask;
- unsigned int is_valid_shift;
+ u32 is_valid_bit;
+ bool needs_control0;
};
static void armadaxp_init_sensor(struct platform_device *pdev,
struct armada_thermal_priv *priv)
{
- unsigned long reg;
+ u32 reg;
- reg = readl_relaxed(priv->control);
+ reg = readl_relaxed(priv->control1);
reg |= PMU_TDC0_OTF_CAL_MASK;
- writel(reg, priv->control);
+ writel(reg, priv->control1);
/* Reference calibration value */
reg &= ~PMU_TDC0_REF_CAL_CNT_MASK;
reg |= (0xf1 << PMU_TDC0_REF_CAL_CNT_OFFS);
- writel(reg, priv->control);
+ writel(reg, priv->control1);
/* Reset the sensor */
- reg = readl_relaxed(priv->control);
- writel((reg | PMU_TDC0_SW_RST_MASK), priv->control);
+ reg = readl_relaxed(priv->control1);
+ writel((reg | PMU_TDC0_SW_RST_MASK), priv->control1);
- writel(reg, priv->control);
+ writel(reg, priv->control1);
/* Enable the sensor */
- reg = readl_relaxed(priv->sensor);
+ reg = readl_relaxed(priv->status);
reg &= ~PMU_TM_DISABLE_MASK;
- writel(reg, priv->sensor);
+ writel(reg, priv->status);
}
static void armada370_init_sensor(struct platform_device *pdev,
struct armada_thermal_priv *priv)
{
- unsigned long reg;
+ u32 reg;
- reg = readl_relaxed(priv->control);
+ reg = readl_relaxed(priv->control1);
reg |= PMU_TDC0_OTF_CAL_MASK;
- writel(reg, priv->control);
+ writel(reg, priv->control1);
/* Reference calibration value */
reg &= ~PMU_TDC0_REF_CAL_CNT_MASK;
reg |= (0xf1 << PMU_TDC0_REF_CAL_CNT_OFFS);
- writel(reg, priv->control);
+ writel(reg, priv->control1);
reg &= ~PMU_TDC0_START_CAL_MASK;
- writel(reg, priv->control);
+ writel(reg, priv->control1);
- mdelay(10);
+ msleep(10);
}
static void armada375_init_sensor(struct platform_device *pdev,
struct armada_thermal_priv *priv)
{
- unsigned long reg;
+ u32 reg;
- reg = readl(priv->control + 4);
+ reg = readl(priv->control1);
reg &= ~(A375_UNIT_CONTROL_MASK << A375_UNIT_CONTROL_SHIFT);
reg &= ~A375_READOUT_INVERT;
reg &= ~A375_HW_RESETn;
- writel(reg, priv->control + 4);
- mdelay(20);
+ writel(reg, priv->control1);
+ msleep(20);
reg |= A375_HW_RESETn;
- writel(reg, priv->control + 4);
- mdelay(50);
+ writel(reg, priv->control1);
+ msleep(50);
+}
+
+static void armada_wait_sensor_validity(struct armada_thermal_priv *priv)
+{
+ u32 reg;
+
+ readl_relaxed_poll_timeout(priv->status, reg,
+ reg & priv->data->is_valid_bit,
+ STATUS_POLL_PERIOD_US,
+ STATUS_POLL_TIMEOUT_US);
}
static void armada380_init_sensor(struct platform_device *pdev,
struct armada_thermal_priv *priv)
{
- unsigned long reg = readl_relaxed(priv->control);
-
- /* Reset hardware once */
- if (!(reg & A380_HW_RESET)) {
- reg |= A380_HW_RESET;
- writel(reg, priv->control);
- mdelay(10);
+ u32 reg = readl_relaxed(priv->control1);
+
+ /* Disable the HW/SW reset */
+ reg |= CONTROL1_EXT_TSEN_HW_RESETn;
+ reg &= ~CONTROL1_EXT_TSEN_SW_RESET;
+ writel(reg, priv->control1);
+
+ /* Set Tsen Tc Trim to correct default value (errata #132698) */
+ if (priv->control0) {
+ reg = readl_relaxed(priv->control0);
+ reg &= ~CONTROL0_TSEN_TC_TRIM_MASK;
+ reg |= CONTROL0_TSEN_TC_TRIM_VAL;
+ writel(reg, priv->control0);
}
+
+ /* Wait the sensors to be valid or the core will warn the user */
+ armada_wait_sensor_validity(priv);
}
static bool armada_is_valid(struct armada_thermal_priv *priv)
{
- unsigned long reg = readl_relaxed(priv->sensor);
+ u32 reg = readl_relaxed(priv->status);
- return (reg >> priv->data->is_valid_shift) & THERMAL_VALID_MASK;
+ return reg & priv->data->is_valid_bit;
}
static int armada_get_temp(struct thermal_zone_device *thermal,
@@ -168,7 +206,7 @@ static int armada_get_temp(struct thermal_zone_device *thermal,
return -EIO;
}
- reg = readl_relaxed(priv->sensor);
+ reg = readl_relaxed(priv->status);
reg = (reg >> priv->data->temp_shift) & priv->data->temp_mask;
/* Get formula coeficients */
@@ -199,7 +237,7 @@ static const struct armada_thermal_data armadaxp_data = {
static const struct armada_thermal_data armada370_data = {
.is_valid = armada_is_valid,
.init_sensor = armada370_init_sensor,
- .is_valid_shift = 9,
+ .is_valid_bit = BIT(9),
.temp_shift = 10,
.temp_mask = 0x1ff,
.coef_b = 3153000000UL,
@@ -210,24 +248,26 @@ static const struct armada_thermal_data armada370_data = {
static const struct armada_thermal_data armada375_data = {
.is_valid = armada_is_valid,
.init_sensor = armada375_init_sensor,
- .is_valid_shift = 10,
+ .is_valid_bit = BIT(10),
.temp_shift = 0,
.temp_mask = 0x1ff,
.coef_b = 3171900000UL,
.coef_m = 10000000UL,
.coef_div = 13616,
+ .needs_control0 = true,
};
static const struct armada_thermal_data armada380_data = {
.is_valid = armada_is_valid,
.init_sensor = armada380_init_sensor,
- .is_valid_shift = 10,
+ .is_valid_bit = BIT(10),
.temp_shift = 0,
.temp_mask = 0x3ff,
.coef_b = 1172499100UL,
.coef_m = 2000096UL,
.coef_div = 4201,
.inverted = true,
+ .needs_control0 = true,
};
static const struct of_device_id armada_thermal_id_table[] = {
@@ -255,6 +295,7 @@ MODULE_DEVICE_TABLE(of, armada_thermal_id_table);
static int armada_thermal_probe(struct platform_device *pdev)
{
+ void __iomem *control = NULL;
struct thermal_zone_device *thermal;
const struct of_device_id *match;
struct armada_thermal_priv *priv;
@@ -268,17 +309,39 @@ static int armada_thermal_probe(struct platform_device *pdev)
if (!priv)
return -ENOMEM;
+ priv->data = (struct armada_thermal_data *)match->data;
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- priv->sensor = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(priv->sensor))
- return PTR_ERR(priv->sensor);
+ priv->status = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(priv->status))
+ return PTR_ERR(priv->status);
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- priv->control = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(priv->control))
- return PTR_ERR(priv->control);
- priv->data = (struct armada_thermal_data *)match->data;
+ /* Calculate control0 address and edit the resource start address and
+ * length to map over all the registers */
+ if (priv->data->needs_control0)
+ res->start -= CONTROL1_OFFSET;
+
+ control = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(control))
+ return PTR_ERR(control);
+
+ dev_info(&pdev->dev, "res size = %d\n", resource_size(res));
+
+ /*
+ * Legacy DT bindings only described "control1" register (also referred
+ * as "control MSB" on old documentation). New bindings cover
+ * "control0/control LSB" and "control1/control MSB" registers within
+ * the same resource, which is then of size 8 instead of 4.
+ */
+ if (resource_size(res) == LEGACY_CONTROL_MEM_LEN) {
+ priv->control1 = control + LEGACY_CONTROL1_OFFSET;
+ } else {
+ priv->control0 = control + CONTROL0_OFFSET;
+ priv->control1 = control + CONTROL1_OFFSET;
+ }
+
priv->data->init_sensor(pdev, priv);
thermal = thermal_zone_device_register("armada_thermal", 0, 0,