static int i2c_ssbi_transfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) { int ret = 0; int rem = num; unsigned long flags; struct i2c_ssbi_dev *ssbi = i2c_get_adapdata(adap); remote_spin_lock_irqsave(&ssbi->rspin_lock, flags); while (rem) { if (msgs->flags & I2C_M_RD) { ret = i2c_ssbi_read_bytes(ssbi, msgs); if (ret) goto transfer_failed; } else { ret = i2c_ssbi_write_bytes(ssbi, msgs); if (ret) goto transfer_failed; } msgs++; rem--; } remote_spin_unlock_irqrestore(&ssbi->rspin_lock, flags); return num; transfer_failed: remote_spin_unlock_irqrestore(&ssbi->rspin_lock, flags); return ret; }
static void msm_i2c_rmutex_unlock(struct msm_i2c_dev *dev) { unsigned long flags; if (!dev->pdata->rmutex) return; remote_spin_lock_irqsave(&dev->rspin_lock, flags); *(dev->pdata->rmutex) = 0; remote_spin_unlock_irqrestore(&dev->rspin_lock, flags); }
static void remote_spinlock_test(struct smp2p_loopback_ctx *ctx) { uint32_t test_request; uint32_t test_response; unsigned long flags; int n; unsigned lock_count = 0; remote_spinlock_t *smem_spinlock; test_request = 0x0; SMP2P_SET_RMT_CMD_TYPE_REQ(test_request); smem_spinlock = smem_get_remote_spinlock(); if (!smem_spinlock) { pr_err("%s: unable to get remote spinlock\n", __func__); return; } for (;;) { remote_spin_lock_irqsave(smem_spinlock, flags); ++lock_count; SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_RSPIN_LOCKED); (void)msm_smp2p_out_write(ctx->out, test_request); for (n = 0; n < 10000; ++n) { (void)msm_smp2p_in_read(ctx->proc_id, "smp2p", &test_response); test_response = SMP2P_GET_RMT_CMD(test_response); if (test_response == SMP2P_LB_CMD_RSPIN_END) break; if (test_response != SMP2P_LB_CMD_RSPIN_UNLOCKED) SMP2P_ERR("%s: invalid spinlock command %x\n", __func__, test_response); } if (test_response == SMP2P_LB_CMD_RSPIN_END) { SMP2P_SET_RMT_CMD_TYPE_RESP(test_request); SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_RSPIN_END); SMP2P_SET_RMT_DATA(test_request, lock_count); (void)msm_smp2p_out_write(ctx->out, test_request); break; } SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_RSPIN_UNLOCKED); (void)msm_smp2p_out_write(ctx->out, test_request); remote_spin_unlock_irqrestore(smem_spinlock, flags); } remote_spin_unlock_irqrestore(smem_spinlock, flags); }
static void msm_i2c_rmutex_lock(struct msm_i2c_dev *dev) { int gotlock = 0; unsigned long flags; if (!dev->pdata->rmutex) return; do { remote_spin_lock_irqsave(&dev->rspin_lock, flags); if (*(dev->pdata->rmutex) == 0) { *(dev->pdata->rmutex) = 1; gotlock = 1; } remote_spin_unlock_irqrestore(&dev->rspin_lock, flags); /* wait for 1-byte clock interval */ if (!gotlock) udelay(10000000/dev->pdata->clk_freq); } while (!gotlock); }
int msm_ssbi_write(struct device *dev, u16 addr, u8 *buf, int len) { struct msm_ssbi *ssbi = to_msm_ssbi(dev); unsigned long flags; int ret; if (ssbi->dev != dev) return -ENXIO; if (ssbi->use_rlock) { remote_spin_lock_irqsave(&ssbi->rspin_lock, flags); ret = ssbi->write(ssbi, addr, buf, len); remote_spin_unlock_irqrestore(&ssbi->rspin_lock, flags); } else { spin_lock_irqsave(&ssbi->lock, flags); ret = ssbi->write(ssbi, addr, buf, len); spin_unlock_irqrestore(&ssbi->lock, flags); } return ret; }