void rtsx_pci_stop_cmd(struct rtsx_pcr *pcr) { rtsx_pci_writel(pcr, RTSX_HCBCTLR, STOP_CMD); rtsx_pci_writel(pcr, RTSX_HDBCTLR, STOP_DMA); rtsx_pci_write_register(pcr, DMACTL, 0x80, 0x80); rtsx_pci_write_register(pcr, RBCTL, 0x80, 0x80); }
static void rts5260_stop_cmd(struct rtsx_pcr *pcr) { rtsx_pci_writel(pcr, RTSX_HCBCTLR, STOP_CMD); rtsx_pci_writel(pcr, RTSX_HDBCTLR, STOP_DMA); rtsx_pci_write_register(pcr, RTS5260_DMA_RST_CTL_0, RTS5260_DMA_RST | RTS5260_ADMA3_RST, RTS5260_DMA_RST | RTS5260_ADMA3_RST); rtsx_pci_write_register(pcr, RBCTL, RB_FLUSH, RB_FLUSH); }
int rtsx_pci_send_cmd(struct rtsx_pcr *pcr, int timeout) { struct completion trans_done; u32 val = 1 << 31; long timeleft; unsigned long flags; int err = 0; spin_lock_irqsave(&pcr->lock, flags); /* set up data structures for the wakeup system */ pcr->done = &trans_done; pcr->trans_result = TRANS_NOT_READY; init_completion(&trans_done); rtsx_pci_writel(pcr, RTSX_HCBAR, pcr->host_cmds_addr); val |= (u32)(pcr->ci * 4) & 0x00FFFFFF; /* Hardware Auto Response */ val |= 0x40000000; rtsx_pci_writel(pcr, RTSX_HCBCTLR, val); spin_unlock_irqrestore(&pcr->lock, flags); /* Wait for TRANS_OK_INT */ timeleft = wait_for_completion_interruptible_timeout( &trans_done, msecs_to_jiffies(timeout)); if (timeleft <= 0) { dev_dbg(&(pcr->pci->dev), "Timeout (%s %d)\n", __func__, __LINE__); err = -ETIMEDOUT; goto finish_send_cmd; } spin_lock_irqsave(&pcr->lock, flags); if (pcr->trans_result == TRANS_RESULT_FAIL) err = -EINVAL; else if (pcr->trans_result == TRANS_RESULT_OK) err = 0; else if (pcr->trans_result == TRANS_NO_DEVICE) err = -ENODEV; spin_unlock_irqrestore(&pcr->lock, flags); finish_send_cmd: spin_lock_irqsave(&pcr->lock, flags); pcr->done = NULL; spin_unlock_irqrestore(&pcr->lock, flags); if ((err < 0) && (err != -ENODEV)) rtsx_pci_stop_cmd(pcr); if (pcr->finish_me) complete(pcr->finish_me); return err; }
void rtsx_pci_send_cmd_no_wait(struct rtsx_pcr *pcr) { u32 val = 1 << 31; rtsx_pci_writel(pcr, RTSX_HCBAR, pcr->host_cmds_addr); val |= (u32)(pcr->ci * 4) & 0x00FFFFFF; /* Hardware Auto Response */ val |= 0x40000000; rtsx_pci_writel(pcr, RTSX_HCBCTLR, val); }
int rtsx_pci_write_register(struct rtsx_pcr *pcr, u16 addr, u8 mask, u8 data) { int i; u32 val = HAIMR_WRITE_START; val |= (u32)(addr & 0x3FFF) << 16; val |= (u32)mask << 8; val |= (u32)data; rtsx_pci_writel(pcr, RTSX_HAIMR, val); for (i = 0; i < MAX_RW_REG_CNT; i++) { val = rtsx_pci_readl(pcr, RTSX_HAIMR); if ((val & HAIMR_TRANS_END) == 0) { if (data != (u8)val) return -EIO; return 0; } } return -ETIMEDOUT; }
int rtsx_pci_read_register(struct rtsx_pcr *pcr, u16 addr, u8 *data) { u32 val = HAIMR_READ_START; int i; val |= (u32)(addr & 0x3FFF) << 16; rtsx_pci_writel(pcr, RTSX_HAIMR, val); for (i = 0; i < MAX_RW_REG_CNT; i++) { val = rtsx_pci_readl(pcr, RTSX_HAIMR); if ((val & HAIMR_TRANS_END) == 0) break; } if (i >= MAX_RW_REG_CNT) return -ETIMEDOUT; if (data) *data = (u8)(val & 0xFF); return 0; }