diff options
-rw-r--r-- | arch/arm/mach-omap1/Kconfig | 1 | ||||
-rw-r--r-- | arch/arm/mach-omap1/pm.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-omap1/timer.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-omap2/pdata-quirks.c | 32 | ||||
-rw-r--r-- | arch/arm/mach-omap2/timer.c | 2 | ||||
-rw-r--r-- | arch/arm/plat-omap/Kconfig | 6 | ||||
-rw-r--r-- | arch/arm/plat-omap/Makefile | 1 | ||||
-rw-r--r-- | drivers/clocksource/Kconfig | 3 | ||||
-rw-r--r-- | drivers/clocksource/Makefile | 1 | ||||
-rw-r--r-- | drivers/clocksource/timer-ti-dm.c (renamed from arch/arm/plat-omap/dmtimer.c) | 293 | ||||
-rw-r--r-- | drivers/pwm/pwm-omap-dmtimer.c | 68 | ||||
-rw-r--r-- | include/clocksource/timer-ti-dm.h (renamed from arch/arm/plat-omap/include/plat/dmtimer.h) | 40 | ||||
-rw-r--r-- | include/linux/platform_data/dmtimer-omap.h | 38 |
13 files changed, 243 insertions, 246 deletions
diff --git a/arch/arm/mach-omap1/Kconfig b/arch/arm/mach-omap1/Kconfig index 45c6b733c881..c4694f26b5c4 100644 --- a/arch/arm/mach-omap1/Kconfig +++ b/arch/arm/mach-omap1/Kconfig @@ -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" diff --git a/arch/arm/mach-omap1/pm.c b/arch/arm/mach-omap1/pm.c index f1135bf8940e..3e1de14805e4 100644 --- a/arch/arm/mach-omap1/pm.c +++ b/arch/arm/mach-omap1/pm.c @@ -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> diff --git a/arch/arm/mach-omap1/timer.c b/arch/arm/mach-omap1/timer.c index 8fb1ec6fa999..4447210c9b0d 100644 --- a/arch/arm/mach-omap1/timer.c +++ b/arch/arm/mach-omap1/timer.c @@ -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" diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c index 6b433fce65a5..e7d7fc7ddaa2 100644 --- a/arch/arm/mach-omap2/pdata-quirks.c +++ b/arch/arm/mach-omap2/pdata-quirks.c @@ -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), diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index d61fbd7a2840..4fb4dc24e5e9 100644 --- a/arch/arm/mach-omap2/timer.c +++ b/arch/arm/mach-omap2/timer.c @@ -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" diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index 7276afee30b3..afc1a1d4f7a5 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -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 diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile index 47e186729d44..7215ada707e4 100644 --- a/arch/arm/plat-omap/Makefile +++ b/arch/arm/plat-omap/Makefile @@ -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 diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index b3b4ed9b6874..5995086ec328 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -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 diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index d6dec4489d66..c8c5109f2e50 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -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 diff --git a/arch/arm/plat-omap/dmtimer.c b/drivers/clocksource/timer-ti-dm.c index d443e481c3e9..4cce6b224b87 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/drivers/clocksource/timer-ti-dm.c @@ -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[] = { diff --git a/drivers/pwm/pwm-omap-dmtimer.c b/drivers/pwm/pwm-omap-dmtimer.c index 5ad42f33e70c..665da3c8fbce 100644 --- a/drivers/pwm/pwm-omap-dmtimer.c +++ b/drivers/pwm/pwm-omap-dmtimer.c @@ -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); diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/include/clocksource/timer-ti-dm.h index 8b7d8a6e02cc..7d9598dc578d 100644 --- a/arch/arm/plat-omap/include/plat/dmtimer.h +++ b/include/clocksource/timer-ti-dm.h @@ -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 */ diff --git a/include/linux/platform_data/dmtimer-omap.h b/include/linux/platform_data/dmtimer-omap.h index a19b78d826e9..757a0f9e26f9 100644 --- a/include/linux/platform_data/dmtimer-omap.h +++ b/include/linux/platform_data/dmtimer-omap.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__ */ |