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

Commit 438587f8 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 full clock support"

parents fa200468 750484ed
Loading
Loading
Loading
Loading
+105 −1
Original line number Diff line number Diff line
/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
/* Copyright (c) 2013-2014, 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
@@ -2108,6 +2108,50 @@ static struct gate_clk pcie_1_phy_ldo = {
	},
};

static struct branch_clk gcc_emac0_axi_clk = {
	.cbcr_reg = EMAC_0_AXI_CBCR,
	.has_sibling = 1,
	.base = &virt_bases[GCC_BASE],
	.c = {
		.dbg_name = "gcc_emac0_axi_clk",
		.ops = &clk_ops_branch,
		CLK_INIT(gcc_emac0_axi_clk.c),
	},
};

static struct branch_clk gcc_emac1_axi_clk = {
	.cbcr_reg = EMAC_1_AXI_CBCR,
	.has_sibling = 1,
	.base = &virt_bases[GCC_BASE],
	.c = {
		.dbg_name = "gcc_emac1_axi_clk",
		.ops = &clk_ops_branch,
		CLK_INIT(gcc_emac1_axi_clk.c),
	},
};

static struct branch_clk gcc_emac0_ahb_clk = {
	.cbcr_reg = EMAC_0_AHB_CBCR,
	.has_sibling = 1,
	.base = &virt_bases[GCC_BASE],
	.c = {
		.dbg_name = "gcc_emac0_ahb_clk",
		.ops = &clk_ops_branch,
		CLK_INIT(gcc_emac0_ahb_clk.c),
	},
};

static struct branch_clk gcc_emac1_ahb_clk = {
	.cbcr_reg = EMAC_1_AHB_CBCR,
	.has_sibling = 1,
	.base = &virt_bases[GCC_BASE],
	.c = {
		.dbg_name = "gcc_emac1_ahb_clk",
		.ops = &clk_ops_branch,
		CLK_INIT(gcc_emac1_ahb_clk.c),
	},
};

static struct clk_freq_tbl ftbl_gcc_emac0_1_125m_clk[] = {
	F(     19200000,              xo,    1, 0, 0),
	F_EXT( 125000000,      emac0_125m,   1, 0, 0),
@@ -2276,6 +2320,50 @@ static struct branch_clk gcc_emac1_tx_clk = {
	},
};

static struct branch_clk gcc_emac0_rx_clk = {
	.cbcr_reg = EMAC_0_RX_CBCR,
	.has_sibling = 1,
	.base = &virt_bases[GCC_BASE],
	.c = {
		.dbg_name = "gcc_emac0_rx_clk",
		.ops = &clk_ops_branch,
		CLK_INIT(gcc_emac0_rx_clk.c),
	},
};

static struct branch_clk gcc_emac1_rx_clk = {
	.cbcr_reg = EMAC_1_RX_CBCR,
	.has_sibling = 1,
	.base = &virt_bases[GCC_BASE],
	.c = {
		.dbg_name = "gcc_emac1_rx_clk",
		.ops = &clk_ops_branch,
		CLK_INIT(gcc_emac1_rx_clk.c),
	},
};

static struct branch_clk gcc_emac0_sys_clk = {
	.cbcr_reg = EMAC_0_SYS_CBCR,
	.has_sibling = 1,
	.base = &virt_bases[GCC_BASE],
	.c = {
		.dbg_name = "gcc_emac0_sys_clk",
		.ops = &clk_ops_branch,
		CLK_INIT(gcc_emac0_sys_clk.c),
	},
};

static struct branch_clk gcc_emac1_sys_clk = {
	.cbcr_reg = EMAC_1_SYS_CBCR,
	.has_sibling = 1,
	.base = &virt_bases[GCC_BASE],
	.c = {
		.dbg_name = "gcc_emac1_sys_clk",
		.ops = &clk_ops_branch,
		CLK_INIT(gcc_emac1_sys_clk.c),
	},
};

static DEFINE_CLK_MEASURE(l2_m_clk);
static DEFINE_CLK_MEASURE(krait0_m_clk);
static DEFINE_CLK_MEASURE(krait1_m_clk);
@@ -2368,12 +2456,20 @@ struct measure_mux_entry measure_mux[] = {
	{&gcc_ce3_clk.c,			GCC_BASE, 0x0228},
	{&gcc_ce3_axi_clk.c,			GCC_BASE, 0x0229},
	{&gcc_ce3_ahb_clk.c,			GCC_BASE, 0x022a},
	{&gcc_emac0_axi_clk.c,			GCC_BASE, 0x01a8},
	{&gcc_emac0_ahb_clk.c,			GCC_BASE, 0x01a9},
	{&gcc_emac0_sys_25m_clk.c,		GCC_BASE, 0x01aa},
	{&gcc_emac0_tx_clk.c,			GCC_BASE, 0x01ab},
	{&gcc_emac0_125m_clk.c,			GCC_BASE, 0x01ac},
	{&gcc_emac0_rx_clk.c,			GCC_BASE, 0x01ad},
	{&gcc_emac0_sys_clk.c,			GCC_BASE, 0x01ae},
	{&gcc_emac1_axi_clk.c,			GCC_BASE, 0x01b0},
	{&gcc_emac1_ahb_clk.c,			GCC_BASE, 0x01b1},
	{&gcc_emac1_sys_25m_clk.c,		GCC_BASE, 0x01b2},
	{&gcc_emac1_tx_clk.c,			GCC_BASE, 0x01b3},
	{&gcc_emac1_125m_clk.c,			GCC_BASE, 0x01b4},
	{&gcc_emac1_rx_clk.c,			GCC_BASE, 0x01b5},
	{&gcc_emac1_sys_clk.c,			GCC_BASE, 0x01b6},

	{&krait0_clk.c,				APCS_BASE, M_ACPU0},
	{&krait1_clk.c,				APCS_BASE, M_ACPU1},
@@ -2630,12 +2726,20 @@ static struct clk_lookup fsm_clocks_9900[] = {
	CLK_LOOKUP("xo",	xo_usb_hs_host_clk.c,      "msm_ehci_host"),

	/* EMAC clocks */
	CLK_LOOKUP("axi_clk",	gcc_emac0_axi_clk.c,	 "feb20000.qcom,emac"),
	CLK_LOOKUP("cfg_ahb_clk", gcc_emac0_ahb_clk.c,	 "feb20000.qcom,emac"),
	CLK_LOOKUP("25m_clk",	emac0_sys_25m_clk_src.c, "feb20000.qcom,emac"),
	CLK_LOOKUP("125m_clk",	emac0_125m_clk_src.c,	 "feb20000.qcom,emac"),
	CLK_LOOKUP("tx_clk",	emac0_tx_clk_src.c,	 "feb20000.qcom,emac"),
	CLK_LOOKUP("rx_clk",	gcc_emac0_rx_clk.c,	 "feb20000.qcom,emac"),
	CLK_LOOKUP("sys_clk",	gcc_emac0_sys_clk.c,	 "feb20000.qcom,emac"),
	CLK_LOOKUP("axi_clk",	gcc_emac1_axi_clk.c,	 "feb00000.qcom,emac"),
	CLK_LOOKUP("cfg_ahb_clk", gcc_emac1_ahb_clk.c,	 "feb00000.qcom,emac"),
	CLK_LOOKUP("25m_clk",	emac1_sys_25m_clk_src.c, "feb00000.qcom,emac"),
	CLK_LOOKUP("125m_clk",	emac1_125m_clk_src.c,	 "feb00000.qcom,emac"),
	CLK_LOOKUP("tx_clk",	emac1_tx_clk_src.c,	 "feb00000.qcom,emac"),
	CLK_LOOKUP("rx_clk",	gcc_emac1_rx_clk.c,	 "feb00000.qcom,emac"),
	CLK_LOOKUP("sys_clk",	gcc_emac1_sys_clk.c,	 "feb00000.qcom,emac"),

	/* PCIE clocks */

