diff options
| -rw-r--r-- | drivers/mmc/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/mmc/wbsd.c | 716 | ||||
| -rw-r--r-- | drivers/mmc/wbsd.h | 12 |
3 files changed, 544 insertions, 186 deletions
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index 2e70d74fbdee..4991bbd054f3 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig | |||
| @@ -51,7 +51,7 @@ config MMC_PXA | |||
| 51 | 51 | ||
| 52 | config MMC_WBSD | 52 | config MMC_WBSD |
| 53 | tristate "Winbond W83L51xD SD/MMC Card Interface support" | 53 | tristate "Winbond W83L51xD SD/MMC Card Interface support" |
| 54 | depends on MMC && ISA && ISA_DMA_API | 54 | depends on MMC && ISA_DMA_API |
| 55 | help | 55 | help |
| 56 | This selects the Winbond(R) W83L51xD Secure digital and | 56 | This selects the Winbond(R) W83L51xD Secure digital and |
| 57 | Multimedia card Interface. | 57 | Multimedia card Interface. |
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c index 39747526c719..b7fbd30b49a0 100644 --- a/drivers/mmc/wbsd.c +++ b/drivers/mmc/wbsd.c | |||
| @@ -28,7 +28,9 @@ | |||
| 28 | #include <linux/ioport.h> | 28 | #include <linux/ioport.h> |
| 29 | #include <linux/device.h> | 29 | #include <linux/device.h> |
| 30 | #include <linux/interrupt.h> | 30 | #include <linux/interrupt.h> |
| 31 | #include <linux/dma-mapping.h> | ||
| 31 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
| 33 | #include <linux/pnp.h> | ||
| 32 | #include <linux/highmem.h> | 34 | #include <linux/highmem.h> |
| 33 | #include <linux/mmc/host.h> | 35 | #include <linux/mmc/host.h> |
| 34 | #include <linux/mmc/protocol.h> | 36 | #include <linux/mmc/protocol.h> |
| @@ -40,7 +42,7 @@ | |||
| 40 | #include "wbsd.h" | 42 | #include "wbsd.h" |
| 41 | 43 | ||
| 42 | #define DRIVER_NAME "wbsd" | 44 | #define DRIVER_NAME "wbsd" |
| 43 | #define DRIVER_VERSION "1.1" | 45 | #define DRIVER_VERSION "1.2" |
| 44 | 46 | ||
| 45 | #ifdef CONFIG_MMC_DEBUG | 47 | #ifdef CONFIG_MMC_DEBUG |
| 46 | #define DBG(x...) \ | 48 | #define DBG(x...) \ |
| @@ -52,10 +54,6 @@ | |||
| 52 | #define DBGF(x...) do { } while (0) | 54 | #define DBGF(x...) do { } while (0) |
| 53 | #endif | 55 | #endif |
| 54 | 56 | ||
| 55 | static unsigned int io = 0x248; | ||
| 56 | static unsigned int irq = 6; | ||
| 57 | static int dma = 2; | ||
| 58 | |||
| 59 | #ifdef CONFIG_MMC_DEBUG | 57 | #ifdef CONFIG_MMC_DEBUG |
| 60 | void DBG_REG(int reg, u8 value) | 58 | void DBG_REG(int reg, u8 value) |
| 61 | { | 59 | { |
| @@ -79,28 +77,61 @@ void DBG_REG(int reg, u8 value) | |||
| 79 | #endif | 77 | #endif |
| 80 | 78 | ||
| 81 | /* | 79 | /* |
| 80 | * Device resources | ||
| 81 | */ | ||
| 82 | |||
| 83 | #ifdef CONFIG_PNP | ||
| 84 | |||
| 85 | static const struct pnp_device_id pnp_dev_table[] = { | ||
| 86 | { "WEC0517", 0 }, | ||
| 87 | { "WEC0518", 0 }, | ||
| 88 | { "", 0 }, | ||
| 89 | }; | ||
| 90 | |||
| 91 | MODULE_DEVICE_TABLE(pnp, pnp_dev_table); | ||
| 92 | |||
| 93 | #endif /* CONFIG_PNP */ | ||
| 94 | |||
| 95 | #ifdef CONFIG_PNP | ||
| 96 | static unsigned int nopnp = 0; | ||
| 97 | #else | ||
| 98 | static const unsigned int nopnp = 1; | ||
| 99 | #endif | ||
| 100 | static unsigned int io = 0x248; | ||
| 101 | static unsigned int irq = 6; | ||
| 102 | static int dma = 2; | ||
| 103 | |||
| 104 | /* | ||
| 82 | * Basic functions | 105 | * Basic functions |
| 83 | */ | 106 | */ |
| 84 | 107 | ||
| 85 | static inline void wbsd_unlock_config(struct wbsd_host* host) | 108 | static inline void wbsd_unlock_config(struct wbsd_host* host) |
| 86 | { | 109 | { |
| 110 | BUG_ON(host->config == 0); | ||
| 111 | |||
| 87 | outb(host->unlock_code, host->config); | 112 | outb(host->unlock_code, host->config); |
| 88 | outb(host->unlock_code, host->config); | 113 | outb(host->unlock_code, host->config); |
| 89 | } | 114 | } |
| 90 | 115 | ||
| 91 | static inline void wbsd_lock_config(struct wbsd_host* host) | 116 | static inline void wbsd_lock_config(struct wbsd_host* host) |
| 92 | { | 117 | { |
| 118 | BUG_ON(host->config == 0); | ||
| 119 | |||
| 93 | outb(LOCK_CODE, host->config); | 120 | outb(LOCK_CODE, host->config); |
| 94 | } | 121 | } |
| 95 | 122 | ||
| 96 | static inline void wbsd_write_config(struct wbsd_host* host, u8 reg, u8 value) | 123 | static inline void wbsd_write_config(struct wbsd_host* host, u8 reg, u8 value) |
| 97 | { | 124 | { |
| 125 | BUG_ON(host->config == 0); | ||
| 126 | |||
| 98 | outb(reg, host->config); | 127 | outb(reg, host->config); |
| 99 | outb(value, host->config + 1); | 128 | outb(value, host->config + 1); |
| 100 | } | 129 | } |
| 101 | 130 | ||
| 102 | static inline u8 wbsd_read_config(struct wbsd_host* host, u8 reg) | 131 | static inline u8 wbsd_read_config(struct wbsd_host* host, u8 reg) |
| 103 | { | 132 | { |
| 133 | BUG_ON(host->config == 0); | ||
| 134 | |||
| 104 | outb(reg, host->config); | 135 | outb(reg, host->config); |
| 105 | return inb(host->config + 1); | 136 | return inb(host->config + 1); |
| 106 | } | 137 | } |
| @@ -133,6 +164,13 @@ static void wbsd_init_device(struct wbsd_host* host) | |||
| 133 | wbsd_write_index(host, WBSD_IDX_SETUP, setup); | 164 | wbsd_write_index(host, WBSD_IDX_SETUP, setup); |
| 134 | 165 | ||
| 135 | /* | 166 | /* |
| 167 | * Set DAT3 to input | ||
| 168 | */ | ||
| 169 | setup &= ~WBSD_DAT3_H; | ||
| 170 | wbsd_write_index(host, WBSD_IDX_SETUP, setup); | ||
| 171 | host->flags &= ~WBSD_FIGNORE_DETECT; | ||
| 172 | |||
| 173 | /* | ||
| 136 | * Read back default clock. | 174 | * Read back default clock. |
| 137 | */ | 175 | */ |
| 138 | host->clk = wbsd_read_index(host, WBSD_IDX_CLK); | 176 | host->clk = wbsd_read_index(host, WBSD_IDX_CLK); |
| @@ -148,6 +186,14 @@ static void wbsd_init_device(struct wbsd_host* host) | |||
| 148 | wbsd_write_index(host, WBSD_IDX_TAAC, 0x7F); | 186 | wbsd_write_index(host, WBSD_IDX_TAAC, 0x7F); |
| 149 | 187 | ||
| 150 | /* | 188 | /* |
| 189 | * Test for card presence | ||
| 190 | */ | ||
| 191 | if (inb(host->base + WBSD_CSR) & WBSD_CARDPRESENT) | ||
| 192 | host->flags |= WBSD_FCARD_PRESENT; | ||
| 193 | else | ||
| 194 | host->flags &= ~WBSD_FCARD_PRESENT; | ||
| 195 | |||
| 196 | /* | ||
| 151 | * Enable interesting interrupts. | 197 | * Enable interesting interrupts. |
| 152 | */ | 198 | */ |
| 153 | ier = 0; | 199 | ier = 0; |
| @@ -407,8 +453,6 @@ static inline void wbsd_get_long_reply(struct wbsd_host* host, | |||
| 407 | } | 453 | } |
| 408 | } | 454 | } |
| 409 | 455 | ||
| 410 | static irqreturn_t wbsd_irq(int irq, void *dev_id, struct pt_regs *regs); | ||
| 411 | |||
| 412 | static void wbsd_send_command(struct wbsd_host* host, struct mmc_command* cmd) | 456 | static void wbsd_send_command(struct wbsd_host* host, struct mmc_command* cmd) |
| 413 | { | 457 | { |
| 414 | int i; | 458 | int i; |
| @@ -646,6 +690,13 @@ static void wbsd_fill_fifo(struct wbsd_host* host) | |||
| 646 | } | 690 | } |
| 647 | 691 | ||
| 648 | wbsd_kunmap_sg(host); | 692 | wbsd_kunmap_sg(host); |
| 693 | |||
| 694 | /* | ||
| 695 | * The controller stops sending interrupts for | ||
| 696 | * 'FIFO empty' under certain conditions. So we | ||
| 697 | * need to be a bit more pro-active. | ||
| 698 | */ | ||
| 699 | tasklet_schedule(&host->fifo_tasklet); | ||
| 649 | } | 700 | } |
| 650 | 701 | ||
| 651 | static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data) | 702 | static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data) |
| @@ -850,9 +901,11 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data) | |||
| 850 | wbsd_request_end(host, host->mrq); | 901 | wbsd_request_end(host, host->mrq); |
| 851 | } | 902 | } |
| 852 | 903 | ||
| 853 | /* | 904 | /*****************************************************************************\ |
| 854 | * MMC Callbacks | 905 | * * |
| 855 | */ | 906 | * MMC layer callbacks * |
| 907 | * * | ||
| 908 | \*****************************************************************************/ | ||
| 856 | 909 | ||
| 857 | static void wbsd_request(struct mmc_host* mmc, struct mmc_request* mrq) | 910 | static void wbsd_request(struct mmc_host* mmc, struct mmc_request* mrq) |
| 858 | { | 911 | { |
| @@ -874,7 +927,7 @@ static void wbsd_request(struct mmc_host* mmc, struct mmc_request* mrq) | |||
| 874 | * If there is no card in the slot then | 927 | * If there is no card in the slot then |
| 875 | * timeout immediatly. | 928 | * timeout immediatly. |
| 876 | */ | 929 | */ |
| 877 | if (!(inb(host->base + WBSD_CSR) & WBSD_CARDPRESENT)) | 930 | if (!(host->flags & WBSD_FCARD_PRESENT)) |
| 878 | { | 931 | { |
| 879 | cmd->error = MMC_ERR_TIMEOUT; | 932 | cmd->error = MMC_ERR_TIMEOUT; |
| 880 | goto done; | 933 | goto done; |
| @@ -953,33 +1006,50 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios) | |||
| 953 | host->clk = clk; | 1006 | host->clk = clk; |
| 954 | } | 1007 | } |
| 955 | 1008 | ||
| 1009 | /* | ||
| 1010 | * Power up card. | ||
| 1011 | */ | ||
| 956 | if (ios->power_mode != MMC_POWER_OFF) | 1012 | if (ios->power_mode != MMC_POWER_OFF) |
| 957 | { | 1013 | { |
| 958 | /* | ||
| 959 | * Power up card. | ||
| 960 | */ | ||
| 961 | pwr = inb(host->base + WBSD_CSR); | 1014 | pwr = inb(host->base + WBSD_CSR); |
| 962 | pwr &= ~WBSD_POWER_N; | 1015 | pwr &= ~WBSD_POWER_N; |
| 963 | outb(pwr, host->base + WBSD_CSR); | 1016 | outb(pwr, host->base + WBSD_CSR); |
| 964 | |||
| 965 | /* | ||
| 966 | * This behaviour is stolen from the | ||
| 967 | * Windows driver. Don't know why, but | ||
| 968 | * it is needed. | ||
| 969 | */ | ||
| 970 | setup = wbsd_read_index(host, WBSD_IDX_SETUP); | ||
| 971 | if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) | ||
| 972 | setup |= WBSD_DAT3_H; | ||
| 973 | else | ||
| 974 | setup &= ~WBSD_DAT3_H; | ||
| 975 | wbsd_write_index(host, WBSD_IDX_SETUP, setup); | ||
| 976 | |||
| 977 | mdelay(1); | ||
| 978 | } | 1017 | } |
| 979 | 1018 | ||
| 1019 | /* | ||
| 1020 | * MMC cards need to have pin 1 high during init. | ||
| 1021 | * Init time corresponds rather nicely with the bus mode. | ||
| 1022 | * It wreaks havoc with the card detection though so | ||
| 1023 | * that needs to be disabed. | ||
| 1024 | */ | ||
| 1025 | setup = wbsd_read_index(host, WBSD_IDX_SETUP); | ||
| 1026 | if ((ios->power_mode == MMC_POWER_ON) && | ||
| 1027 | (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)) | ||
| 1028 | { | ||
| 1029 | setup |= WBSD_DAT3_H; | ||
| 1030 | host->flags |= WBSD_FIGNORE_DETECT; | ||
| 1031 | } | ||
| 1032 | else | ||
| 1033 | { | ||
| 1034 | setup &= ~WBSD_DAT3_H; | ||
| 1035 | host->flags &= ~WBSD_FIGNORE_DETECT; | ||
| 1036 | } | ||
| 1037 | wbsd_write_index(host, WBSD_IDX_SETUP, setup); | ||
| 1038 | |||
| 980 | spin_unlock_bh(&host->lock); | 1039 | spin_unlock_bh(&host->lock); |
| 981 | } | 1040 | } |
| 982 | 1041 | ||
| 1042 | static struct mmc_host_ops wbsd_ops = { | ||
| 1043 | .request = wbsd_request, | ||
| 1044 | .set_ios = wbsd_set_ios, | ||
| 1045 | }; | ||
| 1046 | |||
| 1047 | /*****************************************************************************\ | ||
| 1048 | * * | ||
| 1049 | * Interrupt handling * | ||
| 1050 | * * | ||
| 1051 | \*****************************************************************************/ | ||
| 1052 | |||
| 983 | /* | 1053 | /* |
| 984 | * Tasklets | 1054 | * Tasklets |
| 985 | */ | 1055 | */ |
| @@ -1005,17 +1075,33 @@ static void wbsd_tasklet_card(unsigned long param) | |||
| 1005 | { | 1075 | { |
| 1006 | struct wbsd_host* host = (struct wbsd_host*)param; | 1076 | struct wbsd_host* host = (struct wbsd_host*)param; |
| 1007 | u8 csr; | 1077 | u8 csr; |
| 1078 | int change = 0; | ||
| 1008 | 1079 | ||
| 1009 | spin_lock(&host->lock); | 1080 | spin_lock(&host->lock); |
| 1010 | 1081 | ||
| 1082 | if (host->flags & WBSD_FIGNORE_DETECT) | ||
| 1083 | { | ||
| 1084 | spin_unlock(&host->lock); | ||
| 1085 | return; | ||
| 1086 | } | ||
| 1087 | |||
| 1011 | csr = inb(host->base + WBSD_CSR); | 1088 | csr = inb(host->base + WBSD_CSR); |
| 1012 | WARN_ON(csr == 0xff); | 1089 | WARN_ON(csr == 0xff); |
| 1013 | 1090 | ||
| 1014 | if (csr & WBSD_CARDPRESENT) | 1091 | if (csr & WBSD_CARDPRESENT) |
| 1015 | DBG("Card inserted\n"); | 1092 | { |
| 1016 | else | 1093 | if (!(host->flags & WBSD_FCARD_PRESENT)) |
| 1094 | { | ||
| 1095 | DBG("Card inserted\n"); | ||
| 1096 | host->flags |= WBSD_FCARD_PRESENT; | ||
| 1097 | change = 1; | ||
| 1098 | } | ||
| 1099 | } | ||
| 1100 | else if (host->flags & WBSD_FCARD_PRESENT) | ||
| 1017 | { | 1101 | { |
| 1018 | DBG("Card removed\n"); | 1102 | DBG("Card removed\n"); |
| 1103 | host->flags &= ~WBSD_FCARD_PRESENT; | ||
| 1104 | change = 1; | ||
| 1019 | 1105 | ||
| 1020 | if (host->mrq) | 1106 | if (host->mrq) |
| 1021 | { | 1107 | { |
| @@ -1033,7 +1119,8 @@ static void wbsd_tasklet_card(unsigned long param) | |||
| 1033 | */ | 1119 | */ |
| 1034 | spin_unlock(&host->lock); | 1120 | spin_unlock(&host->lock); |
| 1035 | 1121 | ||
| 1036 | mmc_detect_change(host->mmc); | 1122 | if (change) |
| 1123 | mmc_detect_change(host->mmc); | ||
| 1037 | } | 1124 | } |
| 1038 | 1125 | ||
| 1039 | static void wbsd_tasklet_fifo(unsigned long param) | 1126 | static void wbsd_tasklet_fifo(unsigned long param) |
| @@ -1200,11 +1287,85 @@ static irqreturn_t wbsd_irq(int irq, void *dev_id, struct pt_regs *regs) | |||
| 1200 | return IRQ_HANDLED; | 1287 | return IRQ_HANDLED; |
| 1201 | } | 1288 | } |
| 1202 | 1289 | ||
| 1290 | /*****************************************************************************\ | ||
| 1291 | * * | ||
| 1292 | * Device initialisation and shutdown * | ||
| 1293 | * * | ||
| 1294 | \*****************************************************************************/ | ||
| 1295 | |||
| 1203 | /* | 1296 | /* |
| 1204 | * Support functions for probe | 1297 | * Allocate/free MMC structure. |
| 1205 | */ | 1298 | */ |
| 1206 | 1299 | ||
| 1207 | static int wbsd_scan(struct wbsd_host* host) | 1300 | static int __devinit wbsd_alloc_mmc(struct device* dev) |
| 1301 | { | ||
| 1302 | struct mmc_host* mmc; | ||
| 1303 | struct wbsd_host* host; | ||
| 1304 | |||
| 1305 | /* | ||
| 1306 | * Allocate MMC structure. | ||
| 1307 | */ | ||
| 1308 | mmc = mmc_alloc_host(sizeof(struct wbsd_host), dev); | ||
| 1309 | if (!mmc) | ||
| 1310 | return -ENOMEM; | ||
| 1311 | |||
| 1312 | host = mmc_priv(mmc); | ||
| 1313 | host->mmc = mmc; | ||
| 1314 | |||
| 1315 | host->dma = -1; | ||
| 1316 | |||
| 1317 | /* | ||
| 1318 | * Set host parameters. | ||
| 1319 | */ | ||
| 1320 | mmc->ops = &wbsd_ops; | ||
| 1321 | mmc->f_min = 375000; | ||
| 1322 | mmc->f_max = 24000000; | ||
| 1323 | mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34; | ||
| 1324 | |||
| 1325 | spin_lock_init(&host->lock); | ||
| 1326 | |||
| 1327 | /* | ||
| 1328 | * Maximum number of segments. Worst case is one sector per segment | ||
| 1329 | * so this will be 64kB/512. | ||
| 1330 | */ | ||
| 1331 | mmc->max_hw_segs = 128; | ||
| 1332 | mmc->max_phys_segs = 128; | ||
| 1333 | |||
| 1334 | /* | ||
| 1335 | * Maximum number of sectors in one transfer. Also limited by 64kB | ||
| 1336 | * buffer. | ||
| 1337 | */ | ||
| 1338 | mmc->max_sectors = 128; | ||
| 1339 | |||
| 1340 | /* | ||
| 1341 | * Maximum segment size. Could be one segment with the maximum number | ||
| 1342 | * of segments. | ||
| 1343 | */ | ||
| 1344 | mmc->max_seg_size = mmc->max_sectors * 512; | ||
| 1345 | |||
| 1346 | dev_set_drvdata(dev, mmc); | ||
| 1347 | |||
| 1348 | return 0; | ||
| 1349 | } | ||
| 1350 | |||
| 1351 | static void __devexit wbsd_free_mmc(struct device* dev) | ||
| 1352 | { | ||
| 1353 | struct mmc_host* mmc; | ||
| 1354 | |||
| 1355 | mmc = dev_get_drvdata(dev); | ||
| 1356 | if (!mmc) | ||
| 1357 | return; | ||
| 1358 | |||
| 1359 | mmc_free_host(mmc); | ||
| 1360 | |||
| 1361 | dev_set_drvdata(dev, NULL); | ||
| 1362 | } | ||
| 1363 | |||
| 1364 | /* | ||
| 1365 | * Scan for known chip id:s | ||
| 1366 | */ | ||
| 1367 | |||
| 1368 | static int __devinit wbsd_scan(struct wbsd_host* host) | ||
| 1208 | { | 1369 | { |
| 1209 | int i, j, k; | 1370 | int i, j, k; |
| 1210 | int id; | 1371 | int id; |
| @@ -1258,12 +1419,16 @@ static int wbsd_scan(struct wbsd_host* host) | |||
| 1258 | return -ENODEV; | 1419 | return -ENODEV; |
| 1259 | } | 1420 | } |
| 1260 | 1421 | ||
| 1261 | static int wbsd_request_regions(struct wbsd_host* host) | 1422 | /* |
| 1423 | * Allocate/free io port ranges | ||
| 1424 | */ | ||
| 1425 | |||
| 1426 | static int __devinit wbsd_request_region(struct wbsd_host* host, int base) | ||
| 1262 | { | 1427 | { |
| 1263 | if (io & 0x7) | 1428 | if (io & 0x7) |
| 1264 | return -EINVAL; | 1429 | return -EINVAL; |
| 1265 | 1430 | ||
| 1266 | if (!request_region(io, 8, DRIVER_NAME)) | 1431 | if (!request_region(base, 8, DRIVER_NAME)) |
| 1267 | return -EIO; | 1432 | return -EIO; |
| 1268 | 1433 | ||
| 1269 | host->base = io; | 1434 | host->base = io; |
| @@ -1271,19 +1436,25 @@ static int wbsd_request_regions(struct wbsd_host* host) | |||
| 1271 | return 0; | 1436 | return 0; |
| 1272 | } | 1437 | } |
| 1273 | 1438 | ||
| 1274 | static void wbsd_release_regions(struct wbsd_host* host) | 1439 | static void __devexit wbsd_release_regions(struct wbsd_host* host) |
| 1275 | { | 1440 | { |
| 1276 | if (host->base) | 1441 | if (host->base) |
| 1277 | release_region(host->base, 8); | 1442 | release_region(host->base, 8); |
| 1443 | |||
| 1444 | host->base = 0; | ||
| 1278 | 1445 | ||
| 1279 | if (host->config) | 1446 | if (host->config) |
| 1280 | release_region(host->config, 2); | 1447 | release_region(host->config, 2); |
| 1448 | |||
| 1449 | host->config = 0; | ||
| 1281 | } | 1450 | } |
| 1282 | 1451 | ||
| 1283 | static void wbsd_init_dma(struct wbsd_host* host) | 1452 | /* |
| 1453 | * Allocate/free DMA port and buffer | ||
| 1454 | */ | ||
| 1455 | |||
| 1456 | static void __devinit wbsd_request_dma(struct wbsd_host* host, int dma) | ||
| 1284 | { | 1457 | { |
| 1285 | host->dma = -1; | ||
| 1286 | |||
| 1287 | if (dma < 0) | 1458 | if (dma < 0) |
| 1288 | return; | 1459 | return; |
| 1289 | 1460 | ||
| @@ -1294,7 +1465,7 @@ static void wbsd_init_dma(struct wbsd_host* host) | |||
| 1294 | * We need to allocate a special buffer in | 1465 | * We need to allocate a special buffer in |
| 1295 | * order for ISA to be able to DMA to it. | 1466 | * order for ISA to be able to DMA to it. |
| 1296 | */ | 1467 | */ |
| 1297 | host->dma_buffer = kmalloc(65536, | 1468 | host->dma_buffer = kmalloc(WBSD_DMA_SIZE, |
| 1298 | GFP_NOIO | GFP_DMA | __GFP_REPEAT | __GFP_NOWARN); | 1469 | GFP_NOIO | GFP_DMA | __GFP_REPEAT | __GFP_NOWARN); |
| 1299 | if (!host->dma_buffer) | 1470 | if (!host->dma_buffer) |
| 1300 | goto free; | 1471 | goto free; |
| @@ -1302,7 +1473,8 @@ static void wbsd_init_dma(struct wbsd_host* host) | |||
| 1302 | /* | 1473 | /* |
| 1303 | * Translate the address to a physical address. | 1474 | * Translate the address to a physical address. |
| 1304 | */ | 1475 | */ |
| 1305 | host->dma_addr = isa_virt_to_bus(host->dma_buffer); | 1476 | host->dma_addr = dma_map_single(host->mmc->dev, host->dma_buffer, |
| 1477 | WBSD_DMA_SIZE, DMA_BIDIRECTIONAL); | ||
| 1306 | 1478 | ||
| 1307 | /* | 1479 | /* |
| 1308 | * ISA DMA must be aligned on a 64k basis. | 1480 | * ISA DMA must be aligned on a 64k basis. |
| @@ -1325,6 +1497,10 @@ kfree: | |||
| 1325 | */ | 1497 | */ |
| 1326 | BUG_ON(1); | 1498 | BUG_ON(1); |
| 1327 | 1499 | ||
| 1500 | dma_unmap_single(host->mmc->dev, host->dma_addr, WBSD_DMA_SIZE, | ||
| 1501 | DMA_BIDIRECTIONAL); | ||
| 1502 | host->dma_addr = (dma_addr_t)NULL; | ||
| 1503 | |||
| 1328 | kfree(host->dma_buffer); | 1504 | kfree(host->dma_buffer); |
| 1329 | host->dma_buffer = NULL; | 1505 | host->dma_buffer = NULL; |
| 1330 | 1506 | ||
| @@ -1336,60 +1512,122 @@ err: | |||
| 1336 | "Falling back on FIFO.\n", dma); | 1512 | "Falling back on FIFO.\n", dma); |
| 1337 | } | 1513 | } |
| 1338 | 1514 | ||
| 1339 | static struct mmc_host_ops wbsd_ops = { | 1515 | static void __devexit wbsd_release_dma(struct wbsd_host* host) |
| 1340 | .request = wbsd_request, | 1516 | { |
| 1341 | .set_ios = wbsd_set_ios, | 1517 | if (host->dma_addr) |
| 1342 | }; | 1518 | dma_unmap_single(host->mmc->dev, host->dma_addr, WBSD_DMA_SIZE, |
| 1519 | DMA_BIDIRECTIONAL); | ||
| 1520 | if (host->dma_buffer) | ||
| 1521 | kfree(host->dma_buffer); | ||
| 1522 | if (host->dma >= 0) | ||
| 1523 | free_dma(host->dma); | ||
| 1524 | |||
| 1525 | host->dma = -1; | ||
| 1526 | host->dma_buffer = NULL; | ||
| 1527 | host->dma_addr = (dma_addr_t)NULL; | ||
| 1528 | } | ||
| 1343 | 1529 | ||
| 1344 | /* | 1530 | /* |
| 1345 | * Device probe | 1531 | * Allocate/free IRQ. |
| 1346 | */ | 1532 | */ |
| 1347 | 1533 | ||
| 1348 | static int wbsd_probe(struct device* dev) | 1534 | static int __devinit wbsd_request_irq(struct wbsd_host* host, int irq) |
| 1349 | { | 1535 | { |
| 1350 | struct wbsd_host* host = NULL; | ||
| 1351 | struct mmc_host* mmc = NULL; | ||
| 1352 | int ret; | 1536 | int ret; |
| 1353 | 1537 | ||
| 1354 | /* | 1538 | /* |
| 1355 | * Allocate MMC structure. | 1539 | * Allocate interrupt. |
| 1356 | */ | 1540 | */ |
| 1357 | mmc = mmc_alloc_host(sizeof(struct wbsd_host), dev); | 1541 | |
| 1358 | if (!mmc) | 1542 | ret = request_irq(irq, wbsd_irq, SA_SHIRQ, DRIVER_NAME, host); |
| 1359 | return -ENOMEM; | 1543 | if (ret) |
| 1360 | 1544 | return ret; | |
| 1361 | host = mmc_priv(mmc); | ||
| 1362 | host->mmc = mmc; | ||
| 1363 | 1545 | ||
| 1546 | host->irq = irq; | ||
| 1547 | |||
| 1364 | /* | 1548 | /* |
| 1365 | * Scan for hardware. | 1549 | * Set up tasklets. |
| 1366 | */ | 1550 | */ |
| 1367 | ret = wbsd_scan(host); | 1551 | tasklet_init(&host->card_tasklet, wbsd_tasklet_card, (unsigned long)host); |
| 1368 | if (ret) | 1552 | tasklet_init(&host->fifo_tasklet, wbsd_tasklet_fifo, (unsigned long)host); |
| 1369 | goto freemmc; | 1553 | tasklet_init(&host->crc_tasklet, wbsd_tasklet_crc, (unsigned long)host); |
| 1554 | tasklet_init(&host->timeout_tasklet, wbsd_tasklet_timeout, (unsigned long)host); | ||
| 1555 | tasklet_init(&host->finish_tasklet, wbsd_tasklet_finish, (unsigned long)host); | ||
| 1556 | tasklet_init(&host->block_tasklet, wbsd_tasklet_block, (unsigned long)host); | ||
| 1557 | |||
| 1558 | return 0; | ||
| 1559 | } | ||
| 1370 | 1560 | ||
| 1371 | /* | 1561 | static void __devexit wbsd_release_irq(struct wbsd_host* host) |
| 1372 | * Reset the chip. | 1562 | { |
| 1373 | */ | 1563 | if (!host->irq) |
| 1374 | wbsd_write_config(host, WBSD_CONF_SWRST, 1); | 1564 | return; |
| 1375 | wbsd_write_config(host, WBSD_CONF_SWRST, 0); | ||
| 1376 | 1565 | ||
| 1566 | free_irq(host->irq, host); | ||
| 1567 | |||
| 1568 | host->irq = 0; | ||
| 1569 | |||
| 1570 | tasklet_kill(&host->card_tasklet); | ||
| 1571 | tasklet_kill(&host->fifo_tasklet); | ||
| 1572 | tasklet_kill(&host->crc_tasklet); | ||
| 1573 | tasklet_kill(&host->timeout_tasklet); | ||
| 1574 | tasklet_kill(&host->finish_tasklet); | ||
| 1575 | tasklet_kill(&host->block_tasklet); | ||
| 1576 | } | ||
| 1577 | |||
| 1578 | /* | ||
| 1579 | * Allocate all resources for the host. | ||
| 1580 | */ | ||
| 1581 | |||
| 1582 | static int __devinit wbsd_request_resources(struct wbsd_host* host, | ||
| 1583 | int base, int irq, int dma) | ||
| 1584 | { | ||
| 1585 | int ret; | ||
| 1586 | |||
| 1377 | /* | 1587 | /* |
| 1378 | * Allocate I/O ports. | 1588 | * Allocate I/O ports. |
| 1379 | */ | 1589 | */ |
| 1380 | ret = wbsd_request_regions(host); | 1590 | ret = wbsd_request_region(host, base); |
| 1381 | if (ret) | 1591 | if (ret) |
| 1382 | goto release; | 1592 | return ret; |
| 1383 | 1593 | ||
| 1384 | /* | 1594 | /* |
| 1385 | * Set host parameters. | 1595 | * Allocate interrupt. |
| 1386 | */ | 1596 | */ |
| 1387 | mmc->ops = &wbsd_ops; | 1597 | ret = wbsd_request_irq(host, irq); |
| 1388 | mmc->f_min = 375000; | 1598 | if (ret) |
| 1389 | mmc->f_max = 24000000; | 1599 | return ret; |
| 1390 | mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34; | 1600 | |
| 1601 | /* | ||
| 1602 | * Allocate DMA. | ||
| 1603 | */ | ||
| 1604 | wbsd_request_dma(host, dma); | ||
| 1391 | 1605 | ||
| 1392 | spin_lock_init(&host->lock); | 1606 | return 0; |
| 1607 | } | ||
| 1608 | |||
| 1609 | /* | ||
| 1610 | * Release all resources for the host. | ||
| 1611 | */ | ||
| 1612 | |||
| 1613 | static void __devexit wbsd_release_resources(struct wbsd_host* host) | ||
| 1614 | { | ||
| 1615 | wbsd_release_dma(host); | ||
| 1616 | wbsd_release_irq(host); | ||
| 1617 | wbsd_release_regions(host); | ||
| 1618 | } | ||
| 1619 | |||
| 1620 | /* | ||
| 1621 | * Configure the resources the chip should use. | ||
| 1622 | */ | ||
| 1623 | |||
| 1624 | static void __devinit wbsd_chip_config(struct wbsd_host* host) | ||
| 1625 | { | ||
| 1626 | /* | ||
| 1627 | * Reset the chip. | ||
| 1628 | */ | ||
| 1629 | wbsd_write_config(host, WBSD_CONF_SWRST, 1); | ||
| 1630 | wbsd_write_config(host, WBSD_CONF_SWRST, 0); | ||
| 1393 | 1631 | ||
| 1394 | /* | 1632 | /* |
| 1395 | * Select SD/MMC function. | 1633 | * Select SD/MMC function. |
| @@ -1399,165 +1637,241 @@ static int wbsd_probe(struct device* dev) | |||
| 1399 | /* | 1637 | /* |
| 1400 | * Set up card detection. | 1638 | * Set up card detection. |
| 1401 | */ | 1639 | */ |
| 1402 | wbsd_write_config(host, WBSD_CONF_PINS, 0x02); | 1640 | wbsd_write_config(host, WBSD_CONF_PINS, WBSD_PINS_DETECT_GP11); |
| 1403 | 1641 | ||
| 1404 | /* | 1642 | /* |
| 1405 | * Configure I/O port. | 1643 | * Configure chip |
| 1406 | */ | 1644 | */ |
| 1407 | wbsd_write_config(host, WBSD_CONF_PORT_HI, host->base >> 8); | 1645 | wbsd_write_config(host, WBSD_CONF_PORT_HI, host->base >> 8); |
| 1408 | wbsd_write_config(host, WBSD_CONF_PORT_LO, host->base & 0xff); | 1646 | wbsd_write_config(host, WBSD_CONF_PORT_LO, host->base & 0xff); |
| 1409 | |||
| 1410 | /* | ||
| 1411 | * Allocate interrupt. | ||
| 1412 | */ | ||
| 1413 | ret = request_irq(irq, wbsd_irq, SA_SHIRQ, DRIVER_NAME, host); | ||
| 1414 | if (ret) | ||
| 1415 | goto release; | ||
| 1416 | 1647 | ||
| 1417 | host->irq = irq; | 1648 | wbsd_write_config(host, WBSD_CONF_IRQ, host->irq); |
| 1418 | 1649 | ||
| 1419 | /* | 1650 | if (host->dma >= 0) |
| 1420 | * Set up tasklets. | 1651 | wbsd_write_config(host, WBSD_CONF_DRQ, host->dma); |
| 1421 | */ | ||
| 1422 | tasklet_init(&host->card_tasklet, wbsd_tasklet_card, (unsigned long)host); | ||
| 1423 | tasklet_init(&host->fifo_tasklet, wbsd_tasklet_fifo, (unsigned long)host); | ||
| 1424 | tasklet_init(&host->crc_tasklet, wbsd_tasklet_crc, (unsigned long)host); | ||
| 1425 | tasklet_init(&host->timeout_tasklet, wbsd_tasklet_timeout, (unsigned long)host); | ||
| 1426 | tasklet_init(&host->finish_tasklet, wbsd_tasklet_finish, (unsigned long)host); | ||
| 1427 | tasklet_init(&host->block_tasklet, wbsd_tasklet_block, (unsigned long)host); | ||
| 1428 | 1652 | ||
| 1429 | /* | 1653 | /* |
| 1430 | * Configure interrupt. | 1654 | * Enable and power up chip. |
| 1431 | */ | 1655 | */ |
| 1432 | wbsd_write_config(host, WBSD_CONF_IRQ, host->irq); | 1656 | wbsd_write_config(host, WBSD_CONF_ENABLE, 1); |
| 1657 | wbsd_write_config(host, WBSD_CONF_POWER, 0x20); | ||
| 1658 | } | ||
| 1659 | |||
| 1660 | /* | ||
| 1661 | * Check that configured resources are correct. | ||
| 1662 | */ | ||
| 1663 | |||
| 1664 | static int __devinit wbsd_chip_validate(struct wbsd_host* host) | ||
| 1665 | { | ||
| 1666 | int base, irq, dma; | ||
| 1433 | 1667 | ||
| 1434 | /* | 1668 | /* |
| 1435 | * Allocate DMA. | 1669 | * Select SD/MMC function. |
| 1436 | */ | 1670 | */ |
| 1437 | wbsd_init_dma(host); | 1671 | wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD); |
| 1438 | 1672 | ||
| 1439 | /* | 1673 | /* |
| 1440 | * If all went well, then configure DMA. | 1674 | * Read configuration. |
| 1441 | */ | 1675 | */ |
| 1442 | if (host->dma >= 0) | 1676 | base = wbsd_read_config(host, WBSD_CONF_PORT_HI) << 8; |
| 1443 | wbsd_write_config(host, WBSD_CONF_DRQ, host->dma); | 1677 | base |= wbsd_read_config(host, WBSD_CONF_PORT_LO); |
| 1444 | 1678 | ||
| 1445 | /* | 1679 | irq = wbsd_read_config(host, WBSD_CONF_IRQ); |
| 1446 | * Maximum number of segments. Worst case is one sector per segment | 1680 | |
| 1447 | * so this will be 64kB/512. | 1681 | dma = wbsd_read_config(host, WBSD_CONF_DRQ); |
| 1448 | */ | ||
| 1449 | mmc->max_hw_segs = 128; | ||
| 1450 | mmc->max_phys_segs = 128; | ||
| 1451 | 1682 | ||
| 1452 | /* | 1683 | /* |
| 1453 | * Maximum number of sectors in one transfer. Also limited by 64kB | 1684 | * Validate against given configuration. |
| 1454 | * buffer. | ||
| 1455 | */ | 1685 | */ |
| 1456 | mmc->max_sectors = 128; | 1686 | if (base != host->base) |
| 1687 | return 0; | ||
| 1688 | if (irq != host->irq) | ||
| 1689 | return 0; | ||
| 1690 | if ((dma != host->dma) && (host->dma != -1)) | ||
| 1691 | return 0; | ||
| 1692 | |||
| 1693 | return 1; | ||
| 1694 | } | ||
| 1695 | |||
| 1696 | /*****************************************************************************\ | ||
| 1697 | * * | ||
| 1698 | * Devices setup and shutdown * | ||
| 1699 | * * | ||
| 1700 | \*****************************************************************************/ | ||
| 1701 | |||
| 1702 | static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma, | ||
| 1703 | int pnp) | ||
| 1704 | { | ||
| 1705 | struct wbsd_host* host = NULL; | ||
| 1706 | struct mmc_host* mmc = NULL; | ||
| 1707 | int ret; | ||
| 1708 | |||
| 1709 | ret = wbsd_alloc_mmc(dev); | ||
| 1710 | if (ret) | ||
| 1711 | return ret; | ||
| 1712 | |||
| 1713 | mmc = dev_get_drvdata(dev); | ||
| 1714 | host = mmc_priv(mmc); | ||
| 1457 | 1715 | ||
| 1458 | /* | 1716 | /* |
| 1459 | * Maximum segment size. Could be one segment with the maximum number | 1717 | * Scan for hardware. |
| 1460 | * of segments. | ||
| 1461 | */ | 1718 | */ |
| 1462 | mmc->max_seg_size = mmc->max_sectors * 512; | 1719 | ret = wbsd_scan(host); |
| 1720 | if (ret) | ||
| 1721 | { | ||
| 1722 | if (pnp && (ret == -ENODEV)) | ||
| 1723 | { | ||
| 1724 | printk(KERN_WARNING DRIVER_NAME | ||
| 1725 | ": Unable to confirm device presence. You may " | ||
| 1726 | "experience lock-ups.\n"); | ||
| 1727 | } | ||
| 1728 | else | ||
| 1729 | { | ||
| 1730 | wbsd_free_mmc(dev); | ||
| 1731 | return ret; | ||
| 1732 | } | ||
| 1733 | } | ||
| 1463 | 1734 | ||
| 1464 | /* | 1735 | /* |
| 1465 | * Enable chip. | 1736 | * Request resources. |
| 1466 | */ | 1737 | */ |
| 1467 | wbsd_write_config(host, WBSD_CONF_ENABLE, 1); | 1738 | ret = wbsd_request_resources(host, io, irq, dma); |
| 1739 | if (ret) | ||
| 1740 | { | ||
| 1741 | wbsd_release_resources(host); | ||
| 1742 | wbsd_free_mmc(dev); | ||
| 1743 | return ret; | ||
| 1744 | } | ||
| 1468 | 1745 | ||
| 1469 | /* | 1746 | /* |
| 1470 | * Power up chip. | 1747 | * See if chip needs to be configured. |
| 1471 | */ | 1748 | */ |
| 1472 | wbsd_write_config(host, WBSD_CONF_POWER, 0x20); | 1749 | if (pnp && (host->config != 0)) |
| 1750 | { | ||
| 1751 | if (!wbsd_chip_validate(host)) | ||
| 1752 | { | ||
| 1753 | printk(KERN_WARNING DRIVER_NAME | ||
| 1754 | ": PnP active but chip not configured! " | ||
| 1755 | "You probably have a buggy BIOS. " | ||
| 1756 | "Configuring chip manually.\n"); | ||
| 1757 | wbsd_chip_config(host); | ||
| 1758 | } | ||
| 1759 | } | ||
| 1760 | else | ||
| 1761 | wbsd_chip_config(host); | ||
| 1473 | 1762 | ||
| 1474 | /* | 1763 | /* |
| 1475 | * Power Management stuff. No idea how this works. | 1764 | * Power Management stuff. No idea how this works. |
| 1476 | * Not tested. | 1765 | * Not tested. |
| 1477 | */ | 1766 | */ |
| 1478 | #ifdef CONFIG_PM | 1767 | #ifdef CONFIG_PM |
| 1479 | wbsd_write_config(host, WBSD_CONF_PME, 0xA0); | 1768 | if (host->config) |
| 1769 | wbsd_write_config(host, WBSD_CONF_PME, 0xA0); | ||
| 1480 | #endif | 1770 | #endif |
| 1771 | /* | ||
| 1772 | * Allow device to initialise itself properly. | ||
| 1773 | */ | ||
| 1774 | mdelay(5); | ||
| 1481 | 1775 | ||
| 1482 | /* | 1776 | /* |
| 1483 | * Reset the chip into a known state. | 1777 | * Reset the chip into a known state. |
| 1484 | */ | 1778 | */ |
| 1485 | wbsd_init_device(host); | 1779 | wbsd_init_device(host); |
| 1486 | 1780 | ||
| 1487 | dev_set_drvdata(dev, mmc); | ||
| 1488 | |||
| 1489 | /* | ||
| 1490 | * Add host to MMC layer. | ||
| 1491 | */ | ||
| 1492 | mmc_add_host(mmc); | 1781 | mmc_add_host(mmc); |
| 1493 | 1782 | ||
| 1494 | printk(KERN_INFO "%s: W83L51xD id %x at 0x%x irq %d dma %d\n", | 1783 | printk(KERN_INFO "%s: W83L51xD", mmc->host_name); |
| 1495 | mmc->host_name, (int)host->chip_id, (int)host->base, | 1784 | if (host->chip_id != 0) |
| 1496 | (int)host->irq, (int)host->dma); | 1785 | printk(" id %x", (int)host->chip_id); |
| 1786 | printk(" at 0x%x irq %d", (int)host->base, (int)host->irq); | ||
| 1787 | if (host->dma >= 0) | ||
| 1788 | printk(" dma %d", (int)host->dma); | ||
| 1789 | else | ||
| 1790 | printk(" FIFO"); | ||
| 1791 | if (pnp) | ||
| 1792 | printk(" PnP"); | ||
| 1793 | printk("\n"); | ||
| 1497 | 1794 | ||
| 1498 | return 0; | 1795 | return 0; |
| 1499 | |||
| 1500 | release: | ||
| 1501 | wbsd_release_regions(host); | ||
| 1502 | |||
| 1503 | freemmc: | ||
| 1504 | mmc_free_host(mmc); | ||
| 1505 | |||
| 1506 | return ret; | ||
| 1507 | } | 1796 | } |
| 1508 | 1797 | ||
| 1509 | /* | 1798 | static void __devexit wbsd_shutdown(struct device* dev, int pnp) |
| 1510 | * Device remove | ||
| 1511 | */ | ||
| 1512 | |||
| 1513 | static int wbsd_remove(struct device* dev) | ||
| 1514 | { | 1799 | { |
| 1515 | struct mmc_host* mmc = dev_get_drvdata(dev); | 1800 | struct mmc_host* mmc = dev_get_drvdata(dev); |
| 1516 | struct wbsd_host* host; | 1801 | struct wbsd_host* host; |
| 1517 | 1802 | ||
| 1518 | if (!mmc) | 1803 | if (!mmc) |
| 1519 | return 0; | 1804 | return; |
| 1520 | 1805 | ||
| 1521 | host = mmc_priv(mmc); | 1806 | host = mmc_priv(mmc); |
| 1522 | 1807 | ||
| 1523 | /* | ||
| 1524 | * Unregister host with MMC layer. | ||
| 1525 | */ | ||
| 1526 | mmc_remove_host(mmc); | 1808 | mmc_remove_host(mmc); |
| 1527 | 1809 | ||
| 1528 | /* | 1810 | if (!pnp) |
| 1529 | * Power down the SD/MMC function. | 1811 | { |
| 1530 | */ | 1812 | /* |
| 1531 | wbsd_unlock_config(host); | 1813 | * Power down the SD/MMC function. |
| 1532 | wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD); | 1814 | */ |
| 1533 | wbsd_write_config(host, WBSD_CONF_ENABLE, 0); | 1815 | wbsd_unlock_config(host); |
| 1534 | wbsd_lock_config(host); | 1816 | wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD); |
| 1817 | wbsd_write_config(host, WBSD_CONF_ENABLE, 0); | ||
| 1818 | wbsd_lock_config(host); | ||
| 1819 | } | ||
| 1535 | 1820 | ||
| 1536 | /* | 1821 | wbsd_release_resources(host); |
| 1537 | * Free resources. | ||
| 1538 | */ | ||
| 1539 | if (host->dma_buffer) | ||
| 1540 | kfree(host->dma_buffer); | ||
| 1541 | 1822 | ||
| 1542 | if (host->dma >= 0) | 1823 | wbsd_free_mmc(dev); |
| 1543 | free_dma(host->dma); | 1824 | } |
| 1544 | 1825 | ||
| 1545 | free_irq(host->irq, host); | 1826 | /* |
| 1827 | * Non-PnP | ||
| 1828 | */ | ||
| 1829 | |||
| 1830 | static int __devinit wbsd_probe(struct device* dev) | ||
| 1831 | { | ||
| 1832 | return wbsd_init(dev, io, irq, dma, 0); | ||
| 1833 | } | ||
| 1834 | |||
| 1835 | static int __devexit wbsd_remove(struct device* dev) | ||
| 1836 | { | ||
| 1837 | wbsd_shutdown(dev, 0); | ||
| 1838 | |||
| 1839 | return 0; | ||
| 1840 | } | ||
| 1841 | |||
| 1842 | /* | ||
| 1843 | * PnP | ||
| 1844 | */ | ||
| 1845 | |||
| 1846 | #ifdef CONFIG_PNP | ||
| 1847 | |||
| 1848 | static int __devinit | ||
| 1849 | wbsd_pnp_probe(struct pnp_dev * pnpdev, const struct pnp_device_id *dev_id) | ||
| 1850 | { | ||
| 1851 | int io, irq, dma; | ||
| 1546 | 1852 | ||
| 1547 | tasklet_kill(&host->card_tasklet); | 1853 | /* |
| 1548 | tasklet_kill(&host->fifo_tasklet); | 1854 | * Get resources from PnP layer. |
| 1549 | tasklet_kill(&host->crc_tasklet); | 1855 | */ |
| 1550 | tasklet_kill(&host->timeout_tasklet); | 1856 | io = pnp_port_start(pnpdev, 0); |
| 1551 | tasklet_kill(&host->finish_tasklet); | 1857 | irq = pnp_irq(pnpdev, 0); |
| 1552 | tasklet_kill(&host->block_tasklet); | 1858 | if (pnp_dma_valid(pnpdev, 0)) |
| 1859 | dma = pnp_dma(pnpdev, 0); | ||
| 1860 | else | ||
| 1861 | dma = -1; | ||
| 1553 | 1862 | ||
| 1554 | wbsd_release_regions(host); | 1863 | DBGF("PnP resources: port %3x irq %d dma %d\n", io, irq, dma); |
| 1555 | 1864 | ||
| 1556 | mmc_free_host(mmc); | 1865 | return wbsd_init(&pnpdev->dev, io, irq, dma, 1); |
| 1866 | } | ||
| 1557 | 1867 | ||
| 1558 | return 0; | 1868 | static void __devexit wbsd_pnp_remove(struct pnp_dev * dev) |
| 1869 | { | ||
| 1870 | wbsd_shutdown(&dev->dev, 1); | ||
| 1559 | } | 1871 | } |
| 1560 | 1872 | ||
| 1873 | #endif /* CONFIG_PNP */ | ||
| 1874 | |||
| 1561 | /* | 1875 | /* |
| 1562 | * Power management | 1876 | * Power management |
| 1563 | */ | 1877 | */ |
| @@ -1581,17 +1895,7 @@ static int wbsd_resume(struct device *dev, u32 level) | |||
| 1581 | #define wbsd_resume NULL | 1895 | #define wbsd_resume NULL |
| 1582 | #endif | 1896 | #endif |
| 1583 | 1897 | ||
| 1584 | static void wbsd_release(struct device *dev) | 1898 | static struct platform_device *wbsd_device; |
| 1585 | { | ||
| 1586 | } | ||
| 1587 | |||
| 1588 | static struct platform_device wbsd_device = { | ||
| 1589 | .name = DRIVER_NAME, | ||
| 1590 | .id = -1, | ||
| 1591 | .dev = { | ||
| 1592 | .release = wbsd_release, | ||
| 1593 | }, | ||
| 1594 | }; | ||
| 1595 | 1899 | ||
| 1596 | static struct device_driver wbsd_driver = { | 1900 | static struct device_driver wbsd_driver = { |
| 1597 | .name = DRIVER_NAME, | 1901 | .name = DRIVER_NAME, |
| @@ -1603,6 +1907,17 @@ static struct device_driver wbsd_driver = { | |||
| 1603 | .resume = wbsd_resume, | 1907 | .resume = wbsd_resume, |
| 1604 | }; | 1908 | }; |
| 1605 | 1909 | ||
| 1910 | #ifdef CONFIG_PNP | ||
| 1911 | |||
| 1912 | static struct pnp_driver wbsd_pnp_driver = { | ||
| 1913 | .name = DRIVER_NAME, | ||
| 1914 | .id_table = pnp_dev_table, | ||
| 1915 | .probe = wbsd_pnp_probe, | ||
| 1916 | .remove = wbsd_pnp_remove, | ||
| 1917 | }; | ||
| 1918 | |||
| 1919 | #endif /* CONFIG_PNP */ | ||
| 1920 | |||
| 1606 | /* | 1921 | /* |
| 1607 | * Module loading/unloading | 1922 | * Module loading/unloading |
| 1608 | */ | 1923 | */ |
| @@ -1615,29 +1930,57 @@ static int __init wbsd_drv_init(void) | |||
| 1615 | ": Winbond W83L51xD SD/MMC card interface driver, " | 1930 | ": Winbond W83L51xD SD/MMC card interface driver, " |
| 1616 | DRIVER_VERSION "\n"); | 1931 | DRIVER_VERSION "\n"); |
| 1617 | printk(KERN_INFO DRIVER_NAME ": Copyright(c) Pierre Ossman\n"); | 1932 | printk(KERN_INFO DRIVER_NAME ": Copyright(c) Pierre Ossman\n"); |
| 1618 | |||
| 1619 | result = driver_register(&wbsd_driver); | ||
| 1620 | if (result < 0) | ||
| 1621 | return result; | ||
| 1622 | 1933 | ||
| 1623 | result = platform_device_register(&wbsd_device); | 1934 | #ifdef CONFIG_PNP |
| 1624 | if (result < 0) | 1935 | |
| 1625 | return result; | 1936 | if (!nopnp) |
| 1937 | { | ||
| 1938 | result = pnp_register_driver(&wbsd_pnp_driver); | ||
| 1939 | if (result < 0) | ||
| 1940 | return result; | ||
| 1941 | } | ||
| 1942 | |||
| 1943 | #endif /* CONFIG_PNP */ | ||
| 1944 | |||
| 1945 | if (nopnp) | ||
| 1946 | { | ||
| 1947 | result = driver_register(&wbsd_driver); | ||
| 1948 | if (result < 0) | ||
| 1949 | return result; | ||
| 1950 | |||
| 1951 | wbsd_device = platform_device_register_simple(DRIVER_NAME, -1, | ||
| 1952 | NULL, 0); | ||
| 1953 | if (IS_ERR(wbsd_device)) | ||
| 1954 | return PTR_ERR(wbsd_device); | ||
| 1955 | } | ||
| 1626 | 1956 | ||
| 1627 | return 0; | 1957 | return 0; |
| 1628 | } | 1958 | } |
| 1629 | 1959 | ||
| 1630 | static void __exit wbsd_drv_exit(void) | 1960 | static void __exit wbsd_drv_exit(void) |
| 1631 | { | 1961 | { |
| 1632 | platform_device_unregister(&wbsd_device); | 1962 | #ifdef CONFIG_PNP |
| 1963 | |||
| 1964 | if (!nopnp) | ||
| 1965 | pnp_unregister_driver(&wbsd_pnp_driver); | ||
| 1633 | 1966 | ||
| 1634 | driver_unregister(&wbsd_driver); | 1967 | #endif /* CONFIG_PNP */ |
| 1968 | |||
| 1969 | if (nopnp) | ||
| 1970 | { | ||
| 1971 | platform_device_unregister(wbsd_device); | ||
| 1972 | |||
| 1973 | driver_unregister(&wbsd_driver); | ||
| 1974 | } | ||
| 1635 | 1975 | ||
| 1636 | DBG("unloaded\n"); | 1976 | DBG("unloaded\n"); |
| 1637 | } | 1977 | } |
| 1638 | 1978 | ||
| 1639 | module_init(wbsd_drv_init); | 1979 | module_init(wbsd_drv_init); |
| 1640 | module_exit(wbsd_drv_exit); | 1980 | module_exit(wbsd_drv_exit); |
| 1981 | #ifdef CONFIG_PNP | ||
| 1982 | module_param(nopnp, uint, 0444); | ||
| 1983 | #endif | ||
| 1641 | module_param(io, uint, 0444); | 1984 | module_param(io, uint, 0444); |
| 1642 | module_param(irq, uint, 0444); | 1985 | module_param(irq, uint, 0444); |
| 1643 | module_param(dma, int, 0444); | 1986 | module_param(dma, int, 0444); |
| @@ -1646,6 +1989,9 @@ MODULE_LICENSE("GPL"); | |||
| 1646 | MODULE_DESCRIPTION("Winbond W83L51xD SD/MMC card interface driver"); | 1989 | MODULE_DESCRIPTION("Winbond W83L51xD SD/MMC card interface driver"); |
| 1647 | MODULE_VERSION(DRIVER_VERSION); | 1990 | MODULE_VERSION(DRIVER_VERSION); |
| 1648 | 1991 | ||
| 1992 | #ifdef CONFIG_PNP | ||
| 1993 | MODULE_PARM_DESC(nopnp, "Scan for device instead of relying on PNP. (default 0)"); | ||
| 1994 | #endif | ||
| 1649 | MODULE_PARM_DESC(io, "I/O base to allocate. Must be 8 byte aligned. (default 0x248)"); | 1995 | MODULE_PARM_DESC(io, "I/O base to allocate. Must be 8 byte aligned. (default 0x248)"); |
| 1650 | MODULE_PARM_DESC(irq, "IRQ to allocate. (default 6)"); | 1996 | MODULE_PARM_DESC(irq, "IRQ to allocate. (default 6)"); |
| 1651 | MODULE_PARM_DESC(dma, "DMA channel to allocate. -1 for no DMA. (default 2)"); | 1997 | MODULE_PARM_DESC(dma, "DMA channel to allocate. -1 for no DMA. (default 2)"); |
diff --git a/drivers/mmc/wbsd.h b/drivers/mmc/wbsd.h index fdc03b56a81f..864f30828d01 100644 --- a/drivers/mmc/wbsd.h +++ b/drivers/mmc/wbsd.h | |||
| @@ -35,6 +35,12 @@ const int valid_ids[] = { | |||
| 35 | 35 | ||
| 36 | #define DEVICE_SD 0x03 | 36 | #define DEVICE_SD 0x03 |
| 37 | 37 | ||
| 38 | #define WBSD_PINS_DAT3_HI 0x20 | ||
| 39 | #define WBSD_PINS_DAT3_OUT 0x10 | ||
| 40 | #define WBSD_PINS_GP11_HI 0x04 | ||
| 41 | #define WBSD_PINS_DETECT_GP11 0x02 | ||
| 42 | #define WBSD_PINS_DETECT_DAT3 0x01 | ||
| 43 | |||
| 38 | #define WBSD_CMDR 0x00 | 44 | #define WBSD_CMDR 0x00 |
| 39 | #define WBSD_DFR 0x01 | 45 | #define WBSD_DFR 0x01 |
| 40 | #define WBSD_EIR 0x02 | 46 | #define WBSD_EIR 0x02 |
| @@ -133,6 +139,7 @@ const int valid_ids[] = { | |||
| 133 | #define WBSD_CRC_OK 0x05 /* S010E (00101) */ | 139 | #define WBSD_CRC_OK 0x05 /* S010E (00101) */ |
| 134 | #define WBSD_CRC_FAIL 0x0B /* S101E (01011) */ | 140 | #define WBSD_CRC_FAIL 0x0B /* S101E (01011) */ |
| 135 | 141 | ||
| 142 | #define WBSD_DMA_SIZE 65536 | ||
| 136 | 143 | ||
| 137 | struct wbsd_host | 144 | struct wbsd_host |
| 138 | { | 145 | { |
| @@ -140,6 +147,11 @@ struct wbsd_host | |||
| 140 | 147 | ||
| 141 | spinlock_t lock; /* Mutex */ | 148 | spinlock_t lock; /* Mutex */ |
| 142 | 149 | ||
| 150 | int flags; /* Driver states */ | ||
| 151 | |||
| 152 | #define WBSD_FCARD_PRESENT (1<<0) /* Card is present */ | ||
| 153 | #define WBSD_FIGNORE_DETECT (1<<1) /* Ignore card detection */ | ||
| 154 | |||
| 143 | struct mmc_request* mrq; /* Current request */ | 155 | struct mmc_request* mrq; /* Current request */ |
| 144 | 156 | ||
| 145 | u8 isr; /* Accumulated ISR */ | 157 | u8 isr; /* Accumulated ISR */ |
