Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+69 -12
+69 -12
drivers/gpu/drm/gma500/psb_irq.c
··· 200 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 255 irqreturn_t psb_irq_handler(int irq, void *arg) 204 256 { 205 257 struct drm_device *dev = arg; 206 258 struct drm_psb_private *dev_priv = dev->dev_private; 207 259 uint32_t vdc_stat, dsp_int = 0, sgx_int = 0, hotplug_int = 0; 260 + u32 sgx_stat_1, sgx_stat_2; 208 261 int handled = 0; 209 262 210 263 spin_lock(&dev_priv->irqmask_lock); ··· 286 233 } 287 234 288 235 if (sgx_int) { 289 - /* Not expected - we have it masked, shut it up */ 290 - u32 s, s2; 291 - s = PSB_RSGX32(PSB_CR_EVENT_STATUS); 292 - s2 = PSB_RSGX32(PSB_CR_EVENT_STATUS2); 293 - PSB_WSGX32(s, PSB_CR_EVENT_HOST_CLEAR); 294 - PSB_WSGX32(s2, PSB_CR_EVENT_HOST_CLEAR2); 295 - /* if s & _PSB_CE_TWOD_COMPLETE we have 2D done but 296 - we may as well poll even if we add that ! */ 236 + sgx_stat_1 = PSB_RSGX32(PSB_CR_EVENT_STATUS); 237 + sgx_stat_2 = PSB_RSGX32(PSB_CR_EVENT_STATUS2); 238 + psb_sgx_interrupt(dev, sgx_stat_1, sgx_stat_2); 297 239 handled = 1; 298 240 } 299 241 ··· 317 269 318 270 spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); 319 271 320 - if (gma_power_is_on(dev)) 272 + if (gma_power_is_on(dev)) { 321 273 PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); 274 + PSB_WVDC32(0x00000000, PSB_INT_MASK_R); 275 + PSB_WVDC32(0x00000000, PSB_INT_ENABLE_R); 276 + PSB_WSGX32(0x00000000, PSB_CR_EVENT_HOST_ENABLE); 277 + PSB_RSGX32(PSB_CR_EVENT_HOST_ENABLE); 278 + } 322 279 if (dev->vblank[0].enabled) 323 280 dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEA_FLAG; 324 281 if (dev->vblank[1].enabled) ··· 339 286 /* Revisit this area - want per device masks ? */ 340 287 if (dev_priv->ops->hotplug) 341 288 dev_priv->vdc_irq_mask |= _PSB_IRQ_DISP_HOTSYNC; 342 - dev_priv->vdc_irq_mask |= _PSB_IRQ_ASLE; 289 + dev_priv->vdc_irq_mask |= _PSB_IRQ_ASLE | _PSB_IRQ_SGX_FLAG; 343 290 344 291 /* This register is safe even if display island is off */ 345 292 PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); ··· 348 295 349 296 int psb_irq_postinstall(struct drm_device *dev) 350 297 { 351 - struct drm_psb_private *dev_priv = 352 - (struct drm_psb_private *) dev->dev_private; 298 + struct drm_psb_private *dev_priv = dev->dev_private; 353 299 unsigned long irqflags; 354 300 355 301 spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); 302 + 303 + /* Enable 2D and MMU fault interrupts */ 304 + PSB_WSGX32(_PSB_CE2_BIF_REQUESTER_FAULT, PSB_CR_EVENT_HOST_ENABLE2); 305 + PSB_WSGX32(_PSB_CE_TWOD_COMPLETE, PSB_CR_EVENT_HOST_ENABLE); 306 + PSB_RSGX32(PSB_CR_EVENT_HOST_ENABLE); /* Post */ 356 307 357 308 /* This register is safe even if display island is off */ 358 309 PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);