Lines Matching +full:mmc +full:- +full:host

1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2018 Oleksij Rempel <linux@rempel-privat.de>
10 * As soon as some one with documentation or more experience in SD/MMC, or
12 * thing what I did. 2018 Oleksij Rempel <linux@rempel-privat.de>
25 #include <linux/mmc/host.h>
26 #include <linux/mmc/mmc.h>
73 static inline void alcor_rmw8(struct alcor_sdmmc_host *host, unsigned int addr, in alcor_rmw8() argument
76 struct alcor_pci_priv *priv = host->alcor_pci; in alcor_rmw8()
88 static inline void alcor_mask_sd_irqs(struct alcor_sdmmc_host *host) in alcor_mask_sd_irqs() argument
90 struct alcor_pci_priv *priv = host->alcor_pci; in alcor_mask_sd_irqs()
95 static inline void alcor_unmask_sd_irqs(struct alcor_sdmmc_host *host) in alcor_unmask_sd_irqs() argument
97 struct alcor_pci_priv *priv = host->alcor_pci; in alcor_unmask_sd_irqs()
105 static void alcor_reset(struct alcor_sdmmc_host *host, u8 val) in alcor_reset() argument
107 struct alcor_pci_priv *priv = host->alcor_pci; in alcor_reset()
117 dev_err(host->dev, "%s: timeout\n", __func__); in alcor_reset()
123 static void alcor_data_set_dma(struct alcor_sdmmc_host *host) in alcor_data_set_dma() argument
125 struct alcor_pci_priv *priv = host->alcor_pci; in alcor_data_set_dma()
128 if (!host->sg_count) in alcor_data_set_dma()
131 if (!host->sg) { in alcor_data_set_dma()
132 dev_err(host->dev, "have blocks, but no SG\n"); in alcor_data_set_dma()
136 if (!sg_dma_len(host->sg)) { in alcor_data_set_dma()
137 dev_err(host->dev, "DMA SG len == 0\n"); in alcor_data_set_dma()
142 addr = (u32)sg_dma_address(host->sg); in alcor_data_set_dma()
145 host->sg = sg_next(host->sg); in alcor_data_set_dma()
146 host->sg_count--; in alcor_data_set_dma()
149 static void alcor_trigger_data_transfer(struct alcor_sdmmc_host *host) in alcor_trigger_data_transfer() argument
151 struct alcor_pci_priv *priv = host->alcor_pci; in alcor_trigger_data_transfer()
152 struct mmc_data *data = host->data; in alcor_trigger_data_transfer()
155 if (data->flags & MMC_DATA_WRITE) in alcor_trigger_data_transfer()
158 if (data->host_cookie == COOKIE_MAPPED) { in alcor_trigger_data_transfer()
165 * indicating that the single-page DMA was completed. in alcor_trigger_data_transfer()
167 alcor_data_set_dma(host); in alcor_trigger_data_transfer()
169 host->dma_on = 1; in alcor_trigger_data_transfer()
170 alcor_write32(priv, data->sg_count * 0x1000, in alcor_trigger_data_transfer()
175 * into several sector-sized transfers. When one sector has in alcor_trigger_data_transfer()
179 alcor_write32(priv, data->blksz, AU6601_REG_BLOCK_SIZE); in alcor_trigger_data_transfer()
186 static void alcor_trf_block_pio(struct alcor_sdmmc_host *host, bool read) in alcor_trf_block_pio() argument
188 struct alcor_pci_priv *priv = host->alcor_pci; in alcor_trf_block_pio()
192 if (!host->blocks) in alcor_trf_block_pio()
195 if (host->dma_on) { in alcor_trf_block_pio()
196 dev_err(host->dev, "configured DMA but got PIO request.\n"); in alcor_trf_block_pio()
200 if (!!(host->data->flags & MMC_DATA_READ) != read) { in alcor_trf_block_pio()
201 dev_err(host->dev, "got unexpected direction %i != %i\n", in alcor_trf_block_pio()
202 !!(host->data->flags & MMC_DATA_READ), read); in alcor_trf_block_pio()
205 if (!sg_miter_next(&host->sg_miter)) in alcor_trf_block_pio()
208 blksize = host->data->blksz; in alcor_trf_block_pio()
209 len = min(host->sg_miter.length, blksize); in alcor_trf_block_pio()
211 dev_dbg(host->dev, "PIO, %s block size: 0x%zx\n", in alcor_trf_block_pio()
214 host->sg_miter.consumed = len; in alcor_trf_block_pio()
215 host->blocks--; in alcor_trf_block_pio()
217 buf = host->sg_miter.addr; in alcor_trf_block_pio()
220 ioread32_rep(priv->iobase + AU6601_REG_BUFFER, buf, len >> 2); in alcor_trf_block_pio()
222 iowrite32_rep(priv->iobase + AU6601_REG_BUFFER, buf, len >> 2); in alcor_trf_block_pio()
224 sg_miter_stop(&host->sg_miter); in alcor_trf_block_pio()
227 static void alcor_prepare_sg_miter(struct alcor_sdmmc_host *host) in alcor_prepare_sg_miter() argument
230 struct mmc_data *data = host->data; in alcor_prepare_sg_miter()
232 if (data->flags & MMC_DATA_READ) in alcor_prepare_sg_miter()
236 sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags); in alcor_prepare_sg_miter()
239 static void alcor_prepare_data(struct alcor_sdmmc_host *host, in alcor_prepare_data() argument
242 struct alcor_pci_priv *priv = host->alcor_pci; in alcor_prepare_data()
243 struct mmc_data *data = cmd->data; in alcor_prepare_data()
249 host->data = data; in alcor_prepare_data()
250 host->data->bytes_xfered = 0; in alcor_prepare_data()
251 host->blocks = data->blocks; in alcor_prepare_data()
252 host->sg = data->sg; in alcor_prepare_data()
253 host->sg_count = data->sg_count; in alcor_prepare_data()
254 dev_dbg(host->dev, "prepare DATA: sg %i, blocks: %i\n", in alcor_prepare_data()
255 host->sg_count, host->blocks); in alcor_prepare_data()
257 if (data->host_cookie != COOKIE_MAPPED) in alcor_prepare_data()
258 alcor_prepare_sg_miter(host); in alcor_prepare_data()
263 static void alcor_send_cmd(struct alcor_sdmmc_host *host, in alcor_send_cmd() argument
266 struct alcor_pci_priv *priv = host->alcor_pci; in alcor_send_cmd()
270 host->cmd = cmd; in alcor_send_cmd()
271 alcor_prepare_data(host, cmd); in alcor_send_cmd()
273 dev_dbg(host->dev, "send CMD. opcode: 0x%02x, arg; 0x%08x\n", in alcor_send_cmd()
274 cmd->opcode, cmd->arg); in alcor_send_cmd()
275 alcor_write8(priv, cmd->opcode | 0x40, AU6601_REG_CMD_OPCODE); in alcor_send_cmd()
276 alcor_write32be(priv, cmd->arg, AU6601_REG_CMD_ARG); in alcor_send_cmd()
295 dev_err(host->dev, "%s: cmd->flag (0x%02x) is not valid\n", in alcor_send_cmd()
296 mmc_hostname(mmc_from_priv(host)), mmc_resp_type(cmd)); in alcor_send_cmd()
301 if (!cmd->data && cmd->busy_timeout) in alcor_send_cmd()
302 timeout = cmd->busy_timeout; in alcor_send_cmd()
306 schedule_delayed_work(&host->timeout_work, in alcor_send_cmd()
310 dev_dbg(host->dev, "xfer ctrl: 0x%02x; timeout: %lu\n", ctrl, timeout); in alcor_send_cmd()
315 static void alcor_request_complete(struct alcor_sdmmc_host *host, in alcor_request_complete() argument
324 if (!host->mrq) in alcor_request_complete()
328 cancel_delayed_work(&host->timeout_work); in alcor_request_complete()
330 mrq = host->mrq; in alcor_request_complete()
332 host->mrq = NULL; in alcor_request_complete()
333 host->cmd = NULL; in alcor_request_complete()
334 host->data = NULL; in alcor_request_complete()
335 host->dma_on = 0; in alcor_request_complete()
337 mmc_request_done(mmc_from_priv(host), mrq); in alcor_request_complete()
340 static void alcor_finish_data(struct alcor_sdmmc_host *host) in alcor_finish_data() argument
344 data = host->data; in alcor_finish_data()
345 host->data = NULL; in alcor_finish_data()
346 host->dma_on = 0; in alcor_finish_data()
355 if (data->error) in alcor_finish_data()
356 data->bytes_xfered = 0; in alcor_finish_data()
358 data->bytes_xfered = data->blksz * data->blocks; in alcor_finish_data()
361 * Need to send CMD12 if - in alcor_finish_data()
362 * a) open-ended multiblock transfer (no CMD23) in alcor_finish_data()
365 if (data->stop && in alcor_finish_data()
366 (data->error || in alcor_finish_data()
367 !host->mrq->sbc)) { in alcor_finish_data()
373 if (data->error) in alcor_finish_data()
374 alcor_reset(host, AU6601_RESET_CMD | AU6601_RESET_DATA); in alcor_finish_data()
376 alcor_unmask_sd_irqs(host); in alcor_finish_data()
377 alcor_send_cmd(host, data->stop, false); in alcor_finish_data()
381 alcor_request_complete(host, 1); in alcor_finish_data()
384 static void alcor_err_irq(struct alcor_sdmmc_host *host, u32 intmask) in alcor_err_irq() argument
386 dev_dbg(host->dev, "ERR IRQ %x\n", intmask); in alcor_err_irq()
388 if (host->cmd) { in alcor_err_irq()
390 host->cmd->error = -ETIMEDOUT; in alcor_err_irq()
392 host->cmd->error = -EILSEQ; in alcor_err_irq()
395 if (host->data) { in alcor_err_irq()
397 host->data->error = -ETIMEDOUT; in alcor_err_irq()
399 host->data->error = -EILSEQ; in alcor_err_irq()
401 host->data->bytes_xfered = 0; in alcor_err_irq()
404 alcor_reset(host, AU6601_RESET_CMD | AU6601_RESET_DATA); in alcor_err_irq()
405 alcor_request_complete(host, 1); in alcor_err_irq()
408 static int alcor_cmd_irq_done(struct alcor_sdmmc_host *host, u32 intmask) in alcor_cmd_irq_done() argument
410 struct alcor_pci_priv *priv = host->alcor_pci; in alcor_cmd_irq_done()
420 if (!host->cmd) in alcor_cmd_irq_done()
423 if (host->cmd->flags & MMC_RSP_PRESENT) { in alcor_cmd_irq_done()
424 struct mmc_command *cmd = host->cmd; in alcor_cmd_irq_done()
426 cmd->resp[0] = alcor_read32be(priv, AU6601_REG_CMD_RSP0); in alcor_cmd_irq_done()
427 dev_dbg(host->dev, "RSP0: 0x%04x\n", cmd->resp[0]); in alcor_cmd_irq_done()
428 if (host->cmd->flags & MMC_RSP_136) { in alcor_cmd_irq_done()
429 cmd->resp[1] = in alcor_cmd_irq_done()
431 cmd->resp[2] = in alcor_cmd_irq_done()
433 cmd->resp[3] = in alcor_cmd_irq_done()
435 dev_dbg(host->dev, "RSP1,2,3: 0x%04x 0x%04x 0x%04x\n", in alcor_cmd_irq_done()
436 cmd->resp[1], cmd->resp[2], cmd->resp[3]); in alcor_cmd_irq_done()
441 host->cmd->error = 0; in alcor_cmd_irq_done()
444 if (!host->data) in alcor_cmd_irq_done()
447 alcor_trigger_data_transfer(host); in alcor_cmd_irq_done()
448 host->cmd = NULL; in alcor_cmd_irq_done()
452 static void alcor_cmd_irq_thread(struct alcor_sdmmc_host *host, u32 intmask) in alcor_cmd_irq_thread() argument
459 if (!host->cmd && intmask & AU6601_INT_CMD_END) { in alcor_cmd_irq_thread()
460 …dev_dbg(host->dev, "Got command interrupt 0x%08x even though no command operation was in progress.… in alcor_cmd_irq_thread()
465 if (!host->data) in alcor_cmd_irq_thread()
466 alcor_request_complete(host, 1); in alcor_cmd_irq_thread()
468 alcor_trigger_data_transfer(host); in alcor_cmd_irq_thread()
469 host->cmd = NULL; in alcor_cmd_irq_thread()
472 static int alcor_data_irq_done(struct alcor_sdmmc_host *host, u32 intmask) in alcor_data_irq_done() argument
485 if (!host->data && intmask == AU6601_INT_DATA_END) in alcor_data_irq_done()
489 if (!host->data) in alcor_data_irq_done()
498 alcor_trf_block_pio(host, true); in alcor_data_irq_done()
501 alcor_trf_block_pio(host, false); in alcor_data_irq_done()
504 if (!host->sg_count) in alcor_data_irq_done()
507 alcor_data_set_dma(host); in alcor_data_irq_done()
510 dev_err(host->dev, "Got READ_BUF_RDY and WRITE_BUF_RDY at same time\n"); in alcor_data_irq_done()
515 if (!host->dma_on && host->blocks) { in alcor_data_irq_done()
516 alcor_trigger_data_transfer(host); in alcor_data_irq_done()
526 static void alcor_data_irq_thread(struct alcor_sdmmc_host *host, u32 intmask) in alcor_data_irq_thread() argument
533 if (!host->data) { in alcor_data_irq_thread()
534 dev_dbg(host->dev, "Got data interrupt 0x%08x even though no data operation was in progress.\n", in alcor_data_irq_thread()
536 alcor_reset(host, AU6601_RESET_DATA); in alcor_data_irq_thread()
540 if (alcor_data_irq_done(host, intmask)) in alcor_data_irq_thread()
543 if ((intmask & AU6601_INT_DATA_END) || !host->blocks || in alcor_data_irq_thread()
544 (host->dma_on && !host->sg_count)) in alcor_data_irq_thread()
545 alcor_finish_data(host); in alcor_data_irq_thread()
548 static void alcor_cd_irq(struct alcor_sdmmc_host *host, u32 intmask) in alcor_cd_irq() argument
550 dev_dbg(host->dev, "card %s\n", in alcor_cd_irq()
553 if (host->mrq) { in alcor_cd_irq()
554 dev_dbg(host->dev, "cancel all pending tasks.\n"); in alcor_cd_irq()
556 if (host->data) in alcor_cd_irq()
557 host->data->error = -ENOMEDIUM; in alcor_cd_irq()
559 if (host->cmd) in alcor_cd_irq()
560 host->cmd->error = -ENOMEDIUM; in alcor_cd_irq()
562 host->mrq->cmd->error = -ENOMEDIUM; in alcor_cd_irq()
564 alcor_request_complete(host, 1); in alcor_cd_irq()
567 mmc_detect_change(mmc_from_priv(host), msecs_to_jiffies(1)); in alcor_cd_irq()
572 struct alcor_sdmmc_host *host = d; in alcor_irq_thread() local
576 mutex_lock(&host->cmd_mutex); in alcor_irq_thread()
578 intmask = host->irq_status_sd; in alcor_irq_thread()
582 dev_dbg(host->dev, "unexpected IRQ: 0x%04x\n", intmask); in alcor_irq_thread()
590 alcor_err_irq(host, tmp); in alcor_irq_thread()
592 alcor_cmd_irq_thread(host, tmp); in alcor_irq_thread()
593 alcor_data_irq_thread(host, tmp); in alcor_irq_thread()
599 alcor_cd_irq(host, intmask); in alcor_irq_thread()
604 dev_warn(host->dev, in alcor_irq_thread()
610 dev_dbg(host->dev, "got not handled IRQ: 0x%04x\n", intmask); in alcor_irq_thread()
613 mutex_unlock(&host->cmd_mutex); in alcor_irq_thread()
614 alcor_unmask_sd_irqs(host); in alcor_irq_thread()
621 struct alcor_sdmmc_host *host = d; in alcor_irq() local
622 struct alcor_pci_priv *priv = host->alcor_pci; in alcor_irq()
637 cmd_done = alcor_cmd_irq_done(host, tmp); in alcor_irq()
638 data_done = alcor_data_irq_done(host, tmp); in alcor_irq()
646 host->irq_status_sd = status; in alcor_irq()
648 alcor_mask_sd_irqs(host); in alcor_irq()
653 static void alcor_set_clock(struct alcor_sdmmc_host *host, unsigned int clock) in alcor_set_clock() argument
655 struct alcor_pci_priv *priv = host->alcor_pci; in alcor_set_clock()
669 tmp_div = DIV_ROUND_UP(cfg->clk_src_freq, clock); in alcor_set_clock()
670 if (cfg->min_div > tmp_div || tmp_div > cfg->max_div) in alcor_set_clock()
673 tmp_clock = DIV_ROUND_UP(cfg->clk_src_freq, tmp_div); in alcor_set_clock()
674 tmp_diff = abs(clock - tmp_clock); in alcor_set_clock()
678 clk_src = cfg->clk_src_reg; in alcor_set_clock()
683 clk_src |= ((clk_div - 1) << 8); in alcor_set_clock()
686 dev_dbg(host->dev, "set freq %d cal freq %d, use div %d, mod %x\n", in alcor_set_clock()
693 static void alcor_set_timing(struct mmc_host *mmc, struct mmc_ios *ios) in alcor_set_timing() argument
695 struct alcor_sdmmc_host *host = mmc_priv(mmc); in alcor_set_timing() local
697 if (ios->timing == MMC_TIMING_LEGACY) { in alcor_set_timing()
698 alcor_rmw8(host, AU6601_CLK_DELAY, in alcor_set_timing()
701 alcor_rmw8(host, AU6601_CLK_DELAY, in alcor_set_timing()
706 static void alcor_set_bus_width(struct mmc_host *mmc, struct mmc_ios *ios) in alcor_set_bus_width() argument
708 struct alcor_sdmmc_host *host = mmc_priv(mmc); in alcor_set_bus_width() local
709 struct alcor_pci_priv *priv = host->alcor_pci; in alcor_set_bus_width()
711 if (ios->bus_width == MMC_BUS_WIDTH_1) { in alcor_set_bus_width()
713 } else if (ios->bus_width == MMC_BUS_WIDTH_4) { in alcor_set_bus_width()
717 dev_err(host->dev, "Unknown BUS mode\n"); in alcor_set_bus_width()
721 static int alcor_card_busy(struct mmc_host *mmc) in alcor_card_busy() argument
723 struct alcor_sdmmc_host *host = mmc_priv(mmc); in alcor_card_busy() local
724 struct alcor_pci_priv *priv = host->alcor_pci; in alcor_card_busy()
733 static int alcor_get_cd(struct mmc_host *mmc) in alcor_get_cd() argument
735 struct alcor_sdmmc_host *host = mmc_priv(mmc); in alcor_get_cd() local
736 struct alcor_pci_priv *priv = host->alcor_pci; in alcor_get_cd()
745 static int alcor_get_ro(struct mmc_host *mmc) in alcor_get_ro() argument
747 struct alcor_sdmmc_host *host = mmc_priv(mmc); in alcor_get_ro() local
748 struct alcor_pci_priv *priv = host->alcor_pci; in alcor_get_ro()
757 static void alcor_request(struct mmc_host *mmc, struct mmc_request *mrq) in alcor_request() argument
759 struct alcor_sdmmc_host *host = mmc_priv(mmc); in alcor_request() local
761 mutex_lock(&host->cmd_mutex); in alcor_request()
763 host->mrq = mrq; in alcor_request()
766 if (alcor_get_cd(mmc)) in alcor_request()
767 alcor_send_cmd(host, mrq->cmd, true); in alcor_request()
769 mrq->cmd->error = -ENOMEDIUM; in alcor_request()
770 alcor_request_complete(host, 1); in alcor_request()
773 mutex_unlock(&host->cmd_mutex); in alcor_request()
776 static void alcor_pre_req(struct mmc_host *mmc, in alcor_pre_req() argument
779 struct alcor_sdmmc_host *host = mmc_priv(mmc); in alcor_pre_req() local
780 struct mmc_data *data = mrq->data; in alcor_pre_req()
781 struct mmc_command *cmd = mrq->cmd; in alcor_pre_req()
788 data->host_cookie = COOKIE_UNMAPPED; in alcor_pre_req()
791 if (cmd->opcode != MMC_READ_MULTIPLE_BLOCK in alcor_pre_req()
792 && cmd->opcode != MMC_WRITE_MULTIPLE_BLOCK) in alcor_pre_req()
796 * non-word-aligned buffers or lengths. A future improvement in alcor_pre_req()
797 * could be made to use temporary DMA bounce-buffers when these in alcor_pre_req()
803 if (data->blocks * data->blksz < AU6601_MAX_DMA_BLOCK_SIZE) in alcor_pre_req()
806 if (data->blksz & 3) in alcor_pre_req()
809 for_each_sg(data->sg, sg, data->sg_len, i) { in alcor_pre_req()
810 if (sg->length != AU6601_MAX_DMA_BLOCK_SIZE) in alcor_pre_req()
812 if (sg->offset != 0) in alcor_pre_req()
818 sg_len = dma_map_sg(host->dev, data->sg, data->sg_len, in alcor_pre_req()
821 data->host_cookie = COOKIE_MAPPED; in alcor_pre_req()
823 data->sg_count = sg_len; in alcor_pre_req()
826 static void alcor_post_req(struct mmc_host *mmc, in alcor_post_req() argument
830 struct alcor_sdmmc_host *host = mmc_priv(mmc); in alcor_post_req() local
831 struct mmc_data *data = mrq->data; in alcor_post_req()
836 if (data->host_cookie == COOKIE_MAPPED) { in alcor_post_req()
837 dma_unmap_sg(host->dev, in alcor_post_req()
838 data->sg, in alcor_post_req()
839 data->sg_len, in alcor_post_req()
843 data->host_cookie = COOKIE_UNMAPPED; in alcor_post_req()
846 static void alcor_set_power_mode(struct mmc_host *mmc, struct mmc_ios *ios) in alcor_set_power_mode() argument
848 struct alcor_sdmmc_host *host = mmc_priv(mmc); in alcor_set_power_mode() local
849 struct alcor_pci_priv *priv = host->alcor_pci; in alcor_set_power_mode()
851 switch (ios->power_mode) { in alcor_set_power_mode()
853 alcor_set_clock(host, ios->clock); in alcor_set_power_mode()
881 alcor_set_clock(host, ios->clock); in alcor_set_power_mode()
888 alcor_set_clock(host, ios->clock); in alcor_set_power_mode()
903 dev_err(host->dev, "Unknown power parameter\n"); in alcor_set_power_mode()
907 static void alcor_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) in alcor_set_ios() argument
909 struct alcor_sdmmc_host *host = mmc_priv(mmc); in alcor_set_ios() local
911 mutex_lock(&host->cmd_mutex); in alcor_set_ios()
913 dev_dbg(host->dev, "set ios. bus width: %x, power mode: %x\n", in alcor_set_ios()
914 ios->bus_width, ios->power_mode); in alcor_set_ios()
916 if (ios->power_mode != host->cur_power_mode) { in alcor_set_ios()
917 alcor_set_power_mode(mmc, ios); in alcor_set_ios()
918 host->cur_power_mode = ios->power_mode; in alcor_set_ios()
920 alcor_set_timing(mmc, ios); in alcor_set_ios()
921 alcor_set_bus_width(mmc, ios); in alcor_set_ios()
922 alcor_set_clock(host, ios->clock); in alcor_set_ios()
925 mutex_unlock(&host->cmd_mutex); in alcor_set_ios()
928 static int alcor_signal_voltage_switch(struct mmc_host *mmc, in alcor_signal_voltage_switch() argument
931 struct alcor_sdmmc_host *host = mmc_priv(mmc); in alcor_signal_voltage_switch() local
933 mutex_lock(&host->cmd_mutex); in alcor_signal_voltage_switch()
935 switch (ios->signal_voltage) { in alcor_signal_voltage_switch()
937 alcor_rmw8(host, AU6601_OPT, AU6601_OPT_SD_18V, 0); in alcor_signal_voltage_switch()
940 alcor_rmw8(host, AU6601_OPT, 0, AU6601_OPT_SD_18V); in alcor_signal_voltage_switch()
947 mutex_unlock(&host->cmd_mutex); in alcor_signal_voltage_switch()
965 struct alcor_sdmmc_host *host = container_of(d, struct alcor_sdmmc_host, in alcor_timeout_timer() local
967 mutex_lock(&host->cmd_mutex); in alcor_timeout_timer()
969 dev_dbg(host->dev, "triggered timeout\n"); in alcor_timeout_timer()
970 if (host->mrq) { in alcor_timeout_timer()
971 dev_err(host->dev, "Timeout waiting for hardware interrupt.\n"); in alcor_timeout_timer()
973 if (host->data) { in alcor_timeout_timer()
974 host->data->error = -ETIMEDOUT; in alcor_timeout_timer()
976 if (host->cmd) in alcor_timeout_timer()
977 host->cmd->error = -ETIMEDOUT; in alcor_timeout_timer()
979 host->mrq->cmd->error = -ETIMEDOUT; in alcor_timeout_timer()
982 alcor_reset(host, AU6601_RESET_CMD | AU6601_RESET_DATA); in alcor_timeout_timer()
983 alcor_request_complete(host, 0); in alcor_timeout_timer()
986 mutex_unlock(&host->cmd_mutex); in alcor_timeout_timer()
989 static void alcor_hw_init(struct alcor_sdmmc_host *host) in alcor_hw_init() argument
991 struct alcor_pci_priv *priv = host->alcor_pci; in alcor_hw_init()
992 struct alcor_dev_cfg *cfg = priv->cfg; in alcor_hw_init()
1000 alcor_reset(host, AU6601_RESET_CMD); in alcor_hw_init()
1010 alcor_reset(host, AU6601_RESET_DATA); in alcor_hw_init()
1020 /* for 6601 - dma_boundary; for 6621 - dma_page_cnt in alcor_hw_init()
1023 alcor_write8(priv, cfg->dma, AU6601_DMA_BOUNDARY); in alcor_hw_init()
1031 alcor_unmask_sd_irqs(host); in alcor_hw_init()
1034 static void alcor_hw_uninit(struct alcor_sdmmc_host *host) in alcor_hw_uninit() argument
1036 struct alcor_pci_priv *priv = host->alcor_pci; in alcor_hw_uninit()
1038 alcor_mask_sd_irqs(host); in alcor_hw_uninit()
1039 alcor_reset(host, AU6601_RESET_CMD | AU6601_RESET_DATA); in alcor_hw_uninit()
1049 static void alcor_init_mmc(struct alcor_sdmmc_host *host) in alcor_init_mmc() argument
1051 struct mmc_host *mmc = mmc_from_priv(host); in alcor_init_mmc() local
1053 mmc->f_min = AU6601_MIN_CLOCK; in alcor_init_mmc()
1054 mmc->f_max = AU6601_MAX_CLOCK; in alcor_init_mmc()
1055 mmc->ocr_avail = MMC_VDD_33_34; in alcor_init_mmc()
1056 mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SD_HIGHSPEED in alcor_init_mmc()
1059 mmc->caps2 = MMC_CAP2_NO_SDIO; in alcor_init_mmc()
1060 mmc->ops = &alcor_sdc_ops; in alcor_init_mmc()
1073 mmc->max_segs = AU6601_MAX_DMA_SEGMENTS; in alcor_init_mmc()
1074 mmc->max_seg_size = AU6601_MAX_DMA_BLOCK_SIZE; in alcor_init_mmc()
1075 mmc->max_blk_count = 240; in alcor_init_mmc()
1076 mmc->max_req_size = mmc->max_blk_count * mmc->max_blk_size; in alcor_init_mmc()
1077 dma_set_max_seg_size(host->dev, mmc->max_seg_size); in alcor_init_mmc()
1082 struct alcor_pci_priv *priv = pdev->dev.platform_data; in alcor_pci_sdmmc_drv_probe()
1083 struct mmc_host *mmc; in alcor_pci_sdmmc_drv_probe() local
1084 struct alcor_sdmmc_host *host; in alcor_pci_sdmmc_drv_probe() local
1087 mmc = mmc_alloc_host(sizeof(*host), &pdev->dev); in alcor_pci_sdmmc_drv_probe()
1088 if (!mmc) { in alcor_pci_sdmmc_drv_probe()
1089 dev_err(&pdev->dev, "Can't allocate MMC\n"); in alcor_pci_sdmmc_drv_probe()
1090 return -ENOMEM; in alcor_pci_sdmmc_drv_probe()
1093 host = mmc_priv(mmc); in alcor_pci_sdmmc_drv_probe()
1094 host->dev = &pdev->dev; in alcor_pci_sdmmc_drv_probe()
1095 host->cur_power_mode = MMC_POWER_UNDEFINED; in alcor_pci_sdmmc_drv_probe()
1096 host->alcor_pci = priv; in alcor_pci_sdmmc_drv_probe()
1102 ret = devm_request_threaded_irq(&pdev->dev, priv->irq, in alcor_pci_sdmmc_drv_probe()
1104 DRV_NAME_ALCOR_PCI_SDMMC, host); in alcor_pci_sdmmc_drv_probe()
1107 dev_err(&pdev->dev, "Failed to get irq for data line\n"); in alcor_pci_sdmmc_drv_probe()
1111 mutex_init(&host->cmd_mutex); in alcor_pci_sdmmc_drv_probe()
1112 INIT_DELAYED_WORK(&host->timeout_work, alcor_timeout_timer); in alcor_pci_sdmmc_drv_probe()
1114 alcor_init_mmc(host); in alcor_pci_sdmmc_drv_probe()
1115 alcor_hw_init(host); in alcor_pci_sdmmc_drv_probe()
1117 dev_set_drvdata(&pdev->dev, host); in alcor_pci_sdmmc_drv_probe()
1118 ret = mmc_add_host(mmc); in alcor_pci_sdmmc_drv_probe()
1125 mmc_free_host(mmc); in alcor_pci_sdmmc_drv_probe()
1131 struct alcor_sdmmc_host *host = dev_get_drvdata(&pdev->dev); in alcor_pci_sdmmc_drv_remove() local
1132 struct mmc_host *mmc = mmc_from_priv(host); in alcor_pci_sdmmc_drv_remove() local
1134 if (cancel_delayed_work_sync(&host->timeout_work)) in alcor_pci_sdmmc_drv_remove()
1135 alcor_request_complete(host, 0); in alcor_pci_sdmmc_drv_remove()
1137 alcor_hw_uninit(host); in alcor_pci_sdmmc_drv_remove()
1138 mmc_remove_host(mmc); in alcor_pci_sdmmc_drv_remove()
1139 mmc_free_host(mmc); in alcor_pci_sdmmc_drv_remove()
1145 struct alcor_sdmmc_host *host = dev_get_drvdata(dev); in alcor_pci_sdmmc_suspend() local
1147 if (cancel_delayed_work_sync(&host->timeout_work)) in alcor_pci_sdmmc_suspend()
1148 alcor_request_complete(host, 0); in alcor_pci_sdmmc_suspend()
1150 alcor_hw_uninit(host); in alcor_pci_sdmmc_suspend()
1157 struct alcor_sdmmc_host *host = dev_get_drvdata(dev); in alcor_pci_sdmmc_resume() local
1159 alcor_hw_init(host); in alcor_pci_sdmmc_resume()
1189 MODULE_AUTHOR("Oleksij Rempel <linux@rempel-privat.de>");
1190 MODULE_DESCRIPTION("PCI driver for Alcor Micro AU6601 Secure Digital Host Controller Interface");