Merge tag 'cleanup' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC cleanups on various subarchitectures from Olof Johansson: "Cleanup patches for various ARM platforms and some of their associated drivers. There's also a branch in here that enables Freescale i.MX to be part of the multiplatform support -- the first "big" SoC that is moved over (more multiplatform work comes in a separate branch later during the merge window)." Conflicts fixed as per Olof, including a silent semantic one in arch/arm/mach-omap2/board-generic.c (omap_prcm_restart() was renamed to omap3xxx_restart(), and a new user of the old name was added). * tag 'cleanup' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (189 commits) ARM: omap: fix typo on timer cleanup ARM: EXYNOS: Remove unused regs-mem.h file ARM: EXYNOS: Remove unused non-dt support for dwmci controller ARM: Kirkwood: Use hw_pci.ops instead of hw_pci.scan ARM: OMAP3: cm-t3517: use GPTIMER for system clock ARM: OMAP2+: timer: remove CONFIG_OMAP_32K_TIMER ARM: SAMSUNG: use devm_ functions for ADC driver ARM: EXYNOS: no duplicate mask/unmask in eint0_15 ARM: S3C24XX: SPI clock channel setup is fixed for S3C2443 ARM: EXYNOS: Remove i2c0 resource information and setting of device names ARM: Kirkwood: checkpatch cleanups ARM: Kirkwood: Fix sparse warnings. ARM: Kirkwood: Remove unused includes ARM: kirkwood: cleanup lsxl board includes ARM: integrator: use BUG_ON where possible ARM: integrator: push down SC dependencies ARM: integrator: delete static UART1 mapping ARM: integrator: delete SC mapping on the CP ARM: integrator: remove static CP syscon mapping ARM: integrator: remove static AP syscon mapping ...
This commit is contained in:
@@ -154,6 +154,12 @@ config OMAP_32K_TIMER
|
||||
intra-tick resolution than OMAP_MPU_TIMER. The 32KHz timer is
|
||||
currently only available for OMAP16XX, 24XX, 34XX and OMAP4/5.
|
||||
|
||||
On OMAP2PLUS this value is only used for CONFIG_HZ and
|
||||
CLOCK_TICK_RATE compile time calculation.
|
||||
The actual timer selection is done in the board file
|
||||
through the (DT_)MACHINE_START structure.
|
||||
|
||||
|
||||
config OMAP3_L2_AUX_SECURE_SAVE_RESTORE
|
||||
bool "OMAP3 HS/EMU save and restore for L2 AUX control register"
|
||||
depends on ARCH_OMAP3 && PM
|
||||
|
@@ -111,7 +111,7 @@ static int fpga_probe(struct platform_device *pdev)
|
||||
if (!iomem)
|
||||
return -ENODEV;
|
||||
|
||||
fpga = ioremap(iomem->start, H2P2_DBG_FPGA_SIZE);
|
||||
fpga = ioremap(iomem->start, resource_size(iomem));
|
||||
__raw_writew(0xff, &fpga->leds);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dbg_leds); i++) {
|
||||
|
@@ -35,11 +35,16 @@
|
||||
* 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/platform_data/dmtimer-omap.h>
|
||||
|
||||
#include <plat/dmtimer.h>
|
||||
|
||||
@@ -81,10 +86,6 @@ static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,
|
||||
|
||||
static void omap_timer_restore_context(struct omap_dm_timer *timer)
|
||||
{
|
||||
if (timer->revision == 1)
|
||||
__raw_writel(timer->context.tistat, timer->sys_stat);
|
||||
|
||||
__raw_writel(timer->context.tisr, timer->irq_stat);
|
||||
omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG,
|
||||
timer->context.twer);
|
||||
omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG,
|
||||
@@ -100,39 +101,38 @@ static void omap_timer_restore_context(struct omap_dm_timer *timer)
|
||||
timer->context.tclr);
|
||||
}
|
||||
|
||||
static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
|
||||
static int omap_dm_timer_reset(struct omap_dm_timer *timer)
|
||||
{
|
||||
int c;
|
||||
u32 l, timeout = 100000;
|
||||
|
||||
if (!timer->sys_stat)
|
||||
return;
|
||||
if (timer->revision != 1)
|
||||
return -EINVAL;
|
||||
|
||||
c = 0;
|
||||
while (!(__raw_readl(timer->sys_stat) & 1)) {
|
||||
c++;
|
||||
if (c > 100000) {
|
||||
printk(KERN_ERR "Timer failed to reset\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
|
||||
|
||||
static void omap_dm_timer_reset(struct omap_dm_timer *timer)
|
||||
{
|
||||
omap_dm_timer_enable(timer);
|
||||
if (timer->pdev->id != 1) {
|
||||
omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
|
||||
omap_dm_timer_wait_for_reset(timer);
|
||||
do {
|
||||
l = __omap_dm_timer_read(timer,
|
||||
OMAP_TIMER_V1_SYS_STAT_OFFSET, 0);
|
||||
} while (!l && timeout--);
|
||||
|
||||
if (!timeout) {
|
||||
dev_err(&timer->pdev->dev, "Timer failed to reset\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
__omap_dm_timer_reset(timer, 0, 0);
|
||||
omap_dm_timer_disable(timer);
|
||||
timer->posted = 1;
|
||||
/* Configure timer for smart-idle mode */
|
||||
l = __omap_dm_timer_read(timer, OMAP_TIMER_OCP_CFG_OFFSET, 0);
|
||||
l |= 0x2 << 0x3;
|
||||
__omap_dm_timer_write(timer, OMAP_TIMER_OCP_CFG_OFFSET, l, 0);
|
||||
|
||||
timer->posted = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int omap_dm_timer_prepare(struct omap_dm_timer *timer)
|
||||
static int omap_dm_timer_prepare(struct omap_dm_timer *timer)
|
||||
{
|
||||
int ret;
|
||||
int rc;
|
||||
|
||||
/*
|
||||
* FIXME: OMAP1 devices do not use the clock framework for dmtimers so
|
||||
@@ -147,13 +147,20 @@ int omap_dm_timer_prepare(struct omap_dm_timer *timer)
|
||||
}
|
||||
}
|
||||
|
||||
if (timer->capability & OMAP_TIMER_NEEDS_RESET)
|
||||
omap_dm_timer_reset(timer);
|
||||
omap_dm_timer_enable(timer);
|
||||
|
||||
ret = omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
|
||||
if (timer->capability & OMAP_TIMER_NEEDS_RESET) {
|
||||
rc = omap_dm_timer_reset(timer);
|
||||
if (rc) {
|
||||
omap_dm_timer_disable(timer);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
timer->posted = 1;
|
||||
return ret;
|
||||
__omap_dm_timer_enable_posted(timer);
|
||||
omap_dm_timer_disable(timer);
|
||||
|
||||
return omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
|
||||
}
|
||||
|
||||
static inline u32 omap_dm_timer_reserved_systimer(int id)
|
||||
@@ -209,6 +216,13 @@ struct omap_dm_timer *omap_dm_timer_request_specific(int id)
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
|
||||
/* 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()\n",
|
||||
__func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&dm_timer_lock, flags);
|
||||
list_for_each_entry(t, &omap_timer_list, node) {
|
||||
if (t->pdev->id == id && !t->reserved) {
|
||||
@@ -234,6 +248,58 @@ struct omap_dm_timer *omap_dm_timer_request_specific(int id)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific);
|
||||
|
||||
/**
|
||||
* omap_dm_timer_request_by_cap - Request a timer by capability
|
||||
* @cap: Bit mask of capabilities to match
|
||||
*
|
||||
* Find a timer based upon capabilities bit mask. Callers of this function
|
||||
* should use the definitions found in the plat/dmtimer.h file under the
|
||||
* comment "timer capabilities used in hwmod database". Returns pointer to
|
||||
* timer handle on success and a NULL pointer on failure.
|
||||
*/
|
||||
struct omap_dm_timer *omap_dm_timer_request_by_cap(u32 cap)
|
||||
{
|
||||
struct omap_dm_timer *timer = NULL, *t;
|
||||
unsigned long flags;
|
||||
|
||||
if (!cap)
|
||||
return NULL;
|
||||
|
||||
spin_lock_irqsave(&dm_timer_lock, flags);
|
||||
list_for_each_entry(t, &omap_timer_list, node) {
|
||||
if ((!t->reserved) && ((t->capability & cap) == cap)) {
|
||||
/*
|
||||
* If timer is not NULL, we have already found one timer
|
||||
* but it was not an exact match because it had more
|
||||
* capabilites that what was required. Therefore,
|
||||
* unreserve the last timer found and see if this one
|
||||
* is a better match.
|
||||
*/
|
||||
if (timer)
|
||||
timer->reserved = 0;
|
||||
|
||||
timer = t;
|
||||
timer->reserved = 1;
|
||||
|
||||
/* Exit loop early if we find an exact match */
|
||||
if (t->capability == cap)
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&dm_timer_lock, flags);
|
||||
|
||||
if (timer && omap_dm_timer_prepare(timer)) {
|
||||
timer->reserved = 0;
|
||||
timer = NULL;
|
||||
}
|
||||
|
||||
if (!timer)
|
||||
pr_debug("%s: timer request failed!\n", __func__);
|
||||
|
||||
return timer;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(omap_dm_timer_request_by_cap);
|
||||
|
||||
int omap_dm_timer_free(struct omap_dm_timer *timer)
|
||||
{
|
||||
if (unlikely(!timer))
|
||||
@@ -388,7 +454,6 @@ int omap_dm_timer_stop(struct omap_dm_timer *timer)
|
||||
*/
|
||||
timer->context.tclr =
|
||||
omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
|
||||
timer->context.tisr = __raw_readl(timer->irq_stat);
|
||||
omap_dm_timer_disable(timer);
|
||||
return 0;
|
||||
}
|
||||
@@ -398,7 +463,7 @@ int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
|
||||
{
|
||||
int ret;
|
||||
char *parent_name = NULL;
|
||||
struct clk *fclk, *parent;
|
||||
struct clk *parent;
|
||||
struct dmtimer_platform_data *pdata;
|
||||
|
||||
if (unlikely(!timer))
|
||||
@@ -414,14 +479,11 @@ int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
|
||||
* use the clock framework to set the parent clock. To be removed
|
||||
* once OMAP1 migrated to using clock framework for dmtimers
|
||||
*/
|
||||
if (pdata->set_timer_src)
|
||||
if (pdata && pdata->set_timer_src)
|
||||
return pdata->set_timer_src(timer->pdev, source);
|
||||
|
||||
fclk = clk_get(&timer->pdev->dev, "fck");
|
||||
if (IS_ERR_OR_NULL(fclk)) {
|
||||
pr_err("%s: fck not found\n", __func__);
|
||||
if (!timer->fclk)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (source) {
|
||||
case OMAP_TIMER_SRC_SYS_CLK:
|
||||
@@ -440,18 +502,15 @@ int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
|
||||
parent = clk_get(&timer->pdev->dev, parent_name);
|
||||
if (IS_ERR_OR_NULL(parent)) {
|
||||
pr_err("%s: %s not found\n", __func__, parent_name);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = clk_set_parent(fclk, parent);
|
||||
ret = clk_set_parent(timer->fclk, parent);
|
||||
if (IS_ERR_VALUE(ret))
|
||||
pr_err("%s: failed to set %s as parent\n", __func__,
|
||||
parent_name);
|
||||
|
||||
clk_put(parent);
|
||||
out:
|
||||
clk_put(fclk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -534,8 +593,8 @@ int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
|
||||
l |= OMAP_TIMER_CTRL_CE;
|
||||
else
|
||||
l &= ~OMAP_TIMER_CTRL_CE;
|
||||
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
|
||||
omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
|
||||
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
|
||||
|
||||
/* Save the context */
|
||||
timer->context.tclr = l;
|
||||
@@ -611,6 +670,37 @@ int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable);
|
||||
|
||||
/**
|
||||
* omap_dm_timer_set_int_disable - disable timer interrupts
|
||||
* @timer: pointer to timer handle
|
||||
* @mask: bit mask of interrupts to be disabled
|
||||
*
|
||||
* Disables the specified timer interrupts for a timer.
|
||||
*/
|
||||
int omap_dm_timer_set_int_disable(struct omap_dm_timer *timer, u32 mask)
|
||||
{
|
||||
u32 l = mask;
|
||||
|
||||
if (unlikely(!timer))
|
||||
return -EINVAL;
|
||||
|
||||
omap_dm_timer_enable(timer);
|
||||
|
||||
if (timer->revision == 1)
|
||||
l = __raw_readl(timer->irq_ena) & ~mask;
|
||||
|
||||
__raw_writel(l, timer->irq_dis);
|
||||
l = omap_dm_timer_read_reg(timer, OMAP_TIMER_WAKEUP_EN_REG) & ~mask;
|
||||
omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, l);
|
||||
|
||||
/* Save the context */
|
||||
timer->context.tier &= ~mask;
|
||||
timer->context.twer &= ~mask;
|
||||
omap_dm_timer_disable(timer);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_disable);
|
||||
|
||||
unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
|
||||
{
|
||||
unsigned int l;
|
||||
@@ -632,8 +722,7 @@ int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
|
||||
return -EINVAL;
|
||||
|
||||
__omap_dm_timer_write_status(timer, value);
|
||||
/* Save the context */
|
||||
timer->context.tisr = value;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(omap_dm_timer_write_status);
|
||||
@@ -696,7 +785,7 @@ static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
|
||||
struct device *dev = &pdev->dev;
|
||||
struct dmtimer_platform_data *pdata = pdev->dev.platform_data;
|
||||
|
||||
if (!pdata) {
|
||||
if (!pdata && !dev->of_node) {
|
||||
dev_err(dev, "%s: no platform data.\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
@@ -725,12 +814,25 @@ static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
timer->id = pdev->id;
|
||||
if (dev->of_node) {
|
||||
if (of_find_property(dev->of_node, "ti,timer-alwon", NULL))
|
||||
timer->capability |= OMAP_TIMER_ALWON;
|
||||
if (of_find_property(dev->of_node, "ti,timer-dsp", NULL))
|
||||
timer->capability |= OMAP_TIMER_HAS_DSP_IRQ;
|
||||
if (of_find_property(dev->of_node, "ti,timer-pwm", NULL))
|
||||
timer->capability |= OMAP_TIMER_HAS_PWM;
|
||||
if (of_find_property(dev->of_node, "ti,timer-secure", NULL))
|
||||
timer->capability |= OMAP_TIMER_SECURE;
|
||||
} else {
|
||||
timer->id = pdev->id;
|
||||
timer->errata = pdata->timer_errata;
|
||||
timer->capability = pdata->timer_capability;
|
||||
timer->reserved = omap_dm_timer_reserved_systimer(timer->id);
|
||||
timer->get_context_loss_count = pdata->get_context_loss_count;
|
||||
}
|
||||
|
||||
timer->irq = irq->start;
|
||||
timer->reserved = omap_dm_timer_reserved_systimer(timer->id);
|
||||
timer->pdev = pdev;
|
||||
timer->capability = pdata->timer_capability;
|
||||
timer->get_context_loss_count = pdata->get_context_loss_count;
|
||||
|
||||
/* Skip pm_runtime_enable for OMAP1 */
|
||||
if (!(timer->capability & OMAP_TIMER_NEEDS_RESET)) {
|
||||
@@ -770,7 +872,8 @@ static int __devexit omap_dm_timer_remove(struct platform_device *pdev)
|
||||
|
||||
spin_lock_irqsave(&dm_timer_lock, flags);
|
||||
list_for_each_entry(timer, &omap_timer_list, node)
|
||||
if (timer->pdev->id == pdev->id) {
|
||||
if (!strcmp(dev_name(&timer->pdev->dev),
|
||||
dev_name(&pdev->dev))) {
|
||||
list_del(&timer->node);
|
||||
ret = 0;
|
||||
break;
|
||||
@@ -780,11 +883,18 @@ static int __devexit omap_dm_timer_remove(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct of_device_id omap_timer_match[] = {
|
||||
{ .compatible = "ti,omap2-timer", },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, omap_timer_match);
|
||||
|
||||
static struct platform_driver omap_dm_timer_driver = {
|
||||
.probe = omap_dm_timer_probe,
|
||||
.remove = __devexit_p(omap_dm_timer_remove),
|
||||
.driver = {
|
||||
.name = "omap_timer",
|
||||
.of_match_table = of_match_ptr(omap_timer_match),
|
||||
},
|
||||
};
|
||||
|
||||
|
@@ -32,7 +32,6 @@
|
||||
* 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/platform_device.h>
|
||||
@@ -55,6 +54,10 @@
|
||||
#define OMAP_TIMER_TRIGGER_OVERFLOW 0x01
|
||||
#define OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE 0x02
|
||||
|
||||
/* posted mode types */
|
||||
#define OMAP_TIMER_NONPOSTED 0x00
|
||||
#define OMAP_TIMER_POSTED 0x01
|
||||
|
||||
/* timer capabilities used in hwmod database */
|
||||
#define OMAP_TIMER_SECURE 0x80000000
|
||||
#define OMAP_TIMER_ALWON 0x40000000
|
||||
@@ -62,16 +65,22 @@
|
||||
#define OMAP_TIMER_NEEDS_RESET 0x10000000
|
||||
#define OMAP_TIMER_HAS_DSP_IRQ 0x08000000
|
||||
|
||||
/*
|
||||
* timer errata flags
|
||||
*
|
||||
* Errata i103/i767 impacts all OMAP3/4/5 devices including AM33xx. This
|
||||
* errata prevents us from using posted mode on these devices, unless the
|
||||
* timer counter register is never read. For more details please refer to
|
||||
* the OMAP3/4/5 errata documents.
|
||||
*/
|
||||
#define OMAP_TIMER_ERRATA_I103_I767 0x80000000
|
||||
|
||||
struct omap_timer_capability_dev_attr {
|
||||
u32 timer_capability;
|
||||
};
|
||||
|
||||
struct omap_dm_timer;
|
||||
|
||||
struct timer_regs {
|
||||
u32 tidr;
|
||||
u32 tistat;
|
||||
u32 tisr;
|
||||
u32 tier;
|
||||
u32 twer;
|
||||
u32 tclr;
|
||||
@@ -90,16 +99,35 @@ struct timer_regs {
|
||||
u32 towr;
|
||||
};
|
||||
|
||||
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;
|
||||
struct omap_dm_timer {
|
||||
int id;
|
||||
int irq;
|
||||
struct clk *fclk;
|
||||
|
||||
void __iomem *io_base;
|
||||
void __iomem *irq_stat; /* TISR/IRQSTATUS interrupt status */
|
||||
void __iomem *irq_ena; /* irq enable */
|
||||
void __iomem *irq_dis; /* irq disable, only on v2 ip */
|
||||
void __iomem *pend; /* write pending */
|
||||
void __iomem *func_base; /* function register base */
|
||||
|
||||
unsigned long rate;
|
||||
unsigned reserved:1;
|
||||
unsigned posted:1;
|
||||
struct timer_regs context;
|
||||
int (*get_context_loss_count)(struct device *);
|
||||
int ctx_loss_count;
|
||||
int revision;
|
||||
u32 capability;
|
||||
u32 errata;
|
||||
struct platform_device *pdev;
|
||||
struct list_head node;
|
||||
};
|
||||
|
||||
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);
|
||||
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);
|
||||
@@ -121,6 +149,7 @@ int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, int toggle, i
|
||||
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);
|
||||
@@ -246,34 +275,6 @@ int omap_dm_timers_active(void);
|
||||
#define OMAP_TIMER_TICK_INT_MASK_COUNT_REG \
|
||||
(_OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET | (WP_TOWR << WPSHIFT))
|
||||
|
||||
struct omap_dm_timer {
|
||||
unsigned long phys_base;
|
||||
int id;
|
||||
int irq;
|
||||
struct clk *fclk;
|
||||
|
||||
void __iomem *io_base;
|
||||
void __iomem *sys_stat; /* TISTAT timer status */
|
||||
void __iomem *irq_stat; /* TISR/IRQSTATUS interrupt status */
|
||||
void __iomem *irq_ena; /* irq enable */
|
||||
void __iomem *irq_dis; /* irq disable, only on v2 ip */
|
||||
void __iomem *pend; /* write pending */
|
||||
void __iomem *func_base; /* function register base */
|
||||
|
||||
unsigned long rate;
|
||||
unsigned reserved:1;
|
||||
unsigned posted:1;
|
||||
struct timer_regs context;
|
||||
int (*get_context_loss_count)(struct device *);
|
||||
int ctx_loss_count;
|
||||
int revision;
|
||||
u32 capability;
|
||||
struct platform_device *pdev;
|
||||
struct list_head node;
|
||||
};
|
||||
|
||||
int omap_dm_timer_prepare(struct omap_dm_timer *timer);
|
||||
|
||||
static inline u32 __omap_dm_timer_read(struct omap_dm_timer *timer, u32 reg,
|
||||
int posted)
|
||||
{
|
||||
@@ -302,16 +303,13 @@ static inline void __omap_dm_timer_init_regs(struct omap_dm_timer *timer)
|
||||
tidr = __raw_readl(timer->io_base);
|
||||
if (!(tidr >> 16)) {
|
||||
timer->revision = 1;
|
||||
timer->sys_stat = timer->io_base +
|
||||
OMAP_TIMER_V1_SYS_STAT_OFFSET;
|
||||
timer->irq_stat = timer->io_base + OMAP_TIMER_V1_STAT_OFFSET;
|
||||
timer->irq_ena = timer->io_base + OMAP_TIMER_V1_INT_EN_OFFSET;
|
||||
timer->irq_dis = NULL;
|
||||
timer->irq_dis = timer->io_base + OMAP_TIMER_V1_INT_EN_OFFSET;
|
||||
timer->pend = timer->io_base + _OMAP_TIMER_WRITE_PEND_OFFSET;
|
||||
timer->func_base = timer->io_base;
|
||||
} else {
|
||||
timer->revision = 2;
|
||||
timer->sys_stat = NULL;
|
||||
timer->irq_stat = timer->io_base + OMAP_TIMER_V2_IRQSTATUS;
|
||||
timer->irq_ena = timer->io_base + OMAP_TIMER_V2_IRQENABLE_SET;
|
||||
timer->irq_dis = timer->io_base + OMAP_TIMER_V2_IRQENABLE_CLR;
|
||||
@@ -322,45 +320,44 @@ static inline void __omap_dm_timer_init_regs(struct omap_dm_timer *timer)
|
||||
}
|
||||
}
|
||||
|
||||
/* Assumes the source clock has been set by caller */
|
||||
static inline void __omap_dm_timer_reset(struct omap_dm_timer *timer,
|
||||
int autoidle, int wakeup)
|
||||
/*
|
||||
* __omap_dm_timer_enable_posted - enables write posted mode
|
||||
* @timer: pointer to timer instance handle
|
||||
*
|
||||
* Enables the write posted mode for the timer. When posted mode is enabled
|
||||
* writes to certain timer registers are immediately acknowledged by the
|
||||
* internal bus and hence prevents stalling the CPU waiting for the write to
|
||||
* complete. Enabling this feature can improve performance for writing to the
|
||||
* timer registers.
|
||||
*/
|
||||
static inline void __omap_dm_timer_enable_posted(struct omap_dm_timer *timer)
|
||||
{
|
||||
u32 l;
|
||||
if (timer->posted)
|
||||
return;
|
||||
|
||||
l = __raw_readl(timer->io_base + OMAP_TIMER_OCP_CFG_OFFSET);
|
||||
l |= 0x02 << 3; /* Set to smart-idle mode */
|
||||
l |= 0x2 << 8; /* Set clock activity to perserve f-clock on idle */
|
||||
if (timer->errata & OMAP_TIMER_ERRATA_I103_I767)
|
||||
return;
|
||||
|
||||
if (autoidle)
|
||||
l |= 0x1 << 0;
|
||||
|
||||
if (wakeup)
|
||||
l |= 1 << 2;
|
||||
|
||||
__raw_writel(l, timer->io_base + OMAP_TIMER_OCP_CFG_OFFSET);
|
||||
|
||||
/* Match hardware reset default of posted mode */
|
||||
__omap_dm_timer_write(timer, OMAP_TIMER_IF_CTRL_REG,
|
||||
OMAP_TIMER_CTRL_POSTED, 0);
|
||||
OMAP_TIMER_CTRL_POSTED, 0);
|
||||
timer->context.tsicr = OMAP_TIMER_CTRL_POSTED;
|
||||
timer->posted = OMAP_TIMER_POSTED;
|
||||
}
|
||||
|
||||
static inline int __omap_dm_timer_set_source(struct clk *timer_fck,
|
||||
struct clk *parent)
|
||||
/**
|
||||
* __omap_dm_timer_override_errata - override errata flags for a timer
|
||||
* @timer: pointer to timer handle
|
||||
* @errata: errata flags to be ignored
|
||||
*
|
||||
* For a given timer, override a timer errata by clearing the flags
|
||||
* specified by the errata argument. A specific erratum should only be
|
||||
* overridden for a timer if the timer is used in such a way the erratum
|
||||
* has no impact.
|
||||
*/
|
||||
static inline void __omap_dm_timer_override_errata(struct omap_dm_timer *timer,
|
||||
u32 errata)
|
||||
{
|
||||
int ret;
|
||||
|
||||
clk_disable(timer_fck);
|
||||
ret = clk_set_parent(timer_fck, parent);
|
||||
clk_enable(timer_fck);
|
||||
|
||||
/*
|
||||
* When the functional clock disappears, too quick writes seem
|
||||
* to cause an abort. XXX Is this still necessary?
|
||||
*/
|
||||
__delay(300000);
|
||||
|
||||
return ret;
|
||||
timer->errata &= ~errata;
|
||||
}
|
||||
|
||||
static inline void __omap_dm_timer_stop(struct omap_dm_timer *timer,
|
||||
|
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* arch/arm/plat-omap/include/mach/prcm.h
|
||||
*
|
||||
* Access definations for use in OMAP24XX clock and power management
|
||||
*
|
||||
* Copyright (C) 2005 Texas Instruments, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* XXX This file is deprecated. The PRCM is an OMAP2+-only subsystem,
|
||||
* so this file doesn't belong in plat-omap/include/plat. Please
|
||||
* do not add anything new to this file.
|
||||
*/
|
||||
|
||||
#ifndef __ASM_ARM_ARCH_OMAP_PRCM_H
|
||||
#define __ASM_ARM_ARCH_OMAP_PRCM_H
|
||||
|
||||
u32 omap_prcm_get_reset_sources(void);
|
||||
int omap2_cm_wait_idlest(void __iomem *reg, u32 mask, u8 idlest,
|
||||
const char *name);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user