root/drivers/gpu/drm/msm/edp/edp_aux.c

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

DEFINITIONS

This source file includes following definitions.
  1. edp_msg_fifo_tx
  2. edp_msg_fifo_rx
  3. edp_aux_transfer
  4. msm_edp_aux_init
  5. msm_edp_aux_destroy
  6. msm_edp_aux_irq
  7. msm_edp_aux_ctrl

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
   4  */
   5 
   6 #include "edp.h"
   7 #include "edp.xml.h"
   8 
   9 #define AUX_CMD_FIFO_LEN        144
  10 #define AUX_CMD_NATIVE_MAX      16
  11 #define AUX_CMD_I2C_MAX         128
  12 
  13 #define EDP_INTR_AUX_I2C_ERR    \
  14         (EDP_INTERRUPT_REG_1_WRONG_ADDR | EDP_INTERRUPT_REG_1_TIMEOUT | \
  15         EDP_INTERRUPT_REG_1_NACK_DEFER | EDP_INTERRUPT_REG_1_WRONG_DATA_CNT | \
  16         EDP_INTERRUPT_REG_1_I2C_NACK | EDP_INTERRUPT_REG_1_I2C_DEFER)
  17 #define EDP_INTR_TRANS_STATUS   \
  18         (EDP_INTERRUPT_REG_1_AUX_I2C_DONE | EDP_INTR_AUX_I2C_ERR)
  19 
  20 struct edp_aux {
  21         void __iomem *base;
  22         bool msg_err;
  23 
  24         struct completion msg_comp;
  25 
  26         /* To prevent the message transaction routine from reentry. */
  27         struct mutex msg_mutex;
  28 
  29         struct drm_dp_aux drm_aux;
  30 };
  31 #define to_edp_aux(x) container_of(x, struct edp_aux, drm_aux)
  32 
  33 static int edp_msg_fifo_tx(struct edp_aux *aux, struct drm_dp_aux_msg *msg)
  34 {
  35         u32 data[4];
  36         u32 reg, len;
  37         bool native = msg->request & (DP_AUX_NATIVE_WRITE & DP_AUX_NATIVE_READ);
  38         bool read = msg->request & (DP_AUX_I2C_READ & DP_AUX_NATIVE_READ);
  39         u8 *msgdata = msg->buffer;
  40         int i;
  41 
  42         if (read)
  43                 len = 4;
  44         else
  45                 len = msg->size + 4;
  46 
  47         /*
  48          * cmd fifo only has depth of 144 bytes
  49          */
  50         if (len > AUX_CMD_FIFO_LEN)
  51                 return -EINVAL;
  52 
  53         /* Pack cmd and write to HW */
  54         data[0] = (msg->address >> 16) & 0xf;   /* addr[19:16] */
  55         if (read)
  56                 data[0] |=  BIT(4);             /* R/W */
  57 
  58         data[1] = (msg->address >> 8) & 0xff;   /* addr[15:8] */
  59         data[2] = msg->address & 0xff;          /* addr[7:0] */
  60         data[3] = (msg->size - 1) & 0xff;       /* len[7:0] */
  61 
  62         for (i = 0; i < len; i++) {
  63                 reg = (i < 4) ? data[i] : msgdata[i - 4];
  64                 reg = EDP_AUX_DATA_DATA(reg); /* index = 0, write */
  65                 if (i == 0)
  66                         reg |= EDP_AUX_DATA_INDEX_WRITE;
  67                 edp_write(aux->base + REG_EDP_AUX_DATA, reg);
  68         }
  69 
  70         reg = 0; /* Transaction number is always 1 */
  71         if (!native) /* i2c */
  72                 reg |= EDP_AUX_TRANS_CTRL_I2C;
  73 
  74         reg |= EDP_AUX_TRANS_CTRL_GO;
  75         edp_write(aux->base + REG_EDP_AUX_TRANS_CTRL, reg);
  76 
  77         return 0;
  78 }
  79 
  80 static int edp_msg_fifo_rx(struct edp_aux *aux, struct drm_dp_aux_msg *msg)
  81 {
  82         u32 data;
  83         u8 *dp;
  84         int i;
  85         u32 len = msg->size;
  86 
  87         edp_write(aux->base + REG_EDP_AUX_DATA,
  88                 EDP_AUX_DATA_INDEX_WRITE | EDP_AUX_DATA_READ); /* index = 0 */
  89 
  90         dp = msg->buffer;
  91 
  92         /* discard first byte */
  93         data = edp_read(aux->base + REG_EDP_AUX_DATA);
  94         for (i = 0; i < len; i++) {
  95                 data = edp_read(aux->base + REG_EDP_AUX_DATA);
  96                 dp[i] = (u8)((data >> 8) & 0xff);
  97         }
  98 
  99         return 0;
 100 }
 101 
 102 /*
 103  * This function does the real job to process an AUX transaction.
 104  * It will call msm_edp_aux_ctrl() function to reset the AUX channel,
 105  * if the waiting is timeout.
 106  * The caller who triggers the transaction should avoid the
 107  * msm_edp_aux_ctrl() running concurrently in other threads, i.e.
 108  * start transaction only when AUX channel is fully enabled.
 109  */
 110 static ssize_t edp_aux_transfer(struct drm_dp_aux *drm_aux,
 111                 struct drm_dp_aux_msg *msg)
 112 {
 113         struct edp_aux *aux = to_edp_aux(drm_aux);
 114         ssize_t ret;
 115         unsigned long time_left;
 116         bool native = msg->request & (DP_AUX_NATIVE_WRITE & DP_AUX_NATIVE_READ);
 117         bool read = msg->request & (DP_AUX_I2C_READ & DP_AUX_NATIVE_READ);
 118 
 119         /* Ignore address only message */
 120         if ((msg->size == 0) || (msg->buffer == NULL)) {
 121                 msg->reply = native ?
 122                         DP_AUX_NATIVE_REPLY_ACK : DP_AUX_I2C_REPLY_ACK;
 123                 return msg->size;
 124         }
 125 
 126         /* msg sanity check */
 127         if ((native && (msg->size > AUX_CMD_NATIVE_MAX)) ||
 128                 (msg->size > AUX_CMD_I2C_MAX)) {
 129                 pr_err("%s: invalid msg: size(%zu), request(%x)\n",
 130                         __func__, msg->size, msg->request);
 131                 return -EINVAL;
 132         }
 133 
 134         mutex_lock(&aux->msg_mutex);
 135 
 136         aux->msg_err = false;
 137         reinit_completion(&aux->msg_comp);
 138 
 139         ret = edp_msg_fifo_tx(aux, msg);
 140         if (ret < 0)
 141                 goto unlock_exit;
 142 
 143         DBG("wait_for_completion");
 144         time_left = wait_for_completion_timeout(&aux->msg_comp,
 145                                                 msecs_to_jiffies(300));
 146         if (!time_left) {
 147                 /*
 148                  * Clear GO and reset AUX channel
 149                  * to cancel the current transaction.
 150                  */
 151                 edp_write(aux->base + REG_EDP_AUX_TRANS_CTRL, 0);
 152                 msm_edp_aux_ctrl(aux, 1);
 153                 pr_err("%s: aux timeout,\n", __func__);
 154                 ret = -ETIMEDOUT;
 155                 goto unlock_exit;
 156         }
 157         DBG("completion");
 158 
 159         if (!aux->msg_err) {
 160                 if (read) {
 161                         ret = edp_msg_fifo_rx(aux, msg);
 162                         if (ret < 0)
 163                                 goto unlock_exit;
 164                 }
 165 
 166                 msg->reply = native ?
 167                         DP_AUX_NATIVE_REPLY_ACK : DP_AUX_I2C_REPLY_ACK;
 168         } else {
 169                 /* Reply defer to retry */
 170                 msg->reply = native ?
 171                         DP_AUX_NATIVE_REPLY_DEFER : DP_AUX_I2C_REPLY_DEFER;
 172                 /*
 173                  * The sleep time in caller is not long enough to make sure
 174                  * our H/W completes transactions. Add more defer time here.
 175                  */
 176                 msleep(100);
 177         }
 178 
 179         /* Return requested size for success or retry */
 180         ret = msg->size;
 181 
 182 unlock_exit:
 183         mutex_unlock(&aux->msg_mutex);
 184         return ret;
 185 }
 186 
 187 void *msm_edp_aux_init(struct device *dev, void __iomem *regbase,
 188         struct drm_dp_aux **drm_aux)
 189 {
 190         struct edp_aux *aux = NULL;
 191         int ret;
 192 
 193         DBG("");
 194         aux = devm_kzalloc(dev, sizeof(*aux), GFP_KERNEL);
 195         if (!aux)
 196                 return NULL;
 197 
 198         aux->base = regbase;
 199         mutex_init(&aux->msg_mutex);
 200         init_completion(&aux->msg_comp);
 201 
 202         aux->drm_aux.name = "msm_edp_aux";
 203         aux->drm_aux.dev = dev;
 204         aux->drm_aux.transfer = edp_aux_transfer;
 205         ret = drm_dp_aux_register(&aux->drm_aux);
 206         if (ret) {
 207                 pr_err("%s: failed to register drm aux: %d\n", __func__, ret);
 208                 mutex_destroy(&aux->msg_mutex);
 209         }
 210 
 211         if (drm_aux && aux)
 212                 *drm_aux = &aux->drm_aux;
 213 
 214         return aux;
 215 }
 216 
 217 void msm_edp_aux_destroy(struct device *dev, struct edp_aux *aux)
 218 {
 219         if (aux) {
 220                 drm_dp_aux_unregister(&aux->drm_aux);
 221                 mutex_destroy(&aux->msg_mutex);
 222         }
 223 }
 224 
 225 irqreturn_t msm_edp_aux_irq(struct edp_aux *aux, u32 isr)
 226 {
 227         if (isr & EDP_INTR_TRANS_STATUS) {
 228                 DBG("isr=%x", isr);
 229                 edp_write(aux->base + REG_EDP_AUX_TRANS_CTRL, 0);
 230 
 231                 if (isr & EDP_INTR_AUX_I2C_ERR)
 232                         aux->msg_err = true;
 233                 else
 234                         aux->msg_err = false;
 235 
 236                 complete(&aux->msg_comp);
 237         }
 238 
 239         return IRQ_HANDLED;
 240 }
 241 
 242 void msm_edp_aux_ctrl(struct edp_aux *aux, int enable)
 243 {
 244         u32 data;
 245 
 246         DBG("enable=%d", enable);
 247         data = edp_read(aux->base + REG_EDP_AUX_CTRL);
 248 
 249         if (enable) {
 250                 data |= EDP_AUX_CTRL_RESET;
 251                 edp_write(aux->base + REG_EDP_AUX_CTRL, data);
 252                 /* Make sure full reset */
 253                 wmb();
 254                 usleep_range(500, 1000);
 255 
 256                 data &= ~EDP_AUX_CTRL_RESET;
 257                 data |= EDP_AUX_CTRL_ENABLE;
 258                 edp_write(aux->base + REG_EDP_AUX_CTRL, data);
 259         } else {
 260                 data &= ~EDP_AUX_CTRL_ENABLE;
 261                 edp_write(aux->base + REG_EDP_AUX_CTRL, data);
 262         }
 263 }
 264 

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