1 /* 2 * OMAP2/3 PRM module functions 3 * 4 * Copyright (C) 2010 Texas Instruments, Inc. 5 * Copyright (C) 2010 Nokia Corporation 6 * Benoît Cousson 7 * Paul Walmsley 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License version 2 as 11 * published by the Free Software Foundation. 12 */ 13 14 #include <linux/kernel.h> 15 #include <linux/errno.h> 16 #include <linux/err.h> 17 #include <linux/io.h> 18 19 #include <plat/common.h> 20 #include <plat/cpu.h> 21 #include <plat/prcm.h> 22 23 #include "prm2xxx_3xxx.h" 24 #include "cm2xxx_3xxx.h" 25 #include "prm-regbits-24xx.h" 26 #include "prm-regbits-34xx.h" 27 28 u32 omap2_prm_read_mod_reg(s16 module, u16 idx) 29 { 30 return __raw_readl(prm_base + module + idx); 31 } 32 33 void omap2_prm_write_mod_reg(u32 val, s16 module, u16 idx) 34 { 35 __raw_writel(val, prm_base + module + idx); 36 } 37 38 /* Read-modify-write a register in a PRM module. Caller must lock */ 39 u32 omap2_prm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx) 40 { 41 u32 v; 42 43 v = omap2_prm_read_mod_reg(module, idx); 44 v &= ~mask; 45 v |= bits; 46 omap2_prm_write_mod_reg(v, module, idx); 47 48 return v; 49 } 50 51 /* Read a PRM register, AND it, and shift the result down to bit 0 */ 52 u32 omap2_prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask) 53 { 54 u32 v; 55 56 v = omap2_prm_read_mod_reg(domain, idx); 57 v &= mask; 58 v >>= __ffs(mask); 59 60 return v; 61 } 62 63 u32 omap2_prm_set_mod_reg_bits(u32 bits, s16 module, s16 idx) 64 { 65 return omap2_prm_rmw_mod_reg_bits(bits, bits, module, idx); 66 } 67 68 u32 omap2_prm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx) 69 { 70 return omap2_prm_rmw_mod_reg_bits(bits, 0x0, module, idx); 71 } 72 73 74 /** 75 * omap2_prm_is_hardreset_asserted - read the HW reset line state of 76 * submodules contained in the hwmod module 77 * @prm_mod: PRM submodule base (e.g. CORE_MOD) 78 * @shift: register bit shift corresponding to the reset line to check 79 * 80 * Returns 1 if the (sub)module hardreset line is currently asserted, 81 * 0 if the (sub)module hardreset line is not currently asserted, or 82 * -EINVAL if called while running on a non-OMAP2/3 chip. 83 */ 84 int omap2_prm_is_hardreset_asserted(s16 prm_mod, u8 shift) 85 { 86 if (!(cpu_is_omap24xx() || cpu_is_omap34xx())) 87 return -EINVAL; 88 89 return omap2_prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTCTRL, 90 (1 << shift)); 91 } 92 93 /** 94 * omap2_prm_assert_hardreset - assert the HW reset line of a submodule 95 * @prm_mod: PRM submodule base (e.g. CORE_MOD) 96 * @shift: register bit shift corresponding to the reset line to assert 97 * 98 * Some IPs like dsp or iva contain processors that require an HW 99 * reset line to be asserted / deasserted in order to fully enable the 100 * IP. These modules may have multiple hard-reset lines that reset 101 * different 'submodules' inside the IP block. This function will 102 * place the submodule into reset. Returns 0 upon success or -EINVAL 103 * upon an argument error. 104 */ 105 int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift) 106 { 107 u32 mask; 108 109 if (!(cpu_is_omap24xx() || cpu_is_omap34xx())) 110 return -EINVAL; 111 112 mask = 1 << shift; 113 omap2_prm_rmw_mod_reg_bits(mask, mask, prm_mod, OMAP2_RM_RSTCTRL); 114 115 return 0; 116 } 117 118 /** 119 * omap2_prm_deassert_hardreset - deassert a submodule hardreset line and wait 120 * @prm_mod: PRM submodule base (e.g. CORE_MOD) 121 * @shift: register bit shift corresponding to the reset line to deassert 122 * 123 * Some IPs like dsp or iva contain processors that require an HW 124 * reset line to be asserted / deasserted in order to fully enable the 125 * IP. These modules may have multiple hard-reset lines that reset 126 * different 'submodules' inside the IP block. This function will 127 * take the submodule out of reset and wait until the PRCM indicates 128 * that the reset has completed before returning. Returns 0 upon success or 129 * -EINVAL upon an argument error, -EEXIST if the submodule was already out 130 * of reset, or -EBUSY if the submodule did not exit reset promptly. 131 */ 132 int omap2_prm_deassert_hardreset(s16 prm_mod, u8 shift) 133 { 134 u32 mask; 135 int c; 136 137 if (!(cpu_is_omap24xx() || cpu_is_omap34xx())) 138 return -EINVAL; 139 140 mask = 1 << shift; 141 142 /* Check the current status to avoid de-asserting the line twice */ 143 if (omap2_prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTCTRL, mask) == 0) 144 return -EEXIST; 145 146 /* Clear the reset status by writing 1 to the status bit */ 147 omap2_prm_rmw_mod_reg_bits(0xffffffff, mask, prm_mod, OMAP2_RM_RSTST); 148 /* de-assert the reset control line */ 149 omap2_prm_rmw_mod_reg_bits(mask, 0, prm_mod, OMAP2_RM_RSTCTRL); 150 /* wait the status to be set */ 151 omap_test_timeout(omap2_prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTST, 152 mask), 153 MAX_MODULE_HARDRESET_WAIT, c); 154 155 return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0; 156 } 157