1 /* 2 * OMAP4 PRM instance functions 3 * 4 * Copyright (C) 2009 Nokia Corporation 5 * Copyright (C) 2011 Texas Instruments, Inc. 6 * Paul Walmsley 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11 */ 12 13 #include <linux/kernel.h> 14 #include <linux/types.h> 15 #include <linux/errno.h> 16 #include <linux/err.h> 17 #include <linux/io.h> 18 19 #include <plat/common.h> 20 21 #include "prm44xx.h" 22 #include "prminst44xx.h" 23 #include "prm-regbits-44xx.h" 24 #include "prcm44xx.h" 25 #include "prcm_mpu44xx.h" 26 27 static u32 _prm_bases[OMAP4_MAX_PRCM_PARTITIONS] = { 28 [OMAP4430_INVALID_PRCM_PARTITION] = 0, 29 [OMAP4430_PRM_PARTITION] = OMAP4430_PRM_BASE, 30 [OMAP4430_CM1_PARTITION] = 0, 31 [OMAP4430_CM2_PARTITION] = 0, 32 [OMAP4430_SCRM_PARTITION] = 0, 33 [OMAP4430_PRCM_MPU_PARTITION] = OMAP4430_PRCM_MPU_BASE, 34 }; 35 36 /* Read a register in a PRM instance */ 37 u32 omap4_prminst_read_inst_reg(u8 part, s16 inst, u16 idx) 38 { 39 BUG_ON(part >= OMAP4_MAX_PRCM_PARTITIONS || 40 part == OMAP4430_INVALID_PRCM_PARTITION || 41 !_prm_bases[part]); 42 return __raw_readl(OMAP2_L4_IO_ADDRESS(_prm_bases[part] + inst + 43 idx)); 44 } 45 46 /* Write into a register in a PRM instance */ 47 void omap4_prminst_write_inst_reg(u32 val, u8 part, s16 inst, u16 idx) 48 { 49 BUG_ON(part >= OMAP4_MAX_PRCM_PARTITIONS || 50 part == OMAP4430_INVALID_PRCM_PARTITION || 51 !_prm_bases[part]); 52 __raw_writel(val, OMAP2_L4_IO_ADDRESS(_prm_bases[part] + inst + idx)); 53 } 54 55 /* Read-modify-write a register in PRM. Caller must lock */ 56 u32 omap4_prminst_rmw_inst_reg_bits(u32 mask, u32 bits, u8 part, s16 inst, 57 u16 idx) 58 { 59 u32 v; 60 61 v = omap4_prminst_read_inst_reg(part, inst, idx); 62 v &= ~mask; 63 v |= bits; 64 omap4_prminst_write_inst_reg(v, part, inst, idx); 65 66 return v; 67 } 68 69 /* 70 * Address offset (in bytes) between the reset control and the reset 71 * status registers: 4 bytes on OMAP4 72 */ 73 #define OMAP4_RST_CTRL_ST_OFFSET 4 74 75 /** 76 * omap4_prminst_is_hardreset_asserted - read the HW reset line state of 77 * submodules contained in the hwmod module 78 * @rstctrl_reg: RM_RSTCTRL register address for this module 79 * @shift: register bit shift corresponding to the reset line to check 80 * 81 * Returns 1 if the (sub)module hardreset line is currently asserted, 82 * 0 if the (sub)module hardreset line is not currently asserted, or 83 * -EINVAL upon parameter error. 84 */ 85 int omap4_prminst_is_hardreset_asserted(u8 shift, u8 part, s16 inst, 86 u16 rstctrl_offs) 87 { 88 u32 v; 89 90 v = omap4_prminst_read_inst_reg(part, inst, rstctrl_offs); 91 v &= 1 << shift; 92 v >>= shift; 93 94 return v; 95 } 96 97 /** 98 * omap4_prminst_assert_hardreset - assert the HW reset line of a submodule 99 * @rstctrl_reg: RM_RSTCTRL register address for this module 100 * @shift: register bit shift corresponding to the reset line to assert 101 * 102 * Some IPs like dsp, ipu or iva contain processors that require an HW 103 * reset line to be asserted / deasserted in order to fully enable the 104 * IP. These modules may have multiple hard-reset lines that reset 105 * different 'submodules' inside the IP block. This function will 106 * place the submodule into reset. Returns 0 upon success or -EINVAL 107 * upon an argument error. 108 */ 109 int omap4_prminst_assert_hardreset(u8 shift, u8 part, s16 inst, 110 u16 rstctrl_offs) 111 { 112 u32 mask = 1 << shift; 113 114 omap4_prminst_rmw_inst_reg_bits(mask, mask, part, inst, rstctrl_offs); 115 116 return 0; 117 } 118 119 /** 120 * omap4_prminst_deassert_hardreset - deassert a submodule hardreset line and 121 * wait 122 * @rstctrl_reg: RM_RSTCTRL register address for this module 123 * @shift: register bit shift corresponding to the reset line to deassert 124 * 125 * Some IPs like dsp, ipu or iva contain processors that require an HW 126 * reset line to be asserted / deasserted in order to fully enable the 127 * IP. These modules may have multiple hard-reset lines that reset 128 * different 'submodules' inside the IP block. This function will 129 * take the submodule out of reset and wait until the PRCM indicates 130 * that the reset has completed before returning. Returns 0 upon success or 131 * -EINVAL upon an argument error, -EEXIST if the submodule was already out 132 * of reset, or -EBUSY if the submodule did not exit reset promptly. 133 */ 134 int omap4_prminst_deassert_hardreset(u8 shift, u8 part, s16 inst, 135 u16 rstctrl_offs) 136 { 137 int c; 138 u32 mask = 1 << shift; 139 u16 rstst_offs = rstctrl_offs + OMAP4_RST_CTRL_ST_OFFSET; 140 141 /* Check the current status to avoid de-asserting the line twice */ 142 if (omap4_prminst_is_hardreset_asserted(shift, part, inst, 143 rstctrl_offs) == 0) 144 return -EEXIST; 145 146 /* Clear the reset status by writing 1 to the status bit */ 147 omap4_prminst_rmw_inst_reg_bits(0xffffffff, mask, part, inst, 148 rstst_offs); 149 /* de-assert the reset control line */ 150 omap4_prminst_rmw_inst_reg_bits(mask, 0, part, inst, rstctrl_offs); 151 /* wait the status to be set */ 152 omap_test_timeout(omap4_prminst_is_hardreset_asserted(shift, part, inst, 153 rstst_offs), 154 MAX_MODULE_HARDRESET_WAIT, c); 155 156 return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0; 157 } 158 159 160 void omap4_prminst_global_warm_sw_reset(void) 161 { 162 u32 v; 163 164 v = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION, 165 OMAP4430_PRM_DEVICE_INST, 166 OMAP4_PRM_RSTCTRL_OFFSET); 167 v |= OMAP4430_RST_GLOBAL_WARM_SW_MASK; 168 omap4_prminst_write_inst_reg(v, OMAP4430_PRM_PARTITION, 169 OMAP4430_PRM_DEVICE_INST, 170 OMAP4_PRM_RSTCTRL_OFFSET); 171 172 /* OCP barrier */ 173 v = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION, 174 OMAP4430_PRM_DEVICE_INST, 175 OMAP4_PRM_RSTCTRL_OFFSET); 176 } 177