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

Commit d0cebea9 authored by Suraj Jaiswal's avatar Suraj Jaiswal Committed by Gerrit - the friendly Code Review server
Browse files

net: stmmac: Fix PPS0 not coming up on bootup



Change ppsout_config definition and ioctl handling.

Change-Id: I4173e50368478661122d1f88c78aa1d28d8c8f6d
Signed-off-by: default avatarSuraj Jaiswal <jsuraj@codeaurora.org>
parent e1e04827
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -251,6 +251,7 @@ int ethqos_handle_prv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
	struct stmmac_priv *pdata = netdev_priv(dev);
	struct ifr_data_struct req;
	struct pps_cfg eth_pps_cfg;
	int ret = 0;

	if (copy_from_user(&req, ifr->ifr_ifru.ifru_data,
@@ -259,7 +260,10 @@ int ethqos_handle_prv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)

	switch (req.cmd) {
	case ETHQOS_CONFIG_PPSOUT_CMD:
		ret = ppsout_config(pdata, &req);
		if (copy_from_user(&eth_pps_cfg, (void __user *)req.ptr,
				   sizeof(struct pps_cfg)))
			return -EFAULT;
		ret = ppsout_config(pdata, &eth_pps_cfg);
		break;
	case ETHQOS_AVB_ALGORITHM:
		dwmac_qcom_program_avb_algorithm(pdata, &req);
+3 −1
Original line number Diff line number Diff line
@@ -194,7 +194,7 @@ int create_pps_interrupt_device_node(dev_t *pps_dev_t,
bool qcom_ethqos_is_phy_link_up(struct qcom_ethqos *ethqos);
void *qcom_ethqos_get_priv(struct qcom_ethqos *ethqos);

int ppsout_config(struct stmmac_priv *priv, struct ifr_data_struct *req);
int ppsout_config(struct stmmac_priv *priv, struct pps_cfg *eth_pps_cfg);

u16 dwmac_qcom_select_queue(struct net_device *dev,
			    struct sk_buff *skb,
@@ -225,6 +225,8 @@ u16 dwmac_qcom_select_queue(struct net_device *dev,
#define IP_PKT_INT_MOD 32
#define PTP_INT_MOD 1

#define PPS_19_2_FREQ 19200000

enum dwmac_qcom_queue_operating_mode {
	DWMAC_QCOM_QDISABLED = 0X0,
	DWMAC_QCOM_QAVB,
+30 −62
Original line number Diff line number Diff line
@@ -84,36 +84,6 @@ static u32 pps_config_sub_second_increment(void __iomem *ioaddr,
	return data;
}

static u32 pps_config_default_addend(void __iomem *ioaddr,
				     struct stmmac_priv *priv, u32 ptp_clock)
{
	u64 temp;

	/* formula is :
	 * addend = 2^32/freq_div_ratio;
	 *
	 * where, freq_div_ratio = DWC_ETH_QOS_SYSCLOCK/50MHz
	 *
	 * hence, addend = ((2^32) * 50MHz)/DWC_ETH_QOS_SYSCLOCK;
	 *
	 * NOTE: DWC_ETH_QOS_SYSCLOCK should be >= 50MHz to
	 *       achive 20ns accuracy.
	 *
	 * 2^x * y == (y << x), hence
	 * 2^32 * 50000000 ==> (50000000 << 32)
	 */
	if (ptp_clock == 250000000) {
		// If PTP_CLOCK == SYS_CLOCK, best we can do is 2^32 - 1
		priv->default_addend = 0xFFFFFFFF;
	} else {
		temp = (u64)((u64)ptp_clock << 32);
		priv->default_addend = div_u64(temp, priv->plat->clk_ptp_rate);
	}
	priv->hw->ptp->config_addend(ioaddr, priv->default_addend);

	return 1;
}

int ppsout_stop(struct stmmac_priv *priv, struct pps_cfg *eth_pps_cfg)
{
	u32 val;
@@ -190,23 +160,19 @@ static void ethqos_unregister_pps_isr(struct stmmac_priv *priv, int ch)
	}
}

int ppsout_config(struct stmmac_priv *priv, struct ifr_data_struct *req)
int ppsout_config(struct stmmac_priv *priv, struct pps_cfg *eth_pps_cfg)
{
	int interval, width;
	u32 sub_second_inc, value;
	void __iomem *ioaddr = priv->ioaddr;
	u32 val;
	struct pps_cfg eth_pps_cfg;

	if (copy_from_user(&eth_pps_cfg, (void __user *)req->ptr,
			   sizeof(struct pps_cfg)))
		return -EFAULT;
	u64 temp;

	if (!eth_pps_cfg.ppsout_start) {
		ppsout_stop(priv, &eth_pps_cfg);
		if (eth_pps_cfg.ppsout_ch == DWC_ETH_QOS_PPS_CH_2 ||
		    eth_pps_cfg.ppsout_ch == DWC_ETH_QOS_PPS_CH_3)
			ethqos_unregister_pps_isr(priv, eth_pps_cfg.ppsout_ch);
	if (!eth_pps_cfg->ppsout_start) {
		ppsout_stop(priv, eth_pps_cfg);
		if (eth_pps_cfg->ppsout_ch == DWC_ETH_QOS_PPS_CH_2 ||
		    eth_pps_cfg->ppsout_ch == DWC_ETH_QOS_PPS_CH_3)
			ethqos_unregister_pps_isr(priv, eth_pps_cfg->ppsout_ch);
		return 0;
	}

@@ -218,40 +184,42 @@ int ppsout_config(struct stmmac_priv *priv, struct ifr_data_struct *req)
	val = readl_relaxed(ioaddr + MAC_PPS_CONTROL);

	sub_second_inc = pps_config_sub_second_increment
			 (priv->ptpaddr, eth_pps_cfg.ptpclk_freq,
			 (priv->ptpaddr, eth_pps_cfg->ptpclk_freq,
			  priv->plat->has_gmac4);
	pps_config_default_addend(priv->ptpaddr, priv,
				  eth_pps_cfg.ptpclk_freq);

	val &= ~PPSX_MASK(eth_pps_cfg.ppsout_ch);
	temp = (u64)((u64)eth_pps_cfg->ptpclk_freq << 32);
	priv->default_addend = div_u64(temp, priv->plat->clk_ptp_rate);
	priv->hw->ptp->config_addend(priv->ptpaddr, priv->default_addend);

	val &= ~PPSX_MASK(eth_pps_cfg->ppsout_ch);

	val |= PPSCMDX(eth_pps_cfg.ppsout_ch, 0x2);
	val |= TRGTMODSELX(eth_pps_cfg.ppsout_ch, 0x2);
	val |= PPSCMDX(eth_pps_cfg->ppsout_ch, 0x2);
	val |= TRGTMODSELX(eth_pps_cfg->ppsout_ch, 0x2);
	val |= PPSEN0;

	if (eth_pps_cfg.ppsout_ch == DWC_ETH_QOS_PPS_CH_2 ||
	    eth_pps_cfg.ppsout_ch == DWC_ETH_QOS_PPS_CH_3)
		ethqos_register_pps_isr(priv, eth_pps_cfg.ppsout_ch);
	if (eth_pps_cfg->ppsout_ch == DWC_ETH_QOS_PPS_CH_2 ||
	    eth_pps_cfg->ppsout_ch == DWC_ETH_QOS_PPS_CH_3)
		ethqos_register_pps_isr(priv, eth_pps_cfg->ppsout_ch);

	writel_relaxed(0, ioaddr +
		       MAC_PPSX_TARGET_TIME_SEC(eth_pps_cfg.ppsout_ch));
		       MAC_PPSX_TARGET_TIME_SEC(eth_pps_cfg->ppsout_ch));

	writel_relaxed(0, ioaddr +
		       MAC_PPSX_TARGET_TIME_NSEC(eth_pps_cfg.ppsout_ch));
		       MAC_PPSX_TARGET_TIME_NSEC(eth_pps_cfg->ppsout_ch));

	interval = ((eth_pps_cfg.ptpclk_freq + eth_pps_cfg.ppsout_freq / 2)
		   / eth_pps_cfg.ppsout_freq);
	interval = ((eth_pps_cfg->ptpclk_freq + eth_pps_cfg->ppsout_freq / 2)
		   / eth_pps_cfg->ppsout_freq);

	width = ((interval * eth_pps_cfg.ppsout_duty) + 50) / 100 - 1;
	width = ((interval * eth_pps_cfg->ppsout_duty) + 50) / 100 - 1;
	if (width >= interval)
		width = interval - 1;
	if (width < 0)
		width = 0;

	writel_relaxed(interval, ioaddr +
		       MAC_PPSX_INTERVAL(eth_pps_cfg.ppsout_ch));
		       MAC_PPSX_INTERVAL(eth_pps_cfg->ppsout_ch));

	writel_relaxed(width, ioaddr + MAC_PPSX_WIDTH(eth_pps_cfg.ppsout_ch));
	writel_relaxed(width, ioaddr + MAC_PPSX_WIDTH(eth_pps_cfg->ppsout_ch));

	writel_relaxed(val, ioaddr + MAC_PPS_CONTROL);

@@ -261,7 +229,6 @@ int ppsout_config(struct stmmac_priv *priv, struct ifr_data_struct *req)
int ethqos_init_pps(struct stmmac_priv *priv)
{
	u32 value;
	struct ifr_data_struct req = {0};
	struct pps_cfg eth_pps_cfg = {0};

	priv->ptpaddr = priv->ioaddr + PTP_GMAC4_OFFSET;
@@ -272,13 +239,14 @@ int ethqos_init_pps(struct stmmac_priv *priv)

	/*Configuaring PPS0 PPS output frequency to default 19.2 Mhz*/
	eth_pps_cfg.ppsout_ch = 0;
	eth_pps_cfg.ptpclk_freq = 62500000;
	eth_pps_cfg.ppsout_freq = 19200000;

	eth_pps_cfg.ptpclk_freq = priv->plat->clk_ptp_req_rate;
	eth_pps_cfg.ppsout_freq = PPS_19_2_FREQ;

	eth_pps_cfg.ppsout_start = 1;
	eth_pps_cfg.ppsout_duty = 50;
	req.ptr = (void *)&eth_pps_cfg;

	ppsout_config(priv, &req);
	ppsout_config(priv, &eth_pps_cfg);
	return 0;
}