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
00066 #include <cfg/clock.h>
00067
00068 #include <sys/event.h>
00069
00070 #include <dev/twif.h>
00071 #include <dev/npl.h>
00072 #include <dev/mmcard.h>
00073 #include <dev/cy2239x.h>
00074 #include <dev/nplmmc.h>
00075
00076 #if !defined(NPL_MMC_CLOCK) || (NPL_MMC_CLOCK < 1000)
00077 #undef NPL_MMC_CLOCK
00078 #define NPL_MMC_CLOCK 12500000
00079 #endif
00080
00081 #if 0
00082
00083 #define NUTDEBUG
00084 #include <stdio.h>
00085 #endif
00086
00091
00092 #ifndef I2C_SLA_PLL
00093 #define I2C_SLA_PLL 0x69
00094 #endif
00095
00099 typedef struct _MMCDCB {
00100 int dcb_avail;
00101 int dcb_changed;
00102 } MMCDCB;
00103
00104 static MMCDCB mmc0_dcb;
00105
00111 static int NplMmCard0Init(void)
00112 {
00113 mmc0_dcb.dcb_changed = 0;
00114 if (mmc0_dcb.dcb_avail) {
00115 return 0;
00116 }
00117 return -1;
00118 }
00119
00128 static int NplMmCard0Select(int on)
00129 {
00130 int rc = (inb(NPL_XER) & NPL_MMCS) == NPL_MMCS;
00131
00132 if (on == 1) {
00134 outb(NPL_XER, inb(NPL_XER) & ~NPL_MMCS);
00135 } else if (on == 0) {
00137 outb(NPL_XER, inb(NPL_XER) | NPL_MMCS);
00138 }
00139 return rc;
00140 }
00141
00149 static uint8_t NplMmCard0Io(uint8_t val)
00150 {
00151 uint8_t rc;
00152 u_int tmo = 255;
00153
00154 while ((inb(NPL_SLR) & NPL_MMCREADY) == 0) {
00155 if (--tmo == 0) {
00156 break;
00157 }
00158 }
00159
00160 _NOP(); _NOP(); _NOP(); _NOP();
00161 rc = inb(NPL_MMCDR);
00162 _NOP(); _NOP(); _NOP(); _NOP();
00163 outb(NPL_MMCDR, val);
00164 _NOP(); _NOP(); _NOP(); _NOP();
00165
00166 #ifdef NUTDEBUG
00167 putchar('[');
00168 if (rc != 0xFF) {
00169 printf("r%02X", rc);
00170 } else if (val != 0xFF) {
00171 printf("s%02X", val);
00172 }
00173 putchar(']');
00174 #endif
00175
00176 return rc;
00177 }
00178
00189 int NplMmCard0Avail(void)
00190 {
00191 if (mmc0_dcb.dcb_avail) {
00192 if (mmc0_dcb.dcb_changed) {
00193 return 2;
00194 }
00195 return 1;
00196 }
00197 return 0;
00198 }
00199
00207 int NplMmCard0WrProt(void)
00208 {
00209 return 0;
00210 }
00211
00219 static void NplMmCard0InsIrq(void *arg)
00220 {
00221 NplIrqDisable(&sig_MMCD);
00222 mmc0_dcb.dcb_avail = 1;
00223 mmc0_dcb.dcb_changed = 1;
00224 NplIrqEnable(&sig_NMMCD);
00225 }
00226
00234 static void NplMmCard0RemIrq(void *arg)
00235 {
00236 NplIrqDisable(&sig_NMMCD);
00237 mmc0_dcb.dcb_avail = 0;
00238 NplIrqEnable(&sig_MMCD);
00239 }
00240
00253 static int NplMmcIfcInit(NUTDEVICE * dev)
00254 {
00255 int rc;
00256
00257
00258 NplMmCard0Select(0);
00259
00260 #if defined(NUT_PLL_NPLCLK1)
00261 {
00262 uint32_t val;
00263
00264
00265 val = Cy2239xGetPll(NUT_PLL_NPLCLK1);
00266
00267 val = Cy2239xPllGetFreq((int)val, 7);
00268
00269 val = (val + NPL_MMC_CLOCK - 10) / NPL_MMC_CLOCK;
00270
00271
00272
00273
00274
00275 if (Cy2239xSetDivider(NUT_PLL_NPLCLK1, 1, (int)val)) {
00276 return -1;
00277 }
00278 if (Cy2239xSetDivider(NUT_PLL_NPLCLK1, 0, (int)val)) {
00279 return -1;
00280 }
00281 }
00282 #endif
00283
00284
00285 inb(NPL_MMCDR);
00286 outb(NPL_MMCDR, 0xFF);
00287
00288
00289 if ((rc = NplRegisterIrqHandler(&sig_MMCD, NplMmCard0InsIrq, 0)) == 0) {
00290 rc = NplRegisterIrqHandler(&sig_NMMCD, NplMmCard0RemIrq, 0);
00291 }
00292 NplIrqEnable(&sig_MMCD);
00293
00294 return MmCardDevInit(dev);
00295 }
00296
00297 static MMCIFC mmc0_ifc = {
00298 NplMmCard0Init,
00299 NplMmCard0Io,
00300 NplMmCard0Select,
00301 NplMmCard0Avail,
00302 NplMmCard0WrProt
00303 };
00304
00317 NUTDEVICE devNplMmc0 = {
00318 0,
00319 {'M', 'M', 'C', '0', 0, 0, 0, 0, 0}
00320 ,
00321 0,
00322 0,
00323 0,
00324 &mmc0_ifc,
00325 &mmc0_dcb,
00326 NplMmcIfcInit,
00327 MmCardIOCtl,
00328 MmCardBlockRead,
00329 MmCardBlockWrite,
00330 #ifdef __HARVARD_ARCH__
00331 MmCardBlockWrite_P,
00332 #endif
00333 MmCardMount,
00334 MmCardUnmount,
00335 0
00336 };
00337