^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) * TI FlashMedia driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2007 Alex Dubov <oakad@yahoo.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Special thanks to Carlos Corbacho for providing various MemoryStick cards
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * that made this driver possible.
^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/tifm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/memstick.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/highmem.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/scatterlist.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/log2.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define DRIVER_NAME "tifm_ms"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) static bool no_dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) module_param(no_dma, bool, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * Some control bits of TIFM appear to conform to Sony's reference design,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * so I'm just assuming they all are.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define TIFM_MS_STAT_DRQ 0x04000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define TIFM_MS_STAT_MSINT 0x02000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define TIFM_MS_STAT_RDY 0x01000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define TIFM_MS_STAT_CRC 0x00200
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define TIFM_MS_STAT_TOE 0x00100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define TIFM_MS_STAT_EMP 0x00020
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define TIFM_MS_STAT_FUL 0x00010
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define TIFM_MS_STAT_CED 0x00008
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define TIFM_MS_STAT_ERR 0x00004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define TIFM_MS_STAT_BRQ 0x00002
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define TIFM_MS_STAT_CNK 0x00001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define TIFM_MS_SYS_DMA 0x10000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define TIFM_MS_SYS_RESET 0x08000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define TIFM_MS_SYS_SRAC 0x04000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define TIFM_MS_SYS_INTEN 0x02000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define TIFM_MS_SYS_NOCRC 0x01000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define TIFM_MS_SYS_INTCLR 0x00800
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define TIFM_MS_SYS_MSIEN 0x00400
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define TIFM_MS_SYS_FCLR 0x00200
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define TIFM_MS_SYS_FDIR 0x00100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define TIFM_MS_SYS_DAM 0x00080
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define TIFM_MS_SYS_DRM 0x00040
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define TIFM_MS_SYS_DRQSL 0x00020
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define TIFM_MS_SYS_REI 0x00010
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define TIFM_MS_SYS_REO 0x00008
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define TIFM_MS_SYS_BSY_MASK 0x00007
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define TIFM_MS_SYS_FIFO (TIFM_MS_SYS_INTEN | TIFM_MS_SYS_MSIEN \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) | TIFM_MS_SYS_FCLR | TIFM_MS_SYS_BSY_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) /* Hardware flags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) CMD_READY = 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) FIFO_READY = 0x02,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) CARD_INT = 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) struct tifm_ms {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) struct tifm_dev *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) struct timer_list timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct memstick_request *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) struct tasklet_struct notify;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) unsigned int mode_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) unsigned int block_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) unsigned long timeout_jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) unsigned char eject:1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) use_dma:1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) unsigned char cmd_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) unsigned char io_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) unsigned int io_word;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) static unsigned int tifm_ms_read_data(struct tifm_ms *host,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) unsigned char *buf, unsigned int length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) struct tifm_dev *sock = host->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) unsigned int off = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) while (host->io_pos && length) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) buf[off++] = host->io_word & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) host->io_word >>= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) length--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) host->io_pos--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) if (!length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) return off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) while (!(TIFM_MS_STAT_EMP & readl(sock->addr + SOCK_MS_STATUS))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (length < 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) *(unsigned int *)(buf + off) = __raw_readl(sock->addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) + SOCK_MS_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) length -= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) off += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if (length
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) && !(TIFM_MS_STAT_EMP & readl(sock->addr + SOCK_MS_STATUS))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) host->io_word = readl(sock->addr + SOCK_MS_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) for (host->io_pos = 4; host->io_pos; --host->io_pos) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) buf[off++] = host->io_word & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) host->io_word >>= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) length--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (!length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) return off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) static unsigned int tifm_ms_write_data(struct tifm_ms *host,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) unsigned char *buf, unsigned int length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) struct tifm_dev *sock = host->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) unsigned int off = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if (host->io_pos) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) while (host->io_pos < 4 && length) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) host->io_word |= buf[off++] << (host->io_pos * 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) host->io_pos++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) length--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) if (host->io_pos == 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) && !(TIFM_MS_STAT_FUL & readl(sock->addr + SOCK_MS_STATUS))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) writel(TIFM_MS_SYS_FDIR | readl(sock->addr + SOCK_MS_SYSTEM),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) sock->addr + SOCK_MS_SYSTEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) writel(host->io_word, sock->addr + SOCK_MS_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) host->io_pos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) host->io_word = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) } else if (host->io_pos) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) return off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if (!length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) while (!(TIFM_MS_STAT_FUL & readl(sock->addr + SOCK_MS_STATUS))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) if (length < 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) writel(TIFM_MS_SYS_FDIR | readl(sock->addr + SOCK_MS_SYSTEM),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) sock->addr + SOCK_MS_SYSTEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) __raw_writel(*(unsigned int *)(buf + off),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) sock->addr + SOCK_MS_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) length -= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) off += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) switch (length) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) host->io_word |= buf[off + 2] << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) host->io_pos++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) host->io_word |= buf[off + 1] << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) host->io_pos++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) host->io_word |= buf[off];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) host->io_pos++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) off += host->io_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) return off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) static unsigned int tifm_ms_transfer_data(struct tifm_ms *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) struct tifm_dev *sock = host->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) unsigned int length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) unsigned int off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) unsigned int t_size, p_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) unsigned char *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) struct page *pg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) unsigned long flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) if (host->req->long_data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) length = host->req->sg.length - host->block_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) off = host->req->sg.offset + host->block_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) length = host->req->data_len - host->block_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) off = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) dev_dbg(&sock->dev, "fifo data transfer, %d, %d\n", length,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) host->block_pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) while (length) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) unsigned int p_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (host->req->long_data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) pg = nth_page(sg_page(&host->req->sg),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) off >> PAGE_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) p_off = offset_in_page(off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) p_cnt = PAGE_SIZE - p_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) p_cnt = min(p_cnt, length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) buf = kmap_atomic(pg) + p_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) buf = host->req->data + host->block_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) p_cnt = host->req->data_len - host->block_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) t_size = host->req->data_dir == WRITE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) ? tifm_ms_write_data(host, buf, p_cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) : tifm_ms_read_data(host, buf, p_cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if (host->req->long_data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) kunmap_atomic(buf - p_off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) if (!t_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) host->block_pos += t_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) length -= t_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) off += t_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) dev_dbg(&sock->dev, "fifo data transfer, %d remaining\n", length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) if (!length && (host->req->data_dir == WRITE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) if (host->io_pos) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) writel(TIFM_MS_SYS_FDIR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) | readl(sock->addr + SOCK_MS_SYSTEM),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) sock->addr + SOCK_MS_SYSTEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) writel(host->io_word, sock->addr + SOCK_MS_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) writel(TIFM_MS_SYS_FDIR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) | readl(sock->addr + SOCK_MS_SYSTEM),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) sock->addr + SOCK_MS_SYSTEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) writel(0, sock->addr + SOCK_MS_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) readl(sock->addr + SOCK_MS_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) return length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) static int tifm_ms_issue_cmd(struct tifm_ms *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) struct tifm_dev *sock = host->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) unsigned int data_len, cmd, sys_param;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) host->cmd_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) host->block_pos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) host->io_pos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) host->io_word = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) host->cmd_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) host->use_dma = !no_dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (host->req->long_data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) data_len = host->req->sg.length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (!is_power_of_2(data_len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) host->use_dma = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) data_len = host->req->data_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) host->use_dma = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) writel(TIFM_FIFO_INT_SETALL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) writel(TIFM_FIFO_ENABLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) sock->addr + SOCK_FIFO_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (host->use_dma) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) if (1 != tifm_map_sg(sock, &host->req->sg, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) host->req->data_dir == READ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) ? PCI_DMA_FROMDEVICE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) : PCI_DMA_TODEVICE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) host->req->error = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) return host->req->error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) data_len = sg_dma_len(&host->req->sg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) writel(ilog2(data_len) - 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) sock->addr + SOCK_FIFO_PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) writel(TIFM_FIFO_INTMASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) sys_param = TIFM_DMA_EN | (1 << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) if (host->req->data_dir == WRITE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) sys_param |= TIFM_DMA_TX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) writel(TIFM_FIFO_INTMASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) writel(sg_dma_address(&host->req->sg),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) sock->addr + SOCK_DMA_ADDRESS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) writel(sys_param, sock->addr + SOCK_DMA_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) writel(host->mode_mask | TIFM_MS_SYS_FIFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) sock->addr + SOCK_MS_SYSTEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) writel(TIFM_FIFO_MORE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
^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) mod_timer(&host->timer, jiffies + host->timeout_jiffies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) writel(TIFM_CTRL_LED | readl(sock->addr + SOCK_CONTROL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) sock->addr + SOCK_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) host->req->error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) sys_param = readl(sock->addr + SOCK_MS_SYSTEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) sys_param |= TIFM_MS_SYS_INTCLR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (host->use_dma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) sys_param |= TIFM_MS_SYS_DMA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) sys_param &= ~TIFM_MS_SYS_DMA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) writel(sys_param, sock->addr + SOCK_MS_SYSTEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) cmd = (host->req->tpc & 0xf) << 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) cmd |= data_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) writel(cmd, sock->addr + SOCK_MS_COMMAND);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) dev_dbg(&sock->dev, "executing TPC %x, %x\n", cmd, sys_param);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) static void tifm_ms_complete_cmd(struct tifm_ms *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) struct tifm_dev *sock = host->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) struct memstick_host *msh = tifm_get_drvdata(sock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) del_timer(&host->timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) host->req->int_reg = readl(sock->addr + SOCK_MS_STATUS) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) host->req->int_reg = (host->req->int_reg & 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) | ((host->req->int_reg << 4) & 0xe0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) writel(TIFM_FIFO_INT_SETALL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) writel(TIFM_DMA_RESET, sock->addr + SOCK_DMA_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) if (host->use_dma) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) tifm_unmap_sg(sock, &host->req->sg, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) host->req->data_dir == READ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) ? PCI_DMA_FROMDEVICE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) : PCI_DMA_TODEVICE);
^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) writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) sock->addr + SOCK_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) dev_dbg(&sock->dev, "TPC complete\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) rc = memstick_next_req(msh, &host->req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) } while (!rc && tifm_ms_issue_cmd(host));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) static int tifm_ms_check_status(struct tifm_ms *host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) if (!host->req->error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) if (!(host->cmd_flags & CMD_READY))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) if (!(host->cmd_flags & FIFO_READY))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) if (host->req->need_card_int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) && !(host->cmd_flags & CARD_INT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) /* Called from interrupt handler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) static void tifm_ms_data_event(struct tifm_dev *sock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) struct tifm_ms *host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) unsigned int fifo_status = 0, host_status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) int rc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) spin_lock(&sock->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) host = memstick_priv((struct memstick_host *)tifm_get_drvdata(sock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) fifo_status = readl(sock->addr + SOCK_DMA_FIFO_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) host_status = readl(sock->addr + SOCK_MS_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) dev_dbg(&sock->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) "data event: fifo_status %x, host_status %x, flags %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) fifo_status, host_status, host->cmd_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) if (host->req) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) if (host->use_dma && (fifo_status & 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) host->cmd_flags |= FIFO_READY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) rc = tifm_ms_check_status(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) if (!host->use_dma && (fifo_status & TIFM_FIFO_MORE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) if (!tifm_ms_transfer_data(host)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) host->cmd_flags |= FIFO_READY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) rc = tifm_ms_check_status(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) }
^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) writel(fifo_status, sock->addr + SOCK_DMA_FIFO_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) if (!rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) tifm_ms_complete_cmd(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) spin_unlock(&sock->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) /* Called from interrupt handler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) static void tifm_ms_card_event(struct tifm_dev *sock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) struct tifm_ms *host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) unsigned int host_status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) int rc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) spin_lock(&sock->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) host = memstick_priv((struct memstick_host *)tifm_get_drvdata(sock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) host_status = readl(sock->addr + SOCK_MS_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) dev_dbg(&sock->dev, "host event: host_status %x, flags %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) host_status, host->cmd_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) if (host->req) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) if (host_status & TIFM_MS_STAT_TOE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) host->req->error = -ETIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) else if (host_status & TIFM_MS_STAT_CRC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) host->req->error = -EILSEQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) if (host_status & TIFM_MS_STAT_RDY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) host->cmd_flags |= CMD_READY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) if (host_status & TIFM_MS_STAT_MSINT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) host->cmd_flags |= CARD_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) rc = tifm_ms_check_status(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) writel(TIFM_MS_SYS_INTCLR | readl(sock->addr + SOCK_MS_SYSTEM),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) sock->addr + SOCK_MS_SYSTEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (!rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) tifm_ms_complete_cmd(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) spin_unlock(&sock->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) static void tifm_ms_req_tasklet(unsigned long data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) struct memstick_host *msh = (struct memstick_host *)data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) struct tifm_ms *host = memstick_priv(msh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) struct tifm_dev *sock = host->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) spin_lock_irqsave(&sock->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) if (!host->req) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) if (host->eject) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) rc = memstick_next_req(msh, &host->req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) if (!rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) host->req->error = -ETIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) } while (!rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) spin_unlock_irqrestore(&sock->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) rc = memstick_next_req(msh, &host->req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) } while (!rc && tifm_ms_issue_cmd(host));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) spin_unlock_irqrestore(&sock->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) static void tifm_ms_dummy_submit(struct memstick_host *msh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) static void tifm_ms_submit_req(struct memstick_host *msh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) struct tifm_ms *host = memstick_priv(msh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) tasklet_schedule(&host->notify);
^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 int tifm_ms_set_param(struct memstick_host *msh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) enum memstick_param param,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) struct tifm_ms *host = memstick_priv(msh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) struct tifm_dev *sock = host->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) switch (param) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) case MEMSTICK_POWER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) /* also affected by media detection mechanism */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) if (value == MEMSTICK_POWER_ON) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) host->mode_mask = TIFM_MS_SYS_SRAC | TIFM_MS_SYS_REI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) writel(TIFM_MS_SYS_RESET, sock->addr + SOCK_MS_SYSTEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) writel(TIFM_MS_SYS_FCLR | TIFM_MS_SYS_INTCLR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) sock->addr + SOCK_MS_SYSTEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) writel(0xffffffff, sock->addr + SOCK_MS_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) } else if (value == MEMSTICK_POWER_OFF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) writel(TIFM_MS_SYS_FCLR | TIFM_MS_SYS_INTCLR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) sock->addr + SOCK_MS_SYSTEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) writel(0xffffffff, sock->addr + SOCK_MS_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) case MEMSTICK_INTERFACE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) if (value == MEMSTICK_SERIAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) host->mode_mask = TIFM_MS_SYS_SRAC | TIFM_MS_SYS_REI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) writel((~TIFM_CTRL_FAST_CLK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) & readl(sock->addr + SOCK_CONTROL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) sock->addr + SOCK_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) } else if (value == MEMSTICK_PAR4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) host->mode_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) writel(TIFM_CTRL_FAST_CLK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) | readl(sock->addr + SOCK_CONTROL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) sock->addr + SOCK_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) static void tifm_ms_abort(struct timer_list *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) struct tifm_ms *host = from_timer(host, t, timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) dev_dbg(&host->dev->dev, "status %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) readl(host->dev->addr + SOCK_MS_STATUS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) printk(KERN_ERR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) "%s : card failed to respond for a long period of time "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) "(%x, %x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) dev_name(&host->dev->dev), host->req ? host->req->tpc : 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) host->cmd_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) tifm_eject(host->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) static int tifm_ms_probe(struct tifm_dev *sock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) struct memstick_host *msh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) struct tifm_ms *host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) int rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) if (!(TIFM_SOCK_STATE_OCCUPIED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) & readl(sock->addr + SOCK_PRESENT_STATE))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) printk(KERN_WARNING "%s : card gone, unexpectedly\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) dev_name(&sock->dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) msh = memstick_alloc_host(sizeof(struct tifm_ms), &sock->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) if (!msh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) host = memstick_priv(msh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) tifm_set_drvdata(sock, msh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) host->dev = sock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) host->timeout_jiffies = msecs_to_jiffies(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) timer_setup(&host->timer, tifm_ms_abort, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) tasklet_init(&host->notify, tifm_ms_req_tasklet, (unsigned long)msh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) msh->request = tifm_ms_submit_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) msh->set_param = tifm_ms_set_param;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) sock->card_event = tifm_ms_card_event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) sock->data_event = tifm_ms_data_event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) if (tifm_has_ms_pif(sock))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) msh->caps |= MEMSTICK_CAP_PAR4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) rc = memstick_add_host(msh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) if (!rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) memstick_free_host(msh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) static void tifm_ms_remove(struct tifm_dev *sock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) struct memstick_host *msh = tifm_get_drvdata(sock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) struct tifm_ms *host = memstick_priv(msh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) msh->request = tifm_ms_dummy_submit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) tasklet_kill(&host->notify);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) spin_lock_irqsave(&sock->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) host->eject = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) if (host->req) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) del_timer(&host->timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) writel(TIFM_FIFO_INT_SETALL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) writel(TIFM_DMA_RESET, sock->addr + SOCK_DMA_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) if (host->use_dma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) tifm_unmap_sg(sock, &host->req->sg, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) host->req->data_dir == READ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) ? PCI_DMA_TODEVICE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) : PCI_DMA_FROMDEVICE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) host->req->error = -ETIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) rc = memstick_next_req(msh, &host->req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) if (!rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) host->req->error = -ETIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) } while (!rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) spin_unlock_irqrestore(&sock->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) memstick_remove_host(msh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) memstick_free_host(msh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) static int tifm_ms_suspend(struct tifm_dev *sock, pm_message_t state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) struct memstick_host *msh = tifm_get_drvdata(sock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) memstick_suspend_host(msh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) static int tifm_ms_resume(struct tifm_dev *sock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) struct memstick_host *msh = tifm_get_drvdata(sock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) memstick_resume_host(msh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) #define tifm_ms_suspend NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) #define tifm_ms_resume NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) #endif /* CONFIG_PM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) static struct tifm_device_id tifm_ms_id_tbl[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) { TIFM_TYPE_MS }, { 0 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) static struct tifm_driver tifm_ms_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) .name = DRIVER_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) .owner = THIS_MODULE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) .id_table = tifm_ms_id_tbl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) .probe = tifm_ms_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) .remove = tifm_ms_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) .suspend = tifm_ms_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) .resume = tifm_ms_resume
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) static int __init tifm_ms_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) return tifm_register_driver(&tifm_ms_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) static void __exit tifm_ms_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) tifm_unregister_driver(&tifm_ms_driver);
^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) MODULE_AUTHOR("Alex Dubov");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) MODULE_DESCRIPTION("TI FlashMedia MemoryStick driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) MODULE_DEVICE_TABLE(tifm, tifm_ms_id_tbl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) module_init(tifm_ms_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) module_exit(tifm_ms_exit);