blob: 706f27a79440adae190bc399a639e2a17b77b3ca [file] [log] [blame]
/*
* OMAP4 PRM module functions
*
* Copyright (C) 2011 Texas Instruments, Inc.
* Copyright (C) 2010 Nokia Corporation
* BenoƮt Cousson
* Paul Walmsley
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/io.h>
#include <plat/cpu.h>
#include <plat/irqs.h>
#include <plat/prcm.h>
#include "iomap.h"
#include "common.h"
#include "vp.h"
#include "prm44xx.h"
#include "prm-regbits-44xx.h"
#include "prcm44xx.h"
#include "prminst44xx.h"
static const struct omap_prcm_irq omap4_prcm_irqs[] = {
OMAP_PRCM_IRQ("wkup", 0, 0),
OMAP_PRCM_IRQ("io", 9, 1),
};
static struct omap_prcm_irq_setup omap4_prcm_irq_setup = {
.ack = OMAP4_PRM_IRQSTATUS_MPU_OFFSET,
.mask = OMAP4_PRM_IRQENABLE_MPU_OFFSET,
.nr_regs = 2,
.irqs = omap4_prcm_irqs,
.nr_irqs = ARRAY_SIZE(omap4_prcm_irqs),
.irq = OMAP44XX_IRQ_PRCM,
.read_pending_irqs = &omap44xx_prm_read_pending_irqs,
.ocp_barrier = &omap44xx_prm_ocp_barrier,
.save_and_clear_irqen = &omap44xx_prm_save_and_clear_irqen,
.restore_irqen = &omap44xx_prm_restore_irqen,
};
u32 omap4_prm_read_inst_reg(s16 inst, u16 reg)
{
return __raw_readl(OMAP44XX_PRM_REGADDR(inst, reg));
}
void omap4_prm_write_inst_reg(u32 val, s16 inst, u16 reg)
{
__raw_writel(val, OMAP44XX_PRM_REGADDR(inst, reg));
}
u32 omap4_prm_rmw_inst_reg_bits(u32 mask, u32 bits, s16 inst, s16 reg)
{
u32 v;
v = omap4_prm_read_inst_reg(inst, reg);
v &= ~mask;
v |= bits;
omap4_prm_write_inst_reg(v, inst, reg);
return v;
}
struct omap4_vp {
u32 irqstatus_mpu;
u32 tranxdone_status;
};
static struct omap4_vp omap4_vp[] = {
[OMAP4_VP_VDD_MPU_ID] = {
.irqstatus_mpu = OMAP4_PRM_IRQSTATUS_MPU_2_OFFSET,
.tranxdone_status = OMAP4430_VP_MPU_TRANXDONE_ST_MASK,
},
[OMAP4_VP_VDD_IVA_ID] = {
.irqstatus_mpu = OMAP4_PRM_IRQSTATUS_MPU_OFFSET,
.tranxdone_status = OMAP4430_VP_IVA_TRANXDONE_ST_MASK,
},
[OMAP4_VP_VDD_CORE_ID] = {
.irqstatus_mpu = OMAP4_PRM_IRQSTATUS_MPU_OFFSET,
.tranxdone_status = OMAP4430_VP_CORE_TRANXDONE_ST_MASK,
},
};
u32 omap4_prm_vp_check_txdone(u8 vp_id)
{
struct omap4_vp *vp = &omap4_vp[vp_id];
u32 irqstatus;
irqstatus = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
OMAP4430_PRM_OCP_SOCKET_INST,
vp->irqstatus_mpu);
return irqstatus & vp->tranxdone_status;
}
void omap4_prm_vp_clear_txdone(u8 vp_id)
{
struct omap4_vp *vp = &omap4_vp[vp_id];
omap4_prminst_write_inst_reg(vp->tranxdone_status,
OMAP4430_PRM_PARTITION,
OMAP4430_PRM_OCP_SOCKET_INST,
vp->irqstatus_mpu);
};
u32 omap4_prm_vcvp_read(u8 offset)
{
return omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
OMAP4430_PRM_DEVICE_INST, offset);
}
void omap4_prm_vcvp_write(u32 val, u8 offset)
{
omap4_prminst_write_inst_reg(val, OMAP4430_PRM_PARTITION,
OMAP4430_PRM_DEVICE_INST, offset);
}
u32 omap4_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset)
{
return omap4_prminst_rmw_inst_reg_bits(mask, bits,
OMAP4430_PRM_PARTITION,
OMAP4430_PRM_DEVICE_INST,
offset);
}
static inline u32 _read_pending_irq_reg(u16 irqen_offs, u16 irqst_offs)
{
u32 mask, st;
mask = omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
irqen_offs);
st = omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST, irqst_offs);
return mask & st;
}
void omap44xx_prm_read_pending_irqs(unsigned long *events)
{
events[0] = _read_pending_irq_reg(OMAP4_PRM_IRQENABLE_MPU_OFFSET,
OMAP4_PRM_IRQSTATUS_MPU_OFFSET);
events[1] = _read_pending_irq_reg(OMAP4_PRM_IRQENABLE_MPU_2_OFFSET,
OMAP4_PRM_IRQSTATUS_MPU_2_OFFSET);
}
void omap44xx_prm_ocp_barrier(void)
{
omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
OMAP4_REVISION_PRM_OFFSET);
}
void omap44xx_prm_save_and_clear_irqen(u32 *saved_mask)
{
saved_mask[0] =
omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
OMAP4_PRM_IRQSTATUS_MPU_OFFSET);
saved_mask[1] =
omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
OMAP4_PRM_IRQSTATUS_MPU_2_OFFSET);
omap4_prm_write_inst_reg(0, OMAP4430_PRM_OCP_SOCKET_INST,
OMAP4_PRM_IRQENABLE_MPU_OFFSET);
omap4_prm_write_inst_reg(0, OMAP4430_PRM_OCP_SOCKET_INST,
OMAP4_PRM_IRQENABLE_MPU_2_OFFSET);
omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
OMAP4_REVISION_PRM_OFFSET);
}
void omap44xx_prm_restore_irqen(u32 *saved_mask)
{
omap4_prm_write_inst_reg(saved_mask[0], OMAP4430_PRM_OCP_SOCKET_INST,
OMAP4_PRM_IRQENABLE_MPU_OFFSET);
omap4_prm_write_inst_reg(saved_mask[1], OMAP4430_PRM_OCP_SOCKET_INST,
OMAP4_PRM_IRQENABLE_MPU_2_OFFSET);
}
static int __init omap4xxx_prcm_init(void)
{
if (cpu_is_omap44xx())
return omap_prcm_register_chain_handler(&omap4_prcm_irq_setup);
return 0;
}
subsys_initcall(omap4xxx_prcm_init);