Changeset 3686
- Timestamp:
- 12/19/07 11:03:34 (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/src/target/kernel/2.6.24.x/patches/s3c_mci.patch
r3676 r3686 1 1 This is the latest S3C MMC/SD driver by Thomas Kleffel 2 3 Signed-off-by: Harald Welte <laforge@openmoko.org> 2 4 3 5 Index: linux-2.6/include/asm-arm/arch-s3c2410/regs-sdi.h … … 72 74 #define S3C2410_SDIFSTA_RFFULL (1<<8) 73 75 #define S3C2410_SDIFSTA_RFHALF (1<<7) 74 Index: linux-2.6/drivers/mmc/host/mmc_debug.c75 ===================================================================76 --- /dev/null77 +++ linux-2.6/drivers/mmc/host/mmc_debug.c78 @@ -0,0 +1,57 @@79 +/*80 + * linux/drivers/mmc/mmc_debug.c81 + *82 + * Copyright (C) 2003 maintech GmbH, Thomas Kleffel <tk@maintech.de>83 + *84 + * This file contains debug helper functions for the MMC/SD stack85 + *86 + * This program is free software; you can redistribute it and/or modify87 + * it under the terms of the GNU General Public License version 2 as88 + * published by the Free Software Foundation.89 + *90 + */91 +92 +#include <linux/module.h>93 +#include <linux/mmc/core.h>94 +#include <linux/mmc/mmc.h>95 +#include "mmc_debug.h"96 +97 +char *mmc_cmd2str(int cmd)98 +{99 + switch(cmd) {100 + case 0: return "GO_IDLE_STATE";101 + case 1: return "ALL_SEND_OCR";102 + case 2: return "ALL_SEND_CID";103 + case 3: return "ALL_SEND_RELATIVE_ADD";104 + case 6: return "ACMD: SD_SET_BUSWIDTH";105 + case 7: return "SEL_DESEL_CARD";106 + case 9: return "SEND_CSD";107 + case 10: return "SEND_CID";108 + case 11: return "READ_UNTIL_STOP";109 + case 12: return "STOP_TRANSMISSION";110 + case 13: return "SEND_STATUS";111 + case 15: return "GO_INACTIVE_STATE";112 + case 16: return "SET_BLOCKLEN";113 + case 17: return "READ_SINGLE_BLOCK";114 + case 18: return "READ_MULTIPLE_BLOCK";115 + case 24: return "WRITE_SINGLE_BLOCK";116 + case 25: return "WRITE_MULTIPLE_BLOCK";117 + case 41: return "ACMD: SD_APP_OP_COND";118 + case 55: return "APP_CMD";119 + default: return "UNKNOWN";120 + }121 +}122 +EXPORT_SYMBOL(mmc_cmd2str);123 +124 +char *mmc_err2str(int err)125 +{126 + switch(err) {127 + case 0: return "OK";128 + case -ETIMEDOUT: return "TIMEOUT";129 + case -EILSEQ: return "BADCRC";130 + case -EINVAL: return "EINVAL";131 + case -ENOMEDIUM: return "NOMEDIUM";132 + default: return "UNKNOWN";133 + }134 +}135 +EXPORT_SYMBOL(mmc_err2str);136 Index: linux-2.6/drivers/mmc/host/mmc_debug.h137 ===================================================================138 --- /dev/null139 +++ linux-2.6/drivers/mmc/host/mmc_debug.h140 @@ -0,0 +1,7 @@141 +#ifndef MMC_DEBUG_H142 +#define MMC_DEBUG_H143 +144 +char *mmc_cmd2str(int err);145 +char *mmc_err2str(int err);146 +147 +#endif /* MMC_DEBUG_H */148 76 Index: linux-2.6/drivers/mmc/host/s3cmci.c 149 77 =================================================================== 150 78 --- /dev/null 151 79 +++ linux-2.6/drivers/mmc/host/s3cmci.c 152 @@ -0,0 +1,1 384@@80 @@ -0,0 +1,1409 @@ 153 81 +/* 154 82 + * linux/drivers/mmc/s3cmci.h - Samsung S3C MCI driver … … 178 106 +#include <asm/arch/mci.h> 179 107 + 180 +#include "mmc_debug.h"181 108 +#include "s3cmci.h" 182 109 + … … 200 127 + 201 128 +#define dbg(host, channels, args...) \ 129 + do { \ 202 130 + if (dbgmap_err & channels) \ 203 131 + dev_err(&host->pdev->dev, args); \ … … 205 133 + dev_info(&host->pdev->dev, args);\ 206 134 + else if (dbgmap_debug & channels) \ 207 + dev_dbg(&host->pdev->dev, args); 135 + dev_dbg(&host->pdev->dev, args); \ 136 + } while (0) 208 137 + 209 138 +#define RESSIZE(ressource) (((ressource)->end - (ressource)->start)+1) … … 218 147 + 219 148 +#ifdef CONFIG_MMC_DEBUG 149 + 150 +static char *mmc_cmd2str(int cmd) 151 +{ 152 + switch (cmd) { 153 + case 0: return "GO_IDLE_STATE"; 154 + case 1: return "ALL_SEND_OCR"; 155 + case 2: return "ALL_SEND_CID"; 156 + case 3: return "ALL_SEND_RELATIVE_ADD"; 157 + case 6: return "ACMD: SD_SET_BUSWIDTH"; 158 + case 7: return "SEL_DESEL_CARD"; 159 + case 9: return "SEND_CSD"; 160 + case 10: return "SEND_CID"; 161 + case 11: return "READ_UNTIL_STOP"; 162 + case 12: return "STOP_TRANSMISSION"; 163 + case 13: return "SEND_STATUS"; 164 + case 15: return "GO_INACTIVE_STATE"; 165 + case 16: return "SET_BLOCKLEN"; 166 + case 17: return "READ_SINGLE_BLOCK"; 167 + case 18: return "READ_MULTIPLE_BLOCK"; 168 + case 24: return "WRITE_SINGLE_BLOCK"; 169 + case 25: return "WRITE_MULTIPLE_BLOCK"; 170 + case 41: return "ACMD: SD_APP_OP_COND"; 171 + case 55: return "APP_CMD"; 172 + default: return "UNKNOWN"; 173 + } 174 +} 175 + 176 +static char *mmc_err2str(int err) 177 +{ 178 + switch (err) { 179 + case 0: return "OK"; 180 + case -ETIMEDOUT: return "TIMEOUT"; 181 + case -EILSEQ: return "BADCRC"; 182 + case -EINVAL: return "EINVAL"; 183 + case -ENOMEDIUM: return "NOMEDIUM"; 184 + default: return "UNKNOWN"; 185 + } 186 +} 220 187 + 221 188 +static inline void dbg_dumpregs(struct s3cmci_host *host, char *prefix) … … 259 226 + int stop) 260 227 +{ 261 + snprintf(host->dbgmsg_cmd, 300,228 + snprintf(host->dbgmsg_cmd, 300, 262 229 + "#%u%s op:%s(%i) arg:0x%08x flags:0x08%x retries:%u", 263 230 + host->ccnt, (stop?" (STOP)":""), mmc_cmd2str(cmd->opcode), … … 312 279 + 313 280 + newmask = readl(host->base + host->sdiimsk); 314 + newmask |= imask;281 + newmask |= imask; 315 282 + 316 283 + writel(newmask, host->base + host->sdiimsk); … … 324 291 + 325 292 + newmask = readl(host->base + host->sdiimsk); 326 + newmask &= ~imask;293 + newmask &= ~imask; 327 294 + 328 295 + writel(newmask, host->base + host->sdiimsk); … … 337 304 + 338 305 +static inline int get_data_buffer(struct s3cmci_host *host, 339 + volatile u32 *words, volatileu32 **pointer)306 + u32 *words, u32 **pointer) 340 307 +{ 341 308 + struct scatterlist *sg; … … 354 321 + sg = &host->mrq->data->sg[host->pio_sgptr]; 355 322 + 356 + *words = sg->length >> 2;357 + *pointer = page_address(sg_page(sg)) + sg->offset;323 + *words = sg->length >> 2; 324 + *pointer = page_address(sg_page(sg)) + sg->offset; 358 325 + 359 326 + host->pio_sgptr++; … … 365 332 +} 366 333 + 367 +#define FIFO_FILL(host) ((readl(host->base + S3C2410_SDIFSTA) & S3C2410_SDIFSTA_COUNTMASK) >> 2) 368 +#define FIFO_FREE(host) ((63 - (readl(host->base + S3C2410_SDIFSTA) & S3C2410_SDIFSTA_COUNTMASK)) >> 2) 334 +#define FIFO_FILL(host) ((readl(host->base + S3C2410_SDIFSTA) & \ 335 + S3C2410_SDIFSTA_COUNTMASK) >> 2) 336 +#define FIFO_FREE(host) ((63 - (readl(host->base + S3C2410_SDIFSTA) \ 337 + & S3C2410_SDIFSTA_COUNTMASK)) >> 2) 369 338 + 370 339 +static inline void do_pio_read(struct s3cmci_host *host) … … 374 343 + void __iomem *from_ptr; 375 344 + 376 + / /write real prescaler to host, it might be set slow to fix345 + /* write real prescaler to host, it might be set slow to fix */ 377 346 + writel(host->prescaler, host->base + S3C2410_SDIPRE); 378 347 + … … 388 357 + 389 358 + dbg(host, dbg_pio, "pio_read(): " 390 + "complete (no more data).\n");359 + "complete (no more data).\n"); 391 360 + return; 392 361 + } 393 362 + 394 + dbg(host, dbg_pio, "pio_read(): new target: [%i]@[%p]\n",395 + host->pio_words, host->pio_ptr);363 + dbg(host, dbg_pio, "pio_read(): new target: " 364 + "[%i]@[%p]\n", host->pio_words, host->pio_ptr); 396 365 + } 397 366 + 398 367 + dbg(host, dbg_pio, "pio_read(): fifo:[%02i] " 399 + "buffer:[%03i] dcnt:[%08X]\n", 400 + fifo, host->pio_words, 401 + readl(host->base + S3C2410_SDIDCNT)); 368 + "buffer:[%03i] dcnt:[%08X]\n", fifo, host->pio_words, 369 + readl(host->base + S3C2410_SDIDCNT)); 402 370 + 403 371 + if (fifo > host->pio_words) 404 372 + fifo = host->pio_words; 405 373 + 406 + host->pio_words -= fifo;407 + host->pio_count += fifo;408 + 409 + while (fifo--) {374 + host->pio_words -= fifo; 375 + host->pio_count += fifo; 376 + 377 + while (fifo--) 410 378 + *(host->pio_ptr++) = readl(from_ptr); 411 + }412 379 + } 413 380 + … … 416 383 + if (res) { 417 384 + dbg(host, dbg_pio, "pio_read(): " 418 + "complete (no more buffers).\n");385 + "complete (no more buffers).\n"); 419 386 + host->pio_active = XFER_NONE; 420 387 + host->complete_what = COMPLETION_FINALIZE; … … 424 391 + } 425 392 + 426 + enable_imask(host, S3C2410_SDIIMSK_RXFIFOHALF | S3C2410_SDIIMSK_RXFIFOLAST); 393 + enable_imask(host, S3C2410_SDIIMSK_RXFIFOHALF 394 + | S3C2410_SDIIMSK_RXFIFOLAST); 427 395 +} 428 396 + … … 457 425 + fifo = host->pio_words; 458 426 + 459 + host->pio_words -= fifo;460 + host->pio_count += fifo;461 + 462 + while (fifo--) {427 + host->pio_words -= fifo; 428 + host->pio_count += fifo; 429 + 430 + while (fifo--) 463 431 + writel(*(host->pio_ptr++), to_ptr); 464 + }465 432 + } 466 433 + … … 500 467 + * Communication between driver and ISR works as follows: 501 468 + * host->mrq points to current request 502 + * host->complete_what tells theISR when the request is considered done469 + * host->complete_what tells ISR when the request is considered done 503 470 + * COMPLETION_CMDSENT when the command was sent 504 471 + * COMPLETION_RSPFIN when a response was received … … 576 543 + (mci_fsta & S3C2410_SDIFSTA_RFDET)) { 577 544 + 578 + disable_imask(host, 579 + S3C2410_SDIIMSK_RXFIFOHALF |S3C2410_SDIIMSK_RXFIFOLAST);545 + disable_imask(host, S3C2410_SDIIMSK_RXFIFOHALF | 546 + S3C2410_SDIIMSK_RXFIFOLAST); 580 547 + 581 548 + tasklet_schedule(&host->pio_tasklet); … … 671 638 + } 672 639 + 673 + if (host->complete_what == COMPLETION_XFERFINISH_RSPFIN) {640 + if (host->complete_what == COMPLETION_XFERFINISH_RSPFIN) 674 641 + host->complete_what = COMPLETION_RSPFIN; 675 + }676 642 + 677 643 + mci_dclear |= S3C2410_SDIDSTA_XFERFINISH; … … 799 765 + } 800 766 + 801 + / / Read response767 + /* Read response */ 802 768 + cmd->resp[0] = readl(host->base + S3C2410_SDIRSP0); 803 769 + cmd->resp[1] = readl(host->base + S3C2410_SDIRSP1); … … 805 771 + cmd->resp[3] = readl(host->base + S3C2410_SDIRSP3); 806 772 + 807 + / / reset clock speed, as it could still be set low for773 + /* reset clock speed, as it could still be set low for */ 808 774 + writel(host->prescaler, host->base + S3C2410_SDIPRE); 809 775 + … … 813 779 + if (cmd->data && cmd->data->error) 814 780 + debug_as_failure = 1; 815 +816 + //if(cmd->flags & MMC_RSP_MAYFAIL) debug_as_failure = 0;817 781 + 818 782 +#ifdef CONFIG_MMC_DEBUG 819 783 + dbg_dumpcmd(host, cmd, debug_as_failure); 820 784 +#endif 821 + / /Cleanup controller785 + /* Cleanup controller */ 822 786 + writel(0, host->base + S3C2410_SDICMDARG); 823 787 + writel(S3C2410_SDIDCON_STOP, host->base + S3C2410_SDIDCON); … … 834 798 + } 835 799 + 836 + / / If we have no data transfer we are finished here800 + /* If we have no data transfer we are finished here */ 837 801 + if (!mrq->data) 838 802 + goto request_done; 839 803 + 840 + / /Calulate the amout of bytes transfer, but only if there was841 + // no error842 + if (mrq->data->error == 0) {804 + /* Calulate the amout of bytes transfer, but only if there was 805 + * no error */ 806 + if (mrq->data->error == 0) 843 807 + mrq->data->bytes_xfered = 844 808 + (mrq->data->blocks * mrq->data->blksz); 845 + } else {809 + else 846 810 + mrq->data->bytes_xfered = 0; 847 + } 848 + 849 + // If we had an error while transfering data we flush the 850 + // DMA channel and the fifo to clear out any garbage 811 + 812 + /* If we had an error while transfering data we flush the 813 + * DMA channel and the fifo to clear out any garbage */ 851 814 + if (mrq->data->error) { 852 815 + if (host->dodma) … … 854 817 + 855 818 + if (host->is2440) { 856 + / /Clear failure register and reset fifo819 + /* Clear failure register and reset fifo */ 857 820 + writel(S3C2440_SDIFSTA_FIFORESET | 858 821 + S3C2440_SDIFSTA_FIFOFAIL, … … 861 824 + u32 mci_con; 862 825 + 863 + / /reset fifo826 + /* reset fifo */ 864 827 + mci_con = readl(host->base + S3C2410_SDICON); 865 + mci_con |= S3C2410_SDICON_FIFORESET;828 + mci_con |= S3C2410_SDICON_FIFORESET; 866 829 + 867 830 + writel(mci_con, host->base + S3C2410_SDICON); … … 878 841 +void s3cmci_dma_setup(struct s3cmci_host *host, enum s3c2410_dmasrc source) 879 842 +{ 880 + static int setup_ok = 0;843 + static int setup_ok; 881 844 + static enum s3c2410_dmasrc last_source = -1; 882 845 + … … 892 855 + s3c2410_dma_config(host->dma, 4, 893 856 + (S3C2410_DCON_HWTRIG | S3C2410_DCON_CH0_SDI)); 894 + s3c2410_dma_set_buffdone_fn(host->dma, s3cmci_dma_done_callback); 857 + s3c2410_dma_set_buffdone_fn(host->dma, 858 + s3cmci_dma_done_callback); 895 859 + s3c2410_dma_setflags(host->dma, S3C2410_DMAF_AUTOSTART); 896 860 + setup_ok = 1; … … 909 873 + enable_imask(host, imsk); 910 874 + 911 + if (cmd->data) {875 + if (cmd->data) 912 876 + host->complete_what = COMPLETION_XFERFINISH_RSPFIN; 913 + } else if (cmd->flags & MMC_RSP_PRESENT) {877 + else if (cmd->flags & MMC_RSP_PRESENT) 914 878 + host->complete_what = COMPLETION_RSPFIN; 915 + } else {879 + else 916 880 + host->complete_what = COMPLETION_CMDSENT; 917 + }918 881 + 919 882 + writel(cmd->arg, host->base + S3C2410_SDICMDARG); 920 883 + 921 884 + ccon = cmd->opcode & S3C2410_SDICMDCON_INDEX; 922 + ccon |= S3C2410_SDICMDCON_SENDERHOST | S3C2410_SDICMDCON_CMDSTART;885 + ccon |= S3C2410_SDICMDCON_SENDERHOST | S3C2410_SDICMDCON_CMDSTART; 923 886 + 924 887 + if (cmd->flags & MMC_RSP_PRESENT) … … 926 889 + 927 890 + if (cmd->flags & MMC_RSP_136) 928 + ccon |= S3C2410_SDICMDCON_LONGRSP;891 + ccon |= S3C2410_SDICMDCON_LONGRSP; 929 892 + 930 893 + writel(ccon, host->base + S3C2410_SDICMDCON); … … 933 896 +static int s3cmci_setup_data(struct s3cmci_host *host, struct mmc_data *data) 934 897 +{ 935 + u32 dcon, imsk, stoptries =3;898 + u32 dcon, imsk, stoptries = 3; 936 899 + 937 900 + /* write DCON register */ … … 942 905 + } 943 906 + 944 + while (readl(host->base + S3C2410_SDIDSTA) &907 + while (readl(host->base + S3C2410_SDIDSTA) & 945 908 + (S3C2410_SDIDSTA_TXDATAON | S3C2410_SDIDSTA_RXDATAON)) { 946 909 + 947 910 + dbg(host, dbg_err, 948 + "mci_setup_data() transfer stillin progress.\n");911 + "mci_setup_data() transfer stillin progress.\n"); 949 912 + 950 913 + writel(S3C2410_SDIDCON_STOP, host->base + S3C2410_SDIDCON); … … 962 925 + dcon = data->blocks & S3C2410_SDIDCON_BLKNUM_MASK; 963 926 + 964 + if (host->dodma) {927 + if (host->dodma) 965 928 + dcon |= S3C2410_SDIDCON_DMAEN; 966 + } 967 + 968 + if (host->bus_width == MMC_BUS_WIDTH_4) { 929 + 930 + if (host->bus_width == MMC_BUS_WIDTH_4) 969 931 + dcon |= S3C2410_SDIDCON_WIDEBUS; 970 + } 971 + 972 + if (!(data->flags & MMC_DATA_STREAM)) { 932 + 933 + if (!(data->flags & MMC_DATA_STREAM)) 973 934 + dcon |= S3C2410_SDIDCON_BLOCKMODE; 974 + }975 935 + 976 936 + if (data->flags & MMC_DATA_WRITE) { … … 1008 968 + writel(0x0000FFFF, host->base + S3C2410_SDITIMER); 1009 969 + 1010 + / /FIX: set slow clock to prevent timeouts on read1011 + if (data->flags & MMC_DATA_READ) {970 + /* FIX: set slow clock to prevent timeouts on read */ 971 + if (data->flags & MMC_DATA_READ) 1012 972 + writel(0xFF, host->base + S3C2410_SDIPRE); 1013 + } 1014 + } 1015 + 1016 + //debug_dump_registers(host, "Data setup:"); 973 + } 1017 974 + 1018 975 + return 0; … … 1079 1036 + return -EBUSY; 1080 1037 + } 1081 + }1038 + } 1082 1039 + 1083 1040 + s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_START); … … 1096 1053 + prepare_dbgmsg(host, cmd, host->cmd_is_stop); 1097 1054 +#endif 1098 + / /Clear command, data and fifo status registers1099 + //Fifo clear only necessary on 2440, but doesn't hurt on 24101055 + /* clear command, data and fifo status registers; 1056 + * Fifo clear only necessary on 2440, but doesn't hurt on 2410 */ 1100 1057 + writel(0xFFFFFFFF, host->base + S3C2410_SDICMDSTAT); 1101 1058 + writel(0xFFFFFFFF, host->base + S3C2410_SDIDSTA); … … 1117 1074 + 1118 1075 + 1119 + if (host->dodma) {1076 + if (host->dodma) 1120 1077 + res = s3cmci_prepare_dma(host, cmd->data); 1121 + } else {1078 + else 1122 1079 + res = s3cmci_prepare_pio(host, cmd->data); 1123 + }1124 1080 + 1125 1081 + if (res) { … … 1133 1089 + } 1134 1090 + 1135 + // Send command1136 1091 + s3cmci_send_command(host, cmd); 1137 +1138 + // Enable Interrupt1139 1092 + enable_irq(host->irq); 1140 1093 +} … … 1142 1095 +static void s3cmci_request(struct mmc_host *mmc, struct mmc_request *mrq) 1143 1096 +{ 1144 + struct s3cmci_host *host = mmc_priv(mmc);1097 + struct s3cmci_host *host = mmc_priv(mmc); 1145 1098 + 1146 1099 + host->cmd_is_stop = 0; … … 1155 1108 + u32 mci_psc, mci_con; 1156 1109 + 1157 + / /Set power1110 + /* Set power */ 1158 1111 + mci_con = readl(host->base + S3C2410_SDICON); 1159 + switch (ios->power_mode) {1160 + case MMC_POWER_ON:1161 + case MMC_POWER_UP:1162 + s3c2410_gpio_cfgpin(S3C2410_GPE5, S3C2410_GPE5_SDCLK);1163 + s3c2410_gpio_cfgpin(S3C2410_GPE6, S3C2410_GPE6_SDCMD);1164 + s3c2410_gpio_cfgpin(S3C2410_GPE7, S3C2410_GPE7_SDDAT0);1165 + s3c2410_gpio_cfgpin(S3C2410_GPE8, S3C2410_GPE8_SDDAT1);1166 + s3c2410_gpio_cfgpin(S3C2410_GPE9, S3C2410_GPE9_SDDAT2);1167 + s3c2410_gpio_cfgpin(S3C2410_GPE10, S3C2410_GPE10_SDDAT3);1168 + 1169 + if (host->pdata->set_power)1170 + host->pdata->set_power(ios->power_mode, ios->vdd);1171 + 1172 + if (!host->is2440)1173 + mci_con|=S3C2410_SDICON_FIFORESET;1174 + 1175 + break;1176 + 1177 + case MMC_POWER_OFF:1178 + default:1179 + s3c2410_gpio_setpin(S3C2410_GPE5, 0);1180 + s3c2410_gpio_cfgpin(S3C2410_GPE5, S3C2410_GPE5_OUTP);1181 + 1182 + if (host->pdata->set_power)1183 + host->pdata->set_power(ios->power_mode, ios->vdd);1184 + 1185 + if (host->is2440)1186 + mci_con|=S3C2440_SDICON_SDRESET;1187 + 1188 + break;1189 + } 1190 + 1191 + / /Set clock1192 + for (mci_psc =0; mci_psc<255; mci_psc++) {1112 + switch (ios->power_mode) { 1113 + case MMC_POWER_ON: 1114 + case MMC_POWER_UP: 1115 + s3c2410_gpio_cfgpin(S3C2410_GPE5, S3C2410_GPE5_SDCLK); 1116 + s3c2410_gpio_cfgpin(S3C2410_GPE6, S3C2410_GPE6_SDCMD); 1117 + s3c2410_gpio_cfgpin(S3C2410_GPE7, S3C2410_GPE7_SDDAT0); 1118 + s3c2410_gpio_cfgpin(S3C2410_GPE8, S3C2410_GPE8_SDDAT1); 1119 + s3c2410_gpio_cfgpin(S3C2410_GPE9, S3C2410_GPE9_SDDAT2); 1120 + s3c2410_gpio_cfgpin(S3C2410_GPE10, S3C2410_GPE10_SDDAT3); 1121 + 1122 + if (host->pdata->set_power) 1123 + host->pdata->set_power(ios->power_mode, ios->vdd); 1124 + 1125 + if (!host->is2440) 1126 + mci_con |= S3C2410_SDICON_FIFORESET; 1127 + 1128 + break; 1129 + 1130 + case MMC_POWER_OFF: 1131 + default: 1132 + s3c2410_gpio_setpin(S3C2410_GPE5, 0); 1133 + s3c2410_gpio_cfgpin(S3C2410_GPE5, S3C2410_GPE5_OUTP); 1134 + 1135 + if (host->pdata->set_power) 1136 + host->pdata->set_power(ios->power_mode, ios->vdd); 1137 + 1138 + if (host->is2440) 1139 + mci_con |= S3C2440_SDICON_SDRESET; 1140 + 1141 + break; 1142 + } 1143 + 1144 + /* Set clock */ 1145 + for (mci_psc = 0; mci_psc < 255; mci_psc++) { 1193 1146 + host->real_rate = host->clk_rate / (host->clk_div*(mci_psc+1)); 1194 1147 + … … 1197 1150 + } 1198 1151 + 1199 + if(mci_psc > 255) mci_psc = 255; 1152 + if (mci_psc > 255) 1153 + mci_psc = 255; 1200 1154 + host->prescaler = mci_psc; 1201 1155 + 1202 1156 + writel(host->prescaler, host->base + S3C2410_SDIPRE); 1203 1157 + 1204 + / /If requested clock is 0, real_rate will be 0, too1158 + /* If requested clock is 0, real_rate will be 0, too */ 1205 1159 + if (ios->clock == 0) 1206 1160 + host->real_rate = 0; 1207 1161 + 1208 + / /Set CLOCK_ENABLE1162 + /* Set CLOCK_ENABLE */ 1209 1163 + if (ios->clock) 1210 1164 + mci_con |= S3C2410_SDICON_CLOCKTYPE; 1211 1165 + else 1212 + mci_con &= ~S3C2410_SDICON_CLOCKTYPE;1166 + mci_con &= ~S3C2410_SDICON_CLOCKTYPE; 1213 1167 + 1214 1168 + writel(mci_con, host->base + S3C2410_SDICON); 1215 1169 + 1216 + if ((ios->power_mode ==MMC_POWER_ON)1217 + || (ios->power_mode ==MMC_POWER_UP)) {1170 + if ((ios->power_mode == MMC_POWER_ON) 1171 + || (ios->power_mode == MMC_POWER_UP)) { 1218 1172 + 1219 1173 + dbg(host, dbg_conf, "running at %lukHz (requested: %ukHz).\n", 1220 + host->real_rate/1000, ios->clock/1000);1174 + host->real_rate/1000, ios->clock/1000); 1221 1175 + } else { 1222 1176 + dbg(host, dbg_conf, "powered down.\n"); … … 1371 1325 + } 1372 1326 + 1373 + if ((ret = clk_enable(host->clk))) { 1327 + ret = clk_enable(host->clk); 1328 + if (ret) { 1374 1329 + dev_err(&pdev->dev, "failed to enable clock source.\n"); 1375 1330 + goto clk_free; … … 1392 1347 + mmc->max_hw_segs = 128; 1393 1348 + 1394 + dbg(host, dbg_debug, "probe: mode:%s mapped mci_base:%p irq:%u irq_cd:%u dma:%u.\n", 1395 + (host->is2440?"2440":""), 1396 + host->base, host->irq, host->irq_cd, host->dma); 1397 + 1398 + if ((ret = mmc_add_host(mmc))) { 1349 + dbg(host, dbg_debug, "probe: mode:%s mapped mci_base:%p irq:%u " 1350 + "irq_cd:%u dma:%u.\n", (host->is2440?"2440":""), 1351 + host->base, host->irq, host->irq_cd, host->dma); 1352 + 1353 + ret = mmc_add_host(mmc); 1354 + if (ret) { 1399 1355 + dev_err(&pdev->dev, "failed to add mmc host.\n"); 1400 1356 + goto free_dmabuf; … … 1403 1359 + platform_set_drvdata(pdev, mmc); 1404 1360 + 1405 + dev_info(&pdev->dev, "initialisation done.\n");1361 + dev_info(&pdev->dev, "initialisation done.\n"); 1406 1362 + return 0; 1407 1363 + … … 1413 1369 + 1414 1370 + probe_free_irq_cd: 1415 + free_irq(host->irq_cd, host);1371 + free_irq(host->irq_cd, host); 1416 1372 + 1417 1373 + probe_free_irq: 1418 + free_irq(host->irq, host);1374 + free_irq(host->irq, host); 1419 1375 + 1420 1376 + probe_iounmap: … … 1439 1395 + clk_put(host->clk); 1440 1396 + s3c2410_dma_free(S3CMCI_DMA, &s3cmci_dma_client); 1441 + free_irq(host->irq_cd, host);1442 + free_irq(host->irq, host);1397 + free_irq(host->irq_cd, host); 1398 + free_irq(host->irq, host); 1443 1399 + iounmap(host->base); 1444 1400 + release_mem_region(host->mem->start, RESSIZE(host->mem)); … … 1485 1441 + 1486 1442 + 1487 +static struct platform_driver s3cmci_driver_2410 = 1488 +{ 1443 +static struct platform_driver s3cmci_driver_2410 = { 1489 1444 + .driver.name = "s3c2410-sdi", 1490 1445 + .probe = s3cmci_probe_2410, … … 1494 1449 +}; 1495 1450 + 1496 +static struct platform_driver s3cmci_driver_2412 = 1497 +{ 1451 +static struct platform_driver s3cmci_driver_2412 = { 1498 1452 + .driver.name = "s3c2412-sdi", 1499 1453 + .probe = s3cmci_probe_2412, … … 1503 1457 +}; 1504 1458 + 1505 +static struct platform_driver s3cmci_driver_2440 = 1506 +{ 1459 +static struct platform_driver s3cmci_driver_2440 = { 1507 1460 + .driver.name = "s3c2440-sdi", 1508 1461 + .probe = s3cmci_probe_2440, … … 1539 1492 --- /dev/null 1540 1493 +++ linux-2.6/drivers/mmc/host/s3cmci.h 1541 @@ -0,0 +1,7 2@@1494 @@ -0,0 +1,71 @@ 1542 1495 +/* 1543 1496 + * linux/drivers/mmc/s3cmci.h - Samsung S3C MCI driver … … 1550 1503 + */ 1551 1504 + 1552 +/ /FIXME: DMA Resource management ?!1505 +/* FIXME: DMA Resource management ?! */ 1553 1506 +#define S3CMCI_DMA 0 1554 1507 + … … 1583 1536 + int dodma; 1584 1537 + 1585 + volatile intdmatogo;1538 + int dmatogo; 1586 1539 + 1587 1540 + struct mmc_request *mrq; … … 1589 1542 + 1590 1543 + spinlock_t complete_lock; 1591 + volatile enum s3cmci_waitfor 1592 + complete_what; 1593 + 1594 + volatile int dma_complete; 1595 + 1596 + volatile u32 pio_sgptr; 1597 + volatile u32 pio_words; 1598 + volatile u32 pio_count; 1599 + volatile u32 *pio_ptr; 1544 + enum s3cmci_waitfor complete_what; 1545 + 1546 + int dma_complete; 1547 + 1548 + u32 pio_sgptr; 1549 + u32 pio_words; 1550 + u32 pio_count; 1551 + u32 *pio_ptr; 1600 1552 +#define XFER_NONE 0 1601 1553 +#define XFER_READ 1 1602 1554 +#define XFER_WRITE 2 1603 + volatile u32pio_active;1555 + u32 pio_active; 1604 1556 + 1605 1557 + int bus_width; … … 1607 1559 + char dbgmsg_cmd[301]; 1608 1560 + char dbgmsg_dat[301]; 1609 + volatile char*status;1561 + char *status; 1610 1562 + 1611 1563 + unsigned int ccnt, dcnt; … … 1635 1587 --- linux-2.6.orig/drivers/mmc/host/Makefile 1636 1588 +++ linux-2.6/drivers/mmc/host/Makefile 1637 @@ -17,4 +17, 5@@1589 @@ -17,4 +17,4 @@ 1638 1590 obj-$(CONFIG_MMC_AT91) += at91_mci.o 1639 1591 obj-$(CONFIG_MMC_TIFM_SD) += tifm_sd.o … … 1641 1593 - 1642 1594 +obj-$(CONFIG_MMC_S3C) += s3cmci.o 1643 +obj-$(CONFIG_MMC) += mmc_debug.o
Note: See TracChangeset
for help on using the changeset viewer.
