Go to the documentation of this file.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
00033
00034
00044 #include <cfg/spi.h>
00045
00046 #include <sys/timer.h>
00047 #include <sys/nutdebug.h>
00048
00049 #include <stdlib.h>
00050 #include <memdebug.h>
00051 #include <errno.h>
00052
00053 #include <dev/cy2239x.h>
00054 #include <dev/npl.h>
00055 #include <dev/spibus_npl.h>
00056
00057 #ifndef NPL_MMC_CLOCK
00058 #define NPL_MMC_CLOCK 12500000
00059 #endif
00060
00068 static int NplSpiSetup(NUTSPINODE * node)
00069 {
00070 #if defined(NUT_PLL_NPLCLK1)
00071 uint32_t clk;
00072 uint32_t clkdiv;
00073
00074 NUTASSERT(node != NULL);
00075
00076
00077 clk = Cy2239xGetPll(NUT_PLL_NPLCLK1);
00078
00079 clk = Cy2239xPllGetFreq((int)clk, 7);
00080
00081 clkdiv = (clk + NPL_MMC_CLOCK - 10) / NPL_MMC_CLOCK;
00082
00083
00084
00085
00086
00087
00088 if (Cy2239xSetDivider(NUT_PLL_NPLCLK1, 1, (int)clkdiv)) {
00089 return -1;
00090 }
00091 if (Cy2239xSetDivider(NUT_PLL_NPLCLK1, 0, (int)clkdiv)) {
00092 return -1;
00093 }
00094
00095
00096 node->node_rate = clk / clkdiv;
00097 node->node_mode &= ~SPI_MODE_UPDATE;
00098 #endif
00099
00100 return 0;
00101 }
00102
00112 static int NplSpiChipSelect(uint_fast8_t cs, uint_fast8_t hi)
00113 {
00114 int rc = 0;
00115
00116 switch (cs) {
00117 case 0:
00118 if (hi) {
00119 outb(NPL_XER, inb(NPL_XER) | NPL_MMCS);
00120 } else {
00121 outb(NPL_XER, inb(NPL_XER) & ~NPL_MMCS);
00122 }
00123 break;
00124 case 1:
00125 if (hi) {
00126 outb(NPL_XER, inb(NPL_XER) | NPL_NPCS0);
00127 } else {
00128 outb(NPL_XER, inb(NPL_XER) & ~NPL_NPCS0);
00129 }
00130 break;
00131 default:
00132 errno = EIO;
00133 rc = -1;
00134 break;
00135 }
00136 return rc;
00137 }
00138
00150 int NplSpiBusSelect(NUTSPINODE * node, uint32_t tmo)
00151 {
00152 int rc;
00153
00154
00155 NUTASSERT(node != NULL);
00156 NUTASSERT(node->node_bus != NULL);
00157
00158
00159 rc = NutEventWait(&node->node_bus->bus_mutex, tmo);
00160 if (rc) {
00161 errno = EIO;
00162 } else {
00163
00164 if (node->node_mode & SPI_MODE_UPDATE) {
00165 NplSpiSetup(node);
00166 }
00167
00168
00169 rc = NplSpiChipSelect(node->node_cs, 0);
00170 if (rc) {
00171
00172 NutEventPost(&node->node_bus->bus_mutex);
00173 }
00174 }
00175 return rc;
00176 }
00177
00186 int NplSpiBusDeselect(NUTSPINODE * node)
00187 {
00188
00189 NUTASSERT(node != NULL);
00190 NUTASSERT(node->node_bus != NULL);
00191
00192
00193 NplSpiChipSelect(node->node_cs, 1);
00194
00195
00196 NutEventPost(&node->node_bus->bus_mutex);
00197
00198 return 0;
00199 }
00200
00211 int NplSpiBusNodeInit(NUTSPINODE * node)
00212 {
00213 int rc;
00214
00215
00216 NUTASSERT(node != NULL);
00217
00218
00219 rc = NplSpiChipSelect(node->node_cs, 1);
00220
00221 if (rc == 0) {
00222 NplSpiSetup(node);
00223 }
00224 return rc;
00225 }
00226
00241 int NplSpiBusPollTransfer(NUTSPINODE * node, CONST void *txbuf, void *rxbuf, int xlen)
00242 {
00243 uint8_t rxc;
00244 uint8_t txc = 0xFF;
00245 uint8_t *txp = (uint8_t *) txbuf;
00246 uint8_t *rxp = (uint8_t *) rxbuf;
00247
00248
00249 NUTASSERT(node != NULL);
00250
00251 while (xlen--) {
00252 if (txp) {
00253 txc = *txp++;
00254 }
00255
00256 outb(NPL_MMCDR, txc);
00257
00258 while ((inb(NPL_SLR) & NPL_MMCREADY) == 0);
00259
00260 rxc = inb(NPL_MMCDR);
00261 if (rxp) {
00262 *rxp++ = rxc;
00263 }
00264 }
00265 return 0;
00266 }
00267
00271 NUTSPIBUS spiBusNpl = {
00272 NULL,
00273 NULL,
00274 0,
00275 NULL,
00276 NplSpiBusNodeInit,
00277 NplSpiBusSelect,
00278 NplSpiBusDeselect,
00279 NplSpiBusPollTransfer,
00280 NutSpiBusWait,
00281 NutSpiBusSetMode,
00282 NutSpiBusSetRate,
00283 NutSpiBusSetBits
00284 };