spibus_npl.c
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 NUTSPIBUS *bus;
00215
00216
00217 NUTASSERT(node != NULL);
00218 NUTASSERT(node->node_bus != NULL);
00219 bus = node->node_bus;
00220
00221
00222 rc = NplSpiChipSelect(node->node_cs, 1);
00223
00224 if (rc == 0) {
00225 NplSpiSetup(node);
00226 }
00227 return rc;
00228 }
00229
00244 int NplSpiBusPollTransfer(NUTSPINODE * node, CONST void *txbuf, void *rxbuf, int xlen)
00245 {
00246 uint8_t rxc;
00247 uint8_t txc = 0xFF;
00248 uint8_t *txp = (uint8_t *) txbuf;
00249 uint8_t *rxp = (uint8_t *) rxbuf;
00250
00251
00252 NUTASSERT(node != NULL);
00253
00254 while (xlen--) {
00255 if (txp) {
00256 txc = *txp++;
00257 }
00258
00259 outb(NPL_MMCDR, txc);
00260
00261 while ((inb(NPL_SLR) & NPL_MMCREADY) == 0);
00262
00263 rxc = inb(NPL_MMCDR);
00264 if (rxp) {
00265 *rxp++ = rxc;
00266 }
00267 }
00268 return 0;
00269 }
00270
00274 NUTSPIBUS spiBusNpl = {
00275 NULL,
00276 NULL,
00277 0,
00278 NULL,
00279 NplSpiBusNodeInit,
00280 NplSpiBusSelect,
00281 NplSpiBusDeselect,
00282 NplSpiBusPollTransfer,
00283 NutSpiBusWait,
00284 NutSpiBusSetMode,
00285 NutSpiBusSetRate,
00286 NutSpiBusSetBits
00287 };