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 NUTASSERT(node->node_stat != NULL);
00076 NUTASSERT(node->node_bus != NULL);
00077 NUTASSERT(node->node_bus->bus_base != 0);
00078
00079
00080 clk = Cy2239xGetPll(NUT_PLL_NPLCLK1);
00081
00082 clk = Cy2239xPllGetFreq((int)clk, 7);
00083
00084 clkdiv = (clk + NPL_MMC_CLOCK - 10) / NPL_MMC_CLOCK;
00085
00086
00087
00088
00089
00090
00091 if (Cy2239xSetDivider(NUT_PLL_NPLCLK1, 1, (int)clkdiv)) {
00092 return -1;
00093 }
00094 if (Cy2239xSetDivider(NUT_PLL_NPLCLK1, 0, (int)clkdiv)) {
00095 return -1;
00096 }
00097
00098
00099 node->node_rate = clk / clkdiv;
00100 node->node_mode &= ~SPI_MODE_UPDATE;
00101 #endif
00102
00103 return 0;
00104 }
00105
00115 static int NplSpiChipSelect(uint_fast8_t cs, uint_fast8_t hi)
00116 {
00117 int rc = 0;
00118
00119 switch (cs) {
00120 case 0:
00121 if (hi) {
00122 outb(NPL_XER, inb(NPL_XER) | NPL_MMCS);
00123 } else {
00124 outb(NPL_XER, inb(NPL_XER) & ~NPL_MMCS);
00125 }
00126 break;
00127 case 1:
00128 if (hi) {
00129 outb(NPL_XER, inb(NPL_XER) | NPL_NPCS0);
00130 } else {
00131 outb(NPL_XER, inb(NPL_XER) & ~NPL_NPCS0);
00132 }
00133 break;
00134 default:
00135 errno = EIO;
00136 rc = -1;
00137 break;
00138 }
00139 return rc;
00140 }
00141
00153 int NplSpiBusSelect(NUTSPINODE * node, uint32_t tmo)
00154 {
00155 int rc;
00156
00157
00158 NUTASSERT(node != NULL);
00159 NUTASSERT(node->node_bus != NULL);
00160 NUTASSERT(node->node_stat != NULL);
00161
00162
00163 rc = NutEventWait(&node->node_bus->bus_mutex, tmo);
00164 if (rc) {
00165 errno = EIO;
00166 } else {
00167
00168 if (node->node_mode & SPI_MODE_UPDATE) {
00169 NplSpiSetup(node);
00170 }
00171
00172
00173 rc = NplSpiChipSelect(node->node_cs, 0);
00174 if (rc) {
00175
00176 NutEventPost(&node->node_bus->bus_mutex);
00177 }
00178 }
00179 return rc;
00180 }
00181
00190 int NplSpiBusDeselect(NUTSPINODE * node)
00191 {
00192
00193 NUTASSERT(node != NULL);
00194 NUTASSERT(node->node_bus != NULL);
00195
00196
00197 NplSpiChipSelect(node->node_cs, 1);
00198
00199
00200 NutEventPost(&node->node_bus->bus_mutex);
00201
00202 return 0;
00203 }
00204
00215 int NplSpiBusNodeInit(NUTSPINODE * node)
00216 {
00217 int rc;
00218 NUTSPIBUS *bus;
00219
00220
00221 NUTASSERT(node != NULL);
00222 NUTASSERT(node->node_bus != NULL);
00223 bus = node->node_bus;
00224
00225
00226 rc = NplSpiChipSelect(node->node_cs, 1);
00227
00228 if (rc == 0) {
00229 NplSpiSetup(node);
00230 }
00231 return rc;
00232 }
00233
00248 int NplSpiBusPollTransfer(NUTSPINODE * node, CONST void *txbuf, void *rxbuf, int xlen)
00249 {
00250 uint8_t b = 0xff;
00251 uint8_t *txp = (uint8_t *) txbuf;
00252 uint8_t *rxp = (uint8_t *) rxbuf;
00253 uintptr_t base;
00254
00255
00256 NUTASSERT(node != NULL);
00257 NUTASSERT(node->node_bus != NULL);
00258 NUTASSERT(node->node_bus->bus_base != 0);
00259 base = node->node_bus->bus_base;
00260
00261 while (xlen--) {
00262 if (txp) {
00263 b = *txp++;
00264 }
00265
00266 outb(NPL_MMCDR, b);
00267
00268 while ((inb(NPL_SLR) & NPL_MMCREADY) == 0);
00269
00270 b = inb(NPL_MMCDR);
00271 if (rxp) {
00272 *rxp++ = b;
00273 }
00274 }
00275 return 0;
00276 }
00277
00281 NUTSPIBUS spiBusNpl = {
00282 NULL,
00283 NULL,
00284 0,
00285 NULL,
00286 NplSpiBusNodeInit,
00287 NplSpiBusSelect,
00288 NplSpiBusDeselect,
00289 NplSpiBusPollTransfer,
00290 NutSpiBusWait,
00291 NutSpiBusSetMode,
00292 NutSpiBusSetRate,
00293 NutSpiBusSetBits
00294 };