Loading drivers/clocksource/timer-ti-dm.c +109 −74 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0+ /* * linux/arch/arm/plat-omap/dmtimer.c * Loading @@ -15,28 +16,11 @@ * * Copyright (C) 2009 Texas Instruments * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <linux/clk.h> #include <linux/clk-provider.h> #include <linux/cpu_pm.h> #include <linux/module.h> #include <linux/io.h> #include <linux/device.h> Loading Loading @@ -109,6 +93,47 @@ static void omap_timer_restore_context(struct omap_dm_timer *timer) timer->context.tclr); } static void omap_timer_save_context(struct omap_dm_timer *timer) { timer->context.tclr = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); timer->context.twer = omap_dm_timer_read_reg(timer, OMAP_TIMER_WAKEUP_EN_REG); timer->context.tldr = omap_dm_timer_read_reg(timer, OMAP_TIMER_LOAD_REG); timer->context.tmar = omap_dm_timer_read_reg(timer, OMAP_TIMER_MATCH_REG); timer->context.tier = readl_relaxed(timer->irq_ena); timer->context.tsicr = omap_dm_timer_read_reg(timer, OMAP_TIMER_IF_CTRL_REG); } static int omap_timer_context_notifier(struct notifier_block *nb, unsigned long cmd, void *v) { struct omap_dm_timer *timer; timer = container_of(nb, struct omap_dm_timer, nb); switch (cmd) { case CPU_CLUSTER_PM_ENTER: if ((timer->capability & OMAP_TIMER_ALWON) || !atomic_read(&timer->enabled)) break; omap_timer_save_context(timer); break; case CPU_CLUSTER_PM_ENTER_FAILED: case CPU_CLUSTER_PM_EXIT: if ((timer->capability & OMAP_TIMER_ALWON) || !atomic_read(&timer->enabled)) break; omap_timer_restore_context(timer); break; } return NOTIFY_OK; } static int omap_dm_timer_reset(struct omap_dm_timer *timer) { u32 l, timeout = 100000; Loading Loading @@ -196,21 +221,7 @@ static int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) 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) Loading Loading @@ -477,7 +488,7 @@ __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask) int omap_dm_timer_trigger(struct omap_dm_timer *timer) { if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) { if (unlikely(!timer || !atomic_read(&timer->enabled))) { pr_err("%s: timer not available or enabled.\n", __func__); return -EINVAL; } Loading @@ -501,8 +512,6 @@ static int omap_dm_timer_start(struct omap_dm_timer *timer) omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); } /* Save the context */ timer->context.tclr = l; return 0; } Loading @@ -518,37 +527,19 @@ static int omap_dm_timer_stop(struct omap_dm_timer *timer) __omap_dm_timer_stop(timer, timer->posted, rate); /* * Since the register values are computed and written within * __omap_dm_timer_stop, we need to use read to retrieve the * context. */ timer->context.tclr = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); omap_dm_timer_disable(timer); return 0; } static int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload, static int omap_dm_timer_set_load(struct omap_dm_timer *timer, unsigned int load) { u32 l; if (unlikely(!timer)) return -EINVAL; omap_dm_timer_enable(timer); l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); if (autoreload) l |= OMAP_TIMER_CTRL_AR; else l &= ~OMAP_TIMER_CTRL_AR; omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load); /* Save the context */ timer->context.tclr = l; timer->context.tldr = load; omap_dm_timer_disable(timer); return 0; } Loading @@ -570,15 +561,12 @@ static int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match); omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); /* Save the context */ timer->context.tclr = l; timer->context.tmar = match; 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) int toggle, int trigger, int autoreload) { u32 l; Loading @@ -588,20 +576,34 @@ static int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, omap_dm_timer_enable(timer); l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM | OMAP_TIMER_CTRL_PT | (0x03 << 10)); OMAP_TIMER_CTRL_PT | (0x03 << 10) | OMAP_TIMER_CTRL_AR); if (def_on) l |= OMAP_TIMER_CTRL_SCPWM; if (toggle) l |= OMAP_TIMER_CTRL_PT; l |= trigger << 10; if (autoreload) l |= OMAP_TIMER_CTRL_AR; 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_get_pwm_status(struct omap_dm_timer *timer) { u32 l; if (unlikely(!timer)) return -EINVAL; omap_dm_timer_enable(timer); l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); omap_dm_timer_disable(timer); return l; } static int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler) { Loading @@ -619,8 +621,6 @@ static int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, } 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; } Loading @@ -634,9 +634,6 @@ static int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, omap_dm_timer_enable(timer); __omap_dm_timer_int_enable(timer, value); /* Save the context */ timer->context.tier = value; timer->context.twer = value; omap_dm_timer_disable(timer); return 0; } Loading Loading @@ -664,9 +661,6 @@ static int omap_dm_timer_set_int_disable(struct omap_dm_timer *timer, u32 mask) l = omap_dm_timer_read_reg(timer, OMAP_TIMER_WAKEUP_EN_REG) & ~mask; omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, l); /* Save the context */ timer->context.tier &= ~mask; timer->context.twer &= ~mask; omap_dm_timer_disable(timer); return 0; } Loading @@ -675,7 +669,7 @@ static unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer) { unsigned int l; if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) { if (unlikely(!timer || !atomic_read(&timer->enabled))) { pr_err("%s: timer not available or enabled.\n", __func__); return 0; } Loading @@ -687,7 +681,7 @@ static unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer) static int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value) { if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) if (unlikely(!timer || !atomic_read(&timer->enabled))) return -EINVAL; __omap_dm_timer_write_status(timer, value); Loading @@ -697,7 +691,7 @@ static int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int static unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer) { if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) { if (unlikely(!timer || !atomic_read(&timer->enabled))) { pr_err("%s: timer not iavailable or enabled.\n", __func__); return 0; } Loading @@ -707,7 +701,7 @@ static unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer) static int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value) { if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) { if (unlikely(!timer || !atomic_read(&timer->enabled))) { pr_err("%s: timer not available or enabled.\n", __func__); return -EINVAL; } Loading Loading @@ -735,6 +729,37 @@ int omap_dm_timers_active(void) return 0; } static int __maybe_unused omap_dm_timer_runtime_suspend(struct device *dev) { struct omap_dm_timer *timer = dev_get_drvdata(dev); atomic_set(&timer->enabled, 0); if (timer->capability & OMAP_TIMER_ALWON || !timer->func_base) return 0; omap_timer_save_context(timer); return 0; } static int __maybe_unused omap_dm_timer_runtime_resume(struct device *dev) { struct omap_dm_timer *timer = dev_get_drvdata(dev); if (!(timer->capability & OMAP_TIMER_ALWON) && timer->func_base) omap_timer_restore_context(timer); atomic_set(&timer->enabled, 1); return 0; } static const struct dev_pm_ops omap_dm_timer_pm_ops = { SET_RUNTIME_PM_OPS(omap_dm_timer_runtime_suspend, omap_dm_timer_runtime_resume, NULL) }; static const struct of_device_id omap_timer_match[]; /** Loading Loading @@ -776,6 +801,8 @@ static int omap_dm_timer_probe(struct platform_device *pdev) if (IS_ERR(timer->io_base)) return PTR_ERR(timer->io_base); platform_set_drvdata(pdev, timer); if (dev->of_node) { if (of_find_property(dev->of_node, "ti,timer-alwon", NULL)) timer->capability |= OMAP_TIMER_ALWON; Loading @@ -789,7 +816,11 @@ static int omap_dm_timer_probe(struct platform_device *pdev) timer->id = pdev->id; timer->capability = pdata->timer_capability; timer->reserved = omap_dm_timer_reserved_systimer(timer->id); timer->get_context_loss_count = pdata->get_context_loss_count; } if (!(timer->capability & OMAP_TIMER_ALWON)) { timer->nb.notifier_call = omap_timer_context_notifier; cpu_pm_register_notifier(&timer->nb); } if (pdata) Loading Loading @@ -843,6 +874,8 @@ static int omap_dm_timer_remove(struct platform_device *pdev) list_for_each_entry(timer, &omap_timer_list, node) if (!strcmp(dev_name(&timer->pdev->dev), dev_name(&pdev->dev))) { if (!(timer->capability & OMAP_TIMER_ALWON)) cpu_pm_unregister_notifier(&timer->nb); list_del(&timer->node); ret = 0; break; Loading Loading @@ -871,6 +904,7 @@ static const struct omap_dm_timer_ops dmtimer_ops = { .set_load = omap_dm_timer_set_load, .set_match = omap_dm_timer_set_match, .set_pwm = omap_dm_timer_set_pwm, .get_pwm_status = omap_dm_timer_get_pwm_status, .set_prescaler = omap_dm_timer_set_prescaler, .read_counter = omap_dm_timer_read_counter, .write_counter = omap_dm_timer_write_counter, Loading Loading @@ -921,6 +955,7 @@ static struct platform_driver omap_dm_timer_driver = { .driver = { .name = "omap_timer", .of_match_table = of_match_ptr(omap_timer_match), .pm = &omap_dm_timer_pm_ops, }, }; Loading drivers/pwm/pwm-omap-dmtimer.c +5 −3 Original line number Diff line number Diff line Loading @@ -183,7 +183,7 @@ static int pwm_omap_dmtimer_config(struct pwm_chip *chip, if (timer_active) omap->pdata->stop(omap->dm_timer); omap->pdata->set_load(omap->dm_timer, true, load_value); omap->pdata->set_load(omap->dm_timer, load_value); omap->pdata->set_match(omap->dm_timer, true, match_value); dev_dbg(chip->dev, "load value: %#08x (%d), match value: %#08x (%d)\n", Loading @@ -192,7 +192,8 @@ static int pwm_omap_dmtimer_config(struct pwm_chip *chip, omap->pdata->set_pwm(omap->dm_timer, pwm_get_polarity(pwm) == PWM_POLARITY_INVERSED, true, PWM_OMAP_DMTIMER_TRIGGER_OVERFLOW_AND_COMPARE); PWM_OMAP_DMTIMER_TRIGGER_OVERFLOW_AND_COMPARE, true); /* If config was called while timer was running it must be reenabled. */ if (timer_active) Loading Loading @@ -222,7 +223,8 @@ static int pwm_omap_dmtimer_set_polarity(struct pwm_chip *chip, omap->pdata->set_pwm(omap->dm_timer, polarity == PWM_POLARITY_INVERSED, true, PWM_OMAP_DMTIMER_TRIGGER_OVERFLOW_AND_COMPARE); PWM_OMAP_DMTIMER_TRIGGER_OVERFLOW_AND_COMPARE, true); mutex_unlock(&omap->mutex); return 0; Loading include/clocksource/timer-ti-dm.h +2 −2 Original line number Diff line number Diff line Loading @@ -105,17 +105,17 @@ struct omap_dm_timer { void __iomem *pend; /* write pending */ void __iomem *func_base; /* function register base */ atomic_t enabled; unsigned long rate; unsigned reserved:1; unsigned posted:1; struct timer_regs context; int (*get_context_loss_count)(struct device *); int ctx_loss_count; int revision; u32 capability; u32 errata; struct platform_device *pdev; struct list_head node; struct notifier_block nb; }; int omap_dm_timer_reserve_systimer(int id); Loading include/linux/platform_data/dmtimer-omap.h +3 −3 Original line number Diff line number Diff line Loading @@ -30,12 +30,12 @@ struct omap_dm_timer_ops { int (*stop)(struct omap_dm_timer *timer); int (*set_source)(struct omap_dm_timer *timer, int source); int (*set_load)(struct omap_dm_timer *timer, int autoreload, unsigned int value); int (*set_load)(struct omap_dm_timer *timer, unsigned int value); int (*set_match)(struct omap_dm_timer *timer, int enable, unsigned int match); int (*set_pwm)(struct omap_dm_timer *timer, int def_on, int toggle, int trigger); int toggle, int trigger, int autoreload); int (*get_pwm_status)(struct omap_dm_timer *timer); int (*set_prescaler)(struct omap_dm_timer *timer, int prescaler); unsigned int (*read_counter)(struct omap_dm_timer *timer); Loading Loading
drivers/clocksource/timer-ti-dm.c +109 −74 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0+ /* * linux/arch/arm/plat-omap/dmtimer.c * Loading @@ -15,28 +16,11 @@ * * Copyright (C) 2009 Texas Instruments * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <linux/clk.h> #include <linux/clk-provider.h> #include <linux/cpu_pm.h> #include <linux/module.h> #include <linux/io.h> #include <linux/device.h> Loading Loading @@ -109,6 +93,47 @@ static void omap_timer_restore_context(struct omap_dm_timer *timer) timer->context.tclr); } static void omap_timer_save_context(struct omap_dm_timer *timer) { timer->context.tclr = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); timer->context.twer = omap_dm_timer_read_reg(timer, OMAP_TIMER_WAKEUP_EN_REG); timer->context.tldr = omap_dm_timer_read_reg(timer, OMAP_TIMER_LOAD_REG); timer->context.tmar = omap_dm_timer_read_reg(timer, OMAP_TIMER_MATCH_REG); timer->context.tier = readl_relaxed(timer->irq_ena); timer->context.tsicr = omap_dm_timer_read_reg(timer, OMAP_TIMER_IF_CTRL_REG); } static int omap_timer_context_notifier(struct notifier_block *nb, unsigned long cmd, void *v) { struct omap_dm_timer *timer; timer = container_of(nb, struct omap_dm_timer, nb); switch (cmd) { case CPU_CLUSTER_PM_ENTER: if ((timer->capability & OMAP_TIMER_ALWON) || !atomic_read(&timer->enabled)) break; omap_timer_save_context(timer); break; case CPU_CLUSTER_PM_ENTER_FAILED: case CPU_CLUSTER_PM_EXIT: if ((timer->capability & OMAP_TIMER_ALWON) || !atomic_read(&timer->enabled)) break; omap_timer_restore_context(timer); break; } return NOTIFY_OK; } static int omap_dm_timer_reset(struct omap_dm_timer *timer) { u32 l, timeout = 100000; Loading Loading @@ -196,21 +221,7 @@ static int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) 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) Loading Loading @@ -477,7 +488,7 @@ __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask) int omap_dm_timer_trigger(struct omap_dm_timer *timer) { if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) { if (unlikely(!timer || !atomic_read(&timer->enabled))) { pr_err("%s: timer not available or enabled.\n", __func__); return -EINVAL; } Loading @@ -501,8 +512,6 @@ static int omap_dm_timer_start(struct omap_dm_timer *timer) omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); } /* Save the context */ timer->context.tclr = l; return 0; } Loading @@ -518,37 +527,19 @@ static int omap_dm_timer_stop(struct omap_dm_timer *timer) __omap_dm_timer_stop(timer, timer->posted, rate); /* * Since the register values are computed and written within * __omap_dm_timer_stop, we need to use read to retrieve the * context. */ timer->context.tclr = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); omap_dm_timer_disable(timer); return 0; } static int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload, static int omap_dm_timer_set_load(struct omap_dm_timer *timer, unsigned int load) { u32 l; if (unlikely(!timer)) return -EINVAL; omap_dm_timer_enable(timer); l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); if (autoreload) l |= OMAP_TIMER_CTRL_AR; else l &= ~OMAP_TIMER_CTRL_AR; omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load); /* Save the context */ timer->context.tclr = l; timer->context.tldr = load; omap_dm_timer_disable(timer); return 0; } Loading @@ -570,15 +561,12 @@ static int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match); omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); /* Save the context */ timer->context.tclr = l; timer->context.tmar = match; 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) int toggle, int trigger, int autoreload) { u32 l; Loading @@ -588,20 +576,34 @@ static int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, omap_dm_timer_enable(timer); l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM | OMAP_TIMER_CTRL_PT | (0x03 << 10)); OMAP_TIMER_CTRL_PT | (0x03 << 10) | OMAP_TIMER_CTRL_AR); if (def_on) l |= OMAP_TIMER_CTRL_SCPWM; if (toggle) l |= OMAP_TIMER_CTRL_PT; l |= trigger << 10; if (autoreload) l |= OMAP_TIMER_CTRL_AR; 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_get_pwm_status(struct omap_dm_timer *timer) { u32 l; if (unlikely(!timer)) return -EINVAL; omap_dm_timer_enable(timer); l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); omap_dm_timer_disable(timer); return l; } static int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler) { Loading @@ -619,8 +621,6 @@ static int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, } 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; } Loading @@ -634,9 +634,6 @@ static int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, omap_dm_timer_enable(timer); __omap_dm_timer_int_enable(timer, value); /* Save the context */ timer->context.tier = value; timer->context.twer = value; omap_dm_timer_disable(timer); return 0; } Loading Loading @@ -664,9 +661,6 @@ static int omap_dm_timer_set_int_disable(struct omap_dm_timer *timer, u32 mask) l = omap_dm_timer_read_reg(timer, OMAP_TIMER_WAKEUP_EN_REG) & ~mask; omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, l); /* Save the context */ timer->context.tier &= ~mask; timer->context.twer &= ~mask; omap_dm_timer_disable(timer); return 0; } Loading @@ -675,7 +669,7 @@ static unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer) { unsigned int l; if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) { if (unlikely(!timer || !atomic_read(&timer->enabled))) { pr_err("%s: timer not available or enabled.\n", __func__); return 0; } Loading @@ -687,7 +681,7 @@ static unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer) static int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value) { if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) if (unlikely(!timer || !atomic_read(&timer->enabled))) return -EINVAL; __omap_dm_timer_write_status(timer, value); Loading @@ -697,7 +691,7 @@ static int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int static unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer) { if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) { if (unlikely(!timer || !atomic_read(&timer->enabled))) { pr_err("%s: timer not iavailable or enabled.\n", __func__); return 0; } Loading @@ -707,7 +701,7 @@ static unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer) static int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value) { if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) { if (unlikely(!timer || !atomic_read(&timer->enabled))) { pr_err("%s: timer not available or enabled.\n", __func__); return -EINVAL; } Loading Loading @@ -735,6 +729,37 @@ int omap_dm_timers_active(void) return 0; } static int __maybe_unused omap_dm_timer_runtime_suspend(struct device *dev) { struct omap_dm_timer *timer = dev_get_drvdata(dev); atomic_set(&timer->enabled, 0); if (timer->capability & OMAP_TIMER_ALWON || !timer->func_base) return 0; omap_timer_save_context(timer); return 0; } static int __maybe_unused omap_dm_timer_runtime_resume(struct device *dev) { struct omap_dm_timer *timer = dev_get_drvdata(dev); if (!(timer->capability & OMAP_TIMER_ALWON) && timer->func_base) omap_timer_restore_context(timer); atomic_set(&timer->enabled, 1); return 0; } static const struct dev_pm_ops omap_dm_timer_pm_ops = { SET_RUNTIME_PM_OPS(omap_dm_timer_runtime_suspend, omap_dm_timer_runtime_resume, NULL) }; static const struct of_device_id omap_timer_match[]; /** Loading Loading @@ -776,6 +801,8 @@ static int omap_dm_timer_probe(struct platform_device *pdev) if (IS_ERR(timer->io_base)) return PTR_ERR(timer->io_base); platform_set_drvdata(pdev, timer); if (dev->of_node) { if (of_find_property(dev->of_node, "ti,timer-alwon", NULL)) timer->capability |= OMAP_TIMER_ALWON; Loading @@ -789,7 +816,11 @@ static int omap_dm_timer_probe(struct platform_device *pdev) timer->id = pdev->id; timer->capability = pdata->timer_capability; timer->reserved = omap_dm_timer_reserved_systimer(timer->id); timer->get_context_loss_count = pdata->get_context_loss_count; } if (!(timer->capability & OMAP_TIMER_ALWON)) { timer->nb.notifier_call = omap_timer_context_notifier; cpu_pm_register_notifier(&timer->nb); } if (pdata) Loading Loading @@ -843,6 +874,8 @@ static int omap_dm_timer_remove(struct platform_device *pdev) list_for_each_entry(timer, &omap_timer_list, node) if (!strcmp(dev_name(&timer->pdev->dev), dev_name(&pdev->dev))) { if (!(timer->capability & OMAP_TIMER_ALWON)) cpu_pm_unregister_notifier(&timer->nb); list_del(&timer->node); ret = 0; break; Loading Loading @@ -871,6 +904,7 @@ static const struct omap_dm_timer_ops dmtimer_ops = { .set_load = omap_dm_timer_set_load, .set_match = omap_dm_timer_set_match, .set_pwm = omap_dm_timer_set_pwm, .get_pwm_status = omap_dm_timer_get_pwm_status, .set_prescaler = omap_dm_timer_set_prescaler, .read_counter = omap_dm_timer_read_counter, .write_counter = omap_dm_timer_write_counter, Loading Loading @@ -921,6 +955,7 @@ static struct platform_driver omap_dm_timer_driver = { .driver = { .name = "omap_timer", .of_match_table = of_match_ptr(omap_timer_match), .pm = &omap_dm_timer_pm_ops, }, }; Loading
drivers/pwm/pwm-omap-dmtimer.c +5 −3 Original line number Diff line number Diff line Loading @@ -183,7 +183,7 @@ static int pwm_omap_dmtimer_config(struct pwm_chip *chip, if (timer_active) omap->pdata->stop(omap->dm_timer); omap->pdata->set_load(omap->dm_timer, true, load_value); omap->pdata->set_load(omap->dm_timer, load_value); omap->pdata->set_match(omap->dm_timer, true, match_value); dev_dbg(chip->dev, "load value: %#08x (%d), match value: %#08x (%d)\n", Loading @@ -192,7 +192,8 @@ static int pwm_omap_dmtimer_config(struct pwm_chip *chip, omap->pdata->set_pwm(omap->dm_timer, pwm_get_polarity(pwm) == PWM_POLARITY_INVERSED, true, PWM_OMAP_DMTIMER_TRIGGER_OVERFLOW_AND_COMPARE); PWM_OMAP_DMTIMER_TRIGGER_OVERFLOW_AND_COMPARE, true); /* If config was called while timer was running it must be reenabled. */ if (timer_active) Loading Loading @@ -222,7 +223,8 @@ static int pwm_omap_dmtimer_set_polarity(struct pwm_chip *chip, omap->pdata->set_pwm(omap->dm_timer, polarity == PWM_POLARITY_INVERSED, true, PWM_OMAP_DMTIMER_TRIGGER_OVERFLOW_AND_COMPARE); PWM_OMAP_DMTIMER_TRIGGER_OVERFLOW_AND_COMPARE, true); mutex_unlock(&omap->mutex); return 0; Loading
include/clocksource/timer-ti-dm.h +2 −2 Original line number Diff line number Diff line Loading @@ -105,17 +105,17 @@ struct omap_dm_timer { void __iomem *pend; /* write pending */ void __iomem *func_base; /* function register base */ atomic_t enabled; unsigned long rate; unsigned reserved:1; unsigned posted:1; struct timer_regs context; int (*get_context_loss_count)(struct device *); int ctx_loss_count; int revision; u32 capability; u32 errata; struct platform_device *pdev; struct list_head node; struct notifier_block nb; }; int omap_dm_timer_reserve_systimer(int id); Loading
include/linux/platform_data/dmtimer-omap.h +3 −3 Original line number Diff line number Diff line Loading @@ -30,12 +30,12 @@ struct omap_dm_timer_ops { int (*stop)(struct omap_dm_timer *timer); int (*set_source)(struct omap_dm_timer *timer, int source); int (*set_load)(struct omap_dm_timer *timer, int autoreload, unsigned int value); int (*set_load)(struct omap_dm_timer *timer, unsigned int value); int (*set_match)(struct omap_dm_timer *timer, int enable, unsigned int match); int (*set_pwm)(struct omap_dm_timer *timer, int def_on, int toggle, int trigger); int toggle, int trigger, int autoreload); int (*get_pwm_status)(struct omap_dm_timer *timer); int (*set_prescaler)(struct omap_dm_timer *timer, int prescaler); unsigned int (*read_counter)(struct omap_dm_timer *timer); Loading