+13 −7
Original line number Diff line number Diff line
@@ -36,11 +36,15 @@
#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
/* emac clocks */
#define EMAC_AXI_CLK          0
#define EMAC_CFG_AHB_CLK      1
#define EMAC_125M_CLK         2
#define EMAC_SYS_25M_CLK      3
#define EMAC_TX_CLK           4
#define EMAC_RX_CLK           5
#define EMAC_SYS_CLK          6
#define EMAC_NUM_CLK          7

/* mdio/mdc gpios */
#define EMAC_NUM_GPIO         2
@@ -500,6 +504,8 @@ struct emac_gpio_info {
struct emac_clk_info {
	struct clk           *clk;
	char                 *name;
	bool                  enabled;
	struct emac_adapter  *adpt;
};

/* emac_ring_header represents a single, contiguous block of DMA space
+1 −35
Original line number Diff line number Diff line
@@ -29,11 +29,6 @@

#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

static int emac_hw_sgmii_setup_link(struct emac_hw *hw, u32 speed,
				    bool autoneg, bool fc);

@@ -256,29 +251,6 @@ 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;
@@ -393,17 +365,11 @@ int emac_hw_init_sgmii(struct emac_hw *hw)

	emac_hw_clear_sgmii_intr_status(hw, SGMII_PHY_INTERRUPT_ERR);

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

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

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

	/* It may take about 100ms to reset the SGMII PHY*/
	emac_reg_update32(hw, EMAC_CSR, EMAC_EMAC_WRAPPER_CSR2,
			  PHY_RESET, PHY_RESET);
+119 −16
Original line number Diff line number Diff line
@@ -93,11 +93,41 @@ static struct emac_gpio_info emac_gpio[EMAC_NUM_GPIO] = {
};

static struct emac_clk_info emac_clk[EMAC_NUM_CLK] = {
	{ 0, "125m_clk" },
	{ 0, "25m_clk" },
	{ 0, "tx_clk" },
	{ NULL, "axi_clk", 0, NULL },
	{ NULL, "cfg_ahb_clk", 0, NULL },
	{ NULL, "125m_clk", 0, NULL },
	{ NULL, "25m_clk", 0, NULL },
	{ NULL, "tx_clk", 0, NULL },
	{ NULL, "rx_clk", 0, NULL },
	{ NULL, "sys_clk", 0, NULL },
};

static int emac_clk_prepare_enable(struct emac_clk_info *clk_info)
{
	int retval;

	retval = clk_prepare_enable(clk_info->clk);
	if (retval)
		emac_err(clk_info->adpt, "can't enable clk %s\n",
			 clk_info->name);
	else
		clk_info->enabled = true;

	return retval;
}

static int emac_clk_set_rate(struct emac_clk_info *clk_info, unsigned long rate)
{
	int retval;

	retval = clk_set_rate(clk_info->clk, rate);
	if (retval)
		emac_err(clk_info->adpt, "can't set rate for clk %s\n",
			 clk_info->name);

	return retval;
}

/* reinitialize */
void emac_reinit_locked(struct emac_adapter *adpt)
{
@@ -112,8 +142,11 @@ void emac_reinit_locked(struct emac_adapter *adpt)
	}

	emac_down(adpt, EMAC_HW_CTRL_RESET_MAC);
	if (adpt->phy_mode == PHY_INTERFACE_MODE_SGMII)
	if (adpt->phy_mode == PHY_INTERFACE_MODE_SGMII) {
		emac_clk_set_rate(&adpt->clk_info[EMAC_125M_CLK], 19200000);
		emac_hw_reset_sgmii(&adpt->hw);
		emac_clk_set_rate(&adpt->clk_info[EMAC_125M_CLK], 125000000);
	}
	emac_up(adpt);

	CLI_ADPT_FLAG(STATE_RESETTING);
@@ -2127,9 +2160,6 @@ static void emac_init_adapter(struct emac_adapter *adpt)
	/* others */
	hw->preamble = EMAC_PREAMBLE_DEF;
	adpt->wol = EMAC_WOL_MAGIC | EMAC_WOL_PHY;

	/* phy */
	emac_hw_init_phy(hw);
}

