00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00060 #include <cfg/clock.h>
00061
00062 #include <sys/event.h>
00063
00064 #include <dev/twif.h>
00065 #include <dev/npl.h>
00066 #include <dev/mmcard.h>
00067 #include <dev/cy2239x.h>
00068 #include <dev/nplmmc.h>
00069
00070 #if !defined(NPL_MMC_CLOCK) || (NPL_MMC_CLOCK < 1000)
00071 #undef NPL_MMC_CLOCK
00072 #define NPL_MMC_CLOCK 12500000
00073 #endif
00074
00075 #if 0
00076
00077 #define NUTDEBUG
00078 #include <stdio.h>
00079 #endif
00080
00085
00086 #ifndef I2C_SLA_PLL
00087 #define I2C_SLA_PLL 0x69
00088 #endif
00089
00093 typedef struct _MMCDCB {
00094 int dcb_avail;
00095 int dcb_changed;
00096 } MMCDCB;
00097
00098 static MMCDCB mmc0_dcb;
00099
00105 static int NplMmCard0Init(void)
00106 {
00107 mmc0_dcb.dcb_changed = 0;
00108 if (mmc0_dcb.dcb_avail) {
00109 return 0;
00110 }
00111 return -1;
00112 }
00113
00122 static int NplMmCard0Select(int on)
00123 {
00124 int rc = (inb(NPL_XER) & NPL_MMCS) == NPL_MMCS;
00125
00126 if (on == 1) {
00128 outb(NPL_XER, inb(NPL_XER) & ~NPL_MMCS);
00129 } else if (on == 0) {
00131 outb(NPL_XER, inb(NPL_XER) | NPL_MMCS);
00132 }
00133 return rc;
00134 }
00135
00143 static u_char NplMmCard0Io(u_char val)
00144 {
00145 u_char rc;
00146 u_int tmo = 255;
00147
00148 while ((inb(NPL_SLR) & NPL_MMCREADY) == 0) {
00149 if (--tmo == 0) {
00150 break;
00151 }
00152 }
00153
00154 _NOP();
00155 _NOP();
00156 rc = inb(NPL_MMCDR);
00157 _NOP();
00158 _NOP();
00159 outb(NPL_MMCDR, val);
00160 _NOP();
00161 _NOP();
00162
00163 #ifdef NUTDEBUG
00164 putchar('[');
00165 if (rc != 0xFF) {
00166 printf("r%02X", rc);
00167 } else if (val != 0xFF) {
00168 printf("s%02X", val);
00169 }
00170 putchar(']');
00171 #endif
00172
00173 return rc;
00174 }
00175
00186 int NplMmCard0Avail(void)
00187 {
00188 if (mmc0_dcb.dcb_avail) {
00189 if (mmc0_dcb.dcb_changed) {
00190 return 2;
00191 }
00192 return 1;
00193 }
00194 return 0;
00195 }
00196
00204 int NplMmCard0WrProt(void)
00205 {
00206 return 0;
00207 }
00208
00216 static void NplMmCard0InsIrq(void *arg)
00217 {
00218 NplIrqDisable(&sig_MMCD);
00219 mmc0_dcb.dcb_avail = 1;
00220 mmc0_dcb.dcb_changed = 1;
00221 NplIrqEnable(&sig_NMMCD);
00222 }
00223
00231 static void NplMmCard0RemIrq(void *arg)
00232 {
00233 NplIrqDisable(&sig_NMMCD);
00234 mmc0_dcb.dcb_avail = 0;
00235 NplIrqEnable(&sig_MMCD);
00236 }
00237
00250 static int NplMmcIfcInit(NUTDEVICE * dev)
00251 {
00252 int rc;
00253
00254
00255 NplMmCard0Select(0);
00256
00257 #if defined(NUT_PLL_NPLCLK1)
00258 {
00259 u_long val;
00260
00261
00262 val = Cy2239xGetPll(NUT_PLL_NPLCLK1);
00263
00264 val = Cy2239xPllGetFreq((int)val, 7);
00265
00266 val = (val + NPL_MMC_CLOCK - 10) / NPL_MMC_CLOCK;
00267
00268
00269
00270
00271
00272 if (Cy2239xSetDivider(NUT_PLL_NPLCLK1, 1, (int)val)) {
00273 return -1;
00274 }
00275 if (Cy2239xSetDivider(NUT_PLL_NPLCLK1, 0, (int)val)) {
00276 return -1;
00277 }
00278 }
00279 #endif
00280
00281
00282 inb(NPL_MMCDR);
00283 outb(NPL_MMCDR, 0xFF);
00284
00285
00286 if ((rc = NplRegisterIrqHandler(&sig_MMCD, NplMmCard0InsIrq, 0)) == 0) {
00287 rc = NplRegisterIrqHandler(&sig_NMMCD, NplMmCard0RemIrq, 0);
00288 }
00289 NplIrqEnable(&sig_MMCD);
00290
00291 return MmCardDevInit(dev);
00292 }
00293
00294 static MMCIFC mmc0_ifc = {
00295 NplMmCard0Init,
00296 NplMmCard0Io,
00297 NplMmCard0Select,
00298 NplMmCard0Avail,
00299 NplMmCard0WrProt
00300 };
00301
00314 NUTDEVICE devNplMmc0 = {
00315 0,
00316 {'M', 'M', 'C', '0', 0, 0, 0, 0, 0}
00317 ,
00318 0,
00319 0,
00320 0,
00321 &mmc0_ifc,
00322 &mmc0_dcb,
00323 NplMmcIfcInit,
00324 MmCardIOCtl,
00325 MmCardBlockRead,
00326 MmCardBlockWrite,
00327 #ifdef __HARVARD_ARCH__
00328 MmCardBlockWrite_P,
00329 #endif
00330 MmCardMount,
00331 MmCardUnmount,
00332 0
00333 };
00334