1
0
Fork 0

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
hifive-unleashed-5.1
Arnd Bergmann 2018-03-07 16:16:07 +01:00
commit 6f566c4f30
13 changed files with 243 additions and 246 deletions

View File

@ -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"

View File

@ -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>

View File

@ -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"

View File

@ -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),

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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[] = {

View File

@ -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);

View File

@ -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 */

View File

@ -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__ */