#ifdef CONFIG_PM_RUNTIME
@@ -2266,10 +2296,6 @@ static int emac_get_clk(struct platform_device *pdev,
	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);
@@ -2288,15 +2314,74 @@ static int emac_get_clk(struct platform_device *pdev,
	return retval;
}

static void emac_prepare_enable_clk(struct emac_adapter *adpt)
/* Initialize clocks */
static int emac_init_clks(struct emac_adapter *adpt)
{
	int retval;

	retval = emac_clk_prepare_enable(&adpt->clk_info[EMAC_AXI_CLK]);
	if (retval)
		return retval;

	retval = emac_clk_prepare_enable(&adpt->clk_info[EMAC_CFG_AHB_CLK]);
	if (retval)
		return retval;

	retval = emac_clk_set_rate(&adpt->clk_info[EMAC_125M_CLK], 19200000);
	if (retval)
		return retval;

	retval = emac_clk_prepare_enable(&adpt->clk_info[EMAC_125M_CLK]);

	return retval;
}

/* Enable clocks; needs emac_init_clks to be called before */
static int emac_enable_clks(struct emac_adapter *adpt)
{
	int retval;

	retval = emac_clk_set_rate(&adpt->clk_info[EMAC_TX_CLK], 125000000);
	if (retval)
		return retval;

	retval = emac_clk_prepare_enable(&adpt->clk_info[EMAC_TX_CLK]);
	if (retval)
		return retval;

	retval = emac_clk_set_rate(&adpt->clk_info[EMAC_125M_CLK], 125000000);
	if (retval)
		return retval;

	retval = emac_clk_set_rate(&adpt->clk_info[EMAC_SYS_25M_CLK], 25000000);
	if (retval)
		return retval;

	retval = emac_clk_prepare_enable(&adpt->clk_info[EMAC_SYS_25M_CLK]);
	if (retval)
		return retval;

	retval = emac_clk_prepare_enable(&adpt->clk_info[EMAC_RX_CLK]);
	if (retval)
		return retval;

	retval = emac_clk_prepare_enable(&adpt->clk_info[EMAC_SYS_CLK]);

	return retval;
}

