1cf21405fSPaul Walmsley /*
2cf21405fSPaul Walmsley  * OMAP2/3 PRM module functions
3cf21405fSPaul Walmsley  *
426c98c56SPaul Walmsley  * Copyright (C) 2010-2011 Texas Instruments, Inc.
5cf21405fSPaul Walmsley  * Copyright (C) 2010 Nokia Corporation
6cf21405fSPaul Walmsley  * Benoît Cousson
7cf21405fSPaul Walmsley  * Paul Walmsley
8cf21405fSPaul Walmsley  *
9cf21405fSPaul Walmsley  * This program is free software; you can redistribute it and/or modify
10cf21405fSPaul Walmsley  * it under the terms of the GNU General Public License version 2 as
11cf21405fSPaul Walmsley  * published by the Free Software Foundation.
12cf21405fSPaul Walmsley  */
13cf21405fSPaul Walmsley 
14cf21405fSPaul Walmsley #include <linux/kernel.h>
15cf21405fSPaul Walmsley #include <linux/errno.h>
16cf21405fSPaul Walmsley #include <linux/err.h>
1759fb659bSPaul Walmsley #include <linux/io.h>
18cf21405fSPaul Walmsley 
19cf21405fSPaul Walmsley #include <plat/common.h>
20cf21405fSPaul Walmsley #include <plat/cpu.h>
21cf21405fSPaul Walmsley #include <plat/prcm.h>
22cf21405fSPaul Walmsley 
2358aaa599SKevin Hilman #include "vp.h"
2458aaa599SKevin Hilman 
2559fb659bSPaul Walmsley #include "prm2xxx_3xxx.h"
2659fb659bSPaul Walmsley #include "cm2xxx_3xxx.h"
27cf21405fSPaul Walmsley #include "prm-regbits-24xx.h"
28cf21405fSPaul Walmsley #include "prm-regbits-34xx.h"
29cf21405fSPaul Walmsley 
30c4d7e58fSPaul Walmsley u32 omap2_prm_read_mod_reg(s16 module, u16 idx)
3159fb659bSPaul Walmsley {
3259fb659bSPaul Walmsley 	return __raw_readl(prm_base + module + idx);
3359fb659bSPaul Walmsley }
3459fb659bSPaul Walmsley 
35c4d7e58fSPaul Walmsley void omap2_prm_write_mod_reg(u32 val, s16 module, u16 idx)
3659fb659bSPaul Walmsley {
3759fb659bSPaul Walmsley 	__raw_writel(val, prm_base + module + idx);
3859fb659bSPaul Walmsley }
3959fb659bSPaul Walmsley 
4059fb659bSPaul Walmsley /* Read-modify-write a register in a PRM module. Caller must lock */
41c4d7e58fSPaul Walmsley u32 omap2_prm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx)
4259fb659bSPaul Walmsley {
4359fb659bSPaul Walmsley 	u32 v;
4459fb659bSPaul Walmsley 
45c4d7e58fSPaul Walmsley 	v = omap2_prm_read_mod_reg(module, idx);
4659fb659bSPaul Walmsley 	v &= ~mask;
4759fb659bSPaul Walmsley 	v |= bits;
48c4d7e58fSPaul Walmsley 	omap2_prm_write_mod_reg(v, module, idx);
4959fb659bSPaul Walmsley 
5059fb659bSPaul Walmsley 	return v;
5159fb659bSPaul Walmsley }
5259fb659bSPaul Walmsley 
5359fb659bSPaul Walmsley /* Read a PRM register, AND it, and shift the result down to bit 0 */
54c4d7e58fSPaul Walmsley u32 omap2_prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask)
5559fb659bSPaul Walmsley {
5659fb659bSPaul Walmsley 	u32 v;
5759fb659bSPaul Walmsley 
58c4d7e58fSPaul Walmsley 	v = omap2_prm_read_mod_reg(domain, idx);
5959fb659bSPaul Walmsley 	v &= mask;
6059fb659bSPaul Walmsley 	v >>= __ffs(mask);
6159fb659bSPaul Walmsley 
6259fb659bSPaul Walmsley 	return v;
6359fb659bSPaul Walmsley }
6459fb659bSPaul Walmsley 
65c4d7e58fSPaul Walmsley u32 omap2_prm_set_mod_reg_bits(u32 bits, s16 module, s16 idx)
6659fb659bSPaul Walmsley {
67c4d7e58fSPaul Walmsley 	return omap2_prm_rmw_mod_reg_bits(bits, bits, module, idx);
6859fb659bSPaul Walmsley }
6959fb659bSPaul Walmsley 
70c4d7e58fSPaul Walmsley u32 omap2_prm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx)
7159fb659bSPaul Walmsley {
72c4d7e58fSPaul Walmsley 	return omap2_prm_rmw_mod_reg_bits(bits, 0x0, module, idx);
7359fb659bSPaul Walmsley }
7459fb659bSPaul Walmsley 
7559fb659bSPaul Walmsley 
76cf21405fSPaul Walmsley /**
77cf21405fSPaul Walmsley  * omap2_prm_is_hardreset_asserted - read the HW reset line state of
78cf21405fSPaul Walmsley  * submodules contained in the hwmod module
79cf21405fSPaul Walmsley  * @prm_mod: PRM submodule base (e.g. CORE_MOD)
80cf21405fSPaul Walmsley  * @shift: register bit shift corresponding to the reset line to check
81cf21405fSPaul Walmsley  *
82cf21405fSPaul Walmsley  * Returns 1 if the (sub)module hardreset line is currently asserted,
83cf21405fSPaul Walmsley  * 0 if the (sub)module hardreset line is not currently asserted, or
84cf21405fSPaul Walmsley  * -EINVAL if called while running on a non-OMAP2/3 chip.
85cf21405fSPaul Walmsley  */
86cf21405fSPaul Walmsley int omap2_prm_is_hardreset_asserted(s16 prm_mod, u8 shift)
87cf21405fSPaul Walmsley {
88cf21405fSPaul Walmsley 	if (!(cpu_is_omap24xx() || cpu_is_omap34xx()))
89cf21405fSPaul Walmsley 		return -EINVAL;
90cf21405fSPaul Walmsley 
91c4d7e58fSPaul Walmsley 	return omap2_prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTCTRL,
92cf21405fSPaul Walmsley 				       (1 << shift));
93cf21405fSPaul Walmsley }
94cf21405fSPaul Walmsley 
95cf21405fSPaul Walmsley /**
96cf21405fSPaul Walmsley  * omap2_prm_assert_hardreset - assert the HW reset line of a submodule
97cf21405fSPaul Walmsley  * @prm_mod: PRM submodule base (e.g. CORE_MOD)
98cf21405fSPaul Walmsley  * @shift: register bit shift corresponding to the reset line to assert
99cf21405fSPaul Walmsley  *
100cf21405fSPaul Walmsley  * Some IPs like dsp or iva contain processors that require an HW
101cf21405fSPaul Walmsley  * reset line to be asserted / deasserted in order to fully enable the
102cf21405fSPaul Walmsley  * IP.  These modules may have multiple hard-reset lines that reset
103cf21405fSPaul Walmsley  * different 'submodules' inside the IP block.  This function will
104cf21405fSPaul Walmsley  * place the submodule into reset.  Returns 0 upon success or -EINVAL
105cf21405fSPaul Walmsley  * upon an argument error.
106cf21405fSPaul Walmsley  */
107cf21405fSPaul Walmsley int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift)
108cf21405fSPaul Walmsley {
109cf21405fSPaul Walmsley 	u32 mask;
110cf21405fSPaul Walmsley 
111cf21405fSPaul Walmsley 	if (!(cpu_is_omap24xx() || cpu_is_omap34xx()))
112cf21405fSPaul Walmsley 		return -EINVAL;
113cf21405fSPaul Walmsley 
114cf21405fSPaul Walmsley 	mask = 1 << shift;
115c4d7e58fSPaul Walmsley 	omap2_prm_rmw_mod_reg_bits(mask, mask, prm_mod, OMAP2_RM_RSTCTRL);
116cf21405fSPaul Walmsley 
117cf21405fSPaul Walmsley 	return 0;
118cf21405fSPaul Walmsley }
119cf21405fSPaul Walmsley 
120cf21405fSPaul Walmsley /**
121cf21405fSPaul Walmsley  * omap2_prm_deassert_hardreset - deassert a submodule hardreset line and wait
122cf21405fSPaul Walmsley  * @prm_mod: PRM submodule base (e.g. CORE_MOD)
123cc1226e7Somar ramirez  * @rst_shift: register bit shift corresponding to the reset line to deassert
124cc1226e7Somar ramirez  * @st_shift: register bit shift for the status of the deasserted submodule
125cf21405fSPaul Walmsley  *
126cf21405fSPaul Walmsley  * Some IPs like dsp or iva contain processors that require an HW
127cf21405fSPaul Walmsley  * reset line to be asserted / deasserted in order to fully enable the
128cf21405fSPaul Walmsley  * IP.  These modules may have multiple hard-reset lines that reset
129cf21405fSPaul Walmsley  * different 'submodules' inside the IP block.  This function will
130cf21405fSPaul Walmsley  * take the submodule out of reset and wait until the PRCM indicates
131cf21405fSPaul Walmsley  * that the reset has completed before returning.  Returns 0 upon success or
132cf21405fSPaul Walmsley  * -EINVAL upon an argument error, -EEXIST if the submodule was already out
133cf21405fSPaul Walmsley  * of reset, or -EBUSY if the submodule did not exit reset promptly.
134cf21405fSPaul Walmsley  */
135cc1226e7Somar ramirez int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift, u8 st_shift)
136cf21405fSPaul Walmsley {
137cc1226e7Somar ramirez 	u32 rst, st;
138cf21405fSPaul Walmsley 	int c;
139cf21405fSPaul Walmsley 
140cf21405fSPaul Walmsley 	if (!(cpu_is_omap24xx() || cpu_is_omap34xx()))
141cf21405fSPaul Walmsley 		return -EINVAL;
142cf21405fSPaul Walmsley 
143cc1226e7Somar ramirez 	rst = 1 << rst_shift;
144cc1226e7Somar ramirez 	st = 1 << st_shift;
145cf21405fSPaul Walmsley 
146cf21405fSPaul Walmsley 	/* Check the current status to avoid de-asserting the line twice */
147cc1226e7Somar ramirez 	if (omap2_prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTCTRL, rst) == 0)
148cf21405fSPaul Walmsley 		return -EEXIST;
149cf21405fSPaul Walmsley 
150cf21405fSPaul Walmsley 	/* Clear the reset status by writing 1 to the status bit */
151cc1226e7Somar ramirez 	omap2_prm_rmw_mod_reg_bits(0xffffffff, st, prm_mod, OMAP2_RM_RSTST);
152cf21405fSPaul Walmsley 	/* de-assert the reset control line */
153cc1226e7Somar ramirez 	omap2_prm_rmw_mod_reg_bits(rst, 0, prm_mod, OMAP2_RM_RSTCTRL);
154cf21405fSPaul Walmsley 	/* wait the status to be set */
155c4d7e58fSPaul Walmsley 	omap_test_timeout(omap2_prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTST,
156cc1226e7Somar ramirez 						  st),
157cf21405fSPaul Walmsley 			  MAX_MODULE_HARDRESET_WAIT, c);
158cf21405fSPaul Walmsley 
159cf21405fSPaul Walmsley 	return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0;
160cf21405fSPaul Walmsley }
16158aaa599SKevin Hilman 
16258aaa599SKevin Hilman /* PRM VP */
16358aaa599SKevin Hilman 
16458aaa599SKevin Hilman /*
16558aaa599SKevin Hilman  * struct omap3_vp - OMAP3 VP register access description.
16658aaa599SKevin Hilman  * @tranxdone_status: VP_TRANXDONE_ST bitmask in PRM_IRQSTATUS_MPU reg
16758aaa599SKevin Hilman  */
16858aaa599SKevin Hilman struct omap3_vp {
16958aaa599SKevin Hilman 	u32 tranxdone_status;
17058aaa599SKevin Hilman };
17158aaa599SKevin Hilman 
1724bb73adeSKevin Hilman static struct omap3_vp omap3_vp[] = {
17358aaa599SKevin Hilman 	[OMAP3_VP_VDD_MPU_ID] = {
17458aaa599SKevin Hilman 		.tranxdone_status = OMAP3430_VP1_TRANXDONE_ST_MASK,
17558aaa599SKevin Hilman 	},
17658aaa599SKevin Hilman 	[OMAP3_VP_VDD_CORE_ID] = {
17758aaa599SKevin Hilman 		.tranxdone_status = OMAP3430_VP2_TRANXDONE_ST_MASK,
17858aaa599SKevin Hilman 	},
17958aaa599SKevin Hilman };
18058aaa599SKevin Hilman 
18158aaa599SKevin Hilman #define MAX_VP_ID ARRAY_SIZE(omap3_vp);
18258aaa599SKevin Hilman 
18358aaa599SKevin Hilman u32 omap3_prm_vp_check_txdone(u8 vp_id)
18458aaa599SKevin Hilman {
18558aaa599SKevin Hilman 	struct omap3_vp *vp = &omap3_vp[vp_id];
18658aaa599SKevin Hilman 	u32 irqstatus;
18758aaa599SKevin Hilman 
18858aaa599SKevin Hilman 	irqstatus = omap2_prm_read_mod_reg(OCP_MOD,
18958aaa599SKevin Hilman 					   OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
19058aaa599SKevin Hilman 	return irqstatus & vp->tranxdone_status;
19158aaa599SKevin Hilman }
19258aaa599SKevin Hilman 
19358aaa599SKevin Hilman void omap3_prm_vp_clear_txdone(u8 vp_id)
19458aaa599SKevin Hilman {
19558aaa599SKevin Hilman 	struct omap3_vp *vp = &omap3_vp[vp_id];
19658aaa599SKevin Hilman 
19758aaa599SKevin Hilman 	omap2_prm_write_mod_reg(vp->tranxdone_status,
19858aaa599SKevin Hilman 				OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
19958aaa599SKevin Hilman }
2004bb73adeSKevin Hilman 
2014bb73adeSKevin Hilman u32 omap3_prm_vcvp_read(u8 offset)
2024bb73adeSKevin Hilman {
2034bb73adeSKevin Hilman 	return omap2_prm_read_mod_reg(OMAP3430_GR_MOD, offset);
2044bb73adeSKevin Hilman }
2054bb73adeSKevin Hilman 
2064bb73adeSKevin Hilman void omap3_prm_vcvp_write(u32 val, u8 offset)
2074bb73adeSKevin Hilman {
2084bb73adeSKevin Hilman 	omap2_prm_write_mod_reg(val, OMAP3430_GR_MOD, offset);
2094bb73adeSKevin Hilman }
2104bb73adeSKevin Hilman 
2114bb73adeSKevin Hilman u32 omap3_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset)
2124bb73adeSKevin Hilman {
2134bb73adeSKevin Hilman 	return omap2_prm_rmw_mod_reg_bits(mask, bits, OMAP3430_GR_MOD, offset);
2144bb73adeSKevin Hilman }
21526c98c56SPaul Walmsley 
21626c98c56SPaul Walmsley /**
21726c98c56SPaul Walmsley  * omap3xxx_prm_read_pending_irqs - read pending PRM MPU IRQs into @events
21826c98c56SPaul Walmsley  * @events: ptr to a u32, preallocated by caller
21926c98c56SPaul Walmsley  *
22026c98c56SPaul Walmsley  * Read PRM_IRQSTATUS_MPU bits, AND'ed with the currently-enabled PRM
22126c98c56SPaul Walmsley  * MPU IRQs, and store the result into the u32 pointed to by @events.
22226c98c56SPaul Walmsley  * No return value.
22326c98c56SPaul Walmsley  */
22426c98c56SPaul Walmsley void omap3xxx_prm_read_pending_irqs(unsigned long *events)
22526c98c56SPaul Walmsley {
22626c98c56SPaul Walmsley 	u32 mask, st;
22726c98c56SPaul Walmsley 
22826c98c56SPaul Walmsley 	/* XXX Can the mask read be avoided (e.g., can it come from RAM?) */
22926c98c56SPaul Walmsley 	mask = omap2_prm_read_mod_reg(OCP_MOD, OMAP3_PRM_IRQENABLE_MPU_OFFSET);
23026c98c56SPaul Walmsley 	st = omap2_prm_read_mod_reg(OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
23126c98c56SPaul Walmsley 
23226c98c56SPaul Walmsley 	events[0] = mask & st;
23326c98c56SPaul Walmsley }
23426c98c56SPaul Walmsley 
23526c98c56SPaul Walmsley /**
23626c98c56SPaul Walmsley  * omap3xxx_prm_ocp_barrier - force buffered MPU writes to the PRM to complete
23726c98c56SPaul Walmsley  *
23826c98c56SPaul Walmsley  * Force any buffered writes to the PRM IP block to complete.  Needed
23926c98c56SPaul Walmsley  * by the PRM IRQ handler, which reads and writes directly to the IP
24026c98c56SPaul Walmsley  * block, to avoid race conditions after acknowledging or clearing IRQ
24126c98c56SPaul Walmsley  * bits.  No return value.
24226c98c56SPaul Walmsley  */
24326c98c56SPaul Walmsley void omap3xxx_prm_ocp_barrier(void)
24426c98c56SPaul Walmsley {
24526c98c56SPaul Walmsley 	omap2_prm_read_mod_reg(OCP_MOD, OMAP3_PRM_REVISION_OFFSET);
24626c98c56SPaul Walmsley }
247