mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-16 15:46:41 +07:00
Merge branch 'timers/drivers/timer-ti-dm' of https://git.linaro.org/people/dlezcano/linux into for-next
This commit is contained in:
commit
74c8249f21
@ -1,3 +1,4 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
/*
|
/*
|
||||||
* linux/arch/arm/plat-omap/dmtimer.c
|
* linux/arch/arm/plat-omap/dmtimer.c
|
||||||
*
|
*
|
||||||
@ -15,28 +16,11 @@
|
|||||||
*
|
*
|
||||||
* Copyright (C) 2009 Texas Instruments
|
* Copyright (C) 2009 Texas Instruments
|
||||||
* Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
|
* 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.h>
|
||||||
#include <linux/clk-provider.h>
|
#include <linux/clk-provider.h>
|
||||||
|
#include <linux/cpu_pm.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
@ -109,6 +93,47 @@ static void omap_timer_restore_context(struct omap_dm_timer *timer)
|
|||||||
timer->context.tclr);
|
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)
|
static int omap_dm_timer_reset(struct omap_dm_timer *timer)
|
||||||
{
|
{
|
||||||
u32 l, timeout = 100000;
|
u32 l, timeout = 100000;
|
||||||
@ -225,21 +250,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)
|
static void omap_dm_timer_enable(struct omap_dm_timer *timer)
|
||||||
{
|
{
|
||||||
int c;
|
|
||||||
|
|
||||||
pm_runtime_get_sync(&timer->pdev->dev);
|
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)
|
static void omap_dm_timer_disable(struct omap_dm_timer *timer)
|
||||||
@ -508,7 +519,7 @@ __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
|
|||||||
|
|
||||||
int omap_dm_timer_trigger(struct omap_dm_timer *timer)
|
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__);
|
pr_err("%s: timer not available or enabled.\n", __func__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@ -532,8 +543,6 @@ static int omap_dm_timer_start(struct omap_dm_timer *timer)
|
|||||||
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
|
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save the context */
|
|
||||||
timer->context.tclr = l;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -549,38 +558,19 @@ static int omap_dm_timer_stop(struct omap_dm_timer *timer)
|
|||||||
|
|
||||||
__omap_dm_timer_stop(timer, timer->posted, rate);
|
__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);
|
omap_dm_timer_disable(timer);
|
||||||
return 0;
|
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)
|
unsigned int load)
|
||||||
{
|
{
|
||||||
u32 l;
|
|
||||||
|
|
||||||
if (unlikely(!timer))
|
if (unlikely(!timer))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
omap_dm_timer_enable(timer);
|
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);
|
omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
|
||||||
|
|
||||||
omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
|
|
||||||
/* Save the context */
|
|
||||||
timer->context.tclr = l;
|
|
||||||
timer->context.tldr = load;
|
|
||||||
omap_dm_timer_disable(timer);
|
omap_dm_timer_disable(timer);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -602,15 +592,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_MATCH_REG, match);
|
||||||
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
|
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);
|
omap_dm_timer_disable(timer);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
|
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;
|
u32 l;
|
||||||
|
|
||||||
@ -620,20 +607,34 @@ static int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
|
|||||||
omap_dm_timer_enable(timer);
|
omap_dm_timer_enable(timer);
|
||||||
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
|
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
|
||||||
l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM |
|
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)
|
if (def_on)
|
||||||
l |= OMAP_TIMER_CTRL_SCPWM;
|
l |= OMAP_TIMER_CTRL_SCPWM;
|
||||||
if (toggle)
|
if (toggle)
|
||||||
l |= OMAP_TIMER_CTRL_PT;
|
l |= OMAP_TIMER_CTRL_PT;
|
||||||
l |= trigger << 10;
|
l |= trigger << 10;
|
||||||
|
if (autoreload)
|
||||||
|
l |= OMAP_TIMER_CTRL_AR;
|
||||||
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
|
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
|
||||||
|
|
||||||
/* Save the context */
|
|
||||||
timer->context.tclr = l;
|
|
||||||
omap_dm_timer_disable(timer);
|
omap_dm_timer_disable(timer);
|
||||||
return 0;
|
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,
|
static int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer,
|
||||||
int prescaler)
|
int prescaler)
|
||||||
{
|
{
|
||||||
@ -651,8 +652,6 @@ static int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer,
|
|||||||
}
|
}
|
||||||
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
|
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
|
||||||
|
|
||||||
/* Save the context */
|
|
||||||
timer->context.tclr = l;
|
|
||||||
omap_dm_timer_disable(timer);
|
omap_dm_timer_disable(timer);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -666,9 +665,6 @@ static int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
|
|||||||
omap_dm_timer_enable(timer);
|
omap_dm_timer_enable(timer);
|
||||||
__omap_dm_timer_int_enable(timer, value);
|
__omap_dm_timer_int_enable(timer, value);
|
||||||
|
|
||||||
/* Save the context */
|
|
||||||
timer->context.tier = value;
|
|
||||||
timer->context.twer = value;
|
|
||||||
omap_dm_timer_disable(timer);
|
omap_dm_timer_disable(timer);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -696,9 +692,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;
|
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);
|
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);
|
omap_dm_timer_disable(timer);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -707,7 +700,7 @@ static unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
|
|||||||
{
|
{
|
||||||
unsigned int l;
|
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__);
|
pr_err("%s: timer not available or enabled.\n", __func__);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -719,7 +712,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)
|
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;
|
return -EINVAL;
|
||||||
|
|
||||||
__omap_dm_timer_write_status(timer, value);
|
__omap_dm_timer_write_status(timer, value);
|
||||||
@ -729,7 +722,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)
|
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__);
|
pr_err("%s: timer not iavailable or enabled.\n", __func__);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -739,7 +732,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)
|
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__);
|
pr_err("%s: timer not available or enabled.\n", __func__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@ -767,6 +760,37 @@ int omap_dm_timers_active(void)
|
|||||||
return 0;
|
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[];
|
static const struct of_device_id omap_timer_match[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -808,6 +832,8 @@ static int omap_dm_timer_probe(struct platform_device *pdev)
|
|||||||
if (IS_ERR(timer->io_base))
|
if (IS_ERR(timer->io_base))
|
||||||
return PTR_ERR(timer->io_base);
|
return PTR_ERR(timer->io_base);
|
||||||
|
|
||||||
|
platform_set_drvdata(pdev, timer);
|
||||||
|
|
||||||
if (dev->of_node) {
|
if (dev->of_node) {
|
||||||
if (of_find_property(dev->of_node, "ti,timer-alwon", NULL))
|
if (of_find_property(dev->of_node, "ti,timer-alwon", NULL))
|
||||||
timer->capability |= OMAP_TIMER_ALWON;
|
timer->capability |= OMAP_TIMER_ALWON;
|
||||||
@ -821,7 +847,11 @@ static int omap_dm_timer_probe(struct platform_device *pdev)
|
|||||||
timer->id = pdev->id;
|
timer->id = pdev->id;
|
||||||
timer->capability = pdata->timer_capability;
|
timer->capability = pdata->timer_capability;
|
||||||
timer->reserved = omap_dm_timer_reserved_systimer(timer->id);
|
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)
|
if (pdata)
|
||||||
@ -875,6 +905,8 @@ static int omap_dm_timer_remove(struct platform_device *pdev)
|
|||||||
list_for_each_entry(timer, &omap_timer_list, node)
|
list_for_each_entry(timer, &omap_timer_list, node)
|
||||||
if (!strcmp(dev_name(&timer->pdev->dev),
|
if (!strcmp(dev_name(&timer->pdev->dev),
|
||||||
dev_name(&pdev->dev))) {
|
dev_name(&pdev->dev))) {
|
||||||
|
if (!(timer->capability & OMAP_TIMER_ALWON))
|
||||||
|
cpu_pm_unregister_notifier(&timer->nb);
|
||||||
list_del(&timer->node);
|
list_del(&timer->node);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
@ -903,6 +935,7 @@ static const struct omap_dm_timer_ops dmtimer_ops = {
|
|||||||
.set_load = omap_dm_timer_set_load,
|
.set_load = omap_dm_timer_set_load,
|
||||||
.set_match = omap_dm_timer_set_match,
|
.set_match = omap_dm_timer_set_match,
|
||||||
.set_pwm = omap_dm_timer_set_pwm,
|
.set_pwm = omap_dm_timer_set_pwm,
|
||||||
|
.get_pwm_status = omap_dm_timer_get_pwm_status,
|
||||||
.set_prescaler = omap_dm_timer_set_prescaler,
|
.set_prescaler = omap_dm_timer_set_prescaler,
|
||||||
.read_counter = omap_dm_timer_read_counter,
|
.read_counter = omap_dm_timer_read_counter,
|
||||||
.write_counter = omap_dm_timer_write_counter,
|
.write_counter = omap_dm_timer_write_counter,
|
||||||
@ -953,6 +986,7 @@ static struct platform_driver omap_dm_timer_driver = {
|
|||||||
.driver = {
|
.driver = {
|
||||||
.name = "omap_timer",
|
.name = "omap_timer",
|
||||||
.of_match_table = of_match_ptr(omap_timer_match),
|
.of_match_table = of_match_ptr(omap_timer_match),
|
||||||
|
.pm = &omap_dm_timer_pm_ops,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -183,7 +183,7 @@ static int pwm_omap_dmtimer_config(struct pwm_chip *chip,
|
|||||||
if (timer_active)
|
if (timer_active)
|
||||||
omap->pdata->stop(omap->dm_timer);
|
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);
|
omap->pdata->set_match(omap->dm_timer, true, match_value);
|
||||||
|
|
||||||
dev_dbg(chip->dev, "load value: %#08x (%d), match value: %#08x (%d)\n",
|
dev_dbg(chip->dev, "load value: %#08x (%d), match value: %#08x (%d)\n",
|
||||||
@ -192,7 +192,8 @@ static int pwm_omap_dmtimer_config(struct pwm_chip *chip,
|
|||||||
omap->pdata->set_pwm(omap->dm_timer,
|
omap->pdata->set_pwm(omap->dm_timer,
|
||||||
pwm_get_polarity(pwm) == PWM_POLARITY_INVERSED,
|
pwm_get_polarity(pwm) == PWM_POLARITY_INVERSED,
|
||||||
true,
|
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 config was called while timer was running it must be reenabled. */
|
||||||
if (timer_active)
|
if (timer_active)
|
||||||
@ -222,7 +223,8 @@ static int pwm_omap_dmtimer_set_polarity(struct pwm_chip *chip,
|
|||||||
omap->pdata->set_pwm(omap->dm_timer,
|
omap->pdata->set_pwm(omap->dm_timer,
|
||||||
polarity == PWM_POLARITY_INVERSED,
|
polarity == PWM_POLARITY_INVERSED,
|
||||||
true,
|
true,
|
||||||
PWM_OMAP_DMTIMER_TRIGGER_OVERFLOW_AND_COMPARE);
|
PWM_OMAP_DMTIMER_TRIGGER_OVERFLOW_AND_COMPARE,
|
||||||
|
true);
|
||||||
mutex_unlock(&omap->mutex);
|
mutex_unlock(&omap->mutex);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -105,17 +105,17 @@ struct omap_dm_timer {
|
|||||||
void __iomem *pend; /* write pending */
|
void __iomem *pend; /* write pending */
|
||||||
void __iomem *func_base; /* function register base */
|
void __iomem *func_base; /* function register base */
|
||||||
|
|
||||||
|
atomic_t enabled;
|
||||||
unsigned long rate;
|
unsigned long rate;
|
||||||
unsigned reserved:1;
|
unsigned reserved:1;
|
||||||
unsigned posted:1;
|
unsigned posted:1;
|
||||||
struct timer_regs context;
|
struct timer_regs context;
|
||||||
int (*get_context_loss_count)(struct device *);
|
|
||||||
int ctx_loss_count;
|
|
||||||
int revision;
|
int revision;
|
||||||
u32 capability;
|
u32 capability;
|
||||||
u32 errata;
|
u32 errata;
|
||||||
struct platform_device *pdev;
|
struct platform_device *pdev;
|
||||||
struct list_head node;
|
struct list_head node;
|
||||||
|
struct notifier_block nb;
|
||||||
};
|
};
|
||||||
|
|
||||||
int omap_dm_timer_reserve_systimer(int id);
|
int omap_dm_timer_reserve_systimer(int id);
|
||||||
|
@ -30,12 +30,12 @@ struct omap_dm_timer_ops {
|
|||||||
int (*stop)(struct omap_dm_timer *timer);
|
int (*stop)(struct omap_dm_timer *timer);
|
||||||
int (*set_source)(struct omap_dm_timer *timer, int source);
|
int (*set_source)(struct omap_dm_timer *timer, int source);
|
||||||
|
|
||||||
int (*set_load)(struct omap_dm_timer *timer, int autoreload,
|
int (*set_load)(struct omap_dm_timer *timer, unsigned int value);
|
||||||
unsigned int value);
|
|
||||||
int (*set_match)(struct omap_dm_timer *timer, int enable,
|
int (*set_match)(struct omap_dm_timer *timer, int enable,
|
||||||
unsigned int match);
|
unsigned int match);
|
||||||
int (*set_pwm)(struct omap_dm_timer *timer, int def_on,
|
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);
|
int (*set_prescaler)(struct omap_dm_timer *timer, int prescaler);
|
||||||
|
|
||||||
unsigned int (*read_counter)(struct omap_dm_timer *timer);
|
unsigned int (*read_counter)(struct omap_dm_timer *timer);
|
||||||
|
Loading…
Reference in New Issue
Block a user