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

Commit 092f3d69 authored by Niranjana Vishwanathapura's avatar Niranjana Vishwanathapura
Browse files

msm: emac: Provide the sysfs node to access tstamp



Provide the sysfs node for user to set/get the current timestamp.

Change-Id: Idd41a0312c14ea9394ab031221ad8101e3af6ad1
Signed-off-by: default avatarNiranjana Vishwanathapura <nvishwan@codeaurora.org>
parent 0c313f7c
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -646,7 +646,9 @@ void emac_hw_disable_intr(struct emac_hw *hw)
		emac_reg_w32(hw, EMAC, irq_info->mask_reg, 0);
	}

	emac_reg_w32(hw, EMAC_1588, EMAC_P1588_PTP_EXPANDED_INT_MASK, 0);
	if (adpt->tstamp_en)
		emac_reg_w32(hw, EMAC_1588,
			     EMAC_P1588_PTP_EXPANDED_INT_MASK, 0);

	if (adpt->phy_mode == PHY_INTERFACE_MODE_SGMII) {
		irq_info = &adpt->irq_info[EMAC_SGMII_PHY_IRQ];
@@ -1195,7 +1197,7 @@ void emac_hw_start_mac(struct emac_hw *hw)
		     (INT_RD_CLR_EN | LPW_MODE |
		      IRQ_MODERATOR_EN | IRQ_MODERATOR2_EN));

	if (CHK_HW_FLAG(PTP_EN)) {
	if (CHK_HW_FLAG(PTP_CAP)) {
		if (hw->link_speed == EMAC_LINK_SPEED_1GB_FULL)
			emac_ptp_set_linkspeed(hw, emac_mac_speed_1000);
		else
+12 −4
Original line number Diff line number Diff line
@@ -1624,12 +1624,16 @@ static int emac_mii_ioctl(struct net_device *netdev,
/* IOCTL support for the interface */
static int emac_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
{
	struct emac_adapter *adpt = netdev_priv(netdev);
	struct emac_hw *hw = &adpt->hw;

	switch (cmd) {
	case SIOCGMIIPHY:
	case SIOCGMIIREG:
	case SIOCSMIIREG:
		return emac_mii_ioctl(netdev, ifr, cmd);
	case SIOCSHWTSTAMP:
		if (CHK_HW_FLAG(PTP_CAP))
			return emac_tstamp_ioctl(netdev, ifr, cmd);
	default:
		return -EOPNOTSUPP;
@@ -2063,9 +2067,6 @@ static void emac_init_adapter(struct emac_adapter *adpt)

	/* phy */
	emac_hw_init_phy(hw);

	if (CHK_HW_FLAG(PTP_CAP))
		emac_ptp_init(hw);
}

#ifdef CONFIG_PM_RUNTIME
@@ -2440,6 +2441,9 @@ static int emac_probe(struct platform_device *pdev)
		goto err_register_netdev;
	}

	if (CHK_HW_FLAG(PTP_CAP))
		emac_ptp_init(adpt->netdev);

	pr_info("%s - version %s\n", emac_drv_description, emac_drv_version);
	emac_dbg(adpt, probe, "EMAC HW ID %d.%d\n", hw->devid, hw->revid);
	emac_dbg(adpt, probe, "EMAC HW version %d.%d.%d\n",
@@ -2461,10 +2465,14 @@ static int emac_remove(struct platform_device *pdev)
{
	struct net_device *netdev = dev_get_drvdata(&pdev->dev);
	struct emac_adapter *adpt = netdev_priv(netdev);
	struct emac_hw *hw = &adpt->hw;

	pr_info("exiting %s\n", emac_drv_name);

	unregister_netdev(netdev);
	if (CHK_HW_FLAG(PTP_CAP))
		emac_ptp_remove(netdev);

	emac_release_resources(adpt);
	free_netdev(netdev);
	dev_set_drvdata(&pdev->dev, NULL);
+94 −26
Original line number Diff line number Diff line
@@ -162,21 +162,6 @@ static void rtc_adjtime(struct emac_hw *hw, s64 delta)
	wmb();
}

int emac_ptp_init(struct emac_hw *hw)
{
	int ret = 0;

	if (!CHK_HW_FLAG(PTP_CAP)) {
		emac_err(hw->adpt, "not ieee-1588 capable\n");
		return -ENOTSUPP;
	}

	spin_lock_init(&hw->ptp_lock);
	ret = emac_hw_1588_core_disable(hw);

	return ret;
}

int emac_ptp_config(struct emac_hw *hw)
{
	struct timespec ts;
@@ -233,37 +218,49 @@ int emac_ptp_set_linkspeed(struct emac_hw *hw, enum emac_mac_speed link_speed)
	return 0;
}

int emac_ptp_settime(struct emac_hw *hw, const struct timespec *ts)
static int emac_ptp_settime(struct emac_hw *hw, const struct timespec *ts)
{
	int ret = 0;
	unsigned long flag;

	spin_lock_irqsave(&hw->ptp_lock, flag);
	if (!CHK_HW_FLAG(PTP_EN))
		ret = -EPERM;
	else
		rtc_settime(hw, ts);
	spin_unlock_irqrestore(&hw->ptp_lock, flag);

	return 0;
	return ret;
}

int emac_ptp_gettime(struct emac_hw *hw, struct timespec *ts)
static int emac_ptp_gettime(struct emac_hw *hw, struct timespec *ts)
{
	int ret = 0;
	unsigned long flag;

	spin_lock_irqsave(&hw->ptp_lock, flag);
	if (!CHK_HW_FLAG(PTP_EN))
		ret = -EPERM;
	else
		rtc_gettime(hw, ts);
	spin_unlock_irqrestore(&hw->ptp_lock, flag);

	return 0;
	return ret;
}

int emac_ptp_adjtime(struct emac_hw *hw, s64 delta)
{
	int ret = 0;
	unsigned long flag;

	spin_lock_irqsave(&hw->ptp_lock, flag);
	if (!CHK_HW_FLAG(PTP_EN))
		ret = -EPERM;
	else
		rtc_adjtime(hw, delta);
	spin_unlock_irqrestore(&hw->ptp_lock, flag);

	return 0;
	return ret;
}

int emac_tstamp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
@@ -272,9 +269,6 @@ int emac_tstamp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
	struct emac_hw *hw = &adpt->hw;
	struct hwtstamp_config cfg;

	if (!CHK_HW_FLAG(PTP_CAP))
		return -ENOTSUPP;

	if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
		return -EFAULT;

@@ -312,3 +306,77 @@ int emac_tstamp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
	return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ?
		-EFAULT : 0;
}

static int emac_ptp_sysfs_cmd(struct device *dev, struct device_attribute *attr,
			      const char *buf, size_t count)
{
	struct emac_adapter *adpt = netdev_priv(to_net_dev(dev));
	struct timespec ts;
	int ret = -EINVAL;

	if (!strncmp(buf, "setTs", 5)) {
		getnstimeofday(&ts);
		ret = emac_ptp_settime(&adpt->hw, &ts);
		if (!ret)
			ret = count;
	}

	return ret;
}

static int emac_ptp_sysfs_tstamp_show(struct device *dev,
				      struct device_attribute *attr, char *buf)
{
	struct emac_adapter *adpt = netdev_priv(to_net_dev(dev));
	struct timespec ts, ts_now;
	int count = PAGE_SIZE;
	int retval;

	retval = emac_ptp_gettime(&adpt->hw, &ts);
	if (retval)
		return retval;

	getnstimeofday(&ts_now);
	retval = snprintf(buf, count,
			  "%12u.%09u tstamp  %12u.%08u time-of-day\n",
			  (int)ts.tv_sec, (int)ts.tv_nsec,
			  (int)ts_now.tv_sec, (int)ts_now.tv_nsec);

	return retval;
}

static DEVICE_ATTR(cmd, 0222, NULL, emac_ptp_sysfs_cmd);
static DEVICE_ATTR(tstamp, 0444, emac_ptp_sysfs_tstamp_show, NULL);

static void emac_ptp_sysfs_create(struct net_device *netdev)
{
	struct emac_adapter *adpt = netdev_priv(netdev);

	if (device_create_file(&netdev->dev, &dev_attr_cmd) ||
	    device_create_file(&netdev->dev, &dev_attr_tstamp))
		emac_err(adpt, "emac_ptp: failed to create sysfs files\n");
}

static void emac_ptp_sysfs_remove(struct net_device *netdev)
{
	device_remove_file(&netdev->dev, &dev_attr_cmd);
	device_remove_file(&netdev->dev, &dev_attr_tstamp);
}

int emac_ptp_init(struct net_device *netdev)
{
	struct emac_adapter *adpt = netdev_priv(netdev);
	struct emac_hw *hw = &adpt->hw;
	int ret = 0;

	spin_lock_init(&hw->ptp_lock);
	emac_ptp_sysfs_create(netdev);
	ret = emac_hw_1588_core_disable(hw);

	return ret;
}

void emac_ptp_remove(struct net_device *netdev)
{
	emac_ptp_sysfs_remove(netdev);
}
+2 −4
Original line number Diff line number Diff line
@@ -15,13 +15,11 @@

#define DEFAULT_RTC_REF_CLKRATE	125000000

int emac_ptp_init(struct emac_hw *hw);
int emac_ptp_init(struct net_device *netdev);
void emac_ptp_remove(struct net_device *netdev);
int emac_ptp_config(struct emac_hw *hw);
int emac_ptp_stop(struct emac_hw *hw);
int emac_ptp_set_linkspeed(struct emac_hw *hw, enum emac_mac_speed speed);
int emac_ptp_settime(struct emac_hw *hw, const struct timespec *ts);
int emac_ptp_gettime(struct emac_hw *hw, struct timespec *ts);
int emac_ptp_adjtime(struct emac_hw *hw, s64 delta);
int emac_tstamp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);

#endif /* _EMAC_PTP_H_ */