static int icss_iep_perout_enable_hw(struct icss_iep *iep,
                                     struct ptp_perout_request *req, int on)
 {
+       struct timespec64 ts;
+       u64 ns_width;
        int ret;
        u64 cmp;
 
+       /* Calculate width of the signal for PPS/PEROUT handling */
+       ts.tv_sec = req->on.sec;
+       ts.tv_nsec = req->on.nsec;
+       ns_width = timespec64_to_ns(&ts);
+
        if (iep->ops && iep->ops->perout_enable) {
                ret = iep->ops->perout_enable(iep->clockops_data, req, on, &cmp);
                if (ret)
                        regmap_write(iep->map, ICSS_IEP_CMP1_REG0, lower_32_bits(cmp));
                        if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT)
                                regmap_write(iep->map, ICSS_IEP_CMP1_REG1, upper_32_bits(cmp));
-                       /* Configure SYNC, 1ms pulse width */
-                       regmap_write(iep->map, ICSS_IEP_SYNC_PWIDTH_REG, 1000000);
+                       /* Configure SYNC, based on req on width */
+                       regmap_write(iep->map, ICSS_IEP_SYNC_PWIDTH_REG,
+                                    div_u64(ns_width, iep->def_inc));
                        regmap_write(iep->map, ICSS_IEP_SYNC0_PERIOD_REG, 0);
                        regmap_write(iep->map, ICSS_IEP_SYNC_START_REG, 0);
                        regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG, 0); /* one-shot mode */
                                   + req->period.nsec;
                        icss_iep_update_to_next_boundary(iep, start_ns);
 
+                       regmap_write(iep->map, ICSS_IEP_SYNC_PWIDTH_REG,
+                                    div_u64(ns_width, iep->def_inc));
                        /* Enable Sync in single shot mode  */
                        regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG,
                                     IEP_SYNC_CTRL_SYNC_N_EN(0) | IEP_SYNC_CTRL_SYNC_EN);
 static int icss_iep_perout_enable(struct icss_iep *iep,
                                  struct ptp_perout_request *req, int on)
 {
-       return -EOPNOTSUPP;
+       int ret = 0;
+
+       /* Reject requests with unsupported flags */
+       if (req->flags & ~PTP_PEROUT_DUTY_CYCLE)
+               return -EOPNOTSUPP;
+
+       mutex_lock(&iep->ptp_clk_mutex);
+
+       if (iep->pps_enabled) {
+               ret = -EBUSY;
+               goto exit;
+       }
+
+       if (iep->perout_enabled == !!on)
+               goto exit;
+
+       /* Set default "on" time (1ms) for the signal if not passed by the app */
+       if (!(req->flags & PTP_PEROUT_DUTY_CYCLE)) {
+               req->on.sec = 0;
+               req->on.nsec = NSEC_PER_MSEC;
+       }
+
+       ret = icss_iep_perout_enable_hw(iep, req, on);
+       if (!ret)
+               iep->perout_enabled = !!on;
+
+exit:
+       mutex_unlock(&iep->ptp_clk_mutex);
+
+       return ret;
 }
 
 static void icss_iep_cap_cmp_work(struct work_struct *work)
                rq.perout.period.nsec = 0;
                rq.perout.start.sec = ts.tv_sec + 2;
                rq.perout.start.nsec = 0;
+               rq.perout.on.sec = 0;
+               rq.perout.on.nsec = NSEC_PER_MSEC;
                ret = icss_iep_perout_enable_hw(iep, &rq.perout, on);
        } else {
                ret = icss_iep_perout_enable_hw(iep, &rq.perout, on);