fixes for bc_cat
[sgx.git] / pvr / sgxreset.c
1 /**********************************************************************
2  *
3  * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms and conditions of the GNU General Public License,
7  * version 2, as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope it will be useful but, except
10  * as otherwise stated in writing, without any warranty; without even the
11  * implied warranty of merchantability or fitness for a particular purpose.
12  * See the GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17  *
18  * The full GNU General Public License is included in this distribution in
19  * the file called "COPYING".
20  *
21  * Contact Information:
22  * Imagination Technologies Ltd. <gpl-support@imgtec.com>
23  * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
24  *
25  ******************************************************************************/
26
27 #include "sgxdefs.h"
28 #include "sgxmmu.h"
29 #include "services_headers.h"
30 #include "sgxinfokm.h"
31 #include "sgxconfig.h"
32
33 #include "pvr_pdump.h"
34
35 static void SGXResetSoftReset(struct PVRSRV_SGXDEV_INFO *psDevInfo,
36                                   IMG_BOOL bResetBIF, u32 ui32PDUMPFlags,
37                                   IMG_BOOL bPDump)
38 {
39         u32 ui32SoftResetRegVal =
40             EUR_CR_SOFT_RESET_DPM_RESET_MASK |
41             EUR_CR_SOFT_RESET_TA_RESET_MASK |
42             EUR_CR_SOFT_RESET_USE_RESET_MASK |
43             EUR_CR_SOFT_RESET_ISP_RESET_MASK | EUR_CR_SOFT_RESET_TSP_RESET_MASK;
44
45 #ifdef EUR_CR_SOFT_RESET_TWOD_RESET_MASK
46         ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_TWOD_RESET_MASK;
47 #endif
48
49 #if !defined(PDUMP)
50         PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
51 #endif
52
53         if (bResetBIF)
54                 ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_BIF_RESET_MASK;
55
56         OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_SOFT_RESET,
57                      ui32SoftResetRegVal);
58         if (bPDump)
59                 PDUMPREGWITHFLAGS(EUR_CR_SOFT_RESET, ui32SoftResetRegVal,
60                                   ui32PDUMPFlags);
61 }
62
63 static void SGXResetSleep(struct PVRSRV_SGXDEV_INFO *psDevInfo,
64                               u32 ui32PDUMPFlags, IMG_BOOL bPDump)
65 {
66 #if !defined(PDUMP)
67         PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
68 #endif
69
70         OSWaitus(1000 * 1000000 / psDevInfo->ui32CoreClockSpeed);
71         if (bPDump) {
72                 PDUMPIDLWITHFLAGS(30, ui32PDUMPFlags);
73 #if defined(PDUMP)
74                 PDumpRegRead(EUR_CR_SOFT_RESET, ui32PDUMPFlags);
75 #endif
76         }
77
78 }
79
80 static void SGXResetInvalDC(struct PVRSRV_SGXDEV_INFO *psDevInfo,
81                                 u32 ui32PDUMPFlags, IMG_BOOL bPDump)
82 {
83         u32 ui32RegVal;
84
85         ui32RegVal = EUR_CR_BIF_CTRL_INVALDC_MASK;
86         OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
87         if (bPDump)
88                 PDUMPREGWITHFLAGS(EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
89         SGXResetSleep(psDevInfo, ui32PDUMPFlags, bPDump);
90
91         ui32RegVal = 0;
92         OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
93         if (bPDump)
94                 PDUMPREGWITHFLAGS(EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
95         SGXResetSleep(psDevInfo, ui32PDUMPFlags, bPDump);
96
97         if (PollForValueKM(
98             (u32 __iomem *)((u8 __iomem *)psDevInfo->pvRegsBaseKM +
99                                                 EUR_CR_BIF_MEM_REQ_STAT),
100              0, EUR_CR_BIF_MEM_REQ_STAT_READS_MASK,
101              MAX_HW_TIME_US / WAIT_TRY_COUNT, WAIT_TRY_COUNT) != PVRSRV_OK) {
102                 PVR_DPF(PVR_DBG_ERROR, "Wait for DC invalidate failed.");
103                 PVR_DBG_BREAK;
104         }
105
106         if (bPDump)
107                 PDUMPREGPOLWITHFLAGS(EUR_CR_BIF_MEM_REQ_STAT, 0,
108                                      EUR_CR_BIF_MEM_REQ_STAT_READS_MASK,
109                                      ui32PDUMPFlags);
110 }
111
112 void SGXReset(struct PVRSRV_SGXDEV_INFO *psDevInfo, u32 ui32PDUMPFlags)
113 {
114         u32 ui32RegVal;
115
116         const u32 ui32BifFaultMask = EUR_CR_BIF_INT_STAT_FAULT_MASK;
117
118
119 #ifndef PDUMP
120         PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
121 #endif
122
123         psDevInfo->ui32NumResets++;
124
125         PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags,
126                               "Start of SGX reset sequence\r\n");
127
128         SGXResetSoftReset(psDevInfo, IMG_TRUE, ui32PDUMPFlags, IMG_TRUE);
129
130         SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
131
132
133         ui32RegVal = psDevInfo->sBIFResetPDDevPAddr.uiAddr;
134         OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_DIR_LIST_BASE0,
135                      ui32RegVal);
136
137         SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
138
139         SGXResetSoftReset(psDevInfo, IMG_FALSE, ui32PDUMPFlags, IMG_TRUE);
140         SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
141
142         SGXResetInvalDC(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
143
144         for (;;) {
145                 u32 ui32BifIntStat =
146                     OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_INT_STAT);
147                 struct IMG_DEV_VIRTADDR sBifFault;
148                 u32 ui32PDIndex, ui32PTIndex;
149
150                 if ((ui32BifIntStat & ui32BifFaultMask) == 0)
151                         break;
152
153                 sBifFault.uiAddr =
154                     OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_FAULT);
155                 PVR_DPF(PVR_DBG_WARNING, "SGXReset: Page fault 0x%x/0x%x",
156                          ui32BifIntStat, sBifFault.uiAddr);
157                 ui32PDIndex =
158                     sBifFault.uiAddr >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT);
159                 ui32PTIndex =
160                     (sBifFault.uiAddr & SGX_MMU_PT_MASK) >> SGX_MMU_PAGE_SHIFT;
161
162                 SGXResetSoftReset(psDevInfo, IMG_TRUE, ui32PDUMPFlags,
163                                   IMG_FALSE);
164
165                 psDevInfo->pui32BIFResetPD[ui32PDIndex] =
166                     psDevInfo->sBIFResetPTDevPAddr.uiAddr |
167                                 SGX_MMU_PDE_PAGE_SIZE_4K | SGX_MMU_PDE_VALID;
168                 psDevInfo->pui32BIFResetPT[ui32PTIndex] =
169                     psDevInfo->sBIFResetPageDevPAddr.uiAddr | SGX_MMU_PTE_VALID;
170
171                 ui32RegVal =
172                     OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS);
173                 OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR,
174                              ui32RegVal);
175                 ui32RegVal =
176                     OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS2);
177                 OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR2,
178                              ui32RegVal);
179
180                 SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
181
182                 SGXResetSoftReset(psDevInfo, IMG_FALSE, ui32PDUMPFlags,
183                                   IMG_FALSE);
184                 SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
185
186                 SGXResetInvalDC(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
187
188                 psDevInfo->pui32BIFResetPD[ui32PDIndex] = 0;
189                 psDevInfo->pui32BIFResetPT[ui32PTIndex] = 0;
190         }
191
192         {
193                 u32 ui32EDMDirListReg;
194
195 #if (SGX_BIF_DIR_LIST_INDEX_EDM == 0)
196                 ui32EDMDirListReg = EUR_CR_BIF_DIR_LIST_BASE0;
197 #else
198
199                 ui32EDMDirListReg =
200                     EUR_CR_BIF_DIR_LIST_BASE1 +
201                     4 * (SGX_BIF_DIR_LIST_INDEX_EDM - 1);
202 #endif
203
204                 OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32EDMDirListReg,
205                              psDevInfo->sKernelPDDevPAddr.uiAddr);
206                 PDUMPPDREGWITHFLAGS(ui32EDMDirListReg,
207                                     psDevInfo->sKernelPDDevPAddr.uiAddr,
208                                     ui32PDUMPFlags);
209         }
210
211         SGXResetInvalDC(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
212
213         PVR_DPF(PVR_DBG_MESSAGE, "Soft Reset of SGX");
214         SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
215
216         ui32RegVal = 0;
217         OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_SOFT_RESET, ui32RegVal);
218         PDUMPREGWITHFLAGS(EUR_CR_SOFT_RESET, ui32RegVal, ui32PDUMPFlags);
219
220         SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
221
222         PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "End of SGX reset sequence\r\n");
223 }