^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * linux/drivers/mmc/s3cmci.h - Samsung S3C MCI driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2004-2006 maintech GmbH, Thomas Kleffel <tk@maintech.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Current driver maintained by Ben Dooks and Simtec Electronics
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (C) 2008 Simtec Electronics <ben-linux@fluff.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/dmaengine.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/dma-mapping.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/mmc/host.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/cpufreq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/debugfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/seq_file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/gpio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/mmc/slot-gpio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/platform_data/mmc-s3cmci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include "s3cmci.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define DRIVER_NAME "s3c-mci"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define S3C2410_SDICON (0x00)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define S3C2410_SDIPRE (0x04)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define S3C2410_SDICMDARG (0x08)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define S3C2410_SDICMDCON (0x0C)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define S3C2410_SDICMDSTAT (0x10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define S3C2410_SDIRSP0 (0x14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define S3C2410_SDIRSP1 (0x18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define S3C2410_SDIRSP2 (0x1C)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define S3C2410_SDIRSP3 (0x20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define S3C2410_SDITIMER (0x24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define S3C2410_SDIBSIZE (0x28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define S3C2410_SDIDCON (0x2C)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define S3C2410_SDIDCNT (0x30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define S3C2410_SDIDSTA (0x34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define S3C2410_SDIFSTA (0x38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define S3C2410_SDIDATA (0x3C)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define S3C2410_SDIIMSK (0x40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define S3C2440_SDIDATA (0x40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define S3C2440_SDIIMSK (0x3C)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define S3C2440_SDICON_SDRESET (1 << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define S3C2410_SDICON_SDIOIRQ (1 << 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define S3C2410_SDICON_FIFORESET (1 << 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define S3C2410_SDICON_CLOCKTYPE (1 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define S3C2410_SDICMDCON_LONGRSP (1 << 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define S3C2410_SDICMDCON_WAITRSP (1 << 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define S3C2410_SDICMDCON_CMDSTART (1 << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define S3C2410_SDICMDCON_SENDERHOST (1 << 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define S3C2410_SDICMDCON_INDEX (0x3f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define S3C2410_SDICMDSTAT_CRCFAIL (1 << 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define S3C2410_SDICMDSTAT_CMDSENT (1 << 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define S3C2410_SDICMDSTAT_CMDTIMEOUT (1 << 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define S3C2410_SDICMDSTAT_RSPFIN (1 << 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define S3C2440_SDIDCON_DS_WORD (2 << 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define S3C2410_SDIDCON_TXAFTERRESP (1 << 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define S3C2410_SDIDCON_RXAFTERCMD (1 << 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define S3C2410_SDIDCON_BLOCKMODE (1 << 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define S3C2410_SDIDCON_WIDEBUS (1 << 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define S3C2410_SDIDCON_DMAEN (1 << 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define S3C2410_SDIDCON_STOP (1 << 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define S3C2440_SDIDCON_DATSTART (1 << 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define S3C2410_SDIDCON_XFER_RXSTART (2 << 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define S3C2410_SDIDCON_XFER_TXSTART (3 << 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define S3C2410_SDIDCON_BLKNUM_MASK (0xFFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define S3C2410_SDIDSTA_SDIOIRQDETECT (1 << 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define S3C2410_SDIDSTA_FIFOFAIL (1 << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define S3C2410_SDIDSTA_CRCFAIL (1 << 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define S3C2410_SDIDSTA_RXCRCFAIL (1 << 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define S3C2410_SDIDSTA_DATATIMEOUT (1 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define S3C2410_SDIDSTA_XFERFINISH (1 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define S3C2410_SDIDSTA_TXDATAON (1 << 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define S3C2410_SDIDSTA_RXDATAON (1 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define S3C2440_SDIFSTA_FIFORESET (1 << 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define S3C2440_SDIFSTA_FIFOFAIL (3 << 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define S3C2410_SDIFSTA_TFDET (1 << 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define S3C2410_SDIFSTA_RFDET (1 << 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define S3C2410_SDIFSTA_COUNTMASK (0x7f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define S3C2410_SDIIMSK_RESPONSECRC (1 << 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define S3C2410_SDIIMSK_CMDSENT (1 << 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #define S3C2410_SDIIMSK_CMDTIMEOUT (1 << 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define S3C2410_SDIIMSK_RESPONSEND (1 << 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define S3C2410_SDIIMSK_SDIOIRQ (1 << 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #define S3C2410_SDIIMSK_FIFOFAIL (1 << 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #define S3C2410_SDIIMSK_CRCSTATUS (1 << 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define S3C2410_SDIIMSK_DATACRC (1 << 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #define S3C2410_SDIIMSK_DATATIMEOUT (1 << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #define S3C2410_SDIIMSK_DATAFINISH (1 << 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #define S3C2410_SDIIMSK_TXFIFOHALF (1 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define S3C2410_SDIIMSK_RXFIFOLAST (1 << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) #define S3C2410_SDIIMSK_RXFIFOHALF (1 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) enum dbg_channels {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) dbg_err = (1 << 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) dbg_debug = (1 << 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) dbg_info = (1 << 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) dbg_irq = (1 << 3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) dbg_sg = (1 << 4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) dbg_dma = (1 << 5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) dbg_pio = (1 << 6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) dbg_fail = (1 << 7),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) dbg_conf = (1 << 8),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static const int dbgmap_err = dbg_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) static const int dbgmap_info = dbg_info | dbg_conf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) static const int dbgmap_debug = dbg_err | dbg_debug;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) #define dbg(host, channels, args...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if (dbgmap_err & channels) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) dev_err(&host->pdev->dev, args); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) else if (dbgmap_info & channels) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) dev_info(&host->pdev->dev, args); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) else if (dbgmap_debug & channels) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) dev_dbg(&host->pdev->dev, args); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) static void finalize_request(struct s3cmci_host *host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) static void s3cmci_send_request(struct mmc_host *mmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) static void s3cmci_reset(struct s3cmci_host *host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #ifdef CONFIG_MMC_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) static void dbg_dumpregs(struct s3cmci_host *host, char *prefix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) u32 con, pre, cmdarg, cmdcon, cmdsta, r0, r1, r2, r3, timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) u32 datcon, datcnt, datsta, fsta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) con = readl(host->base + S3C2410_SDICON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) pre = readl(host->base + S3C2410_SDIPRE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) cmdarg = readl(host->base + S3C2410_SDICMDARG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) cmdcon = readl(host->base + S3C2410_SDICMDCON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) cmdsta = readl(host->base + S3C2410_SDICMDSTAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) r0 = readl(host->base + S3C2410_SDIRSP0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) r1 = readl(host->base + S3C2410_SDIRSP1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) r2 = readl(host->base + S3C2410_SDIRSP2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) r3 = readl(host->base + S3C2410_SDIRSP3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) timer = readl(host->base + S3C2410_SDITIMER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) datcon = readl(host->base + S3C2410_SDIDCON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) datcnt = readl(host->base + S3C2410_SDIDCNT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) datsta = readl(host->base + S3C2410_SDIDSTA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) fsta = readl(host->base + S3C2410_SDIFSTA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) dbg(host, dbg_debug, "%s CON:[%08x] PRE:[%08x] TMR:[%08x]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) prefix, con, pre, timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) dbg(host, dbg_debug, "%s CCON:[%08x] CARG:[%08x] CSTA:[%08x]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) prefix, cmdcon, cmdarg, cmdsta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) dbg(host, dbg_debug, "%s DCON:[%08x] FSTA:[%08x]"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) " DSTA:[%08x] DCNT:[%08x]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) prefix, datcon, fsta, datsta, datcnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) dbg(host, dbg_debug, "%s R0:[%08x] R1:[%08x]"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) " R2:[%08x] R3:[%08x]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) prefix, r0, r1, r2, r3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) static void prepare_dbgmsg(struct s3cmci_host *host, struct mmc_command *cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) int stop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) snprintf(host->dbgmsg_cmd, 300,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) "#%u%s op:%i arg:0x%08x flags:0x08%x retries:%u",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) host->ccnt, (stop ? " (STOP)" : ""),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) cmd->opcode, cmd->arg, cmd->flags, cmd->retries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) if (cmd->data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) snprintf(host->dbgmsg_dat, 300,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) "#%u bsize:%u blocks:%u bytes:%u",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) host->dcnt, cmd->data->blksz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) cmd->data->blocks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) cmd->data->blocks * cmd->data->blksz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) host->dbgmsg_dat[0] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) static void dbg_dumpcmd(struct s3cmci_host *host, struct mmc_command *cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) int fail)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) unsigned int dbglvl = fail ? dbg_fail : dbg_debug;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) if (!cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (cmd->error == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) dbg(host, dbglvl, "CMD[OK] %s R0:0x%08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) host->dbgmsg_cmd, cmd->resp[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) dbg(host, dbglvl, "CMD[ERR %i] %s Status:%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) cmd->error, host->dbgmsg_cmd, host->status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (!cmd->data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (cmd->data->error == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) dbg(host, dbglvl, "DAT[OK] %s\n", host->dbgmsg_dat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) dbg(host, dbglvl, "DAT[ERR %i] %s DCNT:0x%08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) cmd->data->error, host->dbgmsg_dat,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) readl(host->base + S3C2410_SDIDCNT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) static void dbg_dumpcmd(struct s3cmci_host *host,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) struct mmc_command *cmd, int fail) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) static void prepare_dbgmsg(struct s3cmci_host *host, struct mmc_command *cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) int stop) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) static void dbg_dumpregs(struct s3cmci_host *host, char *prefix) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) #endif /* CONFIG_MMC_DEBUG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) * s3cmci_host_usedma - return whether the host is using dma or pio
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) * @host: The host state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) * Return true if the host is using DMA to transfer data, else false
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) * to use PIO mode. Will return static data depending on the driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) * configuration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) static inline bool s3cmci_host_usedma(struct s3cmci_host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) #ifdef CONFIG_MMC_S3C_PIO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) #else /* CONFIG_MMC_S3C_DMA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) static inline u32 enable_imask(struct s3cmci_host *host, u32 imask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) u32 newmask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) newmask = readl(host->base + host->sdiimsk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) newmask |= imask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) writel(newmask, host->base + host->sdiimsk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) return newmask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) static inline u32 disable_imask(struct s3cmci_host *host, u32 imask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) u32 newmask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) newmask = readl(host->base + host->sdiimsk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) newmask &= ~imask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) writel(newmask, host->base + host->sdiimsk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) return newmask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) static inline void clear_imask(struct s3cmci_host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) u32 mask = readl(host->base + host->sdiimsk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) /* preserve the SDIO IRQ mask state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) mask &= S3C2410_SDIIMSK_SDIOIRQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) writel(mask, host->base + host->sdiimsk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) * s3cmci_check_sdio_irq - test whether the SDIO IRQ is being signalled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) * @host: The host to check.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) * Test to see if the SDIO interrupt is being signalled in case the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) * controller has failed to re-detect a card interrupt. Read GPE8 and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) * see if it is low and if so, signal a SDIO interrupt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) * This is currently called if a request is finished (we assume that the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) * bus is now idle) and when the SDIO IRQ is enabled in case the IRQ is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) * already being indicated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) static void s3cmci_check_sdio_irq(struct s3cmci_host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) if (host->sdio_irqen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) if (host->pdata->bus[3] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) gpiod_get_value(host->pdata->bus[3]) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) pr_debug("%s: signalling irq\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) mmc_signal_sdio_irq(host->mmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) static inline int get_data_buffer(struct s3cmci_host *host,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) u32 *bytes, u32 **pointer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) struct scatterlist *sg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) if (host->pio_active == XFER_NONE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if ((!host->mrq) || (!host->mrq->data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) if (host->pio_sgptr >= host->mrq->data->sg_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) dbg(host, dbg_debug, "no more buffers (%i/%i)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) host->pio_sgptr, host->mrq->data->sg_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) sg = &host->mrq->data->sg[host->pio_sgptr];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) *bytes = sg->length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) *pointer = sg_virt(sg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) host->pio_sgptr++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) dbg(host, dbg_sg, "new buffer (%i/%i)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) host->pio_sgptr, host->mrq->data->sg_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) static inline u32 fifo_count(struct s3cmci_host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) u32 fifostat = readl(host->base + S3C2410_SDIFSTA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) fifostat &= S3C2410_SDIFSTA_COUNTMASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) return fifostat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) static inline u32 fifo_free(struct s3cmci_host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) u32 fifostat = readl(host->base + S3C2410_SDIFSTA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) fifostat &= S3C2410_SDIFSTA_COUNTMASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) return 63 - fifostat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) * s3cmci_enable_irq - enable IRQ, after having disabled it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) * @host: The device state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) * @more: True if more IRQs are expected from transfer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) * Enable the main IRQ if needed after it has been disabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) * The IRQ can be one of the following states:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) * - disabled during IDLE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) * - disabled whilst processing data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) * - enabled during transfer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) * - enabled whilst awaiting SDIO interrupt detection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) static void s3cmci_enable_irq(struct s3cmci_host *host, bool more)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) bool enable = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) host->irq_enabled = more;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) host->irq_disabled = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) enable = more | host->sdio_irqen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) if (host->irq_state != enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) host->irq_state = enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) if (enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) enable_irq(host->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) disable_irq(host->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) static void s3cmci_disable_irq(struct s3cmci_host *host, bool transfer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) /* pr_debug("%s: transfer %d\n", __func__, transfer); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) host->irq_disabled = transfer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) if (transfer && host->irq_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) host->irq_state = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) disable_irq(host->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) static void do_pio_read(struct s3cmci_host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) u32 fifo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) u32 *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) u32 fifo_words;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) void __iomem *from_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) /* write real prescaler to host, it might be set slow to fix */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) writel(host->prescaler, host->base + S3C2410_SDIPRE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) from_ptr = host->base + host->sdidata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) while ((fifo = fifo_count(host))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) if (!host->pio_bytes) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) res = get_data_buffer(host, &host->pio_bytes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) &host->pio_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) if (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) host->pio_active = XFER_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) host->complete_what = COMPLETION_FINALIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) dbg(host, dbg_pio, "pio_read(): "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) "complete (no more data).\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) dbg(host, dbg_pio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) "pio_read(): new target: [%i]@[%p]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) host->pio_bytes, host->pio_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) dbg(host, dbg_pio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) "pio_read(): fifo:[%02i] buffer:[%03i] dcnt:[%08X]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) fifo, host->pio_bytes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) readl(host->base + S3C2410_SDIDCNT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) /* If we have reached the end of the block, we can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) * read a word and get 1 to 3 bytes. If we in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) * middle of the block, we have to read full words,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) * otherwise we will write garbage, so round down to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) * an even multiple of 4. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) if (fifo >= host->pio_bytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) fifo = host->pio_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) fifo -= fifo & 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) host->pio_bytes -= fifo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) host->pio_count += fifo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) fifo_words = fifo >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) ptr = host->pio_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) while (fifo_words--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) *ptr++ = readl(from_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) host->pio_ptr = ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if (fifo & 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) u32 n = fifo & 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) u32 data = readl(from_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) u8 *p = (u8 *)host->pio_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) while (n--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) *p++ = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) data >>= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) if (!host->pio_bytes) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) res = get_data_buffer(host, &host->pio_bytes, &host->pio_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) if (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) dbg(host, dbg_pio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) "pio_read(): complete (no more buffers).\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) host->pio_active = XFER_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) host->complete_what = COMPLETION_FINALIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) enable_imask(host,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) S3C2410_SDIIMSK_RXFIFOHALF | S3C2410_SDIIMSK_RXFIFOLAST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) static void do_pio_write(struct s3cmci_host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) void __iomem *to_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) u32 fifo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) u32 *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) to_ptr = host->base + host->sdidata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) while ((fifo = fifo_free(host)) > 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) if (!host->pio_bytes) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) res = get_data_buffer(host, &host->pio_bytes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) &host->pio_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) if (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) dbg(host, dbg_pio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) "pio_write(): complete (no more data).\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) host->pio_active = XFER_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) dbg(host, dbg_pio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) "pio_write(): new source: [%i]@[%p]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) host->pio_bytes, host->pio_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) /* If we have reached the end of the block, we have to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) * write exactly the remaining number of bytes. If we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) * in the middle of the block, we have to write full
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) * words, so round down to an even multiple of 4. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) if (fifo >= host->pio_bytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) fifo = host->pio_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) fifo -= fifo & 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) host->pio_bytes -= fifo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) host->pio_count += fifo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) fifo = (fifo + 3) >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) ptr = host->pio_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) while (fifo--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) writel(*ptr++, to_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) host->pio_ptr = ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) enable_imask(host, S3C2410_SDIIMSK_TXFIFOHALF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) static void pio_tasklet(unsigned long data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) struct s3cmci_host *host = (struct s3cmci_host *) data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) s3cmci_disable_irq(host, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) if (host->pio_active == XFER_WRITE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) do_pio_write(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) if (host->pio_active == XFER_READ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) do_pio_read(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) if (host->complete_what == COMPLETION_FINALIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) clear_imask(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) if (host->pio_active != XFER_NONE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) dbg(host, dbg_err, "unfinished %s "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) "- pio_count:[%u] pio_bytes:[%u]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) (host->pio_active == XFER_READ) ? "read" : "write",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) host->pio_count, host->pio_bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) if (host->mrq->data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) host->mrq->data->error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) s3cmci_enable_irq(host, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) finalize_request(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) s3cmci_enable_irq(host, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) * ISR for SDI Interface IRQ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) * Communication between driver and ISR works as follows:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) * host->mrq points to current request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) * host->complete_what Indicates when the request is considered done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) * COMPLETION_CMDSENT when the command was sent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) * COMPLETION_RSPFIN when a response was received
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) * COMPLETION_XFERFINISH when the data transfer is finished
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) * COMPLETION_XFERFINISH_RSPFIN both of the above.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) * host->complete_request is the completion-object the driver waits for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) * 1) Driver sets up host->mrq and host->complete_what
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) * 2) Driver prepares the transfer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) * 3) Driver enables interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) * 4) Driver starts transfer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) * 5) Driver waits for host->complete_rquest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) * 6) ISR checks for request status (errors and success)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) * 6) ISR sets host->mrq->cmd->error and host->mrq->data->error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) * 7) ISR completes host->complete_request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) * 8) ISR disables interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) * 9) Driver wakes up and takes care of the request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) * Note: "->error"-fields are expected to be set to 0 before the request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) * was issued by mmc.c - therefore they are only set, when an error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) * contition comes up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) static irqreturn_t s3cmci_irq(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) struct s3cmci_host *host = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) struct mmc_command *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) u32 mci_csta, mci_dsta, mci_fsta, mci_dcnt, mci_imsk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) u32 mci_cclear = 0, mci_dclear;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) unsigned long iflags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) mci_dsta = readl(host->base + S3C2410_SDIDSTA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) mci_imsk = readl(host->base + host->sdiimsk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) if (mci_dsta & S3C2410_SDIDSTA_SDIOIRQDETECT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) if (mci_imsk & S3C2410_SDIIMSK_SDIOIRQ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) mci_dclear = S3C2410_SDIDSTA_SDIOIRQDETECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) writel(mci_dclear, host->base + S3C2410_SDIDSTA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) mmc_signal_sdio_irq(host->mmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) spin_lock_irqsave(&host->complete_lock, iflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) mci_csta = readl(host->base + S3C2410_SDICMDSTAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) mci_dcnt = readl(host->base + S3C2410_SDIDCNT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) mci_fsta = readl(host->base + S3C2410_SDIFSTA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) mci_dclear = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) if ((host->complete_what == COMPLETION_NONE) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) (host->complete_what == COMPLETION_FINALIZE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) host->status = "nothing to complete";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) clear_imask(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) goto irq_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) if (!host->mrq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) host->status = "no active mrq";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) clear_imask(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) goto irq_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) cmd = host->cmd_is_stop ? host->mrq->stop : host->mrq->cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) if (!cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) host->status = "no active cmd";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) clear_imask(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) goto irq_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) if (!s3cmci_host_usedma(host)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) if ((host->pio_active == XFER_WRITE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) (mci_fsta & S3C2410_SDIFSTA_TFDET)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) disable_imask(host, S3C2410_SDIIMSK_TXFIFOHALF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) tasklet_schedule(&host->pio_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) host->status = "pio tx";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) if ((host->pio_active == XFER_READ) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) (mci_fsta & S3C2410_SDIFSTA_RFDET)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) disable_imask(host,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) S3C2410_SDIIMSK_RXFIFOHALF |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) S3C2410_SDIIMSK_RXFIFOLAST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) tasklet_schedule(&host->pio_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) host->status = "pio rx";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) if (mci_csta & S3C2410_SDICMDSTAT_CMDTIMEOUT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) dbg(host, dbg_err, "CMDSTAT: error CMDTIMEOUT\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) cmd->error = -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) host->status = "error: command timeout";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) goto fail_transfer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) if (mci_csta & S3C2410_SDICMDSTAT_CMDSENT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) if (host->complete_what == COMPLETION_CMDSENT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) host->status = "ok: command sent";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) goto close_transfer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) mci_cclear |= S3C2410_SDICMDSTAT_CMDSENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) if (mci_csta & S3C2410_SDICMDSTAT_CRCFAIL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) if (cmd->flags & MMC_RSP_CRC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) if (host->mrq->cmd->flags & MMC_RSP_136) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) dbg(host, dbg_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) "fixup: ignore CRC fail with long rsp\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) /* note, we used to fail the transfer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) * here, but it seems that this is just
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) * the hardware getting it wrong.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) * cmd->error = -EILSEQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) * host->status = "error: bad command crc";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) * goto fail_transfer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) mci_cclear |= S3C2410_SDICMDSTAT_CRCFAIL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) if (mci_csta & S3C2410_SDICMDSTAT_RSPFIN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) if (host->complete_what == COMPLETION_RSPFIN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) host->status = "ok: command response received";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) goto close_transfer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) if (host->complete_what == COMPLETION_XFERFINISH_RSPFIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) host->complete_what = COMPLETION_XFERFINISH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) mci_cclear |= S3C2410_SDICMDSTAT_RSPFIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) /* errors handled after this point are only relevant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) when a data transfer is in progress */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) if (!cmd->data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) goto clear_status_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) /* Check for FIFO failure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) if (host->is2440) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) if (mci_fsta & S3C2440_SDIFSTA_FIFOFAIL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) dbg(host, dbg_err, "FIFO failure\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) host->mrq->data->error = -EILSEQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) host->status = "error: 2440 fifo failure";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) goto fail_transfer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) if (mci_dsta & S3C2410_SDIDSTA_FIFOFAIL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) dbg(host, dbg_err, "FIFO failure\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) cmd->data->error = -EILSEQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) host->status = "error: fifo failure";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) goto fail_transfer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) if (mci_dsta & S3C2410_SDIDSTA_RXCRCFAIL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) dbg(host, dbg_err, "bad data crc (outgoing)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) cmd->data->error = -EILSEQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) host->status = "error: bad data crc (outgoing)";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) goto fail_transfer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) if (mci_dsta & S3C2410_SDIDSTA_CRCFAIL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) dbg(host, dbg_err, "bad data crc (incoming)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) cmd->data->error = -EILSEQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) host->status = "error: bad data crc (incoming)";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) goto fail_transfer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) if (mci_dsta & S3C2410_SDIDSTA_DATATIMEOUT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) dbg(host, dbg_err, "data timeout\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) cmd->data->error = -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) host->status = "error: data timeout";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) goto fail_transfer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) if (mci_dsta & S3C2410_SDIDSTA_XFERFINISH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) if (host->complete_what == COMPLETION_XFERFINISH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) host->status = "ok: data transfer completed";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) goto close_transfer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) if (host->complete_what == COMPLETION_XFERFINISH_RSPFIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) host->complete_what = COMPLETION_RSPFIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) mci_dclear |= S3C2410_SDIDSTA_XFERFINISH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) clear_status_bits:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) writel(mci_cclear, host->base + S3C2410_SDICMDSTAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) writel(mci_dclear, host->base + S3C2410_SDIDSTA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) goto irq_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) fail_transfer:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) host->pio_active = XFER_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) close_transfer:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) host->complete_what = COMPLETION_FINALIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) clear_imask(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) tasklet_schedule(&host->pio_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) goto irq_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) irq_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) dbg(host, dbg_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) "csta:0x%08x dsta:0x%08x fsta:0x%08x dcnt:0x%08x status:%s.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) mci_csta, mci_dsta, mci_fsta, mci_dcnt, host->status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) spin_unlock_irqrestore(&host->complete_lock, iflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) static void s3cmci_dma_done_callback(void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) struct s3cmci_host *host = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) unsigned long iflags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) BUG_ON(!host->mrq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) BUG_ON(!host->mrq->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) spin_lock_irqsave(&host->complete_lock, iflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) dbg(host, dbg_dma, "DMA FINISHED\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) host->dma_complete = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) host->complete_what = COMPLETION_FINALIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) tasklet_schedule(&host->pio_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) spin_unlock_irqrestore(&host->complete_lock, iflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) static void finalize_request(struct s3cmci_host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) struct mmc_request *mrq = host->mrq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) struct mmc_command *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) int debug_as_failure = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) if (host->complete_what != COMPLETION_FINALIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) if (!mrq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) cmd = host->cmd_is_stop ? mrq->stop : mrq->cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) if (cmd->data && (cmd->error == 0) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) (cmd->data->error == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) if (s3cmci_host_usedma(host) && (!host->dma_complete)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) dbg(host, dbg_dma, "DMA Missing (%d)!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) host->dma_complete);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) /* Read response from controller. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) cmd->resp[0] = readl(host->base + S3C2410_SDIRSP0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) cmd->resp[1] = readl(host->base + S3C2410_SDIRSP1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) cmd->resp[2] = readl(host->base + S3C2410_SDIRSP2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) cmd->resp[3] = readl(host->base + S3C2410_SDIRSP3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) writel(host->prescaler, host->base + S3C2410_SDIPRE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) if (cmd->error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) debug_as_failure = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) if (cmd->data && cmd->data->error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) debug_as_failure = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) dbg_dumpcmd(host, cmd, debug_as_failure);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) /* Cleanup controller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) writel(0, host->base + S3C2410_SDICMDARG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) writel(S3C2410_SDIDCON_STOP, host->base + S3C2410_SDIDCON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) writel(0, host->base + S3C2410_SDICMDCON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) clear_imask(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) if (cmd->data && cmd->error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) cmd->data->error = cmd->error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) if (cmd->data && cmd->data->stop && (!host->cmd_is_stop)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) host->cmd_is_stop = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) s3cmci_send_request(host->mmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) /* If we have no data transfer we are finished here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) if (!mrq->data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) goto request_done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) /* Calculate the amout of bytes transfer if there was no error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) if (mrq->data->error == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) mrq->data->bytes_xfered =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) (mrq->data->blocks * mrq->data->blksz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) mrq->data->bytes_xfered = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) /* If we had an error while transferring data we flush the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) * DMA channel and the fifo to clear out any garbage. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) if (mrq->data->error != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) if (s3cmci_host_usedma(host))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) dmaengine_terminate_all(host->dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) if (host->is2440) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) /* Clear failure register and reset fifo. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) writel(S3C2440_SDIFSTA_FIFORESET |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) S3C2440_SDIFSTA_FIFOFAIL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) host->base + S3C2410_SDIFSTA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) u32 mci_con;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) /* reset fifo */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) mci_con = readl(host->base + S3C2410_SDICON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) mci_con |= S3C2410_SDICON_FIFORESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) writel(mci_con, host->base + S3C2410_SDICON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) request_done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) host->complete_what = COMPLETION_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) host->mrq = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) s3cmci_check_sdio_irq(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) mmc_request_done(host->mmc, mrq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) static void s3cmci_send_command(struct s3cmci_host *host,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) struct mmc_command *cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) u32 ccon, imsk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) imsk = S3C2410_SDIIMSK_CRCSTATUS | S3C2410_SDIIMSK_CMDTIMEOUT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) S3C2410_SDIIMSK_RESPONSEND | S3C2410_SDIIMSK_CMDSENT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) S3C2410_SDIIMSK_RESPONSECRC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) enable_imask(host, imsk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) if (cmd->data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) host->complete_what = COMPLETION_XFERFINISH_RSPFIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) else if (cmd->flags & MMC_RSP_PRESENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) host->complete_what = COMPLETION_RSPFIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) host->complete_what = COMPLETION_CMDSENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) writel(cmd->arg, host->base + S3C2410_SDICMDARG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) ccon = cmd->opcode & S3C2410_SDICMDCON_INDEX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) ccon |= S3C2410_SDICMDCON_SENDERHOST | S3C2410_SDICMDCON_CMDSTART;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) if (cmd->flags & MMC_RSP_PRESENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) ccon |= S3C2410_SDICMDCON_WAITRSP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) if (cmd->flags & MMC_RSP_136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) ccon |= S3C2410_SDICMDCON_LONGRSP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) writel(ccon, host->base + S3C2410_SDICMDCON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) static int s3cmci_setup_data(struct s3cmci_host *host, struct mmc_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) u32 dcon, imsk, stoptries = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) if ((data->blksz & 3) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) /* We cannot deal with unaligned blocks with more than
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) * one block being transferred. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) if (data->blocks > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) pr_warn("%s: can't do non-word sized block transfers (blksz %d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) __func__, data->blksz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) while (readl(host->base + S3C2410_SDIDSTA) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) (S3C2410_SDIDSTA_TXDATAON | S3C2410_SDIDSTA_RXDATAON)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) dbg(host, dbg_err,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) "mci_setup_data() transfer stillin progress.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) writel(S3C2410_SDIDCON_STOP, host->base + S3C2410_SDIDCON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) s3cmci_reset(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) if ((stoptries--) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) dbg_dumpregs(host, "DRF");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) dcon = data->blocks & S3C2410_SDIDCON_BLKNUM_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) if (s3cmci_host_usedma(host))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) dcon |= S3C2410_SDIDCON_DMAEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) if (host->bus_width == MMC_BUS_WIDTH_4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) dcon |= S3C2410_SDIDCON_WIDEBUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) dcon |= S3C2410_SDIDCON_BLOCKMODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) if (data->flags & MMC_DATA_WRITE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) dcon |= S3C2410_SDIDCON_TXAFTERRESP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) dcon |= S3C2410_SDIDCON_XFER_TXSTART;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) if (data->flags & MMC_DATA_READ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) dcon |= S3C2410_SDIDCON_RXAFTERCMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) dcon |= S3C2410_SDIDCON_XFER_RXSTART;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) if (host->is2440) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) dcon |= S3C2440_SDIDCON_DS_WORD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) dcon |= S3C2440_SDIDCON_DATSTART;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) writel(dcon, host->base + S3C2410_SDIDCON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) /* write BSIZE register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) writel(data->blksz, host->base + S3C2410_SDIBSIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) /* add to IMASK register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) imsk = S3C2410_SDIIMSK_FIFOFAIL | S3C2410_SDIIMSK_DATACRC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) S3C2410_SDIIMSK_DATATIMEOUT | S3C2410_SDIIMSK_DATAFINISH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) enable_imask(host, imsk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) /* write TIMER register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) if (host->is2440) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) writel(0x007FFFFF, host->base + S3C2410_SDITIMER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) writel(0x0000FFFF, host->base + S3C2410_SDITIMER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) /* FIX: set slow clock to prevent timeouts on read */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) if (data->flags & MMC_DATA_READ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) writel(0xFF, host->base + S3C2410_SDIPRE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) #define BOTH_DIR (MMC_DATA_WRITE | MMC_DATA_READ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) static int s3cmci_prepare_pio(struct s3cmci_host *host, struct mmc_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) int rw = (data->flags & MMC_DATA_WRITE) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) BUG_ON((data->flags & BOTH_DIR) == BOTH_DIR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) host->pio_sgptr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) host->pio_bytes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) host->pio_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) host->pio_active = rw ? XFER_WRITE : XFER_READ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) if (rw) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) do_pio_write(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) enable_imask(host, S3C2410_SDIIMSK_TXFIFOHALF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) enable_imask(host, S3C2410_SDIIMSK_RXFIFOHALF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) | S3C2410_SDIIMSK_RXFIFOLAST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) static int s3cmci_prepare_dma(struct s3cmci_host *host, struct mmc_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) int rw = data->flags & MMC_DATA_WRITE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) struct dma_async_tx_descriptor *desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) struct dma_slave_config conf = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) .src_addr = host->mem->start + host->sdidata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) .dst_addr = host->mem->start + host->sdidata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) .src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) .dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) BUG_ON((data->flags & BOTH_DIR) == BOTH_DIR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) /* Restore prescaler value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) writel(host->prescaler, host->base + S3C2410_SDIPRE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) if (!rw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) conf.direction = DMA_DEV_TO_MEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) conf.direction = DMA_MEM_TO_DEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) mmc_get_dma_dir(data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) dmaengine_slave_config(host->dma, &conf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) desc = dmaengine_prep_slave_sg(host->dma, data->sg, data->sg_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) conf.direction,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) DMA_CTRL_ACK | DMA_PREP_INTERRUPT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) if (!desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) goto unmap_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) desc->callback = s3cmci_dma_done_callback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) desc->callback_param = host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) dmaengine_submit(desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) dma_async_issue_pending(host->dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) unmap_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) mmc_get_dma_dir(data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) static void s3cmci_send_request(struct mmc_host *mmc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) struct s3cmci_host *host = mmc_priv(mmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) struct mmc_request *mrq = host->mrq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) struct mmc_command *cmd = host->cmd_is_stop ? mrq->stop : mrq->cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) host->ccnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) prepare_dbgmsg(host, cmd, host->cmd_is_stop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) /* Clear command, data and fifo status registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) Fifo clear only necessary on 2440, but doesn't hurt on 2410
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) writel(0xFFFFFFFF, host->base + S3C2410_SDICMDSTAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) writel(0xFFFFFFFF, host->base + S3C2410_SDIDSTA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) writel(0xFFFFFFFF, host->base + S3C2410_SDIFSTA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) if (cmd->data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) int res = s3cmci_setup_data(host, cmd->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) host->dcnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) if (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) dbg(host, dbg_err, "setup data error %d\n", res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) cmd->error = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) cmd->data->error = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) mmc_request_done(mmc, mrq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) if (s3cmci_host_usedma(host))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) res = s3cmci_prepare_dma(host, cmd->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) res = s3cmci_prepare_pio(host, cmd->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) if (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) dbg(host, dbg_err, "data prepare error %d\n", res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) cmd->error = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) cmd->data->error = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) mmc_request_done(mmc, mrq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) /* Send command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) s3cmci_send_command(host, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) /* Enable Interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) s3cmci_enable_irq(host, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) static void s3cmci_request(struct mmc_host *mmc, struct mmc_request *mrq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) struct s3cmci_host *host = mmc_priv(mmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) host->status = "mmc request";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) host->cmd_is_stop = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) host->mrq = mrq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) if (mmc_gpio_get_cd(mmc) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) dbg(host, dbg_err, "%s: no medium present\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) host->mrq->cmd->error = -ENOMEDIUM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) mmc_request_done(mmc, mrq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) s3cmci_send_request(mmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) static void s3cmci_set_clk(struct s3cmci_host *host, struct mmc_ios *ios)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) u32 mci_psc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) /* Set clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) for (mci_psc = 0; mci_psc < 255; mci_psc++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) host->real_rate = host->clk_rate / (host->clk_div*(mci_psc+1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) if (host->real_rate <= ios->clock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) if (mci_psc > 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) mci_psc = 255;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) host->prescaler = mci_psc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) writel(host->prescaler, host->base + S3C2410_SDIPRE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) /* If requested clock is 0, real_rate will be 0, too */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) if (ios->clock == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) host->real_rate = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) static void s3cmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) struct s3cmci_host *host = mmc_priv(mmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) u32 mci_con;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) /* Set the power state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) mci_con = readl(host->base + S3C2410_SDICON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) switch (ios->power_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) case MMC_POWER_ON:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) case MMC_POWER_UP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) if (!host->is2440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) mci_con |= S3C2410_SDICON_FIFORESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) case MMC_POWER_OFF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) if (host->is2440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) mci_con |= S3C2440_SDICON_SDRESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) if (host->pdata->set_power)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) host->pdata->set_power(ios->power_mode, ios->vdd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) s3cmci_set_clk(host, ios);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) /* Set CLOCK_ENABLE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) if (ios->clock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) mci_con |= S3C2410_SDICON_CLOCKTYPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) mci_con &= ~S3C2410_SDICON_CLOCKTYPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) writel(mci_con, host->base + S3C2410_SDICON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) if ((ios->power_mode == MMC_POWER_ON) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) (ios->power_mode == MMC_POWER_UP)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) dbg(host, dbg_conf, "running at %lukHz (requested: %ukHz).\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) host->real_rate/1000, ios->clock/1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) dbg(host, dbg_conf, "powered down.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) host->bus_width = ios->bus_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) static void s3cmci_reset(struct s3cmci_host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) u32 con = readl(host->base + S3C2410_SDICON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) con |= S3C2440_SDICON_SDRESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) writel(con, host->base + S3C2410_SDICON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) static void s3cmci_enable_sdio_irq(struct mmc_host *mmc, int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) struct s3cmci_host *host = mmc_priv(mmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) u32 con;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) con = readl(host->base + S3C2410_SDICON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) host->sdio_irqen = enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) if (enable == host->sdio_irqen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) goto same_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) if (enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) con |= S3C2410_SDICON_SDIOIRQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) enable_imask(host, S3C2410_SDIIMSK_SDIOIRQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) if (!host->irq_state && !host->irq_disabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) host->irq_state = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) enable_irq(host->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) disable_imask(host, S3C2410_SDIIMSK_SDIOIRQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) con &= ~S3C2410_SDICON_SDIOIRQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) if (!host->irq_enabled && host->irq_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) disable_irq_nosync(host->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) host->irq_state = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) writel(con, host->base + S3C2410_SDICON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) same_state:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) s3cmci_check_sdio_irq(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) static const struct mmc_host_ops s3cmci_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) .request = s3cmci_request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) .set_ios = s3cmci_set_ios,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) .get_ro = mmc_gpio_get_ro,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) .get_cd = mmc_gpio_get_cd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) .enable_sdio_irq = s3cmci_enable_sdio_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) #ifdef CONFIG_ARM_S3C24XX_CPUFREQ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) static int s3cmci_cpufreq_transition(struct notifier_block *nb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) unsigned long val, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) struct s3cmci_host *host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) struct mmc_host *mmc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) unsigned long newclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) host = container_of(nb, struct s3cmci_host, freq_transition);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) newclk = clk_get_rate(host->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) mmc = host->mmc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) if ((val == CPUFREQ_PRECHANGE && newclk > host->clk_rate) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) (val == CPUFREQ_POSTCHANGE && newclk < host->clk_rate)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) spin_lock_irqsave(&mmc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) host->clk_rate = newclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) if (mmc->ios.power_mode != MMC_POWER_OFF &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) mmc->ios.clock != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) s3cmci_set_clk(host, &mmc->ios);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) spin_unlock_irqrestore(&mmc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) static inline int s3cmci_cpufreq_register(struct s3cmci_host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) host->freq_transition.notifier_call = s3cmci_cpufreq_transition;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) return cpufreq_register_notifier(&host->freq_transition,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) CPUFREQ_TRANSITION_NOTIFIER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) static inline void s3cmci_cpufreq_deregister(struct s3cmci_host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) cpufreq_unregister_notifier(&host->freq_transition,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) CPUFREQ_TRANSITION_NOTIFIER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) static inline int s3cmci_cpufreq_register(struct s3cmci_host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) static inline void s3cmci_cpufreq_deregister(struct s3cmci_host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) #ifdef CONFIG_DEBUG_FS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) static int s3cmci_state_show(struct seq_file *seq, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) struct s3cmci_host *host = seq->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) seq_printf(seq, "Register base = 0x%p\n", host->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) seq_printf(seq, "Clock rate = %ld\n", host->clk_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) seq_printf(seq, "Prescale = %d\n", host->prescaler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) seq_printf(seq, "is2440 = %d\n", host->is2440);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) seq_printf(seq, "IRQ = %d\n", host->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) seq_printf(seq, "IRQ enabled = %d\n", host->irq_enabled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) seq_printf(seq, "IRQ disabled = %d\n", host->irq_disabled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) seq_printf(seq, "IRQ state = %d\n", host->irq_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) seq_printf(seq, "CD IRQ = %d\n", host->irq_cd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) seq_printf(seq, "Do DMA = %d\n", s3cmci_host_usedma(host));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) seq_printf(seq, "SDIIMSK at %d\n", host->sdiimsk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) seq_printf(seq, "SDIDATA at %d\n", host->sdidata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) DEFINE_SHOW_ATTRIBUTE(s3cmci_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) #define DBG_REG(_r) { .addr = S3C2410_SDI##_r, .name = #_r }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) struct s3cmci_reg {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) unsigned short addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) unsigned char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) static const struct s3cmci_reg debug_regs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) DBG_REG(CON),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) DBG_REG(PRE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) DBG_REG(CMDARG),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) DBG_REG(CMDCON),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) DBG_REG(CMDSTAT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) DBG_REG(RSP0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) DBG_REG(RSP1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) DBG_REG(RSP2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) DBG_REG(RSP3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) DBG_REG(TIMER),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) DBG_REG(BSIZE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) DBG_REG(DCON),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) DBG_REG(DCNT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) DBG_REG(DSTA),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) DBG_REG(FSTA),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) static int s3cmci_regs_show(struct seq_file *seq, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) struct s3cmci_host *host = seq->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) const struct s3cmci_reg *rptr = debug_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) for (; rptr->name; rptr++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) seq_printf(seq, "SDI%s\t=0x%08x\n", rptr->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) readl(host->base + rptr->addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) seq_printf(seq, "SDIIMSK\t=0x%08x\n", readl(host->base + host->sdiimsk));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) DEFINE_SHOW_ATTRIBUTE(s3cmci_regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) static void s3cmci_debugfs_attach(struct s3cmci_host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) struct device *dev = &host->pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) struct dentry *root;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) root = debugfs_create_dir(dev_name(dev), NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) host->debug_root = root;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) debugfs_create_file("state", 0444, root, host, &s3cmci_state_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) debugfs_create_file("regs", 0444, root, host, &s3cmci_regs_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) static void s3cmci_debugfs_remove(struct s3cmci_host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) debugfs_remove_recursive(host->debug_root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) static inline void s3cmci_debugfs_attach(struct s3cmci_host *host) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) static inline void s3cmci_debugfs_remove(struct s3cmci_host *host) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) #endif /* CONFIG_DEBUG_FS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) static int s3cmci_probe_pdata(struct s3cmci_host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) struct platform_device *pdev = host->pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) struct mmc_host *mmc = host->mmc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) struct s3c24xx_mci_pdata *pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) host->is2440 = platform_get_device_id(pdev)->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) pdata = pdev->dev.platform_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) if (!pdata) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) dev_err(&pdev->dev, "need platform data");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) for (i = 0; i < 6; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) pdata->bus[i] = devm_gpiod_get_index(&pdev->dev, "bus", i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) GPIOD_OUT_LOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) if (IS_ERR(pdata->bus[i])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) dev_err(&pdev->dev, "failed to get gpio %d\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) return PTR_ERR(pdata->bus[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) if (pdata->no_wprotect)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) mmc->caps2 |= MMC_CAP2_NO_WRITE_PROTECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) if (pdata->no_detect)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) mmc->caps |= MMC_CAP_NEEDS_POLL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) if (pdata->wprotect_invert)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) /* If we get -ENOENT we have no card detect GPIO line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) ret = mmc_gpiod_request_cd(mmc, "cd", 0, false, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) if (ret != -ENOENT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) dev_err(&pdev->dev, "error requesting GPIO for CD %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) ret = mmc_gpiod_request_ro(host->mmc, "wp", 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) if (ret != -ENOENT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) dev_err(&pdev->dev, "error requesting GPIO for WP %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) static int s3cmci_probe_dt(struct s3cmci_host *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) struct platform_device *pdev = host->pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) struct s3c24xx_mci_pdata *pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) struct mmc_host *mmc = host->mmc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) host->is2440 = (long) of_device_get_match_data(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) ret = mmc_of_parse(mmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) if (!pdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) pdev->dev.platform_data = pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) static int s3cmci_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) struct s3cmci_host *host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) struct mmc_host *mmc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) mmc = mmc_alloc_host(sizeof(struct s3cmci_host), &pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) if (!mmc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) goto probe_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) host = mmc_priv(mmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) host->mmc = mmc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) host->pdev = pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) if (pdev->dev.of_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) ret = s3cmci_probe_dt(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) ret = s3cmci_probe_pdata(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) goto probe_free_host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) host->pdata = pdev->dev.platform_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) spin_lock_init(&host->complete_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) tasklet_init(&host->pio_tasklet, pio_tasklet, (unsigned long) host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) if (host->is2440) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) host->sdiimsk = S3C2440_SDIIMSK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) host->sdidata = S3C2440_SDIDATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) host->clk_div = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) host->sdiimsk = S3C2410_SDIIMSK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) host->sdidata = S3C2410_SDIDATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) host->clk_div = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) host->complete_what = COMPLETION_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) host->pio_active = XFER_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) if (!host->mem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) dev_err(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) "failed to get io memory region resource.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) ret = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) goto probe_free_host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) host->mem = request_mem_region(host->mem->start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) resource_size(host->mem), pdev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) if (!host->mem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) dev_err(&pdev->dev, "failed to request io memory region.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) ret = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) goto probe_free_host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) host->base = ioremap(host->mem->start, resource_size(host->mem));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) if (!host->base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) dev_err(&pdev->dev, "failed to ioremap() io memory region.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) goto probe_free_mem_region;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) host->irq = platform_get_irq(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) if (host->irq <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) goto probe_iounmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) if (request_irq(host->irq, s3cmci_irq, 0, DRIVER_NAME, host)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) dev_err(&pdev->dev, "failed to request mci interrupt.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) ret = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) goto probe_iounmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) /* We get spurious interrupts even when we have set the IMSK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) * register to ignore everything, so use disable_irq() to make
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) * ensure we don't lock the system with un-serviceable requests. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) disable_irq(host->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) host->irq_state = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) /* Depending on the dma state, get a DMA channel to use. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) if (s3cmci_host_usedma(host)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) host->dma = dma_request_chan(&pdev->dev, "rx-tx");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) ret = PTR_ERR_OR_ZERO(host->dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) dev_err(&pdev->dev, "cannot get DMA channel.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) goto probe_free_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) host->clk = clk_get(&pdev->dev, "sdi");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) if (IS_ERR(host->clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) dev_err(&pdev->dev, "failed to find clock source.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) ret = PTR_ERR(host->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) host->clk = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) goto probe_free_dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) ret = clk_prepare_enable(host->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) dev_err(&pdev->dev, "failed to enable clock source.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) goto clk_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) host->clk_rate = clk_get_rate(host->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) mmc->ops = &s3cmci_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) #ifdef CONFIG_MMC_S3C_HW_SDIO_IRQ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) mmc->caps = MMC_CAP_4_BIT_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) mmc->f_min = host->clk_rate / (host->clk_div * 256);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) mmc->f_max = host->clk_rate / host->clk_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) if (host->pdata->ocr_avail)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) mmc->ocr_avail = host->pdata->ocr_avail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) mmc->max_blk_count = 4095;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) mmc->max_blk_size = 4095;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) mmc->max_req_size = 4095 * 512;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) mmc->max_seg_size = mmc->max_req_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) mmc->max_segs = 128;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) dbg(host, dbg_debug,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) "probe: mode:%s mapped mci_base:%p irq:%u irq_cd:%u dma:%p.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) (host->is2440?"2440":""),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) host->base, host->irq, host->irq_cd, host->dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) ret = s3cmci_cpufreq_register(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) dev_err(&pdev->dev, "failed to register cpufreq\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) goto free_dmabuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) ret = mmc_add_host(mmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) dev_err(&pdev->dev, "failed to add mmc host.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) goto free_cpufreq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) s3cmci_debugfs_attach(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) platform_set_drvdata(pdev, mmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) dev_info(&pdev->dev, "%s - using %s, %s SDIO IRQ\n", mmc_hostname(mmc),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) s3cmci_host_usedma(host) ? "dma" : "pio",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) mmc->caps & MMC_CAP_SDIO_IRQ ? "hw" : "sw");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) free_cpufreq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) s3cmci_cpufreq_deregister(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) free_dmabuf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) clk_disable_unprepare(host->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) clk_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) clk_put(host->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) probe_free_dma:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) if (s3cmci_host_usedma(host))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) dma_release_channel(host->dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) probe_free_irq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) free_irq(host->irq, host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) probe_iounmap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) iounmap(host->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) probe_free_mem_region:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) release_mem_region(host->mem->start, resource_size(host->mem));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) probe_free_host:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) mmc_free_host(mmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) probe_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) static void s3cmci_shutdown(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) struct mmc_host *mmc = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) struct s3cmci_host *host = mmc_priv(mmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) if (host->irq_cd >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) free_irq(host->irq_cd, host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) s3cmci_debugfs_remove(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) s3cmci_cpufreq_deregister(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) mmc_remove_host(mmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) clk_disable_unprepare(host->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) static int s3cmci_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) struct mmc_host *mmc = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) struct s3cmci_host *host = mmc_priv(mmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) s3cmci_shutdown(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) clk_put(host->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) tasklet_disable(&host->pio_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) if (s3cmci_host_usedma(host))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) dma_release_channel(host->dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) free_irq(host->irq, host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) iounmap(host->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) release_mem_region(host->mem->start, resource_size(host->mem));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) mmc_free_host(mmc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) static const struct of_device_id s3cmci_dt_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) .compatible = "samsung,s3c2410-sdi",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) .data = (void *)0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) .compatible = "samsung,s3c2412-sdi",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) .data = (void *)1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) .compatible = "samsung,s3c2440-sdi",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) .data = (void *)1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) { /* sentinel */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) MODULE_DEVICE_TABLE(of, s3cmci_dt_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) static const struct platform_device_id s3cmci_driver_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) .name = "s3c2410-sdi",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) .driver_data = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) .name = "s3c2412-sdi",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) .driver_data = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) .name = "s3c2440-sdi",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) .driver_data = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) MODULE_DEVICE_TABLE(platform, s3cmci_driver_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) static struct platform_driver s3cmci_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) .name = "s3c-sdi",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) .probe_type = PROBE_PREFER_ASYNCHRONOUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) .of_match_table = s3cmci_dt_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) .id_table = s3cmci_driver_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) .probe = s3cmci_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) .remove = s3cmci_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) .shutdown = s3cmci_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) module_platform_driver(s3cmci_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) MODULE_DESCRIPTION("Samsung S3C MMC/SD Card Interface driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) MODULE_AUTHOR("Thomas Kleffel <tk@maintech.de>, Ben Dooks <ben-linux@fluff.org>");