Lines Matching refs:cq_host
34 static inline u8 *get_desc(struct cqhci_host *cq_host, u8 tag) in get_desc() argument
36 return cq_host->desc_base + (tag * cq_host->slot_sz); in get_desc()
39 static inline u8 *get_link_desc(struct cqhci_host *cq_host, u8 tag) in get_link_desc() argument
41 u8 *desc = get_desc(cq_host, tag); in get_link_desc()
43 return desc + cq_host->task_desc_len; in get_link_desc()
46 static inline dma_addr_t get_trans_desc_dma(struct cqhci_host *cq_host, u8 tag) in get_trans_desc_dma() argument
48 return cq_host->trans_desc_dma_base + in get_trans_desc_dma()
49 (cq_host->mmc->max_segs * tag * in get_trans_desc_dma()
50 cq_host->trans_desc_len); in get_trans_desc_dma()
53 static inline u8 *get_trans_desc(struct cqhci_host *cq_host, u8 tag) in get_trans_desc() argument
55 return cq_host->trans_desc_base + in get_trans_desc()
56 (cq_host->trans_desc_len * cq_host->mmc->max_segs * tag); in get_trans_desc()
59 static void setup_trans_desc(struct cqhci_host *cq_host, u8 tag) in setup_trans_desc() argument
64 link_temp = get_link_desc(cq_host, tag); in setup_trans_desc()
65 trans_temp = get_trans_desc_dma(cq_host, tag); in setup_trans_desc()
67 memset(link_temp, 0, cq_host->link_desc_len); in setup_trans_desc()
68 if (cq_host->link_desc_len > 8) in setup_trans_desc()
71 if (tag == DCMD_SLOT && (cq_host->mmc->caps2 & MMC_CAP2_CQE_DCMD)) { in setup_trans_desc()
78 if (cq_host->dma64) { in setup_trans_desc()
89 static void cqhci_set_irqs(struct cqhci_host *cq_host, u32 set) in cqhci_set_irqs() argument
91 cqhci_writel(cq_host, set, CQHCI_ISTE); in cqhci_set_irqs()
92 cqhci_writel(cq_host, set, CQHCI_ISGE); in cqhci_set_irqs()
100 static void cqhci_dumpregs(struct cqhci_host *cq_host) in cqhci_dumpregs() argument
102 struct mmc_host *mmc = cq_host->mmc; in cqhci_dumpregs()
107 cqhci_readl(cq_host, CQHCI_CAP), in cqhci_dumpregs()
108 cqhci_readl(cq_host, CQHCI_VER)); in cqhci_dumpregs()
110 cqhci_readl(cq_host, CQHCI_CFG), in cqhci_dumpregs()
111 cqhci_readl(cq_host, CQHCI_CTL)); in cqhci_dumpregs()
113 cqhci_readl(cq_host, CQHCI_IS), in cqhci_dumpregs()
114 cqhci_readl(cq_host, CQHCI_ISTE)); in cqhci_dumpregs()
116 cqhci_readl(cq_host, CQHCI_ISGE), in cqhci_dumpregs()
117 cqhci_readl(cq_host, CQHCI_IC)); in cqhci_dumpregs()
119 cqhci_readl(cq_host, CQHCI_TDLBA), in cqhci_dumpregs()
120 cqhci_readl(cq_host, CQHCI_TDLBAU)); in cqhci_dumpregs()
122 cqhci_readl(cq_host, CQHCI_TDBR), in cqhci_dumpregs()
123 cqhci_readl(cq_host, CQHCI_TCN)); in cqhci_dumpregs()
125 cqhci_readl(cq_host, CQHCI_DQS), in cqhci_dumpregs()
126 cqhci_readl(cq_host, CQHCI_DPT)); in cqhci_dumpregs()
128 cqhci_readl(cq_host, CQHCI_TCLR), in cqhci_dumpregs()
129 cqhci_readl(cq_host, CQHCI_SSC1)); in cqhci_dumpregs()
131 cqhci_readl(cq_host, CQHCI_SSC2), in cqhci_dumpregs()
132 cqhci_readl(cq_host, CQHCI_CRDCT)); in cqhci_dumpregs()
134 cqhci_readl(cq_host, CQHCI_RMEM), in cqhci_dumpregs()
135 cqhci_readl(cq_host, CQHCI_TERRI)); in cqhci_dumpregs()
137 cqhci_readl(cq_host, CQHCI_CRI), in cqhci_dumpregs()
138 cqhci_readl(cq_host, CQHCI_CRA)); in cqhci_dumpregs()
140 if (cq_host->ops->dumpregs) in cqhci_dumpregs()
141 cq_host->ops->dumpregs(mmc); in cqhci_dumpregs()
161 static int cqhci_host_alloc_tdl(struct cqhci_host *cq_host) in cqhci_host_alloc_tdl() argument
166 if (cq_host->caps & CQHCI_TASK_DESC_SZ_128) { in cqhci_host_alloc_tdl()
167 cqhci_writel(cq_host, cqhci_readl(cq_host, CQHCI_CFG) | in cqhci_host_alloc_tdl()
169 cq_host->task_desc_len = 16; in cqhci_host_alloc_tdl()
171 cq_host->task_desc_len = 8; in cqhci_host_alloc_tdl()
179 if (cq_host->dma64) { in cqhci_host_alloc_tdl()
180 if (cq_host->quirks & CQHCI_QUIRK_SHORT_TXFR_DESC_SZ) in cqhci_host_alloc_tdl()
181 cq_host->trans_desc_len = 12; in cqhci_host_alloc_tdl()
183 cq_host->trans_desc_len = 16; in cqhci_host_alloc_tdl()
184 cq_host->link_desc_len = 16; in cqhci_host_alloc_tdl()
186 cq_host->trans_desc_len = 8; in cqhci_host_alloc_tdl()
187 cq_host->link_desc_len = 8; in cqhci_host_alloc_tdl()
191 cq_host->slot_sz = cq_host->task_desc_len + cq_host->link_desc_len; in cqhci_host_alloc_tdl()
193 cq_host->desc_size = cq_host->slot_sz * cq_host->num_slots; in cqhci_host_alloc_tdl()
195 cq_host->data_size = cq_host->trans_desc_len * cq_host->mmc->max_segs * in cqhci_host_alloc_tdl()
196 cq_host->mmc->cqe_qdepth; in cqhci_host_alloc_tdl()
199 mmc_hostname(cq_host->mmc), cq_host->desc_size, cq_host->data_size, in cqhci_host_alloc_tdl()
200 cq_host->slot_sz); in cqhci_host_alloc_tdl()
208 cq_host->desc_base = dmam_alloc_coherent(mmc_dev(cq_host->mmc), in cqhci_host_alloc_tdl()
209 cq_host->desc_size, in cqhci_host_alloc_tdl()
210 &cq_host->desc_dma_base, in cqhci_host_alloc_tdl()
212 if (!cq_host->desc_base) in cqhci_host_alloc_tdl()
215 cq_host->trans_desc_base = dmam_alloc_coherent(mmc_dev(cq_host->mmc), in cqhci_host_alloc_tdl()
216 cq_host->data_size, in cqhci_host_alloc_tdl()
217 &cq_host->trans_desc_dma_base, in cqhci_host_alloc_tdl()
219 if (!cq_host->trans_desc_base) { in cqhci_host_alloc_tdl()
220 dmam_free_coherent(mmc_dev(cq_host->mmc), cq_host->desc_size, in cqhci_host_alloc_tdl()
221 cq_host->desc_base, in cqhci_host_alloc_tdl()
222 cq_host->desc_dma_base); in cqhci_host_alloc_tdl()
223 cq_host->desc_base = NULL; in cqhci_host_alloc_tdl()
224 cq_host->desc_dma_base = 0; in cqhci_host_alloc_tdl()
229 mmc_hostname(cq_host->mmc), cq_host->desc_base, cq_host->trans_desc_base, in cqhci_host_alloc_tdl()
230 (unsigned long long)cq_host->desc_dma_base, in cqhci_host_alloc_tdl()
231 (unsigned long long)cq_host->trans_desc_dma_base); in cqhci_host_alloc_tdl()
233 for (; i < (cq_host->num_slots); i++) in cqhci_host_alloc_tdl()
234 setup_trans_desc(cq_host, i); in cqhci_host_alloc_tdl()
239 static void __cqhci_enable(struct cqhci_host *cq_host) in __cqhci_enable() argument
241 struct mmc_host *mmc = cq_host->mmc; in __cqhci_enable()
244 cqcfg = cqhci_readl(cq_host, CQHCI_CFG); in __cqhci_enable()
249 cqhci_writel(cq_host, cqcfg, CQHCI_CFG); in __cqhci_enable()
257 if (cq_host->caps & CQHCI_TASK_DESC_SZ_128) in __cqhci_enable()
260 cqhci_writel(cq_host, cqcfg, CQHCI_CFG); in __cqhci_enable()
262 cqhci_writel(cq_host, lower_32_bits(cq_host->desc_dma_base), in __cqhci_enable()
264 cqhci_writel(cq_host, upper_32_bits(cq_host->desc_dma_base), in __cqhci_enable()
267 cqhci_writel(cq_host, cq_host->rca, CQHCI_SSC2); in __cqhci_enable()
269 cqhci_set_irqs(cq_host, 0); in __cqhci_enable()
273 cqhci_writel(cq_host, cqcfg, CQHCI_CFG); in __cqhci_enable()
277 if (cq_host->ops->enable) in __cqhci_enable()
278 cq_host->ops->enable(mmc); in __cqhci_enable()
283 cqhci_set_irqs(cq_host, CQHCI_IS_MASK); in __cqhci_enable()
285 cq_host->activated = true; in __cqhci_enable()
288 static void __cqhci_disable(struct cqhci_host *cq_host) in __cqhci_disable() argument
292 cqcfg = cqhci_readl(cq_host, CQHCI_CFG); in __cqhci_disable()
294 cqhci_writel(cq_host, cqcfg, CQHCI_CFG); in __cqhci_disable()
296 cq_host->mmc->cqe_on = false; in __cqhci_disable()
298 cq_host->activated = false; in __cqhci_disable()
303 struct cqhci_host *cq_host = mmc->cqe_private; in cqhci_suspend() local
305 if (cq_host->enabled) in cqhci_suspend()
306 __cqhci_disable(cq_host); in cqhci_suspend()
321 struct cqhci_host *cq_host = mmc->cqe_private; in cqhci_enable() local
324 if (cq_host->enabled) in cqhci_enable()
327 cq_host->rca = card->rca; in cqhci_enable()
329 err = cqhci_host_alloc_tdl(cq_host); in cqhci_enable()
333 __cqhci_enable(cq_host); in cqhci_enable()
335 cq_host->enabled = true; in cqhci_enable()
338 cqhci_dumpregs(cq_host); in cqhci_enable()
348 struct cqhci_host *cq_host = mmc->cqe_private; in cqhci_off() local
353 if (!cq_host->enabled || !mmc->cqe_on || cq_host->recovery_halt) in cqhci_off()
356 if (cq_host->ops->disable) in cqhci_off()
357 cq_host->ops->disable(mmc, false); in cqhci_off()
359 cqhci_writel(cq_host, CQHCI_HALT, CQHCI_CTL); in cqhci_off()
364 reg = cqhci_readl(cq_host, CQHCI_CTL); in cqhci_off()
379 struct cqhci_host *cq_host = mmc->cqe_private; in cqhci_disable() local
381 if (!cq_host->enabled) in cqhci_disable()
386 __cqhci_disable(cq_host); in cqhci_disable()
388 dmam_free_coherent(mmc_dev(mmc), cq_host->data_size, in cqhci_disable()
389 cq_host->trans_desc_base, in cqhci_disable()
390 cq_host->trans_desc_dma_base); in cqhci_disable()
392 dmam_free_coherent(mmc_dev(mmc), cq_host->desc_size, in cqhci_disable()
393 cq_host->desc_base, in cqhci_disable()
394 cq_host->desc_dma_base); in cqhci_disable()
396 cq_host->trans_desc_base = NULL; in cqhci_disable()
397 cq_host->desc_base = NULL; in cqhci_disable()
399 cq_host->enabled = false; in cqhci_disable()
467 struct cqhci_host *cq_host, int tag) in cqhci_prep_tran_desc() argument
472 bool dma64 = cq_host->dma64; in cqhci_prep_tran_desc()
484 desc = get_trans_desc(cq_host, tag); in cqhci_prep_tran_desc()
493 desc += cq_host->trans_desc_len; in cqhci_prep_tran_desc()
507 struct cqhci_host *cq_host = mmc->cqe_private; in cqhci_prep_dcmd_desc() local
523 task_desc = (__le64 __force *)get_desc(cq_host, cq_host->dcmd_slot); in cqhci_prep_dcmd_desc()
524 memset(task_desc, 0, cq_host->task_desc_len); in cqhci_prep_dcmd_desc()
532 if (cq_host->ops->update_dcmd_desc) in cqhci_prep_dcmd_desc()
533 cq_host->ops->update_dcmd_desc(mmc, mrq, &data); in cqhci_prep_dcmd_desc()
565 struct cqhci_host *cq_host = mmc->cqe_private; in cqhci_request() local
568 if (!cq_host->enabled) { in cqhci_request()
574 if (!cq_host->activated) in cqhci_request()
575 __cqhci_enable(cq_host); in cqhci_request()
578 cqhci_writel(cq_host, 0, CQHCI_CTL); in cqhci_request()
581 if (cqhci_readl(cq_host, CQHCI_CTL) && CQHCI_HALT) { in cqhci_request()
585 if (cq_host->ops->enable) in cqhci_request()
586 cq_host->ops->enable(mmc); in cqhci_request()
590 task_desc = (__le64 __force *)get_desc(cq_host, tag); in cqhci_request()
593 err = cqhci_prep_tran_desc(mrq, cq_host, tag); in cqhci_request()
603 spin_lock_irqsave(&cq_host->lock, flags); in cqhci_request()
605 if (cq_host->recovery_halt) { in cqhci_request()
610 cq_host->slot[tag].mrq = mrq; in cqhci_request()
611 cq_host->slot[tag].flags = 0; in cqhci_request()
613 cq_host->qcnt += 1; in cqhci_request()
616 cqhci_writel(cq_host, 1 << tag, CQHCI_TDBR); in cqhci_request()
617 if (!(cqhci_readl(cq_host, CQHCI_TDBR) & (1 << tag))) in cqhci_request()
621 spin_unlock_irqrestore(&cq_host->lock, flags); in cqhci_request()
632 struct cqhci_host *cq_host = mmc->cqe_private; in cqhci_recovery_needed() local
634 if (!cq_host->recovery_halt) { in cqhci_recovery_needed()
635 cq_host->recovery_halt = true; in cqhci_recovery_needed()
637 wake_up(&cq_host->wait_queue); in cqhci_recovery_needed()
660 struct cqhci_host *cq_host = mmc->cqe_private; in cqhci_error_irq() local
665 spin_lock(&cq_host->lock); in cqhci_error_irq()
667 terri = cqhci_readl(cq_host, CQHCI_TERRI); in cqhci_error_irq()
673 if (cq_host->recovery_halt) in cqhci_error_irq()
676 if (!cq_host->qcnt) { in cqhci_error_irq()
685 slot = &cq_host->slot[tag]; in cqhci_error_irq()
694 slot = &cq_host->slot[tag]; in cqhci_error_irq()
701 if (!cq_host->recovery_halt) { in cqhci_error_irq()
707 slot = &cq_host->slot[tag]; in cqhci_error_irq()
717 spin_unlock(&cq_host->lock); in cqhci_error_irq()
722 struct cqhci_host *cq_host = mmc->cqe_private; in cqhci_finish_mrq() local
723 struct cqhci_slot *slot = &cq_host->slot[tag]; in cqhci_finish_mrq()
734 if (cq_host->recovery_halt) { in cqhci_finish_mrq()
741 cq_host->qcnt -= 1; in cqhci_finish_mrq()
759 struct cqhci_host *cq_host = mmc->cqe_private; in cqhci_irq() local
761 status = cqhci_readl(cq_host, CQHCI_IS); in cqhci_irq()
762 cqhci_writel(cq_host, status, CQHCI_IS); in cqhci_irq()
771 comp_status = cqhci_readl(cq_host, CQHCI_TCN); in cqhci_irq()
772 cqhci_writel(cq_host, comp_status, CQHCI_TCN); in cqhci_irq()
776 spin_lock(&cq_host->lock); in cqhci_irq()
778 for_each_set_bit(tag, &comp_status, cq_host->num_slots) { in cqhci_irq()
785 if (cq_host->waiting_for_idle && !cq_host->qcnt) { in cqhci_irq()
786 cq_host->waiting_for_idle = false; in cqhci_irq()
787 wake_up(&cq_host->wait_queue); in cqhci_irq()
790 spin_unlock(&cq_host->lock); in cqhci_irq()
794 wake_up(&cq_host->wait_queue); in cqhci_irq()
797 wake_up(&cq_host->wait_queue); in cqhci_irq()
803 static bool cqhci_is_idle(struct cqhci_host *cq_host, int *ret) in cqhci_is_idle() argument
808 spin_lock_irqsave(&cq_host->lock, flags); in cqhci_is_idle()
809 is_idle = !cq_host->qcnt || cq_host->recovery_halt; in cqhci_is_idle()
810 *ret = cq_host->recovery_halt ? -EBUSY : 0; in cqhci_is_idle()
811 cq_host->waiting_for_idle = !is_idle; in cqhci_is_idle()
812 spin_unlock_irqrestore(&cq_host->lock, flags); in cqhci_is_idle()
819 struct cqhci_host *cq_host = mmc->cqe_private; in cqhci_wait_for_idle() local
822 wait_event(cq_host->wait_queue, cqhci_is_idle(cq_host, &ret)); in cqhci_wait_for_idle()
830 struct cqhci_host *cq_host = mmc->cqe_private; in cqhci_timeout() local
832 struct cqhci_slot *slot = &cq_host->slot[tag]; in cqhci_timeout()
836 spin_lock_irqsave(&cq_host->lock, flags); in cqhci_timeout()
841 *recovery_needed = cq_host->recovery_halt; in cqhci_timeout()
843 spin_unlock_irqrestore(&cq_host->lock, flags); in cqhci_timeout()
848 cqhci_dumpregs(cq_host); in cqhci_timeout()
854 static bool cqhci_tasks_cleared(struct cqhci_host *cq_host) in cqhci_tasks_cleared() argument
856 return !(cqhci_readl(cq_host, CQHCI_CTL) & CQHCI_CLEAR_ALL_TASKS); in cqhci_tasks_cleared()
861 struct cqhci_host *cq_host = mmc->cqe_private; in cqhci_clear_all_tasks() local
865 cqhci_set_irqs(cq_host, CQHCI_IS_TCL); in cqhci_clear_all_tasks()
867 ctl = cqhci_readl(cq_host, CQHCI_CTL); in cqhci_clear_all_tasks()
869 cqhci_writel(cq_host, ctl, CQHCI_CTL); in cqhci_clear_all_tasks()
871 wait_event_timeout(cq_host->wait_queue, cqhci_tasks_cleared(cq_host), in cqhci_clear_all_tasks()
874 cqhci_set_irqs(cq_host, 0); in cqhci_clear_all_tasks()
876 ret = cqhci_tasks_cleared(cq_host); in cqhci_clear_all_tasks()
885 static bool cqhci_halted(struct cqhci_host *cq_host) in cqhci_halted() argument
887 return cqhci_readl(cq_host, CQHCI_CTL) & CQHCI_HALT; in cqhci_halted()
892 struct cqhci_host *cq_host = mmc->cqe_private; in cqhci_halt() local
896 if (cqhci_halted(cq_host)) in cqhci_halt()
899 cqhci_set_irqs(cq_host, CQHCI_IS_HAC); in cqhci_halt()
901 ctl = cqhci_readl(cq_host, CQHCI_CTL); in cqhci_halt()
903 cqhci_writel(cq_host, ctl, CQHCI_CTL); in cqhci_halt()
905 wait_event_timeout(cq_host->wait_queue, cqhci_halted(cq_host), in cqhci_halt()
908 cqhci_set_irqs(cq_host, 0); in cqhci_halt()
910 ret = cqhci_halted(cq_host); in cqhci_halt()
928 struct cqhci_host *cq_host = mmc->cqe_private; in cqhci_recovery_start() local
932 WARN_ON(!cq_host->recovery_halt); in cqhci_recovery_start()
936 if (cq_host->ops->disable) in cqhci_recovery_start()
937 cq_host->ops->disable(mmc, true); in cqhci_recovery_start()
957 static void cqhci_recover_mrq(struct cqhci_host *cq_host, unsigned int tag) in cqhci_recover_mrq() argument
959 struct cqhci_slot *slot = &cq_host->slot[tag]; in cqhci_recover_mrq()
968 cq_host->qcnt -= 1; in cqhci_recover_mrq()
978 mmc_cqe_request_done(cq_host->mmc, mrq); in cqhci_recover_mrq()
981 static void cqhci_recover_mrqs(struct cqhci_host *cq_host) in cqhci_recover_mrqs() argument
985 for (i = 0; i < cq_host->num_slots; i++) in cqhci_recover_mrqs()
986 cqhci_recover_mrq(cq_host, i); in cqhci_recover_mrqs()
1001 struct cqhci_host *cq_host = mmc->cqe_private; in cqhci_recovery_finish() local
1008 WARN_ON(!cq_host->recovery_halt); in cqhci_recovery_finish()
1023 cqcfg = cqhci_readl(cq_host, CQHCI_CFG); in cqhci_recovery_finish()
1025 cqhci_writel(cq_host, cqcfg, CQHCI_CFG); in cqhci_recovery_finish()
1027 cqhci_writel(cq_host, cqcfg, CQHCI_CFG); in cqhci_recovery_finish()
1035 cqhci_recover_mrqs(cq_host); in cqhci_recovery_finish()
1037 WARN_ON(cq_host->qcnt); in cqhci_recovery_finish()
1039 spin_lock_irqsave(&cq_host->lock, flags); in cqhci_recovery_finish()
1040 cq_host->qcnt = 0; in cqhci_recovery_finish()
1041 cq_host->recovery_halt = false; in cqhci_recovery_finish()
1043 spin_unlock_irqrestore(&cq_host->lock, flags); in cqhci_recovery_finish()
1048 cqhci_writel(cq_host, CQHCI_IS_HAC | CQHCI_IS_TCL, CQHCI_IS); in cqhci_recovery_finish()
1050 cqhci_set_irqs(cq_host, CQHCI_IS_MASK); in cqhci_recovery_finish()
1069 struct cqhci_host *cq_host; in cqhci_pltfm_init() local
1080 cq_host = devm_kzalloc(&pdev->dev, sizeof(*cq_host), GFP_KERNEL); in cqhci_pltfm_init()
1081 if (!cq_host) in cqhci_pltfm_init()
1083 cq_host->mmio = devm_ioremap(&pdev->dev, in cqhci_pltfm_init()
1086 if (!cq_host->mmio) { in cqhci_pltfm_init()
1092 return cq_host; in cqhci_pltfm_init()
1096 static unsigned int cqhci_ver_major(struct cqhci_host *cq_host) in cqhci_ver_major() argument
1098 return CQHCI_VER_MAJOR(cqhci_readl(cq_host, CQHCI_VER)); in cqhci_ver_major()
1101 static unsigned int cqhci_ver_minor(struct cqhci_host *cq_host) in cqhci_ver_minor() argument
1103 u32 ver = cqhci_readl(cq_host, CQHCI_VER); in cqhci_ver_minor()
1108 int cqhci_init(struct cqhci_host *cq_host, struct mmc_host *mmc, in cqhci_init() argument
1113 cq_host->dma64 = dma64; in cqhci_init()
1114 cq_host->mmc = mmc; in cqhci_init()
1115 cq_host->mmc->cqe_private = cq_host; in cqhci_init()
1117 cq_host->num_slots = NUM_SLOTS; in cqhci_init()
1118 cq_host->dcmd_slot = DCMD_SLOT; in cqhci_init()
1126 cq_host->slot = devm_kcalloc(mmc_dev(mmc), cq_host->num_slots, in cqhci_init()
1127 sizeof(*cq_host->slot), GFP_KERNEL); in cqhci_init()
1128 if (!cq_host->slot) { in cqhci_init()
1133 spin_lock_init(&cq_host->lock); in cqhci_init()
1135 init_completion(&cq_host->halt_comp); in cqhci_init()
1136 init_waitqueue_head(&cq_host->wait_queue); in cqhci_init()
1139 mmc_hostname(mmc), cqhci_ver_major(cq_host), in cqhci_init()
1140 cqhci_ver_minor(cq_host)); in cqhci_init()
1146 mmc_hostname(mmc), cqhci_ver_major(cq_host), in cqhci_init()
1147 cqhci_ver_minor(cq_host), err); in cqhci_init()