mirror of
https://github.com/torvalds/linux.git
synced 2026-05-27 00:22:00 +02:00
Merge branch 'add-perout-configuration-support-in-iep-driver'
Meghana Malladi says: ==================== Add perout configuration support in IEP driver IEP driver supported both perout and pps signal generation but perout feature is faulty with half-cooked support due to some missing configuration. Hence perout feature is removed as a bug fix. This patch series adds back this feature which configures perout signal based on the arguments passed by the perout request. This patch series is continuation to the bug fix: https://lore.kernel.org/20250227092441.1848419-1-m-malladi@ti.com as suggested by Jakub Kicinski and Jacob Keller: https://lore.kernel.org/20250220172410.025b96d6@kernel.org v3: https://lore.kernel.org/20250303135124.632845-1-m-malladi@ti.com ==================== Link: https://patch.msgid.link/20250304105753.1552159-1-m-malladi@ti.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
92d3690520
|
|
@ -406,9 +406,25 @@ static void icss_iep_update_to_next_boundary(struct icss_iep *iep, u64 start_ns)
|
|||
static int icss_iep_perout_enable_hw(struct icss_iep *iep,
|
||||
struct ptp_perout_request *req, int on)
|
||||
{
|
||||
struct timespec64 ts;
|
||||
u64 ns_start;
|
||||
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 (req->flags & PTP_PEROUT_PHASE) {
|
||||
ts.tv_sec = req->phase.sec;
|
||||
ts.tv_nsec = req->phase.nsec;
|
||||
ns_start = timespec64_to_ns(&ts);
|
||||
} else {
|
||||
ns_start = 0;
|
||||
}
|
||||
|
||||
if (iep->ops && iep->ops->perout_enable) {
|
||||
ret = iep->ops->perout_enable(iep->clockops_data, req, on, &cmp);
|
||||
if (ret)
|
||||
|
|
@ -419,10 +435,12 @@ static int icss_iep_perout_enable_hw(struct icss_iep *iep,
|
|||
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_START_REG,
|
||||
div_u64(ns_start, iep->def_inc));
|
||||
regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG, 0); /* one-shot mode */
|
||||
/* Enable CMP 1 */
|
||||
regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG,
|
||||
|
|
@ -447,6 +465,10 @@ static int icss_iep_perout_enable_hw(struct icss_iep *iep,
|
|||
+ 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));
|
||||
regmap_write(iep->map, ICSS_IEP_SYNC_START_REG,
|
||||
div_u64(ns_start, 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);
|
||||
|
|
@ -474,7 +496,37 @@ static int icss_iep_perout_enable_hw(struct icss_iep *iep,
|
|||
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 |
|
||||
PTP_PEROUT_PHASE))
|
||||
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)
|
||||
|
|
@ -549,10 +601,13 @@ static int icss_iep_pps_enable(struct icss_iep *iep, int on)
|
|||
if (on) {
|
||||
ns = icss_iep_gettime(iep, NULL);
|
||||
ts = ns_to_timespec64(ns);
|
||||
rq.perout.flags = 0;
|
||||
rq.perout.period.sec = 1;
|
||||
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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user