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

Commit 0942766e authored by Alok Chauhan's avatar Alok Chauhan Committed by Gerrit - the friendly Code Review server
Browse files

msm: emac: Add runtime PM support to EMAC core



Added Runtime PM framework to EMAC core. This framework
manages the common resources (clock/gpio/regulator) for
EMAC core at runtime based on Ethernet Link connection status.

This framework turns on all the resources when Ethernet Link
is up and vice-versa.

Change-Id: I8a2668ae8beca614bb8411efb4ca6c3d8a36f79c
Signed-off-by: default avatarAlok Chauhan <alokc@codeaurora.org>
parent 50239ba4
Loading
Loading
Loading
Loading
+49 −18
Original line number Diff line number Diff line
@@ -70,6 +70,9 @@ Optional properties:
- tstamp-eble : Enables the PTP (1588) timestamping feature in ACPI mode.
- <supply-name>-supply: phandle to the regulator device tree node
			Required "supply-name" are "emac_vreg*"
- qcom,vdd-voltage-level: This property must be a list of five integer
        values (max voltage value for supply 1/2/3/4/5) where each value
	represents a voltage in microvolts.

Example1:
	emac0: qcom,emac@feb20000 {
@@ -93,19 +96,47 @@ Example1:
Example2:
        emac0: qcom,emac@7c40000 {
                cell-index = <0>;
		compatible = "qcom,emac";
                compatible = "qcom,mdm9607-emac";
                reg-names = "emac", "emac_csr", "emac_1588", "emac_sgmii";
                reg = <0x7c40000 0x10000>,
                        <0x7c56000 0x1000>,
                        <0x7c5C000 0x4000>,
                        <0x7c58000 0x400>;
		interrupts = <0 76 0>, <0 80 0>;
		interrupt-names = "emac_core0_irq", "emac_sgmii_irq";
		pinctrl-names = "emac_active", "emac_sleep";
		pinctrl-0 = <&emac0_active &emac0_irq_active &emac0_rst_active>;
		pinctrl-1 = <&emac0_sleep &emac0_irq_sleep &emac0_rst_sleep>;
                #address-cells = <0>;
                interrupt-parent = <&emac0>;
                #interrupt-cells = <1>;
                interrupts = <0 1 2>;
                interrupt-map-mask = <0xffffffff>;
                interrupt-map = <0 &intc 0 76 0
                                1 &intc 0 80 0
                                2 &tlmm_pinmux 30 0x8>;
                interrupt-names = "emac_core0_irq",
                                "emac_sgmii_irq",
                                "emac_wol_irq";
                emac_vreg1-supply = <&mdm9607_l1>;
                emac_vreg2-supply = <&mdm9607_l3>;
                emac_vreg3-supply = <&mdm9607_l5>;
                emac_vreg4-supply = <&mdm9607_l11>;
                emac_vreg5-supply = <&emac_lan_vreg>;
                qcom,vdd-voltage-level = <1250000 1800000 2850000 1800000 0>;
                clocks = <&clock_gcc clk_gcc_emac_0_axi_clk>,
                         <&clock_gcc clk_gcc_emac_0_ahb_clk>,
                         <&clock_gcc clk_gcc_emac_0_125m_clk>,
                         <&clock_gcc clk_gcc_emac_0_sys_25m_clk>,
                         <&clock_gcc clk_gcc_emac_0_tx_clk>,
                         <&clock_gcc clk_gcc_emac_0_rx_clk>,
                         <&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_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";
                phy-addr = <0>;
                status = "disable";
        };
+1 −0
Original line number Diff line number Diff line
@@ -1395,6 +1395,7 @@
		emac_vreg3-supply = <&mdm9607_l5>;
		emac_vreg4-supply = <&mdm9607_l11>;
		emac_vreg5-supply = <&emac_lan_vreg>;
		qcom,vdd-voltage-level = <1250000 1800000 2850000 1800000 0>;
		clocks = <&clock_gcc clk_gcc_emac_0_axi_clk>,
			 <&clock_gcc clk_gcc_emac_0_ahb_clk>,
			 <&clock_gcc clk_gcc_emac_0_125m_clk>,
+3 −2
Original line number Diff line number Diff line
@@ -549,8 +549,8 @@ struct emac_clk {

struct emac_regulator {
	struct regulator *vreg;
	int	voltage_uv;
	bool	enabled;
	bool			set_voltage;
};

/* emac_ring_header represents a single, contiguous block of DMA space
@@ -730,6 +730,7 @@ struct emac_adapter {
	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;
	bool		runtime_enable;
};

static inline struct emac_adapter *emac_hw_get_adap(struct emac_hw *hw)
+15 −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
@@ -14,6 +14,7 @@
 */

#include <linux/ethtool.h>
#include <linux/pm_runtime.h>

#include "emac.h"
#include "emac_hw.h"
@@ -186,6 +187,8 @@ static int emac_set_settings(struct net_device *netdev,
	    (phy->autoneg_advertised == advertised))
		goto done;

	pm_runtime_get_sync(netdev->dev.parent);

	/* If there is no EPHY, the EMAC internal PHY may get reset in
	 * emac_phy_setup_link_speed. Reset the MAC to avoid the memory
	 * corruption.
@@ -205,6 +208,8 @@ static int emac_set_settings(struct net_device *netdev,
		if (!phy->external)
			emac_up(adpt);
	}
	pm_runtime_mark_last_busy(netdev->dev.parent);
	pm_runtime_put_autosuspend(netdev->dev.parent);

done:
	CLR_FLAG(adpt, ADPT_STATE_RESETTING);
@@ -264,6 +269,7 @@ static int emac_set_pauseparam(struct net_device *netdev,
		CLR_FLAG(adpt, ADPT_STATE_RESETTING);
		return -EINVAL;
	}
	pm_runtime_get_sync(netdev->dev.parent);

	if ((phy->req_fc_mode != req_fc_mode) ||
	    (phy->disable_fc_autoneg != disable_fc_autoneg)) {
@@ -277,6 +283,8 @@ static int emac_set_pauseparam(struct net_device *netdev,
		if (!retval)
			emac_phy_config_fc(adpt);
	}
	pm_runtime_mark_last_busy(netdev->dev.parent);
	pm_runtime_put_autosuspend(netdev->dev.parent);

	CLR_FLAG(adpt, ADPT_STATE_RESETTING);
	return retval;
@@ -318,8 +326,11 @@ static void emac_get_regs(struct net_device *netdev,
	regs->len = EMAC_MAX_REG_SIZE * sizeof(u32);

	memset(val, 0, EMAC_MAX_REG_SIZE * sizeof(u32));
	pm_runtime_get_sync(netdev->dev.parent);
	for (i = 0; i < ARRAY_SIZE(reg); i++)
		val[i] = emac_reg_r32(hw, EMAC, reg[i]);
	pm_runtime_mark_last_busy(netdev->dev.parent);
	pm_runtime_put_autosuspend(netdev->dev.parent);
}

static void emac_get_drvinfo(struct net_device *netdev,
@@ -409,7 +420,10 @@ static int emac_set_intr_coalesce(struct net_device *netdev,
	val |= ((ec->tx_coalesce_usecs / 2) << IRQ_MODERATOR_INIT_SHFT) &
		IRQ_MODERATOR_INIT_BMSK;

	pm_runtime_get_sync(netdev->dev.parent);
	emac_reg_w32(hw, EMAC, EMAC_IRQ_MOD_TIM_INIT, val);
	pm_runtime_mark_last_busy(netdev->dev.parent);
	pm_runtime_put_autosuspend(netdev->dev.parent);
	hw->irq_mod = val;

	return 0;
+6 −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
@@ -124,6 +124,8 @@ bool emac_hw_read_tx_tstamp(struct emac_hw *hw, struct emac_hwtxtstamp *ts);
#define MII_PSSR                        0x11 /* PHY Specific Status Reg */
#define MII_DBG_ADDR                    0x1D /* PHY Debug Address Reg */
#define MII_DBG_DATA                    0x1E /* PHY Debug Data Reg */
#define MII_INT_ENABLE			0x12 /* PHY Interrupt Enable Reg */
#define MII_INT_STATUS			0x13 /* PHY Interrupt Status Reg */

/* MII_BMCR (0x00) */
#define BMCR_SPEED10                    0x0000
@@ -144,4 +146,7 @@ bool emac_hw_read_tx_tstamp(struct emac_hw *hw, struct emac_hwtxtstamp *ts);
/* HIBERNATE_CTRL_REG */
#define HIBERNATE_EN                    0x8000

/* MII_INT_ENABLE/MII_INT_STATUS */
#define LINK_SUCCESS_INTERRUPT		0x400
#define LINK_SUCCESS_BX			0x80
#endif /*_EMAC_HW_H_*/
Loading