root/drivers/gpu/host1x/hw/intr_hw.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. host1x_intr_syncpt_handle
  2. syncpt_thresh_isr
  3. _host1x_intr_disable_all_syncpt_intrs
  4. intr_hw_init
  5. _host1x_intr_init_host_sync
  6. _host1x_intr_set_syncpt_threshold
  7. _host1x_intr_enable_syncpt_intr
  8. _host1x_intr_disable_syncpt_intr
  9. _host1x_free_syncpt_irq

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Tegra host1x Interrupt Management
   4  *
   5  * Copyright (C) 2010 Google, Inc.
   6  * Copyright (c) 2010-2013, NVIDIA Corporation.
   7  */
   8 
   9 #include <linux/interrupt.h>
  10 #include <linux/irq.h>
  11 #include <linux/io.h>
  12 
  13 #include "../intr.h"
  14 #include "../dev.h"
  15 
  16 /*
  17  * Sync point threshold interrupt service function
  18  * Handles sync point threshold triggers, in interrupt context
  19  */
  20 static void host1x_intr_syncpt_handle(struct host1x_syncpt *syncpt)
  21 {
  22         unsigned int id = syncpt->id;
  23         struct host1x *host = syncpt->host;
  24 
  25         host1x_sync_writel(host, BIT(id % 32),
  26                 HOST1X_SYNC_SYNCPT_THRESH_INT_DISABLE(id / 32));
  27         host1x_sync_writel(host, BIT(id % 32),
  28                 HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(id / 32));
  29 
  30         schedule_work(&syncpt->intr.work);
  31 }
  32 
  33 static irqreturn_t syncpt_thresh_isr(int irq, void *dev_id)
  34 {
  35         struct host1x *host = dev_id;
  36         unsigned long reg;
  37         unsigned int i, id;
  38 
  39         for (i = 0; i < DIV_ROUND_UP(host->info->nb_pts, 32); i++) {
  40                 reg = host1x_sync_readl(host,
  41                         HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(i));
  42                 for_each_set_bit(id, &reg, 32) {
  43                         struct host1x_syncpt *syncpt =
  44                                 host->syncpt + (i * 32 + id);
  45                         host1x_intr_syncpt_handle(syncpt);
  46                 }
  47         }
  48 
  49         return IRQ_HANDLED;
  50 }
  51 
  52 static void _host1x_intr_disable_all_syncpt_intrs(struct host1x *host)
  53 {
  54         unsigned int i;
  55 
  56         for (i = 0; i < DIV_ROUND_UP(host->info->nb_pts, 32); ++i) {
  57                 host1x_sync_writel(host, 0xffffffffu,
  58                         HOST1X_SYNC_SYNCPT_THRESH_INT_DISABLE(i));
  59                 host1x_sync_writel(host, 0xffffffffu,
  60                         HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(i));
  61         }
  62 }
  63 
  64 static void intr_hw_init(struct host1x *host, u32 cpm)
  65 {
  66 #if HOST1X_HW < 6
  67         /* disable the ip_busy_timeout. this prevents write drops */
  68         host1x_sync_writel(host, 0, HOST1X_SYNC_IP_BUSY_TIMEOUT);
  69 
  70         /*
  71          * increase the auto-ack timout to the maximum value. 2d will hang
  72          * otherwise on Tegra2.
  73          */
  74         host1x_sync_writel(host, 0xff, HOST1X_SYNC_CTXSW_TIMEOUT_CFG);
  75 
  76         /* update host clocks per usec */
  77         host1x_sync_writel(host, cpm, HOST1X_SYNC_USEC_CLK);
  78 #endif
  79 }
  80 
  81 static int
  82 _host1x_intr_init_host_sync(struct host1x *host, u32 cpm,
  83                             void (*syncpt_thresh_work)(struct work_struct *))
  84 {
  85         unsigned int i;
  86         int err;
  87 
  88         host1x_hw_intr_disable_all_syncpt_intrs(host);
  89 
  90         for (i = 0; i < host->info->nb_pts; i++)
  91                 INIT_WORK(&host->syncpt[i].intr.work, syncpt_thresh_work);
  92 
  93         err = devm_request_irq(host->dev, host->intr_syncpt_irq,
  94                                syncpt_thresh_isr, IRQF_SHARED,
  95                                "host1x_syncpt", host);
  96         if (err < 0) {
  97                 WARN_ON(1);
  98                 return err;
  99         }
 100 
 101         intr_hw_init(host, cpm);
 102 
 103         return 0;
 104 }
 105 
 106 static void _host1x_intr_set_syncpt_threshold(struct host1x *host,
 107                                               unsigned int id,
 108                                               u32 thresh)
 109 {
 110         host1x_sync_writel(host, thresh, HOST1X_SYNC_SYNCPT_INT_THRESH(id));
 111 }
 112 
 113 static void _host1x_intr_enable_syncpt_intr(struct host1x *host,
 114                                             unsigned int id)
 115 {
 116         host1x_sync_writel(host, BIT(id % 32),
 117                 HOST1X_SYNC_SYNCPT_THRESH_INT_ENABLE_CPU0(id / 32));
 118 }
 119 
 120 static void _host1x_intr_disable_syncpt_intr(struct host1x *host,
 121                                              unsigned int id)
 122 {
 123         host1x_sync_writel(host, BIT(id % 32),
 124                 HOST1X_SYNC_SYNCPT_THRESH_INT_DISABLE(id / 32));
 125         host1x_sync_writel(host, BIT(id % 32),
 126                 HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(id / 32));
 127 }
 128 
 129 static int _host1x_free_syncpt_irq(struct host1x *host)
 130 {
 131         unsigned int i;
 132 
 133         devm_free_irq(host->dev, host->intr_syncpt_irq, host);
 134 
 135         for (i = 0; i < host->info->nb_pts; i++)
 136                 cancel_work_sync(&host->syncpt[i].intr.work);
 137 
 138         return 0;
 139 }
 140 
 141 static const struct host1x_intr_ops host1x_intr_ops = {
 142         .init_host_sync = _host1x_intr_init_host_sync,
 143         .set_syncpt_threshold = _host1x_intr_set_syncpt_threshold,
 144         .enable_syncpt_intr = _host1x_intr_enable_syncpt_intr,
 145         .disable_syncpt_intr = _host1x_intr_disable_syncpt_intr,
 146         .disable_all_syncpt_intrs = _host1x_intr_disable_all_syncpt_intrs,
 147         .free_syncpt_irq = _host1x_free_syncpt_irq,
 148 };

/* [<][>][^][v][top][bottom][index][help] */