diff options
author | Patrik Jakobsson <patrik.r.jakobsson@gmail.com> | 2014-01-02 19:52:46 -0500 |
---|---|---|
committer | Patrik Jakobsson <patrik.r.jakobsson@gmail.com> | 2014-03-17 15:11:38 -0400 |
commit | 64a4aff283ac838b92a8a73c99c71af2c8bff956 (patch) | |
tree | 15db198089d2638e9158da117525b80a09c57101 | |
parent | b219372dff810fec82c7671b93e1f8dc05e10af4 (diff) |
drm/gma500: Add support for SGX interrupts
Add 2D blit status and MMU fault interrupts to the IRQ handler.
Signed-off-by: Patrik Jakobsson <patrik.r.jakobsson@gmail.com>
-rw-r--r-- | drivers/gpu/drm/gma500/psb_irq.c | 81 |
1 files changed, 69 insertions, 12 deletions
diff --git a/drivers/gpu/drm/gma500/psb_irq.c b/drivers/gpu/drm/gma500/psb_irq.c index f883f9e4c524..624eb36511c5 100644 --- a/drivers/gpu/drm/gma500/psb_irq.c +++ b/drivers/gpu/drm/gma500/psb_irq.c | |||
@@ -200,11 +200,64 @@ static void psb_vdc_interrupt(struct drm_device *dev, uint32_t vdc_stat) | |||
200 | mid_pipe_event_handler(dev, 1); | 200 | mid_pipe_event_handler(dev, 1); |
201 | } | 201 | } |
202 | 202 | ||
203 | /* | ||
204 | * SGX interrupt handler | ||
205 | */ | ||
206 | static void psb_sgx_interrupt(struct drm_device *dev, u32 stat_1, u32 stat_2) | ||
207 | { | ||
208 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
209 | u32 val, addr; | ||
210 | int error = false; | ||
211 | |||
212 | if (stat_1 & _PSB_CE_TWOD_COMPLETE) | ||
213 | val = PSB_RSGX32(PSB_CR_2D_BLIT_STATUS); | ||
214 | |||
215 | if (stat_2 & _PSB_CE2_BIF_REQUESTER_FAULT) { | ||
216 | val = PSB_RSGX32(PSB_CR_BIF_INT_STAT); | ||
217 | addr = PSB_RSGX32(PSB_CR_BIF_FAULT); | ||
218 | if (val) { | ||
219 | if (val & _PSB_CBI_STAT_PF_N_RW) | ||
220 | DRM_ERROR("SGX MMU page fault:"); | ||
221 | else | ||
222 | DRM_ERROR("SGX MMU read / write protection fault:"); | ||
223 | |||
224 | if (val & _PSB_CBI_STAT_FAULT_CACHE) | ||
225 | DRM_ERROR("\tCache requestor"); | ||
226 | if (val & _PSB_CBI_STAT_FAULT_TA) | ||
227 | DRM_ERROR("\tTA requestor"); | ||
228 | if (val & _PSB_CBI_STAT_FAULT_VDM) | ||
229 | DRM_ERROR("\tVDM requestor"); | ||
230 | if (val & _PSB_CBI_STAT_FAULT_2D) | ||
231 | DRM_ERROR("\t2D requestor"); | ||
232 | if (val & _PSB_CBI_STAT_FAULT_PBE) | ||
233 | DRM_ERROR("\tPBE requestor"); | ||
234 | if (val & _PSB_CBI_STAT_FAULT_TSP) | ||
235 | DRM_ERROR("\tTSP requestor"); | ||
236 | if (val & _PSB_CBI_STAT_FAULT_ISP) | ||
237 | DRM_ERROR("\tISP requestor"); | ||
238 | if (val & _PSB_CBI_STAT_FAULT_USSEPDS) | ||
239 | DRM_ERROR("\tUSSEPDS requestor"); | ||
240 | if (val & _PSB_CBI_STAT_FAULT_HOST) | ||
241 | DRM_ERROR("\tHost requestor"); | ||
242 | |||
243 | DRM_ERROR("\tMMU failing address is 0x%08x.\n", | ||
244 | (unsigned int)addr); | ||
245 | error = true; | ||
246 | } | ||
247 | } | ||
248 | |||
249 | /* Clear bits */ | ||
250 | PSB_WSGX32(stat_1, PSB_CR_EVENT_HOST_CLEAR); | ||
251 | PSB_WSGX32(stat_2, PSB_CR_EVENT_HOST_CLEAR2); | ||
252 | PSB_RSGX32(PSB_CR_EVENT_HOST_CLEAR2); | ||
253 | } | ||
254 | |||
203 | irqreturn_t psb_irq_handler(int irq, void *arg) | 255 | irqreturn_t psb_irq_handler(int irq, void *arg) |
204 | { | 256 | { |
205 | struct drm_device *dev = arg; | 257 | struct drm_device *dev = arg; |
206 | struct drm_psb_private *dev_priv = dev->dev_private; | 258 | struct drm_psb_private *dev_priv = dev->dev_private; |
207 | uint32_t vdc_stat, dsp_int = 0, sgx_int = 0, hotplug_int = 0; | 259 | uint32_t vdc_stat, dsp_int = 0, sgx_int = 0, hotplug_int = 0; |
260 | u32 sgx_stat_1, sgx_stat_2; | ||
208 | int handled = 0; | 261 | int handled = 0; |
209 | 262 | ||
210 | spin_lock(&dev_priv->irqmask_lock); | 263 | spin_lock(&dev_priv->irqmask_lock); |
@@ -233,14 +286,9 @@ irqreturn_t psb_irq_handler(int irq, void *arg) | |||
233 | } | 286 | } |
234 | 287 | ||
235 | if (sgx_int) { | 288 | if (sgx_int) { |
236 | /* Not expected - we have it masked, shut it up */ | 289 | sgx_stat_1 = PSB_RSGX32(PSB_CR_EVENT_STATUS); |
237 | u32 s, s2; | 290 | sgx_stat_2 = PSB_RSGX32(PSB_CR_EVENT_STATUS2); |
238 | s = PSB_RSGX32(PSB_CR_EVENT_STATUS); | 291 | psb_sgx_interrupt(dev, sgx_stat_1, sgx_stat_2); |
239 | s2 = PSB_RSGX32(PSB_CR_EVENT_STATUS2); | ||
240 | PSB_WSGX32(s, PSB_CR_EVENT_HOST_CLEAR); | ||
241 | PSB_WSGX32(s2, PSB_CR_EVENT_HOST_CLEAR2); | ||
242 | /* if s & _PSB_CE_TWOD_COMPLETE we have 2D done but | ||
243 | we may as well poll even if we add that ! */ | ||
244 | handled = 1; | 292 | handled = 1; |
245 | } | 293 | } |
246 | 294 | ||
@@ -269,8 +317,13 @@ void psb_irq_preinstall(struct drm_device *dev) | |||
269 | 317 | ||
270 | spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); | 318 | spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); |
271 | 319 | ||
272 | if (gma_power_is_on(dev)) | 320 | if (gma_power_is_on(dev)) { |
273 | PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); | 321 | PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); |
322 | PSB_WVDC32(0x00000000, PSB_INT_MASK_R); | ||
323 | PSB_WVDC32(0x00000000, PSB_INT_ENABLE_R); | ||
324 | PSB_WSGX32(0x00000000, PSB_CR_EVENT_HOST_ENABLE); | ||
325 | PSB_RSGX32(PSB_CR_EVENT_HOST_ENABLE); | ||
326 | } | ||
274 | if (dev->vblank[0].enabled) | 327 | if (dev->vblank[0].enabled) |
275 | dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEA_FLAG; | 328 | dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEA_FLAG; |
276 | if (dev->vblank[1].enabled) | 329 | if (dev->vblank[1].enabled) |
@@ -286,7 +339,7 @@ void psb_irq_preinstall(struct drm_device *dev) | |||
286 | /* Revisit this area - want per device masks ? */ | 339 | /* Revisit this area - want per device masks ? */ |
287 | if (dev_priv->ops->hotplug) | 340 | if (dev_priv->ops->hotplug) |
288 | dev_priv->vdc_irq_mask |= _PSB_IRQ_DISP_HOTSYNC; | 341 | dev_priv->vdc_irq_mask |= _PSB_IRQ_DISP_HOTSYNC; |
289 | dev_priv->vdc_irq_mask |= _PSB_IRQ_ASLE; | 342 | dev_priv->vdc_irq_mask |= _PSB_IRQ_ASLE | _PSB_IRQ_SGX_FLAG; |
290 | 343 | ||
291 | /* This register is safe even if display island is off */ | 344 | /* This register is safe even if display island is off */ |
292 | PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); | 345 | PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); |
@@ -295,12 +348,16 @@ void psb_irq_preinstall(struct drm_device *dev) | |||
295 | 348 | ||
296 | int psb_irq_postinstall(struct drm_device *dev) | 349 | int psb_irq_postinstall(struct drm_device *dev) |
297 | { | 350 | { |
298 | struct drm_psb_private *dev_priv = | 351 | struct drm_psb_private *dev_priv = dev->dev_private; |
299 | (struct drm_psb_private *) dev->dev_private; | ||
300 | unsigned long irqflags; | 352 | unsigned long irqflags; |
301 | 353 | ||
302 | spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); | 354 | spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); |
303 | 355 | ||
356 | /* Enable 2D and MMU fault interrupts */ | ||
357 | PSB_WSGX32(_PSB_CE2_BIF_REQUESTER_FAULT, PSB_CR_EVENT_HOST_ENABLE2); | ||
358 | PSB_WSGX32(_PSB_CE_TWOD_COMPLETE, PSB_CR_EVENT_HOST_ENABLE); | ||
359 | PSB_RSGX32(PSB_CR_EVENT_HOST_ENABLE); /* Post */ | ||
360 | |||
304 | /* This register is safe even if display island is off */ | 361 | /* This register is safe even if display island is off */ |
305 | PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); | 362 | PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); |
306 | PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); | 363 | PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); |