mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 20:51:44 +00:00
Move omap timer to drivers for 4.17
This series from Keerthy and Ladislav Michl move omap dmtimer code to drivers. As we don't want to export custom timer functions to random drivers, we also need to update the related PWM driver to pass the timer specific functions in platform data. Note that this series is based on a merge of omap1 specific timer fix and omap2+ platform data clean-up to keep things working and make the move a bit simpler. -----BEGIN PGP SIGNATURE----- iQJFBAABCAAvFiEEkgNvrZJU/QSQYIcQG9Q+yVyrpXMFAlqdd1IRHHRvbnlAYXRv bWlkZS5jb20ACgkQG9Q+yVyrpXNziQ/+OywQPRLgeYodIl5AXJCMaZhyFJPN1BP3 OXsDllCnqJOpH4yjIPz4WoEI3ciVRJw+iBOl28pDtomdyejyE9qx/FmIhL081Wgm T7TgJTieungliRfZu3UWRJdinpEyEzvTtEWlSVWa++lH5Bsub7lIPJsZ3A2bYVMh 9n6uE9bzU/ECdq/1hP9fhM2rssf8mu5l1IKlYmPWuxoFm/YSYoiyneU+rOILnJQ6 dsbc71p3+VdsZBDI+nMGcLE923LGXKEmxlHoR9+9EY12MOIwbTt/jxcI8j+Iugfk vetncsXbpKnbutTP1iXr64IXa5QFOZKtMNlfNqLo4aihWMJ6tV4570w/pxk/qMgq +qCidWm9RgVUm1N4t8kMm8aWm1BC1L8g9fw2/l0JFBHcuIlOYewa6cZ6gcUI6XxN BqcET9iyxG9HgqgB6yekHRI3niywgGcpw420RS0DLmxIzpnpeQHGkXrva0tVcVS7 4SZ9UWgLQVCKgm/8mSDv4PkIzuPXyu4fqjxzMihQdNUHAG1xeqODfU8SLsItW43a sGojvPPNWhCyvL2hpWuyWsRSOTc8MyAteeowYN1PzoSCO0cI3MTL0TUpxRTBV/9/ y1l5DYmdc1HUARXxJWreBSl3uToADguqzYUv3rHe/B20+LA19F9GRzoc9uOhqTGn ePjiA5EC64o= =2B8N -----END PGP SIGNATURE----- Merge tag 'omap-for-v4.17/timer-signed' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap into next/soc Pull "Move omap timer to drivers for 4.17" from Tony Lindgren: This series from Keerthy and Ladislav Michl move omap dmtimer code to drivers. As we don't want to export custom timer functions to random drivers, we also need to update the related PWM driver to pass the timer specific functions in platform data. Note that this series is based on a merge of omap1 specific timer fix and omap2+ platform data clean-up to keep things working and make the move a bit simpler. * tag 'omap-for-v4.17/timer-signed' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap: clocksource: timer-ti-dm: Check prescaler value clocksource: timer-ti-dm: Consolidate set source clocksource: timer-ti-dm: Make unexported functions static ARM: OMAP: pdata-quirks: Remove unused timer pdata pwm: pwm-omap-dmtimer: Adapt driver to utilize dmtimer pdata ops clocksource: timer-ti-dm: Hook device platform data if not already assigned clocksource: timer-ti-dm: Populate the timer ops to the pdata clocksource: timer-ti-dm: Add timer ops to the platform data structure ARM: OMAP: Move dmtimer driver out of plat-omap to drivers under clocksource clocksource: timer-ti-dm: Replace architecture ARM: OMAP: Move dmtimer.h out of plat-omap ARM: OMAP: timer: Wrap the inline functions under OMAP2PLUS define ARM: OMAP: dmtimer: Remove all the exports ARM: OMAP: Fix dmtimer init for omap1
This commit is contained in:
commit
6f566c4f30
@ -30,6 +30,7 @@ config ARCH_OMAP16XX
|
||||
bool "OMAP16xx Based System"
|
||||
select ARCH_OMAP_OTG
|
||||
select CPU_ARM926T
|
||||
select OMAP_DM_TIMER
|
||||
|
||||
config OMAP_MUX
|
||||
bool "OMAP multiplexing support"
|
||||
|
@ -55,7 +55,7 @@
|
||||
#include <mach/tc.h>
|
||||
#include <mach/mux.h>
|
||||
#include <linux/omap-dma.h>
|
||||
#include <plat/dmtimer.h>
|
||||
#include <clocksource/timer-ti-dm.h>
|
||||
|
||||
#include <mach/irqs.h>
|
||||
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/platform_data/dmtimer-omap.h>
|
||||
|
||||
#include <plat/dmtimer.h>
|
||||
#include <clocksource/timer-ti-dm.h>
|
||||
|
||||
#include "soc.h"
|
||||
|
||||
|
@ -24,10 +24,8 @@
|
||||
#include <linux/platform_data/hsmmc-omap.h>
|
||||
#include <linux/platform_data/iommu-omap.h>
|
||||
#include <linux/platform_data/wkup_m3.h>
|
||||
#include <linux/platform_data/pwm_omap_dmtimer.h>
|
||||
#include <linux/platform_data/media/ir-rx51.h>
|
||||
#include <linux/platform_data/asoc-ti-mcbsp.h>
|
||||
#include <plat/dmtimer.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "common-board-devices.h"
|
||||
@ -477,33 +475,6 @@ void omap_auxdata_legacy_init(struct device *dev)
|
||||
dev->platform_data = &twl_gpio_auxdata;
|
||||
}
|
||||
|
||||
/* Dual mode timer PWM callbacks platdata */
|
||||
#if IS_ENABLED(CONFIG_OMAP_DM_TIMER)
|
||||
static struct pwm_omap_dmtimer_pdata pwm_dmtimer_pdata = {
|
||||
.request_by_node = omap_dm_timer_request_by_node,
|
||||
.request_specific = omap_dm_timer_request_specific,
|
||||
.request = omap_dm_timer_request,
|
||||
.set_source = omap_dm_timer_set_source,
|
||||
.get_irq = omap_dm_timer_get_irq,
|
||||
.set_int_enable = omap_dm_timer_set_int_enable,
|
||||
.set_int_disable = omap_dm_timer_set_int_disable,
|
||||
.free = omap_dm_timer_free,
|
||||
.enable = omap_dm_timer_enable,
|
||||
.disable = omap_dm_timer_disable,
|
||||
.get_fclk = omap_dm_timer_get_fclk,
|
||||
.start = omap_dm_timer_start,
|
||||
.stop = omap_dm_timer_stop,
|
||||
.set_load = omap_dm_timer_set_load,
|
||||
.set_match = omap_dm_timer_set_match,
|
||||
.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_status = omap_dm_timer_read_status,
|
||||
.write_status = omap_dm_timer_write_status,
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct ir_rx51_platform_data __maybe_unused rx51_ir_data = {
|
||||
.set_max_mpu_wakeup_lat = omap_pm_set_max_mpu_wakeup_lat,
|
||||
};
|
||||
@ -572,9 +543,6 @@ static struct of_dev_auxdata omap_auxdata_lookup[] __initdata = {
|
||||
OF_DEV_AUXDATA("ti,am4372-wkup-m3", 0x44d00000, "44d00000.wkup_m3",
|
||||
&wkup_m3_data),
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_OMAP_DM_TIMER)
|
||||
OF_DEV_AUXDATA("ti,omap-dmtimer-pwm", 0, NULL, &pwm_dmtimer_pdata),
|
||||
#endif
|
||||
#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5)
|
||||
OF_DEV_AUXDATA("ti,omap4-iommu", 0x4a066000, "4a066000.mmu",
|
||||
&omap4_iommu_pdata),
|
||||
|
@ -49,7 +49,7 @@
|
||||
#include "omap_hwmod.h"
|
||||
#include "omap_device.h"
|
||||
#include <plat/counter-32k.h>
|
||||
#include <plat/dmtimer.h>
|
||||
#include <clocksource/timer-ti-dm.h>
|
||||
#include "omap-pm.h"
|
||||
|
||||
#include "soc.h"
|
||||
|
@ -106,12 +106,6 @@ config OMAP3_L2_AUX_SECURE_SERVICE_SET_ID
|
||||
help
|
||||
PPA routine service ID for setting L2 auxiliary control register.
|
||||
|
||||
config OMAP_DM_TIMER
|
||||
bool "Use dual-mode timer"
|
||||
depends on ARCH_OMAP16XX || ARCH_OMAP2PLUS
|
||||
help
|
||||
Select this option if you want to use OMAP Dual-Mode timers.
|
||||
|
||||
config OMAP_SERIAL_WAKE
|
||||
bool "Enable wake-up events for serial ports"
|
||||
depends on ARCH_OMAP1 && OMAP_MUX
|
||||
|
@ -9,5 +9,4 @@ obj-y := sram.o dma.o counter_32k.o
|
||||
|
||||
# omap_device support (OMAP2+ only at the moment)
|
||||
|
||||
obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o
|
||||
obj-$(CONFIG_OMAP_DEBUG_LEDS) += debug-leds.o
|
||||
|
@ -21,6 +21,9 @@ config CLKEVT_I8253
|
||||
config I8253_LOCK
|
||||
bool
|
||||
|
||||
config OMAP_DM_TIMER
|
||||
bool
|
||||
|
||||
config CLKBLD_I8253
|
||||
def_bool y if CLKSRC_I8253 || CLKEVT_I8253 || I8253_LOCK
|
||||
|
||||
|
@ -16,6 +16,7 @@ obj-$(CONFIG_EM_TIMER_STI) += em_sti.o
|
||||
obj-$(CONFIG_CLKBLD_I8253) += i8253.o
|
||||
obj-$(CONFIG_CLKSRC_MMIO) += mmio.o
|
||||
obj-$(CONFIG_DIGICOLOR_TIMER) += timer-digicolor.o
|
||||
obj-$(CONFIG_OMAP_DM_TIMER) += timer-ti-dm.o
|
||||
obj-$(CONFIG_DW_APB_TIMER) += dw_apb_timer.o
|
||||
obj-$(CONFIG_DW_APB_TIMER_OF) += dw_apb_timer_of.o
|
||||
obj-$(CONFIG_FTTMR010_TIMER) += timer-fttmr010.o
|
||||
|
@ -47,7 +47,7 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/platform_data/dmtimer-omap.h>
|
||||
|
||||
#include <plat/dmtimer.h>
|
||||
#include <clocksource/timer-ti-dm.h>
|
||||
|
||||
static u32 omap_reserved_systimers;
|
||||
static LIST_HEAD(omap_timer_list);
|
||||
@ -163,6 +163,86 @@ 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;
|
||||
const char *parent_name;
|
||||
struct clk *parent;
|
||||
struct dmtimer_platform_data *pdata;
|
||||
|
||||
if (unlikely(!timer) || IS_ERR(timer->fclk))
|
||||
return -EINVAL;
|
||||
|
||||
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
|
||||
* 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 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
|
||||
|
||||
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,24 +378,22 @@ found:
|
||||
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);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(omap_dm_timer_request);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return _omap_dm_timer_request(REQUEST_BY_ID, &id);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific);
|
||||
|
||||
/**
|
||||
* omap_dm_timer_request_by_cap - Request a timer by capability
|
||||
@ -330,7 +408,6 @@ struct omap_dm_timer *omap_dm_timer_request_by_cap(u32 cap)
|
||||
{
|
||||
return _omap_dm_timer_request(REQUEST_BY_CAP, &cap);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(omap_dm_timer_request_by_cap);
|
||||
|
||||
/**
|
||||
* omap_dm_timer_request_by_node - Request a timer by device-tree node
|
||||
@ -339,16 +416,15 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_request_by_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;
|
||||
|
||||
return _omap_dm_timer_request(REQUEST_BY_NODE, np);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(omap_dm_timer_request_by_node);
|
||||
|
||||
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;
|
||||
@ -359,33 +435,6 @@ int omap_dm_timer_free(struct omap_dm_timer *timer)
|
||||
timer->reserved = 0;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(omap_dm_timer_free);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(omap_dm_timer_enable);
|
||||
|
||||
void omap_dm_timer_disable(struct omap_dm_timer *timer)
|
||||
{
|
||||
pm_runtime_put_sync(&timer->pdev->dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(omap_dm_timer_disable);
|
||||
|
||||
int omap_dm_timer_get_irq(struct omap_dm_timer *timer)
|
||||
{
|
||||
@ -393,10 +442,15 @@ int omap_dm_timer_get_irq(struct omap_dm_timer *timer)
|
||||
return timer->irq;
|
||||
return -EINVAL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(omap_dm_timer_get_irq);
|
||||
|
||||
#if defined(CONFIG_ARCH_OMAP1)
|
||||
#include <mach/hardware.h>
|
||||
|
||||
static struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* omap_dm_timer_modify_idlect_mask - Check if any running timers use ARMXOR
|
||||
* @inputmask: current value of idlect mask
|
||||
@ -429,17 +483,15 @@ __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
|
||||
|
||||
return inputmask;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
|
||||
|
||||
#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;
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(omap_dm_timer_get_fclk);
|
||||
|
||||
__u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
|
||||
{
|
||||
@ -447,7 +499,6 @@ __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
|
||||
|
||||
#endif
|
||||
|
||||
@ -461,9 +512,8 @@ int omap_dm_timer_trigger(struct omap_dm_timer *timer)
|
||||
omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(omap_dm_timer_trigger);
|
||||
|
||||
int omap_dm_timer_start(struct omap_dm_timer *timer)
|
||||
static int omap_dm_timer_start(struct omap_dm_timer *timer)
|
||||
{
|
||||
u32 l;
|
||||
|
||||
@ -482,9 +532,8 @@ int omap_dm_timer_start(struct omap_dm_timer *timer)
|
||||
timer->context.tclr = l;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(omap_dm_timer_start);
|
||||
|
||||
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;
|
||||
|
||||
@ -506,73 +555,9 @@ int omap_dm_timer_stop(struct omap_dm_timer *timer)
|
||||
omap_dm_timer_disable(timer);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
|
||||
|
||||
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;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
|
||||
|
||||
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;
|
||||
|
||||
@ -595,7 +580,6 @@ int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
|
||||
omap_dm_timer_disable(timer);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(omap_dm_timer_set_load);
|
||||
|
||||
/* 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,
|
||||
@ -625,10 +609,8 @@ int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
|
||||
timer->context.tcrr = load;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(omap_dm_timer_set_load_start);
|
||||
|
||||
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;
|
||||
|
||||
@ -650,10 +632,9 @@ int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
|
||||
omap_dm_timer_disable(timer);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(omap_dm_timer_set_match);
|
||||
|
||||
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;
|
||||
|
||||
@ -676,19 +657,19 @@ int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
|
||||
omap_dm_timer_disable(timer);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(omap_dm_timer_set_pwm);
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
@ -699,10 +680,9 @@ int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
|
||||
omap_dm_timer_disable(timer);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(omap_dm_timer_set_prescaler);
|
||||
|
||||
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;
|
||||
@ -716,7 +696,6 @@ int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
|
||||
omap_dm_timer_disable(timer);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable);
|
||||
|
||||
/**
|
||||
* omap_dm_timer_set_int_disable - disable timer interrupts
|
||||
@ -725,7 +704,7 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable);
|
||||
*
|
||||
* 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;
|
||||
|
||||
@ -747,9 +726,8 @@ int omap_dm_timer_set_int_disable(struct omap_dm_timer *timer, u32 mask)
|
||||
omap_dm_timer_disable(timer);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_disable);
|
||||
|
||||
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;
|
||||
|
||||
@ -762,9 +740,8 @@ unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
|
||||
|
||||
return l;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(omap_dm_timer_read_status);
|
||||
|
||||
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;
|
||||
@ -773,9 +750,8 @@ int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(omap_dm_timer_write_status);
|
||||
|
||||
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__);
|
||||
@ -784,9 +760,8 @@ unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
|
||||
|
||||
return __omap_dm_timer_read_counter(timer, timer->posted);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter);
|
||||
|
||||
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__);
|
||||
@ -799,7 +774,6 @@ int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
|
||||
timer->context.tcrr = value;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(omap_dm_timer_write_counter);
|
||||
|
||||
int omap_dm_timers_active(void)
|
||||
{
|
||||
@ -816,7 +790,6 @@ int omap_dm_timers_active(void)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(omap_dm_timers_active);
|
||||
|
||||
static const struct of_device_id omap_timer_match[];
|
||||
|
||||
@ -833,14 +806,16 @@ static int omap_dm_timer_probe(struct platform_device *pdev)
|
||||
struct omap_dm_timer *timer;
|
||||
struct resource *mem, *irq;
|
||||
struct device *dev = &pdev->dev;
|
||||
const struct of_device_id *match;
|
||||
const struct dmtimer_platform_data *pdata;
|
||||
int ret;
|
||||
|
||||
match = of_match_device(of_match_ptr(omap_timer_match), dev);
|
||||
pdata = match ? match->data : dev->platform_data;
|
||||
pdata = of_device_get_match_data(dev);
|
||||
if (!pdata)
|
||||
pdata = dev_get_platdata(dev);
|
||||
else
|
||||
dev->platform_data = (void *)pdata;
|
||||
|
||||
if (!pdata && !dev->of_node) {
|
||||
if (!pdata) {
|
||||
dev_err(dev, "%s: no platform data.\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
@ -888,11 +863,8 @@ static int omap_dm_timer_probe(struct platform_device *pdev)
|
||||
timer->irq = irq->start;
|
||||
timer->pdev = pdev;
|
||||
|
||||
/* Skip pm_runtime_enable for OMAP1 */
|
||||
if (!(timer->capability & OMAP_TIMER_NEEDS_RESET)) {
|
||||
pm_runtime_enable(dev);
|
||||
pm_runtime_irq_safe(dev);
|
||||
}
|
||||
pm_runtime_enable(dev);
|
||||
pm_runtime_irq_safe(dev);
|
||||
|
||||
if (!timer->reserved) {
|
||||
ret = pm_runtime_get_sync(dev);
|
||||
@ -949,8 +921,33 @@ static int omap_dm_timer_remove(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
const static struct omap_dm_timer_ops dmtimer_ops = {
|
||||
.request_by_node = omap_dm_timer_request_by_node,
|
||||
.request_specific = omap_dm_timer_request_specific,
|
||||
.request = omap_dm_timer_request,
|
||||
.set_source = omap_dm_timer_set_source,
|
||||
.get_irq = omap_dm_timer_get_irq,
|
||||
.set_int_enable = omap_dm_timer_set_int_enable,
|
||||
.set_int_disable = omap_dm_timer_set_int_disable,
|
||||
.free = omap_dm_timer_free,
|
||||
.enable = omap_dm_timer_enable,
|
||||
.disable = omap_dm_timer_disable,
|
||||
.get_fclk = omap_dm_timer_get_fclk,
|
||||
.start = omap_dm_timer_start,
|
||||
.stop = omap_dm_timer_stop,
|
||||
.set_load = omap_dm_timer_set_load,
|
||||
.set_match = omap_dm_timer_set_match,
|
||||
.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_status = omap_dm_timer_read_status,
|
||||
.write_status = omap_dm_timer_write_status,
|
||||
};
|
||||
|
||||
static const struct dmtimer_platform_data omap3plus_pdata = {
|
||||
.timer_errata = OMAP_TIMER_ERRATA_I103_I767,
|
||||
.timer_ops = &dmtimer_ops,
|
||||
};
|
||||
|
||||
static const struct of_device_id omap_timer_match[] = {
|
@ -23,6 +23,7 @@
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_data/dmtimer-omap.h>
|
||||
#include <linux/platform_data/pwm_omap_dmtimer.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
@ -37,7 +38,7 @@ struct pwm_omap_dmtimer_chip {
|
||||
struct pwm_chip chip;
|
||||
struct mutex mutex;
|
||||
pwm_omap_dmtimer *dm_timer;
|
||||
struct pwm_omap_dmtimer_pdata *pdata;
|
||||
const struct omap_dm_timer_ops *pdata;
|
||||
struct platform_device *dm_timer_pdev;
|
||||
};
|
||||
|
||||
@ -242,19 +243,35 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct device_node *timer;
|
||||
struct platform_device *timer_pdev;
|
||||
struct pwm_omap_dmtimer_chip *omap;
|
||||
struct pwm_omap_dmtimer_pdata *pdata;
|
||||
struct dmtimer_platform_data *timer_pdata;
|
||||
const struct omap_dm_timer_ops *pdata;
|
||||
pwm_omap_dmtimer *dm_timer;
|
||||
u32 v;
|
||||
int status;
|
||||
int ret = 0;
|
||||
|
||||
pdata = dev_get_platdata(&pdev->dev);
|
||||
if (!pdata) {
|
||||
dev_err(&pdev->dev, "Missing dmtimer platform data\n");
|
||||
return -EINVAL;
|
||||
timer = of_parse_phandle(np, "ti,timers", 0);
|
||||
if (!timer)
|
||||
return -ENODEV;
|
||||
|
||||
timer_pdev = of_find_device_by_node(timer);
|
||||
if (!timer_pdev) {
|
||||
dev_err(&pdev->dev, "Unable to find Timer pdev\n");
|
||||
ret = -ENODEV;
|
||||
goto put;
|
||||
}
|
||||
|
||||
if (!pdata->request_by_node ||
|
||||
timer_pdata = dev_get_platdata(&timer_pdev->dev);
|
||||
if (!timer_pdata) {
|
||||
dev_err(&pdev->dev, "dmtimer pdata structure NULL\n");
|
||||
ret = -EINVAL;
|
||||
goto put;
|
||||
}
|
||||
|
||||
pdata = timer_pdata->timer_ops;
|
||||
|
||||
if (!pdata || !pdata->request_by_node ||
|
||||
!pdata->free ||
|
||||
!pdata->enable ||
|
||||
!pdata->disable ||
|
||||
@ -267,21 +284,26 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev)
|
||||
!pdata->set_prescaler ||
|
||||
!pdata->write_counter) {
|
||||
dev_err(&pdev->dev, "Incomplete dmtimer pdata structure\n");
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto put;
|
||||
}
|
||||
|
||||
timer = of_parse_phandle(np, "ti,timers", 0);
|
||||
if (!timer)
|
||||
return -ENODEV;
|
||||
|
||||
if (!of_get_property(timer, "ti,timer-pwm", NULL)) {
|
||||
dev_err(&pdev->dev, "Missing ti,timer-pwm capability\n");
|
||||
return -ENODEV;
|
||||
ret = -ENODEV;
|
||||
goto put;
|
||||
}
|
||||
|
||||
dm_timer = pdata->request_by_node(timer);
|
||||
if (!dm_timer)
|
||||
return -EPROBE_DEFER;
|
||||
if (!dm_timer) {
|
||||
ret = -EPROBE_DEFER;
|
||||
goto put;
|
||||
}
|
||||
|
||||
put:
|
||||
of_node_put(timer);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
omap = devm_kzalloc(&pdev->dev, sizeof(*omap), GFP_KERNEL);
|
||||
if (!omap) {
|
||||
@ -291,13 +313,7 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev)
|
||||
|
||||
omap->pdata = pdata;
|
||||
omap->dm_timer = dm_timer;
|
||||
|
||||
omap->dm_timer_pdev = of_find_device_by_node(timer);
|
||||
if (!omap->dm_timer_pdev) {
|
||||
dev_err(&pdev->dev, "Unable to find timer pdev\n");
|
||||
omap->pdata->free(dm_timer);
|
||||
return -EINVAL;
|
||||
}
|
||||
omap->dm_timer_pdev = timer_pdev;
|
||||
|
||||
/*
|
||||
* Ensure that the timer is stopped before we allow PWM core to call
|
||||
@ -322,11 +338,11 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev)
|
||||
|
||||
mutex_init(&omap->mutex);
|
||||
|
||||
status = pwmchip_add(&omap->chip);
|
||||
if (status < 0) {
|
||||
ret = pwmchip_add(&omap->chip);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "failed to register PWM\n");
|
||||
omap->pdata->free(omap->dm_timer);
|
||||
return status;
|
||||
return ret;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, omap);
|
||||
|
@ -1,6 +1,4 @@
|
||||
/*
|
||||
* arch/arm/plat-omap/include/plat/dmtimer.h
|
||||
*
|
||||
* OMAP Dual-Mode Timers
|
||||
*
|
||||
* Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
|
||||
@ -36,8 +34,8 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#ifndef __ASM_ARCH_DMTIMER_H
|
||||
#define __ASM_ARCH_DMTIMER_H
|
||||
#ifndef __CLOCKSOURCE_DMTIMER_H
|
||||
#define __CLOCKSOURCE_DMTIMER_H
|
||||
|
||||
/* clock sources */
|
||||
#define OMAP_TIMER_SRC_SYS_CLK 0x00
|
||||
@ -121,37 +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);
|
||||
struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer);
|
||||
|
||||
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);
|
||||
|
||||
@ -272,6 +246,12 @@ int omap_dm_timers_active(void);
|
||||
#define OMAP_TIMER_TICK_INT_MASK_COUNT_REG \
|
||||
(_OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET | (WP_TOWR << WPSHIFT))
|
||||
|
||||
/*
|
||||
* The below are inlined to optimize code size for system timers. Other code
|
||||
* should not need these at all, see
|
||||
* include/linux/platform_data/pwm_omap_dmtimer.h
|
||||
*/
|
||||
#if defined(CONFIG_ARCH_OMAP1) || defined(CONFIG_ARCH_OMAP2PLUS)
|
||||
static inline u32 __omap_dm_timer_read(struct omap_dm_timer *timer, u32 reg,
|
||||
int posted)
|
||||
{
|
||||
@ -410,5 +390,5 @@ static inline void __omap_dm_timer_write_status(struct omap_dm_timer *timer,
|
||||
{
|
||||
writel_relaxed(value, timer->irq_stat);
|
||||
}
|
||||
|
||||
#endif /* __ASM_ARCH_DMTIMER_H */
|
||||
#endif /* CONFIG_ARCH_OMAP1 || CONFIG_ARCH_OMAP2PLUS */
|
||||
#endif /* __CLOCKSOURCE_DMTIMER_H */
|
@ -20,12 +20,50 @@
|
||||
#ifndef __PLATFORM_DATA_DMTIMER_OMAP_H__
|
||||
#define __PLATFORM_DATA_DMTIMER_OMAP_H__
|
||||
|
||||
struct omap_dm_timer_ops {
|
||||
struct omap_dm_timer *(*request_by_node)(struct device_node *np);
|
||||
struct omap_dm_timer *(*request_specific)(int timer_id);
|
||||
struct omap_dm_timer *(*request)(void);
|
||||
|
||||
int (*free)(struct omap_dm_timer *timer);
|
||||
|
||||
void (*enable)(struct omap_dm_timer *timer);
|
||||
void (*disable)(struct omap_dm_timer *timer);
|
||||
|
||||
int (*get_irq)(struct omap_dm_timer *timer);
|
||||
int (*set_int_enable)(struct omap_dm_timer *timer,
|
||||
unsigned int value);
|
||||
int (*set_int_disable)(struct omap_dm_timer *timer, u32 mask);
|
||||
|
||||
struct clk *(*get_fclk)(struct omap_dm_timer *timer);
|
||||
|
||||
int (*start)(struct omap_dm_timer *timer);
|
||||
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_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 (*set_prescaler)(struct omap_dm_timer *timer, int prescaler);
|
||||
|
||||
unsigned int (*read_counter)(struct omap_dm_timer *timer);
|
||||
int (*write_counter)(struct omap_dm_timer *timer,
|
||||
unsigned int value);
|
||||
unsigned int (*read_status)(struct omap_dm_timer *timer);
|
||||
int (*write_status)(struct omap_dm_timer *timer,
|
||||
unsigned int value);
|
||||
};
|
||||
|
||||
struct dmtimer_platform_data {
|
||||
/* set_timer_src - Only used for OMAP1 devices */
|
||||
int (*set_timer_src)(struct platform_device *pdev, int source);
|
||||
u32 timer_capability;
|
||||
u32 timer_errata;
|
||||
int (*get_context_loss_count)(struct device *);
|
||||
const struct omap_dm_timer_ops *timer_ops;
|
||||
};
|
||||
|
||||
#endif /* __PLATFORM_DATA_DMTIMER_OMAP_H__ */
|
||||
|
Loading…
Reference in New Issue
Block a user