Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 579438a0 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: emac: Add handling of ephy RST pin"

parents 5afbff8d d4182881
Loading
Loading
Loading
Loading
+10 −8
Original line number Diff line number Diff line
@@ -791,7 +791,7 @@
		};

		emac0 {
			emac0_active: emac0_active {
			emac0_mdio_active: emac0_mdio_active {
				/* active state */
				mux {
					/* MDC MDIO */
@@ -806,7 +806,7 @@
				};
			};

			emac0_sleep: emac0_sleep {
			emac0_mdio_sleep: emac0_mdio_sleep {
				/* suspended state */
				mux {
					/* MDC MDIO */
@@ -821,25 +821,26 @@
				};
			};

			emac0_rst_active: emac0_rst_active {
			emac0_ephy_active: emac0_ephy_active {
				/* active state */
				mux {
					/* ETH RST */
					/* EPHY RST */
					pins = "gpio29";
					function = "gpio";
				};

				config {
					pins = "gpio29";
					drive-strength = <16>; /* 8 MA */
					drive-strength = <16>; /* 16 MA */
					bias-pull-up;
					output-high;
				};
			};

			emac0_rst_sleep: emac0_rst_sleep {
			emac0_ephy_sleep: emac0_ephy_sleep {
				/* suspended state */
				mux {
					/* ETH RST */
					/* EPHY RST */
					pins = "gpio29";
					function = "gpio";
				};
@@ -847,7 +848,8 @@
				config {
					pins = "gpio29";
					drive-strength = <2>; /* 2 MA */
					bias-pull-down;
					bias-disable;
					output-low;
				};
			};
		};
+6 −3
Original line number Diff line number Diff line
@@ -1369,9 +1369,12 @@
			 <&clock_gcc clk_gcc_emac_0_sys_clk>;
		clock-names = "axi_clk", "cfg_ahb_clk", "125m_clk",
			"25m_clk", "tx_clk", "rx_clk", "sys_clk";
		pinctrl-names = "emac_active", "emac_sleep";
		pinctrl-0 = <&emac0_active &emac0_rst_active>;
		pinctrl-1 = <&emac0_sleep &emac0_rst_sleep>;
		pinctrl-names = "emac_mdio_active", "emac_mdio_sleep",
			"emac_ephy_active", "emac_ephy_sleep";
		pinctrl-0 = <&emac0_mdio_active>;
		pinctrl-1 = <&emac0_mdio_sleep>;
		pinctrl-2 = <&emac0_ephy_active>;
		pinctrl-3 = <&emac0_ephy_sleep>;
		qcom,emac-tstamp-en;
		qcom,emac-ptp-frac-ns-adj = <125000000 1>;
		phy-mode = "sgmii";
+6 −4
Original line number Diff line number Diff line
@@ -723,10 +723,12 @@ struct emac_adapter {
	u16             msg_enable;
	unsigned long   flags;
	struct pinctrl	*pinctrl;
	struct pinctrl_state	*pins_active;
	struct pinctrl_state	*pins_sleep;
	int	(*gpio_on)(struct emac_adapter *adpt);
	int	(*gpio_off)(struct emac_adapter *adpt);
	struct pinctrl_state	*mdio_pins_active;
	struct pinctrl_state	*mdio_pins_sleep;
	struct pinctrl_state	*ephy_pins_active;
	struct pinctrl_state	*ephy_pins_sleep;
	int	(*gpio_on)(struct emac_adapter *adpt, bool mdio, bool ephy);
	int	(*gpio_off)(struct emac_adapter *adpt, bool mdio, bool ephy);
	struct wakeup_source link_wlock;
};

+121 −47
Original line number Diff line number Diff line
@@ -70,8 +70,10 @@ static struct of_device_id emac_dt_match[];

#define EMAC_SKB_CB(skb) ((struct emac_skb_cb *)(skb)->cb)

#define EMAC_PINCTRL_STATE_ACTIVE "emac_active"
#define EMAC_PINCTRL_STATE_SLEEP "emac_sleep"
#define EMAC_PINCTRL_STATE_MDIO_ACTIVE "emac_mdio_active"
#define EMAC_PINCTRL_STATE_MDIO_SLEEP  "emac_mdio_sleep"
#define EMAC_PINCTRL_STATE_EPHY_ACTIVE "emac_ephy_active"
#define EMAC_PINCTRL_STATE_EPHY_SLEEP  "emac_ephy_sleep"

#define EMAC_VREG1_VOLTAGE	1250000
#define EMAC_VREG2_VOLTAGE	1800000
@@ -1873,58 +1875,110 @@ static int emac_change_mtu(struct net_device *netdev, int new_mtu)
	return 0;
}

static inline int msm_emac_request_gpio_on(struct emac_adapter *adpt)
static inline int msm_emac_request_gpio_on(struct emac_adapter *adpt,
					   bool mdio, bool ephy)
{
	int i = 0;
	int result = 0;
	struct emac_phy *phy = &adpt->phy;

	if (phy->external) {
		for (i = 0; phy->uses_gpios && i < EMAC_GPIO_CNT; i++) {
			result = gpio_request(adpt->gpio[i], emac_gpio_name[i]);
			if (result) {
			emac_err(adpt, "error:%d on gpio_request(%d:%s)\n",
				emac_err(adpt,
					 "error:%d on gpio_request(%d:%s)\n",
					 result, adpt->gpio[i],
					 emac_gpio_name[i]);

				while (--i >= 0)
					gpio_free(adpt->gpio[i]);
				goto error;
			}
		}
	}
	return 0;
error:
	return result;
}

static inline int msm_emac_request_gpio_off(struct emac_adapter *adpt)
static inline int msm_emac_request_gpio_off(struct emac_adapter *adpt,
					    bool mdio, bool ephy)
{
	int i = 0;
	struct emac_phy *phy = &adpt->phy;

	if (phy->external) {
		for (i = 0; phy->uses_gpios && i < EMAC_GPIO_CNT; i++)
			gpio_free(adpt->gpio[i]);
	}
	return 0;
}

static inline int msm_emac_request_pinctrl_on(struct emac_adapter *adpt)
static inline int msm_emac_request_pinctrl_on(struct emac_adapter *adpt,
					      bool mdio, bool ephy)
{
	int result = 0;
	int ret    = 0;
	struct emac_phy *phy = &adpt->phy;

	result = pinctrl_select_state(adpt->pinctrl, adpt->pins_active);
	if (phy->external) {
		if (mdio) {
			result = pinctrl_select_state(adpt->pinctrl,
						      adpt->mdio_pins_active);
			if (result)
		emac_err(adpt, "error:%d Can not set %s pins\n",
			 result, EMAC_PINCTRL_STATE_ACTIVE);
	return result;
				emac_err(adpt,
					 "error:%d Can not switch on %s pins\n",
					 result,
					 EMAC_PINCTRL_STATE_MDIO_ACTIVE);
			ret = result;
		}

		if (ephy) {
			result = pinctrl_select_state(adpt->pinctrl,
						      adpt->ephy_pins_active);
			if (result)
				emac_err(adpt,
					 "error:%d Can not switch on %s pins\n",
					 result,
					 EMAC_PINCTRL_STATE_EPHY_ACTIVE);
			if (!ret)
				ret = result;
		}
	}
	return ret;
}

static inline int msm_emac_request_pinctrl_off(struct emac_adapter *adpt)
static inline int msm_emac_request_pinctrl_off(struct emac_adapter *adpt,
					       bool mdio, bool ephy)
{
	int result = 0;
	int ret    = 0;
	struct emac_phy *phy = &adpt->phy;

	result = pinctrl_select_state(adpt->pinctrl, adpt->pins_sleep);
	if (phy->external) {
		if (mdio) {
			result = pinctrl_select_state(adpt->pinctrl,
						      adpt->mdio_pins_sleep);
			if (result)
		emac_err(adpt, "error:%d Can not set %s pins\n",
			 result, EMAC_PINCTRL_STATE_SLEEP);
	return result;
				emac_err(adpt,
					 "error:%d Can not switch off %s pins\n",
					 result, EMAC_PINCTRL_STATE_MDIO_SLEEP);
			ret = result;
		}

		if (ephy) {
			result = pinctrl_select_state(adpt->pinctrl,
						      adpt->ephy_pins_sleep);
			if (result)
				emac_err(adpt,
					 "error:%d Can not switch off %s pins\n",
					 result, EMAC_PINCTRL_STATE_EPHY_SLEEP);
			if (!ret)
				ret = result;
		}
	}
	return ret;
}

/* Bringup the interface/HW */
@@ -1946,10 +2000,6 @@ int emac_up(struct emac_adapter *adpt)
	if (retval)
		return retval;

	retval = adpt->gpio_on(adpt);
	if (retval < 0)
		goto err_request_gpio;

	for (i = 0; i < EMAC_IRQ_CNT; i++) {
		struct emac_irq_per_dev *irq = &adpt->irq[i];
		const struct emac_irq_common *irq_cmn = &emac_irq_cmn_tbl[i];
@@ -1989,8 +2039,6 @@ int emac_up(struct emac_adapter *adpt)
	return retval;

err_request_irq:
	adpt->gpio_off(adpt);
err_request_gpio:
	adpt->phy.ops.down(adpt);
	return retval;
}
@@ -2018,8 +2066,6 @@ void emac_down(struct emac_adapter *adpt, u32 ctrl)
		if (adpt->irq[i].irq)
			free_irq(adpt->irq[i].irq, &adpt->irq[i]);

	adpt->gpio_off(adpt);

	CLR_FLAG(adpt, ADPT_TASK_LSC_REQ);
	CLR_FLAG(adpt, ADPT_TASK_REINIT_REQ);
	CLR_FLAG(adpt, ADPT_TASK_CHK_SGMII_REQ);
@@ -2718,20 +2764,36 @@ static int msm_emac_pinctrl_init(struct emac_adapter *adpt, struct device *dev)
			 PTR_ERR(adpt->pinctrl));
		return PTR_ERR(adpt->pinctrl);
	}
	adpt->pins_active = pinctrl_lookup_state(adpt->pinctrl,
				EMAC_PINCTRL_STATE_ACTIVE);
	if (IS_ERR_OR_NULL(adpt->pins_active)) {
		emac_dbg(adpt, probe, "error:%ld Failed to lookup pinctrl active state\n",
			 PTR_ERR(adpt->pins_active));
		return PTR_ERR(adpt->pins_active);
	adpt->mdio_pins_active = pinctrl_lookup_state(adpt->pinctrl,
				EMAC_PINCTRL_STATE_MDIO_ACTIVE);
	if (IS_ERR_OR_NULL(adpt->mdio_pins_active)) {
		emac_dbg(adpt, probe, "error:%ld Failed to lookup mdio pinctrl active state\n",
			 PTR_ERR(adpt->mdio_pins_active));
		return PTR_ERR(adpt->mdio_pins_active);
	}

	adpt->mdio_pins_sleep = pinctrl_lookup_state(adpt->pinctrl,
				EMAC_PINCTRL_STATE_MDIO_SLEEP);
	if (IS_ERR_OR_NULL(adpt->mdio_pins_sleep)) {
		emac_dbg(adpt, probe, "error:%ld Failed to lookup mdio pinctrl sleep state\n",
			 PTR_ERR(adpt->mdio_pins_sleep));
		return PTR_ERR(adpt->mdio_pins_sleep);
	}

	adpt->ephy_pins_active = pinctrl_lookup_state(adpt->pinctrl,
				EMAC_PINCTRL_STATE_EPHY_ACTIVE);
	if (IS_ERR_OR_NULL(adpt->ephy_pins_active)) {
		emac_dbg(adpt, probe, "error:%ld Failed to lookup ephy pinctrl active state\n",
			 PTR_ERR(adpt->ephy_pins_active));
		return PTR_ERR(adpt->ephy_pins_active);
	}

	adpt->pins_sleep = pinctrl_lookup_state(adpt->pinctrl,
				EMAC_PINCTRL_STATE_SLEEP);
	if (IS_ERR_OR_NULL(adpt->pins_sleep)) {
		emac_dbg(adpt, probe, "error:%ld Failed to lookup pinctrl sleep state\n",
			 PTR_ERR(adpt->pins_sleep));
		return PTR_ERR(adpt->pins_sleep);
	adpt->ephy_pins_sleep = pinctrl_lookup_state(adpt->pinctrl,
				EMAC_PINCTRL_STATE_EPHY_SLEEP);
	if (IS_ERR_OR_NULL(adpt->ephy_pins_sleep)) {
		emac_dbg(adpt, probe, "error:%ld Failed to lookup ephy pinctrl sleep state\n",
			 PTR_ERR(adpt->ephy_pins_sleep));
		return PTR_ERR(adpt->ephy_pins_sleep);
	}

	return 0;
@@ -3116,6 +3178,8 @@ static int emac_suspend(struct device *device)
	emac_hw_config_pow_save(hw, phy->link_speed, !!wufc,
				!!(wufc & EMAC_WOL_MAGIC));

	/* Don't reset ephy as need it for WOL/Link detection later */
	adpt->gpio_off(adpt, true, false);
	emac_disable_clks(adpt);
	emac_disable_regulator(adpt);
	return 0;
@@ -3130,11 +3194,13 @@ static int emac_resume(struct device *device)
	struct emac_hw  *hw  = &adpt->hw;
	u32 retval;

	adpt->gpio_on(adpt, true, false);
	emac_enable_regulator(adpt);
	emac_init_clks(adpt);
	emac_enable_clks(adpt);

	emac_hw_reset_mac(hw);
	emac_phy_reset_external(adpt);
	retval = emac_phy_setup_link(adpt, phy->autoneg_advertised, true,
				     !phy->disable_fc_autoneg);
	if (retval)
@@ -3244,6 +3310,11 @@ static int emac_probe(struct platform_device *pdev)
	if (retval)
		goto err_clk_en;

	/* Configure MDIO lines */
	retval = adpt->gpio_on(adpt, true, true);
	if (retval)
		goto err_init_mdio_gpio;

	/* init external phy */
	retval = emac_phy_init_external(adpt);
	if (retval)
@@ -3313,6 +3384,8 @@ static int emac_probe(struct platform_device *pdev)
err_register_netdev:
err_phy_link:
err_init_ephy:
	adpt->gpio_off(adpt, true, true);
err_init_mdio_gpio:
err_clk_en:
err_init_phy:
err_clk_init:
@@ -3339,6 +3412,7 @@ static int emac_remove(struct platform_device *pdev)
	if (TEST_FLAG(hw, HW_PTP_CAP))
		emac_ptp_remove(netdev);

	adpt->gpio_off(adpt, true, true);
	emac_disable_regulator(adpt);
	emac_disable_clks(adpt);
	emac_release_resources(adpt);
+16 −1
Original line number Diff line number Diff line
/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -217,6 +217,19 @@ int emac_phy_write(struct emac_adapter *adpt, u16 phy_addr, u16 reg_addr,
	return retval;
}

/* reset external phy */
void emac_phy_reset_external(struct emac_adapter *adpt)
{
	/* Trigger ephy reset by pulling line low */
	adpt->gpio_off(adpt, false, true);
	/* need delay to complete ephy reset */
	usleep_range(10000, 20000);
	/* Complete ephy reset by pulling line back up */
	adpt->gpio_on(adpt, false, true);
	/* need delay to complete ephy reset */
	usleep_range(10000, 20000);
}

/* initialize external phy */
int emac_phy_init_external(struct emac_adapter *adpt)
{
@@ -226,6 +239,8 @@ int emac_phy_init_external(struct emac_adapter *adpt)
	int retval = 0;

	if (phy->external) {
		emac_phy_reset_external(adpt);

		retval = emac_phy_read(adpt, phy->addr, MII_PHYSID1,
				       &phy_id[0]);
		if (retval)
Loading