Beispiel #1
0
int uwbd_msg_handle_reset(struct uwb_event *evt)
{
	struct uwb_rc *rc = evt->rc;
	int ret;

	dev_info(&rc->uwb_dev.dev, "resetting radio controller\n");
	ret = rc->reset(rc);
	if (ret < 0) {
		dev_err(&rc->uwb_dev.dev, "failed to reset hardware: %d\n", ret);
		goto error;
	}
	return 0;
error:
	/* Nothing can be done except try the reset again. Wait a bit
	   to avoid reset loops during probe() or remove(). */
	msleep(1000);
	uwb_rc_reset_all(rc);
	return ret;
}
/**
 * Execute an UWB RC command on WHCI/RC
 *
 * @rc:       Instance of a Radio Controller that is a whcrc
 * @cmd:      Buffer containing the RCCB and payload to execute
 * @cmd_size: Size of the command buffer.
 *
 * We copy the command into whcrc->cmd_buf (as it is pretty and
 * aligned`and physically contiguous) and then press the right keys in
 * the controller's URCCMD register to get it to read it. We might
 * have to wait for the cmd_sem to be open to us.
 *
 * NOTE: rc's mutex has to be locked
 */
static int whcrc_cmd(struct uwb_rc *uwb_rc,
	      const struct uwb_rccb *cmd, size_t cmd_size)
{
	int result = 0;
	struct whcrc *whcrc = uwb_rc->priv;
	struct device *dev = &whcrc->umc_dev->dev;
	u32 urccmd;

	if (cmd_size >= 4096)
		return -EINVAL;

	/*
	 * If the URC is halted, then the hardware has reset itself.
	 * Attempt to recover by restarting the device and then return
	 * an error as it's likely that the current command isn't
	 * valid for a newly started RC.
	 */
	if (le_readl(whcrc->rc_base + URCSTS) & URCSTS_HALTED) {
		dev_err(dev, "requesting reset of halted radio controller\n");
		uwb_rc_reset_all(uwb_rc);
		return -EIO;
	}

	result = wait_event_timeout(whcrc->cmd_wq,
		!(le_readl(whcrc->rc_base + URCCMD) & URCCMD_ACTIVE), HZ/2);
	if (result == 0) {
		dev_err(dev, "device is not ready to execute commands\n");
		return -ETIMEDOUT;
	}

	memmove(whcrc->cmd_buf, cmd, cmd_size);
	le_writeq(whcrc->cmd_dma_buf, whcrc->rc_base + URCCMDADDR);

	spin_lock(&whcrc->irq_lock);
	urccmd = le_readl(whcrc->rc_base + URCCMD);
	urccmd &= ~(URCCMD_EARV | URCCMD_SIZE_MASK);
	le_writel(urccmd | URCCMD_ACTIVE | URCCMD_IWR | cmd_size,
		  whcrc->rc_base + URCCMD);
	spin_unlock(&whcrc->irq_lock);

	return 0;
}
Beispiel #3
0
/**
 * wusbhc_reset_all - reset the HC hardware
 * @wusbhc: the host controller to reset.
 *
 * Request a full hardware reset of the chip.  This will also reset
 * the radio controller and any other PALs.
 */
void wusbhc_reset_all(struct wusbhc *wusbhc)
{
	uwb_rc_reset_all(wusbhc->uwb_rc);
}