/* Disable clocks */
static void emac_disable_clks(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);
		if (clk_info->enabled) {
			clk_disable_unprepare(clk_info->clk);
			clk_info->enabled = false;
		}
	}
}

@@ -2482,7 +2567,10 @@ 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->clk_info, emac_clk, sizeof(emac_clk));
	for (i = 0; i < EMAC_NUM_CLK; i++)
		adpt->clk_info[i].adpt = adpt;

	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++) {
@@ -2498,7 +2586,10 @@ static int emac_probe(struct platform_device *pdev)
	if (retval)
		goto err_res;

	emac_prepare_enable_clk(adpt);
	/* initialize clocks */
	retval = emac_init_clks(adpt);
	if (retval)
		goto err_clk_init;

	hw_ver = emac_reg_r32(hw, EMAC, EMAC_CORE_HW_VERSION);

@@ -2526,6 +2617,14 @@ static int emac_probe(struct platform_device *pdev)
	/* init adapter */
	emac_init_adapter(adpt);

	/* init phy */
	emac_hw_init_phy(hw);

	/* enable clocks */
	retval = emac_enable_clks(adpt);
	if (retval)
		goto err_clk_en;

	/* reset phy */
	emac_hw_reset_phy(hw);

@@ -2586,6 +2685,9 @@ static int emac_probe(struct platform_device *pdev)

err_register_netdev:
err_phy_link:
err_clk_en:
err_clk_init:
	emac_disable_clks(adpt);
	emac_release_resources(adpt);
err_res:
	free_netdev(netdev);
@@ -2605,6 +2707,7 @@ static int emac_remove(struct platform_device *pdev)
	if (CHK_HW_FLAG(PTP_CAP))
		emac_ptp_remove(netdev);

	emac_disable_clks(adpt);
	emac_release_resources(adpt);
	free_netdev(netdev);
	dev_set_drvdata(&pdev->dev, NULL);