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

Commit 0ebc9c40 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: Setup the SGMII clock"

parents f8e43d78 21b29f35
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
#include <asm/byteorder.h>
#include <linux/interrupt.h>
#include <linux/netdevice.h>
#include <linux/clk.h>

/* Device IDs */
#define EMAC_DEV_ID                0x0040
@@ -35,6 +36,12 @@
#define EMAC_SGMII_PHY_IRQ    5
#define EMAC_NUM_IRQ          6

/* emac clock */
#define EMAC_SGMII_125M_CLK	0
#define EMAC_SGMII_SYS_25M_CLK	1
#define EMAC_SGMII_TX_CLK	2
#define EMAC_NUM_CLK		3

/* mdio/mdc gpios */
#define EMAC_NUM_GPIO         2

@@ -483,6 +490,11 @@ struct emac_gpio_info {
	char *name;
};

struct emac_clk_info {
	struct clk *clk;
	char *name;
};

/* emac_ring_header represents a single, contiguous block of DMA space
 * mapped for the three descriptor rings (tpd, rfd, rrd)
 */
@@ -588,6 +600,7 @@ struct emac_adapter {

	struct emac_irq_info  irq_info[EMAC_NUM_IRQ];
	struct emac_gpio_info gpio_info[EMAC_NUM_GPIO];
	struct emac_clk_info  clk_info[EMAC_NUM_CLK];

	/* dma parameters */
	u64                             dma_mask;
+35 −1
Original line number Diff line number Diff line
@@ -29,6 +29,11 @@

#define RXD_TH              0x100

#define SGMII_125M_CLK_RATE	125000000
#define SGMII_25M_CLK_RATE	25000000
#define SGMII_TX_CLK_RATE	125000000
#define SGMII_CXO_CLK_RATE	19200000

/* REG */
u32 emac_reg_r32(struct emac_hw *hw, u8 base, u32 reg)
{
@@ -238,6 +243,29 @@ int emac_hw_ack_phy_intr(struct emac_hw *hw)
	return 0;
}

static int emac_hw_sgmii_setclk(struct emac_hw *hw, bool cxo)
{
	struct clk *clk;
	int retval;

	clk = hw->adpt->clk_info[EMAC_SGMII_125M_CLK].clk;
	retval = clk_set_rate(clk,
			      (cxo) ? SGMII_CXO_CLK_RATE : SGMII_125M_CLK_RATE);
	if (retval)
		return retval;

	clk = hw->adpt->clk_info[EMAC_SGMII_SYS_25M_CLK].clk;
	retval = clk_set_rate(clk,
			      (cxo) ? SGMII_CXO_CLK_RATE : SGMII_25M_CLK_RATE);
	if (retval)
		return retval;

	clk = hw->adpt->clk_info[EMAC_SGMII_TX_CLK].clk;
	retval = clk_set_rate(clk,
			      (cxo) ? SGMII_CXO_CLK_RATE : SGMII_TX_CLK_RATE);
	return retval;
}

int emac_hw_init_sgmii(struct emac_hw *hw)
{
	int i;
@@ -350,11 +378,17 @@ int emac_hw_init_sgmii(struct emac_hw *hw)

	emac_hw_clear_sgmii_intr_status(hw, SGMII_PHY_INTERRUPT_ERR);

	return 0;
	return emac_hw_sgmii_setclk(hw, false);
}

int emac_hw_reset_sgmii(struct emac_hw *hw)
{
	int retval;

	retval = emac_hw_sgmii_setclk(hw, true);
	if (retval)
		return retval;

	emac_reg_w32(hw, EMAC_SGMII_PHY, EMAC_SGMII_PHY_RESET_CTRL,
		     PHY_SW_RESET);
	wmb();
+71 −2
Original line number Diff line number Diff line
@@ -90,6 +90,12 @@ static struct emac_gpio_info emac_gpio[EMAC_NUM_GPIO] = {
	{ 0, "qcom,emac-gpio-mdio" },
};

static struct emac_clk_info emac_clk[EMAC_NUM_CLK] = {
	{ 0, "125m_clk" },
	{ 0, "25m_clk" },
	{ 0, "tx_clk" },
};

/* reinitialize */
void emac_reinit_locked(struct emac_adapter *adpt)
{
@@ -2208,6 +2214,49 @@ static int emac_resume(struct device *device)
}
#endif

/* Get the clock */
static int emac_get_clk(struct platform_device *pdev,
			struct emac_adapter *adpt)
{
	struct emac_clk_info *clk_info;
	struct clk *clk;
	int retval = 0;
	u8 i;

	/* currently all clocks are sgmii clocks */
	if (adpt->phy_mode != PHY_INTERFACE_MODE_SGMII)
		return 0;

	for (i = 0; i < EMAC_NUM_CLK; i++) {
		clk_info = &adpt->clk_info[i];
		clk = clk_get(&pdev->dev, clk_info->name);
		if (IS_ERR(clk)) {
			emac_err(adpt, "can't get clk %s\n", clk_info->name);
			retval = PTR_ERR(clk);
			while (--i >= 0) {
				if (adpt->clk_info[i].clk)
					clk_put(adpt->clk_info[i].clk);
			}
			break;
		}
		clk_info->clk = clk;
	}

	return retval;
}

static void emac_prepare_enable_clk(struct emac_adapter *adpt)
{
	struct emac_clk_info *clk_info;
	u8 i;

	for (i = 0; i < EMAC_NUM_CLK; i++) {
		clk_info = &adpt->clk_info[i];
		if (clk_info->clk)
			clk_prepare_enable(clk_info->clk);
	}
}

/* Get the resources */
static int emac_get_resources(struct platform_device *pdev,
			      struct emac_adapter *adpt)
@@ -2283,6 +2332,10 @@ static int emac_get_resources(struct platform_device *pdev,
		irq_info->irq = retval;
	}

	retval = emac_get_clk(pdev, adpt);
	if (retval)
		return retval;

	/* get register addresses */
	retval = 0;
	for (i = 0; i < NUM_EMAC_REG_BASES; i++) {
@@ -2315,8 +2368,16 @@ static int emac_get_resources(struct platform_device *pdev,
		while (--i >= 0)
			if (adpt->hw.reg_addr[i])
				iounmap(adpt->hw.reg_addr[i]);
	} else {
		goto err_reg_res;
	}

	netdev->base_addr = (unsigned long)adpt->hw.reg_addr[EMAC];
	return 0;

err_reg_res:
	for (i = 0; i < EMAC_NUM_CLK; i++) {
		if (adpt->clk_info[i].clk)
			clk_put(adpt->clk_info[i].clk);
	}

	return retval;
@@ -2331,6 +2392,11 @@ static void emac_release_resources(struct emac_adapter *adpt)
		if (adpt->hw.reg_addr[i])
			iounmap(adpt->hw.reg_addr[i]);
	}

	for (i = 0; i < EMAC_NUM_CLK; i++) {
		if (adpt->clk_info[i].clk)
			clk_put(adpt->clk_info[i].clk);
	}
}

/* Probe function */
@@ -2367,6 +2433,7 @@ static int emac_probe(struct platform_device *pdev)
	dma_set_max_seg_size(&pdev->dev, 65536);
	dma_set_seg_boundary(&pdev->dev, 0xffffffff);

	memcpy(&adpt->clk_info, emac_clk, sizeof(emac_clk));
	memcpy(adpt->gpio_info, emac_gpio, sizeof(adpt->gpio_info));
	memcpy(adpt->irq_info, emac_irq, sizeof(adpt->irq_info));
	for (i = 0; i < EMAC_NUM_CORE_IRQ; i++) {
@@ -2380,6 +2447,8 @@ static int emac_probe(struct platform_device *pdev)
	if (retval)
		goto err_res;

	emac_prepare_enable_clk(adpt);

	hw_ver = emac_reg_r32(hw, EMAC, EMAC_CORE_HW_VERSION);

	netdev->watchdog_timeo = EMAC_WATCHDOG_TIME;