Implement event capture for OMAP (draft)
Subsystems (2)
cover Implement event capture for OMAP (draft)
Hi,
this patchset based on next-20180223 first cleans up playground (patches 1-4 which I'd appreciate to be reviewed and merged eventually) and then adds event capture functionality which is just good for doing:
$ echo 0 > /sys/class/pwm/pwmchip4/export $ cat /sys/class/pwm/pwmchip4/pwm0/capture 1000000 500000 $ cat /sys/class/pwm/pwmchip4/pwm0/capture 100000 50000 $ cat /sys/class/pwm/pwmchip4/pwm0/capture 100000 75000
Above measured frequencies are 1kHz and 10kHz with 50% duty cycle, the last one is with 75% duty cycle. However with 100kHz it sometimes ends with:
$ cat /sys/class/pwm/pwmchip4/pwm0/capture omap_dm_timer_read_status: timer not available or enabled. 12462 6231
So locking is probably not done right, therefore patches 5 and 6 are sent only for reference, as there's also another fundamental problem:
Hardware can be told to capture both edges, but there's no way to tell it which one should be captured first. Other posibility would be first configure for rising edge and reconfigure in interrupt for falling one. Here we meet latency problem again:
https://www.spinics.net/lists/linux-omap/msg140081.html
Attached test patch shows average diff around 150us (sometimes over 300us) which pretty much limits maximum measurable frequency.
I tried to misuse PM_QOS_CPU_DMA_LATENCY to overcome latency issue, but with no luck.
Ladislav Michl (6):
clocksource: timer-ti-dm: Make unexported functions static
clocksource: timer-ti-dm: Consolidate set source
clocksource: timer-ti-dm: Check prescaler value
pwm: pwm-omap-dmtimer: Fix frequency when using prescaler
clocksource: timer-ti-dm: Add event capture
pwm: pwm-omap-dmtimer: Add capture functionality
drivers/clocksource/timer-ti-dm.c | 263 ++++++++++++++++------------- drivers/pwm/pwm-omap-dmtimer.c | 220 +++++++++++++++++++----- include/clocksource/timer-ti-dm.h | 33 ---- include/linux/platform_data/dmtimer-omap.h | 8 + 4 files changed, 340 insertions(+), 184 deletions(-)
Latency test patch:
drivers/pwm/pwm-omap-dmtimer.c +5 -1
@@ -46,7 +46,7 @@ struct pwm_omap_dmtimer_chip {const struct omap_dm_timer_ops *pdata;struct platform_device *dm_timer_pdev;unsigned long freq; -unsigned int ev_cnt, overflow, width; +unsigned int ev_cnt, overflow, width, counter_irq, counter_captured; }; static inline struct pwm_omap_dmtimer_chip *
@@ -280,6 +280,8 @@ static int pwm_omap_dmtimer_capture(struct pwm_chip *chip, omap->ev_cnt = omap->width =0 ;spin_unlock_irqrestore (&omap->lock, flags); +printk ("diff: %d\n" ,pwm_omap_dmtimer_ticks_to_ns (omap, omap->counter_irq - omap->counter_captured)); + res =wait_event_interruptible_timeout (omap->wait, omap->width >0 , timeout);
@@ -317,6 +319,8 @@ static irqreturn_t pwm_omap_dmtimer_irq(int irq, void *dev_id)if (l &OMAP_TIMER_INT_CAPTURE ) {if (!omap->width && omap->ev_cnt ==1 ) { omap->pdata->read_capture (omap->dm_timer, &c1, &c2); + omap->counter_irq = omap->pdata->read_counter (omap->dm_timer); + omap->counter_captured = c2; omap->width =pwm_omap_dmtimer_get_width (omap, c1, c2);wake_up (&omap->wait); }
Signature · 1 line
2.16.1
PATCH 1/6 clocksource: timer-ti-dm: Make unexported functions static
As dmtimer no longer exports functions, make those previously exported static (this requires few functions to be moved around as their prototypes were deleted).
--- drivers/clocksource/timer-ti-dm.c | 218 +++++++++++++++++++------------------- include/clocksource/timer-ti-dm.h | 33 ------ 2 files changed, 109 insertions(+), 142 deletions(-)
drivers/clocksource/timer-ti-dm.c +109 -109
@@ -163,6 +163,92 @@ static int omap_dm_timer_of_set_source(struct omap_dm_timer *timer)return ret; } +static int omap_dm_timer_set_source (struct omap_dm_timer *timer,int source) +{ +int ret; +char *parent_name =NULL ; +struct clk *parent; +struct dmtimer_platform_data *pdata; + +if (unlikely (!timer)) +return -EINVAL ; + + pdata = timer->pdev->dev.platform_data; + +if (source <0 || source >=3 ) +return -EINVAL ; + +/* +* FIXME: Used for OMAP1 devices only because they do not currently +* use the clock framework to set the parent clock. To be removed +* once OMAP1 migrated to using clock framework for dmtimers +*/ +if (pdata && pdata->set_timer_src) +return pdata->set_timer_src (timer->pdev, source); + +if (IS_ERR (timer->fclk)) +return -EINVAL ; + +#if defined(CONFIG_COMMON_CLK ) +/* Check if the clock has configurable parents */ +if (clk_hw_get_num_parents (__clk_get_hw (timer->fclk)) <2 ) +return 0 ; +#endif + +switch (source) { +case OMAP_TIMER_SRC_SYS_CLK : + parent_name ="timer_sys_ck" ; +break ; + +case OMAP_TIMER_SRC_32_KHZ : + parent_name ="timer_32k_ck" ; +break ; + +case OMAP_TIMER_SRC_EXT_CLK : + parent_name ="timer_ext_ck" ; +break ; + } + + parent =clk_get (&timer->pdev->dev, parent_name); +if (IS_ERR (parent)) { +pr_err ("%s: %s not found\n" , __func__, parent_name); +return -EINVAL ; + } + + ret =clk_set_parent (timer->fclk, parent); +if (ret <0 ) +pr_err ("%s: failed to set %s as parent\n" , __func__, + parent_name); + +clk_put (parent); + +return ret; +} + +static void omap_dm_timer_enable (struct omap_dm_timer *timer) +{ +int c; + +pm_runtime_get_sync (&timer->pdev->dev); + +if (!(timer->capability &OMAP_TIMER_ALWON )) { +if (timer->get_context_loss_count) { + c = timer->get_context_loss_count (&timer->pdev->dev); +if (c != timer->ctx_loss_count) { +omap_timer_restore_context (timer); + timer->ctx_loss_count = c; + } + }else { +omap_timer_restore_context (timer); + } + } +} + +static void omap_dm_timer_disable (struct omap_dm_timer *timer) +{ +pm_runtime_put_sync (&timer->pdev->dev); +} +static int omap_dm_timer_prepare (struct omap_dm_timer *timer) {int rc;
@@ -298,16 +384,16 @@ static struct omap_dm_timer *_omap_dm_timer_request(int req_type, void *data)return timer; } -struct omap_dm_timer *omap_dm_timer_request (void ) +static struct omap_dm_timer *omap_dm_timer_request (void ) {return _omap_dm_timer_request (REQUEST_ANY ,NULL ); } -struct omap_dm_timer *omap_dm_timer_request_specific (int id) +static struct omap_dm_timer *omap_dm_timer_request_specific (int id) {/* Requesting timer by ID is not supported when device tree is used */ if (of_have_populated_dt ()) { -pr_warn ("%s: Please use omap_dm_timer_request_by_cap/node()\n" , +pr_warn ("%s: Please use omap_dm_timer_request_by_node()\n" , __func__);return NULL ; }
@@ -336,7 +422,7 @@ struct omap_dm_timer *omap_dm_timer_request_by_cap(u32 cap)* Request a timer based upon a device node pointer. Returns pointer to * timer handle on success and a NULL pointer on failure. */ -struct omap_dm_timer *omap_dm_timer_request_by_node (struct device_node *np) +static struct omap_dm_timer *omap_dm_timer_request_by_node (struct device_node *np) {if (!np)return NULL ;
@@ -344,7 +430,7 @@ struct omap_dm_timer *omap_dm_timer_request_by_node(struct device_node *np)return _omap_dm_timer_request (REQUEST_BY_NODE , np); } -int omap_dm_timer_free (struct omap_dm_timer *timer) +static int omap_dm_timer_free (struct omap_dm_timer *timer) {if (unlikely (!timer))return -EINVAL ;
@@ -356,30 +442,6 @@ int omap_dm_timer_free(struct omap_dm_timer *timer)return 0 ; } -void omap_dm_timer_enable (struct omap_dm_timer *timer) -{ -int c; - -pm_runtime_get_sync (&timer->pdev->dev); - -if (!(timer->capability &OMAP_TIMER_ALWON )) { -if (timer->get_context_loss_count) { - c = timer->get_context_loss_count (&timer->pdev->dev); -if (c != timer->ctx_loss_count) { -omap_timer_restore_context (timer); - timer->ctx_loss_count = c; - } - }else { -omap_timer_restore_context (timer); - } - } -} - -void omap_dm_timer_disable (struct omap_dm_timer *timer) -{ -pm_runtime_put_sync (&timer->pdev->dev); -} -int omap_dm_timer_get_irq (struct omap_dm_timer *timer) {if (timer)
@@ -424,7 +486,7 @@ __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)#else -struct clk *omap_dm_timer_get_fclk (struct omap_dm_timer *timer) +static struct clk *omap_dm_timer_get_fclk (struct omap_dm_timer *timer) {if (timer && !IS_ERR (timer->fclk))return timer->fclk;
@@ -451,7 +513,7 @@ int omap_dm_timer_trigger(struct omap_dm_timer *timer)return 0 ; } -int omap_dm_timer_start (struct omap_dm_timer *timer) +static int omap_dm_timer_start (struct omap_dm_timer *timer) {u32 l;
@@ -471,7 +533,7 @@ int omap_dm_timer_start(struct omap_dm_timer *timer)return 0 ; } -int omap_dm_timer_stop (struct omap_dm_timer *timer) +static int omap_dm_timer_stop (struct omap_dm_timer *timer) {unsigned long rate =0 ;
@@ -494,70 +556,8 @@ int omap_dm_timer_stop(struct omap_dm_timer *timer)return 0 ; } -int omap_dm_timer_set_source (struct omap_dm_timer *timer,int source) -{ -int ret; -char *parent_name =NULL ; -struct clk *parent; -struct dmtimer_platform_data *pdata; - -if (unlikely (!timer)) -return -EINVAL ; - - pdata = timer->pdev->dev.platform_data; - -if (source <0 || source >=3 ) -return -EINVAL ; - -/* -* FIXME: Used for OMAP1 devices only because they do not currently -* use the clock framework to set the parent clock. To be removed -* once OMAP1 migrated to using clock framework for dmtimers -*/ -if (pdata && pdata->set_timer_src) -return pdata->set_timer_src (timer->pdev, source); - -if (IS_ERR (timer->fclk)) -return -EINVAL ; - -#if defined(CONFIG_COMMON_CLK ) -/* Check if the clock has configurable parents */ -if (clk_hw_get_num_parents (__clk_get_hw (timer->fclk)) <2 ) -return 0 ; -#endif - -switch (source) { -case OMAP_TIMER_SRC_SYS_CLK : - parent_name ="timer_sys_ck" ; -break ; - -case OMAP_TIMER_SRC_32_KHZ : - parent_name ="timer_32k_ck" ; -break ; - -case OMAP_TIMER_SRC_EXT_CLK : - parent_name ="timer_ext_ck" ; -break ; - } - - parent =clk_get (&timer->pdev->dev, parent_name); -if (IS_ERR (parent)) { -pr_err ("%s: %s not found\n" , __func__, parent_name); -return -EINVAL ; - } - - ret =clk_set_parent (timer->fclk, parent); -if (ret <0 ) -pr_err ("%s: failed to set %s as parent\n" , __func__, - parent_name); - -clk_put (parent); - -return ret; -} - -int omap_dm_timer_set_load (struct omap_dm_timer *timer,int autoreload, -unsigned int load) +static int omap_dm_timer_set_load (struct omap_dm_timer *timer,int autoreload, +unsigned int load) {u32 l;
@@ -609,9 +609,8 @@ int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload, timer->context.tcrr = load;return 0 ; } - -int omap_dm_timer_set_match (struct omap_dm_timer *timer,int enable, -unsigned int match) +static int omap_dm_timer_set_match (struct omap_dm_timer *timer,int enable, +unsigned int match) {u32 l;
@@ -634,8 +633,8 @@ int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,return 0 ; } -int omap_dm_timer_set_pwm (struct omap_dm_timer *timer,int def_on, -int toggle,int trigger) +static int omap_dm_timer_set_pwm (struct omap_dm_timer *timer,int def_on, +int toggle,int trigger) {u32 l;
@@ -659,7 +658,8 @@ int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,return 0 ; } -int omap_dm_timer_set_prescaler (struct omap_dm_timer *timer,int prescaler) +static int omap_dm_timer_set_prescaler (struct omap_dm_timer *timer, +int prescaler) {u32 l;
@@ -681,8 +681,8 @@ int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)return 0 ; } -int omap_dm_timer_set_int_enable (struct omap_dm_timer *timer, -unsigned int value) +static int omap_dm_timer_set_int_enable (struct omap_dm_timer *timer, +unsigned int value) {if (unlikely (!timer))return -EINVAL ;
@@ -704,7 +704,7 @@ int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,* * Disables the specified timer interrupts for a timer. */ -int omap_dm_timer_set_int_disable (struct omap_dm_timer *timer,u32 mask) +static int omap_dm_timer_set_int_disable (struct omap_dm_timer *timer,u32 mask) {u32 l = mask;
@@ -727,7 +727,7 @@ int omap_dm_timer_set_int_disable(struct omap_dm_timer *timer, u32 mask)return 0 ; } -unsigned int omap_dm_timer_read_status (struct omap_dm_timer *timer) +static unsigned int omap_dm_timer_read_status (struct omap_dm_timer *timer) {unsigned int l;
@@ -741,7 +741,7 @@ unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)return l; } -int omap_dm_timer_write_status (struct omap_dm_timer *timer,unsigned int value) +static int omap_dm_timer_write_status (struct omap_dm_timer *timer,unsigned int value) {if (unlikely (!timer ||pm_runtime_suspended (&timer->pdev->dev)))return -EINVAL ;
@@ -751,7 +751,7 @@ int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)return 0 ; } -unsigned int omap_dm_timer_read_counter (struct omap_dm_timer *timer) +static unsigned int omap_dm_timer_read_counter (struct omap_dm_timer *timer) {if (unlikely (!timer ||pm_runtime_suspended (&timer->pdev->dev))) {pr_err ("%s: timer not iavailable or enabled.\n" , __func__);
@@ -761,7 +761,7 @@ unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)return __omap_dm_timer_read_counter (timer, timer->posted); } -int omap_dm_timer_write_counter (struct omap_dm_timer *timer,unsigned int value) +static int omap_dm_timer_write_counter (struct omap_dm_timer *timer,unsigned int value) {if (unlikely (!timer ||pm_runtime_suspended (&timer->pdev->dev))) {pr_err ("%s: timer not available or enabled.\n" , __func__);
include/clocksource/timer-ti-dm.h +0 -33
@@ -119,46 +119,13 @@ struct omap_dm_timer { };int omap_dm_timer_reserve_systimer (int id); -struct omap_dm_timer *omap_dm_timer_request (void ); -struct omap_dm_timer *omap_dm_timer_request_specific (int timer_id);struct omap_dm_timer *omap_dm_timer_request_by_cap (u32 cap); -struct omap_dm_timer *omap_dm_timer_request_by_node (struct device_node *np); -int omap_dm_timer_free (struct omap_dm_timer *timer); -void omap_dm_timer_enable (struct omap_dm_timer *timer); -void omap_dm_timer_disable (struct omap_dm_timer *timer);int omap_dm_timer_get_irq (struct omap_dm_timer *timer);u32 omap_dm_timer_modify_idlect_mask (u32 inputmask); -#ifndef CONFIG_ARCH_OMAP1 -struct clk *omap_dm_timer_get_fclk (struct omap_dm_timer *timer); -#else -static inline -struct clk *omap_dm_timer_get_fclk (struct omap_dm_timer *timer) -{ -return NULL ; -} -#endif -int omap_dm_timer_trigger (struct omap_dm_timer *timer); -int omap_dm_timer_start (struct omap_dm_timer *timer); -int omap_dm_timer_stop (struct omap_dm_timer *timer); - -int omap_dm_timer_set_source (struct omap_dm_timer *timer,int source); -int omap_dm_timer_set_load (struct omap_dm_timer *timer,int autoreload,unsigned int value); -int omap_dm_timer_set_load_start (struct omap_dm_timer *timer,int autoreload,unsigned int value); -int omap_dm_timer_set_match (struct omap_dm_timer *timer,int enable,unsigned int match); -int omap_dm_timer_set_pwm (struct omap_dm_timer *timer,int def_on,int toggle,int trigger); -int omap_dm_timer_set_prescaler (struct omap_dm_timer *timer,int prescaler); - -int omap_dm_timer_set_int_enable (struct omap_dm_timer *timer,unsigned int value); -int omap_dm_timer_set_int_disable (struct omap_dm_timer *timer,u32 mask); - -unsigned int omap_dm_timer_read_status (struct omap_dm_timer *timer); -int omap_dm_timer_write_status (struct omap_dm_timer *timer,unsigned int value); -unsigned int omap_dm_timer_read_counter (struct omap_dm_timer *timer); -int omap_dm_timer_write_counter (struct omap_dm_timer *timer,unsigned int value);int omap_dm_timers_active (void );
Signature · 1 line
2.16.1
PATCH 2/6 clocksource: timer-ti-dm: Consolidate set source
In reply to Ladislav MichlReorder omap_dm_timer_set_source internals to get
source verification more straightforward.
--- drivers/clocksource/timer-ti-dm.c | 38 ++++++++++++++++---------------------- 1 file changed, 16 insertions(+), 22 deletions(-)
drivers/clocksource/timer-ti-dm.c +16 -22
@@ -166,17 +166,28 @@ static int omap_dm_timer_of_set_source(struct omap_dm_timer *timer)static int omap_dm_timer_set_source (struct omap_dm_timer *timer,int source) {int ret; -char *parent_name =NULL ; +const char *parent_name;struct clk *parent;struct dmtimer_platform_data *pdata; -if (unlikely (!timer)) +if (unlikely (!timer) ||IS_ERR (timer->fclk))return -EINVAL ; - pdata = timer->pdev->dev.platform_data; - -if (source <0 || source >=3 ) +switch (source) { +case OMAP_TIMER_SRC_SYS_CLK : + parent_name ="timer_sys_ck" ; +break ; +case OMAP_TIMER_SRC_32_KHZ : + parent_name ="timer_32k_ck" ; +break ; +case OMAP_TIMER_SRC_EXT_CLK : + parent_name ="timer_ext_ck" ; +break ; +default :return -EINVAL ; + } + + pdata = timer->pdev->dev.platform_data;/* * FIXME: Used for OMAP1 devices only because they do not currently
@@ -186,29 +197,12 @@ static int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)if (pdata && pdata->set_timer_src)return pdata->set_timer_src (timer->pdev, source); -if (IS_ERR (timer->fclk)) -return -EINVAL ; -#if defined(CONFIG_COMMON_CLK )/* Check if the clock has configurable parents */ if (clk_hw_get_num_parents (__clk_get_hw (timer->fclk)) <2 )return 0 ;#endif -switch (source) { -case OMAP_TIMER_SRC_SYS_CLK : - parent_name ="timer_sys_ck" ; -break ; - -case OMAP_TIMER_SRC_32_KHZ : - parent_name ="timer_32k_ck" ; -break ; - -case OMAP_TIMER_SRC_EXT_CLK : - parent_name ="timer_ext_ck" ; -break ; - } - parent =clk_get (&timer->pdev->dev, parent_name);if (IS_ERR (parent)) {pr_err ("%s: %s not found\n" , __func__, parent_name);
Signature · 1 line
2.16.1
PATCH 3/6 clocksource: timer-ti-dm: Check prescaler value
In reply to Ladislav MichlInvalid value silently disables use of the prescaler. Use -1 explicitely for that purpose and error out on invalid value.
--- drivers/clocksource/timer-ti-dm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/clocksource/timer-ti-dm.c +2 -2
@@ -657,13 +657,13 @@ static int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, {u32 l; -if (unlikely (!timer)) +if (unlikely (!timer) || prescaler <-1 || prescaler >7 )return -EINVAL ;omap_dm_timer_enable (timer); l =omap_dm_timer_read_reg (timer,OMAP_TIMER_CTRL_REG ); l &= ~(OMAP_TIMER_CTRL_PRE | (0x07 <<2 )); -if (prescaler >=0x00 && prescaler <=0x07 ) { +if (prescaler >=0 ) { l |=OMAP_TIMER_CTRL_PRE ; l |= prescaler <<2 ; }
Signature · 1 line
2.16.1
PATCH 4/6 pwm: pwm-omap-dmtimer: Fix frequency when using prescaler
In reply to Ladislav MichlPrescaler setting is currently not taken into account. Fix that by introducing freq member variable and initialize it at device probe time. This also avoids frequency recomputing at each pwm configure time.
--- drivers/pwm/pwm-omap-dmtimer.c | 93 +++++++++++++++++++++++++----------------- 1 file changed, 55 insertions(+), 38 deletions(-)
drivers/pwm/pwm-omap-dmtimer.c +55 -38
@@ -40,6 +40,7 @@ struct pwm_omap_dmtimer_chip {pwm_omap_dmtimer *dm_timer;const struct omap_dm_timer_ops *pdata;struct platform_device *dm_timer_pdev; +unsigned long freq; }; static inline struct pwm_omap_dmtimer_chip *
@@ -48,9 +49,10 @@ to_pwm_omap_dmtimer_chip(struct pwm_chip *chip) return container_of(chip, struct pwm_omap_dmtimer_chip, chip); } -static u32 pwm_omap_dmtimer_get_clock_cycles (unsigned long clk_rate,int ns) +static inline u32 +pwm_omap_dmtimer_get_clock_cycles (struct pwm_omap_dmtimer_chip *omap,int ns) { -return DIV_ROUND_CLOSEST_ULL ((u64 )clk_rate * ns,NSEC_PER_SEC ); +return DIV_ROUND_CLOSEST_ULL ((u64 )omap->freq * ns,NSEC_PER_SEC ); }static void pwm_omap_dmtimer_start (struct pwm_omap_dmtimer_chip *omap)
@@ -99,8 +101,6 @@ static int pwm_omap_dmtimer_config(struct pwm_chip *chip,struct pwm_omap_dmtimer_chip *omap =to_pwm_omap_dmtimer_chip (chip);u32 period_cycles, duty_cycles;u32 load_value, match_value; -struct clk *fclk; -unsigned long clk_rate;bool timer_active; dev_dbg(chip->dev, "requested duty cycle: %d ns, period: %d ns\n",
@@ -114,19 +114,6 @@ static int pwm_omap_dmtimer_config(struct pwm_chip *chip,return 0 ; } - fclk = omap->pdata->get_fclk (omap->dm_timer); -if (!fclk) { -dev_err (chip->dev,"invalid pmtimer fclk\n" ); - goto err_einval; - } - - clk_rate =clk_get_rate (fclk); -if (!clk_rate) { -dev_err (chip->dev,"invalid pmtimer fclk rate\n" ); - goto err_einval; - } - -dev_dbg (chip->dev,"clk rate: %luHz\n" , clk_rate);/* * Calculate the appropriate load and match values based on the
@@ -144,35 +131,35 @@ static int pwm_omap_dmtimer_config(struct pwm_chip *chip,* OMAP4430/60/70 TRM sections 22.2.4.10 and 22.2.4.11 * AM335x Sitara TRM sections 20.1.3.5 and 20.1.3.6 */ - period_cycles =pwm_omap_dmtimer_get_clock_cycles (clk_rate, period_ns); - duty_cycles =pwm_omap_dmtimer_get_clock_cycles (clk_rate, duty_ns); + period_cycles =pwm_omap_dmtimer_get_clock_cycles (omap, period_ns); + duty_cycles =pwm_omap_dmtimer_get_clock_cycles (omap, duty_ns);if (period_cycles <2 ) {dev_info (chip->dev,"period %d ns too short for clock rate %lu Hz\n" , - period_ns, clk_rate); + period_ns, omap->freq); goto err_einval; }if (duty_cycles <1 ) {dev_dbg (chip->dev,"duty cycle %d ns is too short for clock rate %lu Hz\n" , - duty_ns, clk_rate); + duty_ns, omap->freq);dev_dbg (chip->dev,"using minimum of 1 clock cycle\n" ); duty_cycles =1 ; }else if (duty_cycles >= period_cycles) {dev_dbg (chip->dev,"duty cycle %d ns is too long for period %d ns at clock rate %lu Hz\n" , - duty_ns, period_ns, clk_rate); + duty_ns, period_ns, omap->freq);dev_dbg (chip->dev,"using maximum of 1 clock cycle less than period\n" ); duty_cycles = period_cycles -1 ; }dev_dbg (chip->dev,"effective duty cycle: %lld ns, period: %lld ns\n" ,DIV_ROUND_CLOSEST_ULL ((u64 )NSEC_PER_SEC * duty_cycles, - clk_rate), + omap->freq),DIV_ROUND_CLOSEST_ULL ((u64 )NSEC_PER_SEC * period_cycles, - clk_rate)); + omap->freq)); load_value = (DM_TIMER_MAX - period_cycles) +1 ; match_value = load_value + duty_cycles -1 ;
@@ -248,6 +235,7 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev)struct dmtimer_platform_data *timer_pdata;const struct omap_dm_timer_ops *pdata;pwm_omap_dmtimer *dm_timer; +struct clk *fclk;u32 v;int ret =0 ;
@@ -295,10 +283,8 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev) } dm_timer = pdata->request_by_node (timer); -if (!dm_timer) { +if (!dm_timer) ret = -EPROBE_DEFER ; - goto put; - } put:of_node_put (timer);
@@ -307,8 +293,8 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev) omap =devm_kzalloc (&pdev->dev,sizeof (*omap),GFP_KERNEL );if (!omap) { - pdata->free (dm_timer); -return -ENOMEM ; + ret = -ENOMEM ; + goto free_dm_timer; } omap->pdata = pdata;
@@ -319,15 +305,42 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev)* Ensure that the timer is stopped before we allow PWM core to call * pwm_enable. */ -if (pm_runtime_active (&omap->dm_timer_pdev->dev)) - omap->pdata->stop (omap->dm_timer); - -if (!of_property_read_u32 (pdev->dev.of_node,"ti,prescaler" , &v)) - omap->pdata->set_prescaler (omap->dm_timer, v); +if (pm_runtime_active (&timer_pdev->dev)) + pdata->stop (dm_timer);/* setup dmtimer clock source */ -if (!of_property_read_u32 (pdev->dev.of_node,"ti,clock-source" , &v)) - omap->pdata->set_source (omap->dm_timer, v); +if (!of_property_read_u32 (pdev->dev.of_node,"ti,clock-source" , &v)) { + ret = pdata->set_source (dm_timer, v); +if (ret) { +dev_err (&pdev->dev,"invalid clock-source\n" ); + goto free_dm_timer; + } + } + + fclk = pdata->get_fclk (dm_timer); +if (!fclk) { +dev_err (&pdev->dev,"invalid fclk\n" ); + ret = -EINVAL ; + goto free_dm_timer; + } + + omap->freq =clk_get_rate (fclk); +if (!omap->freq) { +dev_err (&pdev->dev,"invalid fclk rate\n" ); + ret = -EINVAL ; + goto free_dm_timer; + } + +if (!of_property_read_u32 (pdev->dev.of_node,"ti,prescaler" , &v)) { + ret = pdata->set_prescaler (dm_timer, v); +if (ret) { +dev_err (&pdev->dev,"invalid prescaler\n" ); + goto free_dm_timer; + } + omap->freq >>= v +1 ; + } + +dev_dbg (&pdev->dev,"clk rate: %luHz\n" , omap->freq); omap->chip.dev = &pdev->dev; omap->chip.ops = &pwm_omap_dmtimer_ops;
@@ -341,13 +354,17 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev) ret =pwmchip_add (&omap->chip);if (ret <0 ) {dev_err (&pdev->dev,"failed to register PWM\n" ); - omap->pdata->free (omap->dm_timer); -return ret; + goto free_dm_timer; }platform_set_drvdata (pdev, omap);return 0 ; + +free_dm_timer: + pdata->free (dm_timer); + +return ret; }static int pwm_omap_dmtimer_remove (struct platform_device *pdev)
Signature · 1 line
2.16.1
PATCH 5/6 clocksource: timer-ti-dm: Add event capture
In reply to Ladislav MichlImplement event capture functions.
--- drivers/clocksource/timer-ti-dm.c | 47 ++++++++++++++++++++++++++++-- include/linux/platform_data/dmtimer-omap.h | 8 +++++ 2 files changed, 53 insertions(+), 2 deletions(-)
drivers/clocksource/timer-ti-dm.c +45 -2
@@ -576,8 +576,8 @@ static int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload, }/* Optimized set_load which removes costly spin wait in timer_start */ -int omap_dm_timer_set_load_start (struct omap_dm_timer *timer,int autoreload, -unsigned int load) +static int omap_dm_timer_set_load_start (struct omap_dm_timer *timer, +int autoreload,unsigned int load) {u32 l;
@@ -627,6 +627,30 @@ static int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,return 0 ; } +static int omap_dm_timer_set_capture (struct omap_dm_timer *timer, +int captmode,int edges) +{ +u32 l; + +if (unlikely (!timer)) +return -EINVAL ; + +omap_dm_timer_enable (timer); + l =omap_dm_timer_read_reg (timer,OMAP_TIMER_CTRL_REG ); + l &= ~(OMAP_TIMER_CTRL_CAPTMODE |OMAP_TIMER_CTRL_SCPWM | +OMAP_TIMER_CTRL_PT |OMAP_TIMER_CTRL_TCM_BOTHEDGES ); + l |=OMAP_TIMER_CTRL_GPOCFG ; +if (captmode) + l |=OMAP_TIMER_CTRL_CAPTMODE ; + l |= edges <<8 ; +omap_dm_timer_write_reg (timer,OMAP_TIMER_CTRL_REG , l); + +/* Save the context */ + timer->context.tclr = l; +omap_dm_timer_disable (timer); +return 0 ; +} +static int omap_dm_timer_set_pwm (struct omap_dm_timer *timer,int def_on,int toggle,int trigger) {
@@ -785,6 +809,22 @@ int omap_dm_timers_active(void)return 0 ; } +static int omap_dm_timer_read_capture (struct omap_dm_timer *timer, +unsigned int *reg, +unsigned int *reg2) +{ +if (unlikely (!timer ||pm_runtime_suspended (&timer->pdev->dev))) { +pr_err ("%s: timer not available or enabled.\n" , __func__); +return -EINVAL ; + } + + *reg =omap_dm_timer_read_reg (timer,OMAP_TIMER_CAPTURE_REG ); +if (reg2) + *reg2 =omap_dm_timer_read_reg (timer,OMAP_TIMER_CAPTURE2_REG ); + +return 0 ; +} +static const struct of_device_id omap_timer_match[];/**
@@ -930,11 +970,14 @@ const static struct omap_dm_timer_ops dmtimer_ops = { .start = omap_dm_timer_start, .stop = omap_dm_timer_stop, .set_load = omap_dm_timer_set_load, + .set_load_start = omap_dm_timer_set_load_start, .set_match = omap_dm_timer_set_match, + .set_capture = omap_dm_timer_set_capture, .set_pwm = omap_dm_timer_set_pwm, .set_prescaler = omap_dm_timer_set_prescaler, .read_counter = omap_dm_timer_read_counter, .write_counter = omap_dm_timer_write_counter, + .read_capture = omap_dm_timer_read_capture, .read_status = omap_dm_timer_read_status, .write_status = omap_dm_timer_write_status, };
include/linux/platform_data/dmtimer-omap.h +8 -0
@@ -43,8 +43,12 @@ struct omap_dm_timer_ops {int (*set_load)(struct omap_dm_timer *timer,int autoreload,unsigned int value); +int (*set_load_start)(struct omap_dm_timer *timer,int autoreload, +unsigned int value);int (*set_match)(struct omap_dm_timer *timer,int enable,unsigned int match); +int (*set_capture)(struct omap_dm_timer *timer,int captmode, +int edges);int (*set_pwm)(struct omap_dm_timer *timer,int def_on,int toggle,int trigger);int (*set_prescaler)(struct omap_dm_timer *timer,int prescaler);
@@ -52,6 +56,10 @@ struct omap_dm_timer_ops {unsigned int (*read_counter)(struct omap_dm_timer *timer);int (*write_counter)(struct omap_dm_timer *timer,unsigned int value); + +int (*read_capture)(struct omap_dm_timer *timer,unsigned int *reg, +unsigned int *reg2); +unsigned int (*read_status)(struct omap_dm_timer *timer);int (*write_status)(struct omap_dm_timer *timer,unsigned int value);
Signature · 1 line
2.16.1
PATCH 6/6 pwm: pwm-omap-dmtimer: Add capture functionality
In reply to Ladislav MichlImplement event capture.
---
Note: Please see cover letter
drivers/pwm/pwm-omap-dmtimer.c | 127 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+)
drivers/pwm/pwm-omap-dmtimer.c +127 -0
@@ -16,8 +16,10 @@* PWM driver / controller, using the OMAP's dual-mode timers. */ +#include <clocksource/timer-ti-dm.h> #include <linux/clk.h> #include <linux/err.h> +#include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/mutex.h>
@@ -30,17 +32,21 @@#include <linux/pwm.h> #include <linux/slab.h> #include <linux/time.h> +#include <linux/wait.h> #define DM_TIMER_LOAD_MIN 0xfffffffe#define DM_TIMER_MAX 0xffffffffstruct pwm_omap_dmtimer_chip {struct pwm_chip chip; +spinlock_t lock;struct mutex mutex; +wait_queue_head_t wait;pwm_omap_dmtimer *dm_timer;const struct omap_dm_timer_ops *pdata;struct platform_device *dm_timer_pdev;unsigned long freq; +unsigned int ev_cnt, overflow, width; }; static inline struct pwm_omap_dmtimer_chip *
@@ -55,6 +61,22 @@ pwm_omap_dmtimer_get_clock_cycles(struct pwm_omap_dmtimer_chip *omap, int ns)return DIV_ROUND_CLOSEST_ULL ((u64 )omap->freq * ns,NSEC_PER_SEC ); } +static inline unsigned int +pwm_omap_dmtimer_ticks_to_ns (struct pwm_omap_dmtimer_chip *omap, +unsigned int ticks) +{ +return DIV_ROUND_CLOSEST_ULL ((u64 )ticks *NSEC_PER_SEC , omap->freq); +} + +static unsigned int pwm_omap_dmtimer_get_width (struct pwm_omap_dmtimer_chip *omap, +unsigned int c1,unsigned int c2) +{ +if (c1 <= c2) +return c2 - c1; + +return (c2 - omap->overflow) + (DM_TIMER_MAX - c1); +} +static void pwm_omap_dmtimer_start (struct pwm_omap_dmtimer_chip *omap) {/*
@@ -218,7 +240,101 @@ static int pwm_omap_dmtimer_set_polarity(struct pwm_chip *chip,return 0 ; } +static int pwm_omap_dmtimer_capture (struct pwm_chip *chip, +struct pwm_device *pwm, +struct pwm_capture *result, +unsigned long timeout) + +{ +int res; +unsigned long flags; +struct pwm_omap_dmtimer_chip *omap =to_pwm_omap_dmtimer_chip (chip); + +mutex_lock (&omap->mutex); + +if (pm_runtime_active (&omap->dm_timer_pdev->dev)) + omap->pdata->stop (omap->dm_timer); + +/* Let timer overflow every 1 second */ + omap->overflow =DM_TIMER_MAX - (1 * omap->freq); + timeout =msecs_to_jiffies (timeout); + result->period = result->duty_cycle =0 ; + +spin_lock_irqsave (&omap->lock, flags); + omap->pdata->set_int_enable (omap->dm_timer,OMAP_TIMER_INT_CAPTURE | +OMAP_TIMER_INT_OVERFLOW ); + omap->pdata->set_capture (omap->dm_timer,1 ,1 ); + omap->pdata->set_load_start (omap->dm_timer, true, omap->overflow); + omap->ev_cnt = omap->width =0 ; +spin_unlock_irqrestore (&omap->lock, flags); + + res =wait_event_interruptible_timeout (omap->wait, + omap->width >0 , timeout); +if (res >0 ) { +spin_lock_irqsave (&omap->lock, flags); + result->period = +pwm_omap_dmtimer_ticks_to_ns (omap, omap->width); + omap->pdata->stop (omap->dm_timer); + omap->pdata->set_capture (omap->dm_timer,1 ,3 ); + omap->pdata->start (omap->dm_timer); + omap->ev_cnt = omap->width =0 ; +spin_unlock_irqrestore (&omap->lock, flags); + + res =wait_event_interruptible_timeout (omap->wait, + omap->width >0 , + timeout); + } + +spin_lock_irqsave (&omap->lock, flags); + omap->pdata->stop (omap->dm_timer); + omap->pdata->set_int_disable (omap->dm_timer,OMAP_TIMER_INT_CAPTURE | +OMAP_TIMER_INT_OVERFLOW ); +spin_unlock_irqrestore (&omap->lock, flags); + +if (res ==0 ) { + res = -ETIMEDOUT ; + }else if (res >0 ) { + result->duty_cycle = +pwm_omap_dmtimer_ticks_to_ns (omap, omap->width); + res =0 ; + } + +mutex_unlock (&omap->mutex); + +return res; +} + +static irqreturn_t pwm_omap_dmtimer_irq (int irq,void *dev_id) +{ +u32 l; +unsigned int c1, c2; +unsigned long flags; +struct pwm_omap_dmtimer_chip *omap = dev_id; + +spin_lock_irqsave (&omap->lock, flags); + + l = omap->pdata->read_status (omap->dm_timer); +if (l &OMAP_TIMER_INT_CAPTURE ) { +if (!omap->width && omap->ev_cnt ==1 ) { + omap->pdata->read_capture (omap->dm_timer, &c1, &c2); + omap->width =pwm_omap_dmtimer_get_width (omap, c1, c2); +wake_up (&omap->wait); + } + omap->ev_cnt++; + } +/* TODO: handle overflow as well +if (l & OMAP_TIMER_INT_OVERFLOW) +overflow++; +*/ + omap->pdata->write_status (omap->dm_timer, l); + +spin_unlock_irqrestore (&omap->lock, flags); + +return IRQ_HANDLED ; +} +static const struct pwm_ops pwm_omap_dmtimer_ops = { + .capture = pwm_omap_dmtimer_capture, .enable = pwm_omap_dmtimer_enable, .disable = pwm_omap_dmtimer_disable, .config = pwm_omap_dmtimer_config,
@@ -349,7 +465,18 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev) omap->chip.of_xlate = of_pwm_xlate_with_flags; omap->chip.of_pwm_n_cells =3 ; +spin_lock_init (&omap->lock);mutex_init (&omap->mutex); +init_waitqueue_head (&omap->wait); + + ret = omap->pdata->get_irq (omap->dm_timer); +if (ret <0 ) + goto free_dm_timer; + + ret =devm_request_irq (&pdev->dev, ret, pwm_omap_dmtimer_irq,0 , +"event_capture" , omap); +if (ret) + goto free_dm_timer; ret =pwmchip_add (&omap->chip);if (ret <0 ) {
Signature · 1 line
2.16.1
PATCH 1/6 clocksource: timer-ti-dm: Make unexported functions static
In reply to Ladislav MichlQuoted 3 lines · Ladislav Michl
As dmtimer no longer exports functions, make those previously exported static (this requires few functions to be moved around as their prototypes were deleted).
Looks like this one fails to build with omap1_defconfig:
drivers/clocksource/timer-ti-dm.c:935:14: error:
'omap_dm_timer_get_fclk' undeclared here
Other than that the first three patches seem like nice clean-up :)
Regards,
Tony
PATCH 1/6 clocksource: timer-ti-dm: Make unexported functions static
Quoted 9 lines · Tony Lindgren
Quoted 3 lines · Ladislav Michl
As dmtimer no longer exports functions, make those previously exported static (this requires few functions to be moved around as their prototypes were deleted).
Looks like this one fails to build with
omap1_defconfig:
drivers/clocksource/timer-ti-dm.c:935:14: error:
'omap_dm_timer_get_fclk' undeclared here
Umm, it compiled fine on top of previous versions, so I didn't bother to retest. I'm sorry about it.
Quoted 2 lines
Other than that the first three patches seem like nice clean-up :)
So are you okay with sending those separately as cleanup with above issue fixed?
But to be honest, I'm more interested how to do the last two patches right ;-)
Quoted 3 lines
Regards,
Tony
PATCH 1/6 clocksource: timer-ti-dm: Make unexported functions static
Quoted 11 lines · Ladislav Michl
Quoted 9 lines · Tony Lindgren
Quoted 3 lines · Ladislav Michl
As dmtimer no longer exports functions, make those previously exported static (this requires few functions to be moved around as their prototypes were deleted).
Looks like this one fails to build with
omap1_defconfig:
drivers/clocksource/timer-ti-dm.c:935:14: error:
'omap_dm_timer_get_fclk' undeclared here
Quoted 8 lines
Umm, it compiled fine on top of previous versions, so I didn't bother to retest. I'm sorry about it.
Quoted 2 lines
Other than that the first three patches seem like nice clean-up :)
So are you okay with sending those separately as cleanup with above issue fixed?
Yeah seems like those first three are suitable for applying on top of the patches in omap-for-v4.17/timer :)
Quoted 2 lines
But to be honest, I'm more interested how to do the last two patches right ;-)
Yeah well if patch 4 can be sent separately as a fix, then send that separately to Thierry?
Then you're just left with the pending pwm changes that still need work it seems.
Regards,
Tony
PATCH 1/6 clocksource: timer-ti-dm: Make unexported functions static
Quoted 15 lines · Tony Lindgren
Quoted 14 lines · Ladislav Michl
Quoted 9 lines · Tony Lindgren
Quoted 3 lines · Ladislav Michl
As dmtimer no longer exports functions, make those previously exported static (this requires few functions to be moved around as their prototypes were deleted).
Looks like this one fails to build with
omap1_defconfig:
drivers/clocksource/timer-ti-dm.c:935:14: error:
'omap_dm_timer_get_fclk' undeclared hereUmm, it compiled fine on top of previous versions, so I didn't bother to retest. I'm sorry about it.
Quoted 8 lines
Quoted 5 lines
Quoted 2 lines
Other than that the first three patches seem like nice clean-up :)
So are you okay with sending those separately as cleanup with above issue fixed?
Yeah seems like those first three are suitable for applying on top of the patches in omap-for-v4.17/timer :)
I've now applied your v2 of patch 1 and patches 2 and 3 of this series into omap-for-v4.17/timer.
Thanks,
Tony
Thierry Reding
AppliedPATCH 4/6 pwm: pwm-omap-dmtimer: Fix frequency when using prescaler
In reply to Ladislav MichlQuoted 9 lines · Ladislav Michl
Prescaler setting is currently not taken into account. Fix that by introducing freq member variable and initialize it at device probe time. This also avoids frequency recomputing at each pwm configure time.
Signed-off-by Ladislav Michl <[email protected]>--- drivers/pwm/pwm-omap-dmtimer.c | 93 +++++++++++++++++++++++++----------------- 1 file changed, 55 insertions(+), 38 deletions(-)
Applied, thanks.
Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180327/ab6ece91/attachment.sig>
PATCH 4/6 pwm: pwm-omap-dmtimer: Fix frequency when using prescaler
Quoted 6 lines · Thierry Reding
Quoted 5 lines · Ladislav Michl
Prescaler setting is currently not taken into account. Fix that by introducing freq member variable and initialize it at device probe time. This also avoids frequency recomputing at each pwm configure time.
Quoted 6 lines
Quoted 4 lines
Signed-off-by Ladislav Michl <[email protected]>--- drivers/pwm/pwm-omap-dmtimer.c | 93 +++++++++++++++++++++++++----------------- 1 file changed, 55 insertions(+), 38 deletions(-)Applied, thanks.
Actually, that was a little premature. It seems like this conflicts with a patch series by Keerthy that Tony merged into his tree and that you've based this on.
I think it'd be easiest if Tony merged this through the TI tree, or we wait until v4.17-rc1 to resolve the dependency. Given how late we are in the release cycle, I think it'd have to be the latter.
Tony, if you think you can find a way to still take this in for v4.17-rc1, feel free to do so:
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180328/c2b783c6/attachment.sig>
PATCH 4/6 pwm: pwm-omap-dmtimer: Fix frequency when using prescaler
Quoted 14 lines · Thierry Reding
Quoted 6 lines · Thierry Reding
Quoted 5 lines · Ladislav Michl
Prescaler setting is currently not taken into account. Fix that by introducing freq member variable and initialize it at device probe time. This also avoids frequency recomputing at each pwm configure time.
Quoted 6 lines
Quoted 4 lines
Signed-off-by Ladislav Michl <[email protected]>--- drivers/pwm/pwm-omap-dmtimer.c | 93 +++++++++++++++++++++++++----------------- 1 file changed, 55 insertions(+), 38 deletions(-)Applied, thanks.
Quoted 7 lines
Actually, that was a little premature. It seems like this conflicts with a patch series by Keerthy that Tony merged into his tree and that you've based this on.
I think it'd be easiest if Tony merged this through the TI tree, or we wait until v4.17-rc1 to resolve the dependency. Given how late we are in the release cycle, I think it'd have to be the latter.
Sorry about the extra hassle caused by the timer move to drivers.
Quoted 4 lines
Tony, if you think you can find a way to still take this in for v4.17-rc1, feel free to do so:
Acked-by Thierry Reding <[email protected]>
I pretty much only apply fixes after -rc6. So let's wait for the dependencies to clear at this point. This seems like a "fix for a feature that never worked" so might be hard to justify it as a fix :)
Ladis, can you please resend the pending patches again to Thierry after v4.17-rc? Then Thierry can queue it as a fix or for v4.18.
Regards,
Tony
PATCH 4/6 pwm: pwm-omap-dmtimer: Fix frequency when using prescaler
Quoted 28 lines · Tony Lindgren
Quoted 14 lines · Thierry Reding
Quoted 6 lines · Thierry Reding
Quoted 5 lines · Ladislav Michl
Prescaler setting is currently not taken into account. Fix that by introducing freq member variable and initialize it at device probe time. This also avoids frequency recomputing at each pwm configure time.
Quoted 6 lines
Quoted 4 lines
Signed-off-by Ladislav Michl <[email protected]>--- drivers/pwm/pwm-omap-dmtimer.c | 93 +++++++++++++++++++++++++----------------- 1 file changed, 55 insertions(+), 38 deletions(-)Applied, thanks.
Quoted 7 lines
Actually, that was a little premature. It seems like this conflicts with a patch series by Keerthy that Tony merged into his tree and that you've based this on.
I think it'd be easiest if Tony merged this through the TI tree, or we wait until v4.17-rc1 to resolve the dependency. Given how late we are in the release cycle, I think it'd have to be the latter.
Sorry about the extra hassle caused by the timer move to drivers.
Quoted 3 lines
Tony, if you think you can find a way to still take this in for v4.17-rc1, feel free to do so:
Quoted 6 lines
Quoted 1 line
Acked-by Thierry Reding <[email protected]>I pretty much only apply fixes after -rc6. So let's wait for the dependencies to clear at this point. This seems like a "fix for a feature that never worked" so might be hard to justify it as a fix :)
Well, DT bindings already contain prescaler, so technically it is a fix which also optimizes code a bit ;-) But of course, I can keep this patch localy and resend for 4.18 merge window.
Quoted 3 lines
Ladis, can you please resend the pending patches again to Thierry after v4.17-rc? Then Thierry can queue it as a fix or for v4.18.
In fact, there is the only one patch ready to be applied - this one - and The others (event capture) needs to be yet sorted out. Unfortunately I do not have time for that at the moment.
Best regards,
ladis