From 08b4a61636f1289a773ac4cb67f07a758f852c19 Mon Sep 17 00:00:00 2001 From: patacongo Date: Sun, 2 May 2010 17:29:37 +0000 Subject: Add ENC28J60 GPIO configuration git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@2644 42af7a65-404d-4744-a932-0658087f49c3 --- nuttx/configs/olimex-strp711/README.txt | 48 ++- nuttx/configs/olimex-strp711/nettest/defconfig | 4 +- nuttx/configs/olimex-strp711/src/up_enc28j60.c | 57 ++- nuttx/configs/olimex-strp711/src/up_spi.c | 465 ++++++++++++++++++------- 4 files changed, 431 insertions(+), 143 deletions(-) (limited to 'nuttx/configs/olimex-strp711') diff --git a/nuttx/configs/olimex-strp711/README.txt b/nuttx/configs/olimex-strp711/README.txt index 2f7431a03..8eaf3224e 100644 --- a/nuttx/configs/olimex-strp711/README.txt +++ b/nuttx/configs/olimex-strp711/README.txt @@ -228,9 +228,33 @@ GENERAL STEPS: The same commands from the telnet interface can now be accessed through the 'monitor' command, e.g. 'monitor help' +MMC/SD Slot +^^^^^^^^^^^ + + STR-P711 PIN MMC/SD USAGE PIN CONFIGURATION + ------------ ---------------- ----------------------- + P0.7/S1.SS 1 CD/DAT3/CS P.07 output + P0.5/S1.MOSI 2 CMD/DI MOSI1 + --- 3 VSS1 --- + --- 4 VDD --- + P0.6/S1.SCLK 5 CLK/SCLK SLCK1 + --- 6 VSS2 --- + P0.4/S1.MISO 7 DAT0/D0 MISO1 + --- 8 DAT1/RES (Pulled up) + --- 9 DAT2/RES (Pulled up) + + P1.10/USBCLK 10/14 WP P1.10 input + P1.15/HTXD 13/15 CP P1.15 input + + Use of SPI1 doesn't conflict with anything. WP conflicts USB; CP conflicts + with NTXD. + ENC28J60 Module ^^^^^^^^^^^^^^^ + The ENC28J60 module does not come on the Olimex-STR-P711, but this describes + how I have connected it: + Module CON5 QFN ENC2860 Description --------------- ------------------------------------------------------- 1 J8-1 NET CS 5 ~CS Chip select input pin for SPI interface (active low) @@ -244,22 +268,24 @@ ENC28J60 Module 7 4 CLKOUT 27 CLKOUT Programmable clock output pin 6 5 NET RST 6 ~RESET Active-low device Reset input - For the Olimex STR-P711, the ENC28J60 module is placed on SPI1 (with - the MMC slot) and uses P0.0 for CS, P0.1 for an interrupt, and P0.2 as - a reset: + For the Olimex STR-P711, the ENC28J60 module is placed on SPI0 and uses + P0.3 for CS, P1.4 for an interrupt, and P1.5 as a reset: Module CON5 Olimex STR-P711 Connection --------------- ------------------------------------------------------- - 1 J8-1 NET CS SPI0-4 P0.0 P0.0/S0.MISO/U3.TX - 2 2 SCK SPI1-5 SCLK1 P0.6/S1.SCLK - 3 3 MOSI SPI1-3 MOSI1 P0.5/S1.MOSI - 4 4 MISO SPI1-4 MISO1 P0.4/S1.MISO - 5 5 GND SPI1-1 GND - 10 J9-1 3V3 SPI1-6 3.3V + 1 J8-1 NET CS SPI0-2 P0.3 output P0.3/S0.SS/I1.SDA + 2 2 SCK SPI0-5 SCLK0 P0.2/S0.SCLK/I1.SCL + 3 3 MOSI SPI0-3 MOSI0 P0.0/S0.MOSI/U3.RX + 4 4 MISO SPI0-4 MISO0 P0.1/S0.MISO/U3.TX + 5 5 GND SPI0-1 GND + 10 J9-1 3V3 SPI0-6 3.3V 9 2 WOL NC - 8 3 NET INT SPI0-3 P0.1 P0.1/S0.MOSI/U3.RX + 8 3 NET INT TMR1_EXT-5 P1.4 input P1.4/T1.ICAPA/T1.EXTCLK 7 4 CLKOUT NC - 6 5 NET RST SPI0-5 P0.2 P0.2/S0 + 6 5 NET RST TMR1_EXT_4 P1.5 output P1.5/T1.ICAPB + + UART3, I2C cannot be used with SPI0. The GPIOs selected for the ENC28J60 + interrupt conflict with TIM1. Configurations: --------------- diff --git a/nuttx/configs/olimex-strp711/nettest/defconfig b/nuttx/configs/olimex-strp711/nettest/defconfig index 9088ec8f7..80c48d7ac 100755 --- a/nuttx/configs/olimex-strp711/nettest/defconfig +++ b/nuttx/configs/olimex-strp711/nettest/defconfig @@ -115,8 +115,8 @@ CONFIG_STR71X_UART2=n CONFIG_STR71X_UART3=n CONFIG_STR71X_USB=n CONFIG_STR71X_CAN=n -CONFIG_STR71X_BSPI0=n -CONFIG_STR71X_BSPI1=y +CONFIG_STR71X_BSPI0=y +CONFIG_STR71X_BSPI1=n CONFIG_STR71X_HDLC=n CONFIG_STR71X_XTI=n CONFIG_STR71X_GPIO0=y diff --git a/nuttx/configs/olimex-strp711/src/up_enc28j60.c b/nuttx/configs/olimex-strp711/src/up_enc28j60.c index 4bccb572f..cc285a3dc 100755 --- a/nuttx/configs/olimex-strp711/src/up_enc28j60.c +++ b/nuttx/configs/olimex-strp711/src/up_enc28j60.c @@ -33,6 +33,45 @@ * ****************************************************************************/ +/* + * ENC28J60 Module + * + * The ENC28J60 module does not come on the Olimex-STR-P711, but this describes + * how I have connected it: + * + * Module CON5 QFN ENC2860 Description + * --------------- ------------------------------------------------------- + * 1 J8-1 NET CS 5 ~CS Chip select input pin for SPI interface (active low) + * 2 2 SCK 4 SCK Clock in pin for SPI interface + * 3 3 MOSI 3 SI Data in pin for SPI interface + * 4 4 MISO 2 SO Data out pin for SPI interface + * 5 5 GND -- --- --- + * 10 J9-1 3V3 -- --- --- + * 9 2 WOL 1 ~WOL Unicast WOL filter + * 8 3 NET INT 28 ~INT Interrupt output pin (active low) + * 7 4 CLKOUT 27 CLKOUT Programmable clock output pin + * 6 5 NET RST 6 ~RESET Active-low device Reset input + * + * For the Olimex STR-P711, the ENC28J60 module is placed on SPI0 and uses + * P0.3 for CS, P1.4 for an interrupt, and P1.5 as a reset: + * + * Module CON5 Olimex STR-P711 Connection + * --------------- ------------------------------------------------------- + * 1 J8-1 NET CS SPI0-2 P0.3 output P0.3/S0.SS/I1.SDA + * 2 2 SCK SPI0-5 SCLK0 P0.2/S0.SCLK/I1.SCL + * 3 3 MOSI SPI0-3 MOSI0 P0.0/S0.MOSI/U3.RX + * 4 4 MISO SPI0-4 MISO0 P0.1/S0.MISO/U3.TX + * 5 5 GND SPI0-1 GND + * 10 J9-1 3V3 SPI0-6 3.3V + * 9 2 WOL NC + * 8 3 NET INT TMR1_EXT-5 P1.4 input P1.4/T1.ICAPA/T1.EXTCLK + * 7 4 CLKOUT NC + * 6 5 NET RST TMR1_EXT_4 P1.5 output P1.5/T1.ICAPB + * + * UART3, I2C cannot be used with SPI0. The GPIOs selected for the ENC28J60 + * interrupt conflict with TMR1. + */ + /**************************************************************************** * Included Files ****************************************************************************/ @@ -60,8 +99,22 @@ /* Configuration ************************************************************/ -#ifndef CONFIG_STR71X_BSPI1 -# error "Need CONFIG_STR71X_BSP1 in the configuration" +/* We assume that the ENC28J60 is on SPI0 */ + +#ifndef CONFIG_STR71X_BSPI0 +# error "Need CONFIG_STR71X_BSPI0 in the configuration" +#endif + +/* UART3, I2C cannot be used with SPI0. The GPIOs selected for the ENC28J60 + * interrupt conflict with TIM1. + */ + +#ifdef CONFIG_STR71X_UART3 +# error "CONFIG_STR71X_UART3 cannot be used in this configuration" +#endif + +#ifdef CONFIG_STR71X_TIM1 +# error "CONFIG_STR71X_TIM1 cannot be used in this configuration" #endif /* SPI Assumptions **********************************************************/ diff --git a/nuttx/configs/olimex-strp711/src/up_spi.c b/nuttx/configs/olimex-strp711/src/up_spi.c index 4f6036c3f..cfddffeef 100644 --- a/nuttx/configs/olimex-strp711/src/up_spi.c +++ b/nuttx/configs/olimex-strp711/src/up_spi.c @@ -1,7 +1,7 @@ /**************************************************************************** * config/olimex-strp711/src/up_spi.c * - * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Copyright (C) 2008-2010 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -116,27 +116,143 @@ * ****************************************************************************/ -#define BSPI0_GPIO0_MISO (0x0001) -#define BSPI0_GPIO0_MOSI (0x0002) -#define BSPI0_GPIO0_SCLK (0x0004) -#define BSPI0_GPIO0_SS (0x0008) +/* SPI0 *********************************************************************/ -#define BSPIO_GPIO0_ALT (BSPI0_GPIO0_MISO|BSPI0_GPIO0_MOSI|BSPI0_GPIO0_SCLK) -#define BSPIO_GPIO0_OUT BSPI0_GPIO0_SS -#define BSPIO_GPIO0_ALL (0x000f) +#define BSPI0_GPIO0_MISO (1 << 0) +#define BSPI0_GPIO0_MOSI (1 << 1) +#define BSPI0_GPIO0_SCLK (1 << 2) +#define BSPI0_GPIO0_SS (1 << 3) /* Not used */ -#define BSPI1_GPIO0_MISO (0x0010) -#define BSPI1_GPIO0_MOSI (0x0020) -#define BSPI1_GPIO0_SCLK (0x0040) -#define BSPI1_GPIO0_SS (0x0080) +#define BSPI0_GPIO0_ALT (BSPI0_GPIO0_MISO|BSPI0_GPIO0_MOSI|BSPI0_GPIO0_SCLK) + +/* ENC28J60 Module + * + * The ENC28J60 module does not come on the Olimex-STR-P711, but this describes + * how I have connected it: + * + * STR-P711 PIN PIN CONFIGURATION ENC28J60 CONNECTION + * ----------------------- ----------------- ----------------------- + * P0.3/S0.SS/I1.SDA P0.3 output CON5 1 J8-1 NET CS + * P0.2/S0.SCLK/I1.SCL SCLK0 2 2 SCK + * P0.0/S0.MOSI/U3.RX MOSI0 3 3 MOSI + * P0.1/S0.MISO/U3.TX MISO0 4 4 MISO + * GND GND 5 5 GND + * 3.3V 3.3V 10 J9-1 3V3 + * NC NC 9 2 WOL + * P1.4/T1.ICAPA/T1.EXTCLK P1.4 input 8 3 NET INT + * NC NC 7 4 CLKOUT + * P1.5/T1.ICAPB P1.5 output 6 5 NET RST + */ + +#ifdef CONFIG_NET_ENC28J60 + +/* UART3, I2C cannot be used with SPI0. The GPIOs selected for the ENC28J60 + * interrupt conflict with TMR1. + */ + +# ifdef CONFIG_STR71X_UART3 +# error "CONFIG_STR71X_UART3 cannot be used in this configuration" +# endif + +# ifdef CONFIG_STR71X_TIM3 +# error "CONFIG_STR71X_TIM3 cannot be used in this configuration" +# endif + +/* ENC28J60 additional pins + * + * NOTE: The ENC28J60 is a 3.3V part; however, it was designed to be + * easily integrated into 5V systems. The SPI CS, SCK and SI inputs, + * as well as the RESET pin, are all 5V tolerant. On the other hand, + * if the host controller is operated at 5V, it quite likely will + * not be within specifications when its SPI and interrupt inputs + * are driven by the 3.3V CMOS outputs on the ENC28J60. A + * unidirectional level translator would be necessary. + */ + +# define ENC_GPIO0_CS (1 << 3) +# define ENC_GPIO0_INTTL (0) +# define ENC_GPIO0_INCMOS (0) +# define ENC_GPIO0_OUTPP ENC_GPIO0_CS +# define ENC_GPIO0_ALL ENC_GPIO0_CS + +# define ENC_GPIO1_NETINT ( 1 << 4) +# define ENC_GPIO1_NETRST (1 << 5) +# define ENC_GPIO1_INTTL (0) +# define ENC_GPIO1_INCMOS ENC_GPIO1_NETINT +# define ENC_GPIO1_OUTPP ENC_GPIO1_NETRST +# define ENC_GPIO1_ALL (ENC_GPIO1_NETINT|ENC_GPIO1_NETRST) + +# define BSPI0_GPIO0_INTTL ENC_GPIO0_INTTL +# define BSPI0_GPIO0_INCMOS ENC_GPIO0_INCMOS +# define BSPI0_GPIO0_OUTPP ENC_GPIO0_OUTPP +# define BSPI0_GPIO0_ALL (BSPI0_GPIO0_ALT|ENC_GPIO0_ALL) + +# define BSPI0_GPIO1_INTTL ENC_GPIO1_INTTL +# define BSPI0_GPIO1_INCMOS ENC_GPIO1_INCMOS +# define BSPI0_GPIO1_OUTPP ENC_GPIO1_OUTPP +# define BSPI0_GPIO1_ALL ENC_GPIO1_ALL + +#else +# define BSPI0_GPIO0_INTTL (0) +# define BSPI0_GPIO0_INCMOS (0) +# define BSPI0_GPIO0_OUTPP (0) +# define BSPI0_GPIO0_ALL BSPI0_GPIO0_ALT +#endif + +/* SPI1 *********************************************************************/ + +#define BSPI1_GPIO0_MISO (1 << 4) +#define BSPI1_GPIO0_MOSI (1 << 5) +#define BSPI1_GPIO0_SCLK (1 << 6) +#define BSPI1_GPIO0_SS (1 << 7) /* Not used */ #define BSPI1_GPIO0_ALT (BSPI1_GPIO0_MISO|BSPI1_GPIO0_MOSI|BSPI1_GPIO0_SCLK) -#define BSPI1_GPIO0_OUT BSPI1_GPIO0_SS -#define BSPI1_GPIO0_ALL (0x00f0) -#define MMCSD_GPIO1_WPIN (0x0400) -#define MMCSD_GPIO1_CPIN (0x8000) -#define MMCSD_GPIO1_ALL (MMCSD_GPIO1_WPIN|MMCSD_GPIO1_CPIN) +/* MMC/SD Pin Usage: + * + * STR-P711 PIN MMC/SD USAGE PIN CONFIGURATION + * ------------ ---------------- ----------------------- + * P0.7/S1.SS 1 CD/DAT3/CS P0.7 output + * P0.5/S1.MOSI 2 CMD/DI MOSI1 + * --- 3 VSS1 --- + * --- 4 VDD --- + * P0.6/S1.SCLK 5 CLK/SCLK SLCK1 + * --- 6 VSS2 --- + * P0.4/S1.MISO 7 DAT0/D0 MISO1 + * --- 8 DAT1/RES (Pulled up) + * --- 9 DAT2/RES (Pulled up) + * + * P1.10/USBCLK 10/14 WP P1.10 input + * P1.15/HTXD 13/15 CP P1.15 input + * + * Use of SPI1 doesn't conflict with anything. WP conflicts USB; CP conflicts + * with NTXD. + */ + +/* MMC/SD additional pins */ + +#define MMCSD_GPIO0_CS (1 << 7) +#define MMCSD_GPIO0_INTTL (0) +#define MMCSD_GPIO0_INCMOS (0) +#define MMCSD_GPIO0_OUTPP MMCSD_GPIO0_CS +#define MMCSD_GPIO0_ALL MMCSD_GPIO0_CS + +#define MMCSD_GPIO1_WPIN (1 << 10) +#define MMCSD_GPIO1_CPIN (1 << 15) +#define MMCSD_GPIO1_INTTL (MMCSD_GPIO1_WPIN|MMCSD_GPIO1_CPIN) +#define MMCSD_GPIO1_INCMOS (0) +#define MMCSD_GPIO1_OUTPP (0) +#define MMCSD_GPIO1_ALL (MMCSD_GPIO1_WPIN|MMCSD_GPIO1_CPIN) + +#define BSPI1_GPIO0_INTTL MMCSD_GPIO0_INTTL +#define BSPI1_GPIO0_INCMOS MMCSD_GPIO0_INCMOS +#define BSPI1_GPIO0_OUTPP MMCSD_GPIO0_OUTPP +#define BSPI1_GPIO0_ALL (BSPI1_GPIO0_ALT|MMCSD_GPIO0_ALL) + +#define BSPI1_GPIO1_INTTL MMCSD_GPIO1_INTTL +#define BSPI1_GPIO1_INCMOS MMCSD_GPIO1_INCMOS +#define BSPI1_GPIO1_OUTPP MMCSD_GPIO1_OUTPP +#define BSPI1_GPIO1_ALL MMCSD_GPIO1_ALL /* Configuration register settings ******************************************/ @@ -250,11 +366,18 @@ * Private Types ****************************************************************************/ +/* NOTE: As implemented here, this driver will support only one device per + * SPI bus: Only one chip select, csbit, per bus; no locking, not mode or + * bits-per-word settings. To support multiple devices per but, spi_select + * would also require some logic changes. + */ + struct str71x_spidev_s { - struct spi_dev_s spidev; /* Externally visible part of the SPI interface */ - uint32_t spibase; /* BSPIn base address */ - uint16_t csbit; /* BSPIn SS bit int GPIO0 */ + struct spi_dev_s spidev; /* Externally visible part of the SPI interface */ + bool initialized; /* Initialize port only once! */ + uint32_t spibase; /* BSPIn base address */ + uint16_t csbit; /* BSPIn SS bit int GPIO0 */ }; /**************************************************************************** @@ -265,6 +388,7 @@ struct str71x_spidev_s static inline uint16_t spi_getreg(FAR struct str71x_spidev_s *priv, uint8_t offset); static inline void spi_putreg(FAR struct str71x_spidev_s *priv, uint8_t offset, uint16_t value); +static inline void spi_drain(FAR struct str71x_spidev_s *priv); /* SPI methods */ @@ -296,7 +420,7 @@ static struct str71x_spidev_s g_spidev0 = { .spidev = { &g_spiops }, .spibase = STR71X_BSPI0_BASE, - .csbit = BSPI0_GPIO0_SS + .csbit = MMCSD_GPIO0_CS }; #endif @@ -305,7 +429,7 @@ static struct str71x_spidev_s g_spidev1 = { .spidev = { &g_spiops }, .spibase = STR71X_BSPI1_BASE, - .csbit = BSPI1_GPIO0_SS + .csbit = ENC_GPIO0_CS }; #endif @@ -358,6 +482,52 @@ static inline void spi_putreg(FAR struct str71x_spidev_s *priv, uint8_t offset, putreg16(value, priv->spibase + offset); } +/**************************************************************************** + * Name: spi_drain + * + * Description: + * Drain any bytes left in the fifos. + * + * Input Parameters: + * dev - Device-specific state data + * + * Returned Value: + * None + * + ****************************************************************************/ + +static inline void spi_drain(FAR struct str71x_spidev_s *priv) +{ +#if CONFIG_STR714X_BSPI0_TXFIFO_DEPTH > 1 + /* Wait while the TX FIFO is full */ + + while ((spi_getreg(priv, STR71X_BSPI_CSR2_OFFSET) & STR71X_BSPICSR2_TFF) != 0); +#else + /* Wait until the TX FIFO is empty */ + + while ((spi_getreg(priv, STR71X_BSPI_CSR2_OFFSET) & STR71X_BSPICSR2_TFE) == 0); +#endif + /* Write 0xff to the TX FIFO */ + + spi_putreg(priv, STR71X_BSPI_TXR_OFFSET, 0xff00); + + /* Wait for the TX FIFO empty */ + + while ((spi_getreg(priv, STR71X_BSPI_CSR2_OFFSET) & STR71X_BSPICSR2_TFNE) != 0); + + /* Wait for the RX FIFO not empty */ + + while ((spi_getreg(priv, STR71X_BSPI_CSR2_OFFSET) & STR71X_BSPICSR2_RFNE) == 0); + + /* Then read and discard bytes until the RX FIFO is empty */ + + do + { + (void)spi_getreg(priv, STR71X_BSPI_RXR_OFFSET); + } + while (spi_getreg(priv, STR71X_BSPI_CSR2_OFFSET & STR71X_BSPICSR2_RFNE) != 0); +} + /**************************************************************************** * Name: spi_select * @@ -398,34 +568,9 @@ static void spi_select(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool sel reg16 |= priv->csbit; spi_putreg(priv, STR71X_GPIO_PD_OFFSET, reg16); -#if CONFIG_STR714X_BSPI0_TXFIFO_DEPTH > 1 - /* Wait while the TX FIFO is full */ - - while ((spi_getreg(priv, STR71X_BSPI_CSR2_OFFSET) & STR71X_BSPICSR2_TFF) != 0); -#else - /* Wait until the TX FIFO is empty */ - - while ((spi_getreg(priv, STR71X_BSPI_CSR2_OFFSET) & STR71X_BSPICSR2_TFE) == 0); -#endif - /* Write 0xff to the TX FIFO */ - - spi_putreg(priv, STR71X_BSPI_TXR_OFFSET, 0xff00); - - /* Wait for the TX FIFO empty */ - - while ((spi_getreg(priv, STR71X_BSPI_CSR2_OFFSET) & STR71X_BSPICSR2_TFNE) != 0); + /* And drain the FIFOs */ - /* Wait for the RX FIFO not empty */ - - while ((spi_getreg(priv, STR71X_BSPI_CSR2_OFFSET) & STR71X_BSPICSR2_RFNE) == 0); - - /* Then read and discard bytes until the RX FIFO is empty */ - - do - { - (void)spi_getreg(priv, STR71X_BSPI_RXR_OFFSET); - } - while (spi_getreg(priv, STR71X_BSPI_CSR2_OFFSET & STR71X_BSPICSR2_RFNE) != 0); + spi_drain(priv); } } @@ -704,7 +849,8 @@ static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer, size_t bu * Name: up_spiinitialize * * Description: - * Initialize the selected SPI port + * Initialize the selected SPI port. This function could get called + * multiple times for each STR7 devices that needs an SPI reference. * * Input Parameter: * Port number (for hardware that has mutiple SPI interfaces) @@ -724,49 +870,87 @@ FAR struct spi_dev_s *up_spiinitialize(int port) #ifdef CONFIG_STR71X_BSPI0 if (port == 0) { - /* The default, alternate functionality of the GPIO0 pin selections is - * UART3/I2C1. In order to have BSP0 functionality, we also have to - * set the BSPI0 enable bit in the PCU BOOTCR register. - */ + /* Check if this port has already been initialized */ - reg16 = getreg16(STR71X_PCU_BOOTCR); - reg16 |= STR71X_PCUBOOTCR_BSPIOEN; - putreg16(reg16, STR71X_PCU_BOOTCR); + if (!g_spidev0.initialized) + { + /* The default, alternate functionality of the GPIO0 pin selections is + * UART3/I2C1. In order to have BSP0 functionality, we also have to + * set the BSPI0 enable bit in the PCU BOOTCR register. + */ + + reg16 = getreg16(STR71X_PCU_BOOTCR); + reg16 |= STR71X_PCUBOOTCR_BSPIOEN; + putreg16(reg16, STR71X_PCU_BOOTCR); + + /* Configure all GPIO pins to their appropriate function: + * + * PC0=1 PC1=1 PC2=1: Alternate function, push-pull + * PC0=1 PC1=0 PC2=0: In, TTL + * PC0=0 PC1=1 PC2=0: In, CMOS + * PC0=1 PC1=0 PC2=1: Output, push pull + */ + + reg16 = getreg16(STR71X_GPIO0_PC0); + reg16 &= ~BSPI0_GPIO0_ALL; + reg16 |= (BSPI0_GPIO0_ALT|BSPI0_GPIO0_INTTL|BSPI0_GPIO0_OUTPP); + putreg16(reg16, STR71X_GPIO0_PC0); + + reg16 = getreg16(STR71X_GPIO0_PC1); + reg16 &= ~BSPI0_GPIO0_ALL; + reg16 |= (BSPI0_GPIO0_ALT|BSPI0_GPIO0_INCMOS); + putreg16(reg16, STR71X_GPIO0_PC1); + + reg16 = getreg16(STR71X_GPIO0_PC2); + reg16 &= ~BSPI0_GPIO0_ALL; + reg16 |= (BSPI0_GPIO0_ALT|BSPI0_GPIO0_OUTPP); + putreg16(reg16, STR71X_GPIO0_PC2); + + /* Start with enc28j60 disabled */ + +#ifdef CONFIG_NET_ENC28J60 + reg16 = getreg16(STR71X_GPIO0_PD); + reg16 |= ENC_GPIO0_CS; + putreg16(reg16, STR71X_GPIO0_PD); +#endif - /* Configure all GPIO pins to their alternate function EXCEPT - * for the SS pin .. will will configure that as an output - * and control the chip select as a normal GPIO. - */ + /* Set the clock divider to the maximum */ - reg16 = getreg16(STR71X_GPIO0_PC0); - reg16 |= BSPIO_GPIO0_ALL; - putreg16(reg16, STR71X_GPIO0_PC0); + putreg16(255, STR71X_BSPI0_CLK); - reg16 = getreg16(STR71X_GPIO0_PC1); - reg16 &= ~BSPIO_GPIO0_ALL; - reg16 |= BSPIO_GPIO0_ALT; - putreg16(reg16, STR71X_GPIO0_PC1); + /* Set FIFO sizes and disable the BSP1. It won't be enabled + * until the frequency is set. + */ - reg16 = getreg16(STR71X_GPIO0_PC2); - reg16 |= BSPIO_GPIO0_ALL; - putreg16(reg16, STR71X_GPIO0_PC2); + putreg16(STR71X_BSPI0_CSR1DISABLE, STR71X_BSPI0_CSR1); + putreg16(STR71X_BSPI0_CSR2VALUE, STR71X_BSPI0_CSR2); - /* Start with chip slave disabled */ + /* Configure GPIO1 pins for ENC28J60 inputs and outputs. + * + * PC0=1 PC1=0 PC2=0: In, TTL + * PC0=0 PC1=1 PC2=0: In, CMOS + * PC0=1 PC1=0 PC2=1: Output, push pull + */ - reg16 = getreg16(STR71X_GPIO0_PD); - reg16 |= BSPI0_GPIO0_SS; - putreg16(reg16, STR71X_GPIO0_PD); + reg16 = getreg16(STR71X_GPIO1_PC0); + reg16 &= ~BSPI0_GPIO1_ALL; + reg16 |= (BSPI0_GPIO1_INTTL|BSPI0_GPIO1_OUTPP); + putreg16(reg16, STR71X_GPIO1_PC0); - /* Set the clock divider to the maximum */ + reg16 = getreg16(STR71X_GPIO1_PC1); + reg16 &= ~BSPI0_GPIO1_ALL; + reg16 |= BSPI0_GPIO0_INCMOS; + putreg16(reg16, STR71X_GPIO1_PC1); - putreg16(255, STR71X_BSPI0_CLK); + reg16 = getreg16(STR71X_GPIO1_PC2); + reg16 &= ~BSPI0_GPIO1_ALL; + reg16 |= BSPI0_GPIO0_OUTPP; + putreg16(reg16, STR71X_GPIO1_PC2); - /* Set FIFO sizes and disable the BSP1. It won't be enabled - * until the frequency is set. - */ + g_spidev0.initialized = true; + } - putreg16(STR71X_BSPI0_CSR1DISABLE, STR71X_BSPI0_CSR1); - putreg16(STR71X_BSPI0_CSR2VALUE, STR71X_BSPI0_CSR2); + /* Return the SPI device reference */ ret = &g_spidev0.spidev; } @@ -775,54 +959,79 @@ FAR struct spi_dev_s *up_spiinitialize(int port) #ifdef CONFIG_STR71X_BSPI1 if (port == 1) { - /* Configure all GPIO pins to their alternate function EXCEPT - * for the SS pin .. will will configure that as an output - * and control the chip select as a normal GPIO. - */ - - reg16 = getreg16(STR71X_GPIO0_PC0); - reg16 |= BSPI1_GPIO0_ALL; - putreg16(reg16, STR71X_GPIO0_PC0); - - reg16 = getreg16(STR71X_GPIO0_PC1); - reg16 &= ~BSPI1_GPIO0_ALL; - reg16 |= BSPI1_GPIO0_ALT; - putreg16(reg16, STR71X_GPIO0_PC1); - - reg16 = getreg16(STR71X_GPIO0_PC2); - reg16 |= BSPI1_GPIO0_ALL; - putreg16(reg16, STR71X_GPIO0_PC2); - - /* Start with chip slave disabled */ - - reg16 = getreg16(STR71X_GPIO0_PD); - reg16 |= BSPI1_GPIO0_SS; - putreg16(reg16, STR71X_GPIO0_PD); + /* Check if this port has already been initialized */ - /* Set the clock divider to the maximum */ - - putreg16(255, STR71X_BSPI1_CLK); - - /* Set FIFO sizes and disable the BSP1. It won't be enabled - * until the frequency is set. - */ - - putreg16(STR71X_BSPI1_CSR1DISABLE, STR71X_BSPI1_CSR1); - putreg16(STR71X_BSPI1_CSR2VALUE, STR71X_BSPI1_CSR2); - - /* Configure GPIO1 pins for WP/CP input */ - - reg16 = getreg16(STR71X_GPIO1_PC0); - reg16 |= MMCSD_GPIO1_ALL; - putreg16(reg16, STR71X_GPIO1_PC0); - - reg16 = getreg16(STR71X_GPIO1_PC1); - reg16 &= ~MMCSD_GPIO1_ALL; - putreg16(reg16, STR71X_GPIO1_PC1); + if (!g_spidev1.initialized) + { + /* Configure all GPIO pins to their alternate function EXCEPT for + * the CS pin .. we will configure that as an push-pull output + * and control the chip select as a normal GPIO. + * + * PC0=1 PC1=1 PC2=1: Alternate function, push-pull + * PC0=1 PC1=0 PC2=0: In, TTL + * PC0=0 PC1=1 PC2=0: In, CMOS + * PC0=1 PC1=0 PC2=1: Output, push pull + */ + + reg16 = getreg16(STR71X_GPIO0_PC0); + reg16 &= ~BSPI1_GPIO0_ALL; + reg16 |= (BSPI1_GPIO0_ALT|BSPI1_GPIO0_INTTL|BSPI1_GPIO0_OUTPP); + putreg16(reg16, STR71X_GPIO0_PC0); + + reg16 = getreg16(STR71X_GPIO0_PC1); + reg16 &= ~BSPI1_GPIO0_ALL; + reg16 |= (BSPI1_GPIO0_ALT|BSPI1_GPIO0_INCMOS); + putreg16(reg16, STR71X_GPIO0_PC1); + + reg16 = getreg16(STR71X_GPIO0_PC2); + reg16 &= ~BSPI1_GPIO0_ALL; + reg16 |= (BSPI1_GPIO0_ALT|BSPI1_GPIO0_OUTPP); + putreg16(reg16, STR71X_GPIO0_PC2); + + /* Start with MMC/SD disabled */ + + reg16 = getreg16(STR71X_GPIO0_PD); + reg16 |= MMCSD_GPIO0_CS; + putreg16(reg16, STR71X_GPIO0_PD); + + /* Set the clock divider to the maximum */ + + putreg16(255, STR71X_BSPI1_CLK); + + /* Set FIFO sizes and disable the BSP1. It won't be enabled + * until the frequency is set. + */ + + putreg16(STR71X_BSPI1_CSR1DISABLE, STR71X_BSPI1_CSR1); + putreg16(STR71X_BSPI1_CSR2VALUE, STR71X_BSPI1_CSR2); + + /* Configure GPIO1 pins for WP/CP input + * + * PC0=1 PC1=0 PC2=0: In, TTL + * PC0=0 PC1=1 PC2=0: In, CMOS + * PC0=1 PC1=0 PC2=1: Output, push pull + */ + +#ifdef BSPI1_GPIO1_ALL + reg16 = getreg16(STR71X_GPIO1_PC0); + reg16 &= ~BSPI1_GPIO1_ALL; + reg16 |= (BSPI1_GPIO1_INTTL|BSPI1_GPIO1_OUTPP); + putreg16(reg16, STR71X_GPIO1_PC0); + + reg16 = getreg16(STR71X_GPIO1_PC1); + reg16 &= ~BSPI1_GPIO1_ALL; + reg16 |= BSPI1_GPIO0_INCMOS; + putreg16(reg16, STR71X_GPIO1_PC1); + + reg16 = getreg16(STR71X_GPIO1_PC2); + reg16 &= ~BSPI1_GPIO1_ALL; + reg16 |= BSPI1_GPIO0_OUTPP; + putreg16(reg16, STR71X_GPIO1_PC2); +#endif + g_spidev1.initialized = true; + } - reg16 = getreg16(STR71X_GPIO1_PC2); - reg16 &= ~MMCSD_GPIO1_ALL; - putreg16(reg16, STR71X_GPIO1_PC2); + /* Return the SPI device reference */ ret = &g_spidev1.spidev; } -- cgit v1.2.3