1 /**************************************************************************//**
\r
3 * @brief SPI implementation of Board Control interface
\r
4 * This implementation use the USART2 SPI interface to control board
\r
5 * control registers. It works
\r
6 * @author Energy Micro AS
\r
8 ******************************************************************************
\r
10 * <b>(C) Copyright 2009 Energy Micro AS, http://www.energymicro.com</b>
\r
11 ******************************************************************************
\r
13 * This source code is the property of Energy Micro AS. The source and compiled
\r
14 * code may only be used on Energy Micro "EFM32" microcontrollers.
\r
16 * This copyright notice may not be removed from the source code nor changed.
\r
18 * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Energy Micro AS has no
\r
19 * obligation to support this Software. Energy Micro AS is providing the
\r
20 * Software "AS IS", with no express or implied warranties of any kind,
\r
21 * including, but not limited to, any implied warranties of merchantability
\r
22 * or fitness for any particular purpose or warranties against infringement
\r
23 * of any proprietary rights of a third party.
\r
25 * Energy Micro AS will not be liable for any consequential, incidental, or
\r
26 * special damages, or any other relief, or for any claim by any third party,
\r
27 * arising from your use of this Software.
\r
29 *****************************************************************************/
\r
33 #include "dvk_bcregisters.h"
\r
35 #define clear_bit(reg, bit) (reg &= ~(1 << bit))
\r
37 static volatile uint16_t *lastAddr = 0;
\r
39 /**************************************************************************//**
\r
40 * @brief Initializes USART2 SPI interface for access to FPGA registers
\r
42 *****************************************************************************/
\r
43 static void spiInit(void)
\r
45 USART_TypeDef *usart = USART2;
\r
46 GPIO_TypeDef *gpio = GPIO;
\r
47 uint32_t clk, spidiv;
\r
48 const uint32_t baudrate = 7000000;
\r
49 const uint32_t div = (2 * baudrate / 256);
\r
51 /* Configure SPI bus connect pins */
\r
52 gpio->P[2].MODEH &= ~(_GPIO_P_MODEH_MODE13_MASK);
\r
53 gpio->P[2].MODEH |= (GPIO_P_MODEH_MODE13_PUSHPULL);
\r
54 gpio->P[2].DOUT &= ~(1UL << 13);
\r
56 /* Configure SPI pins */
\r
57 gpio->P[2].MODEL &= ~(_GPIO_P_MODEL_MODE2_MASK |
\r
58 _GPIO_P_MODEL_MODE3_MASK |
\r
59 _GPIO_P_MODEL_MODE4_MASK |
\r
60 _GPIO_P_MODEL_MODE5_MASK);
\r
61 gpio->P[2].MODEL |= (GPIO_P_MODEL_MODE2_PUSHPULL |
\r
62 GPIO_P_MODEL_MODE3_PUSHPULL |
\r
63 GPIO_P_MODEL_MODE4_PUSHPULL |
\r
64 GPIO_P_MODEL_MODE5_PUSHPULL);
\r
65 gpio->P[2].DOUT |= (1UL << 5);
\r
67 /* Configure USART2 as SPI master with manual CS */
\r
68 /* Get peripheral clock - ensure updated SystemCoreClock */
\r
69 SystemCoreClockUpdate();
\r
70 clk = (SystemCoreClock >> ((CMU->HFPERCLKDIV & _CMU_HFPERCLKDIV_HFPERCLKDIV_MASK) >>
\r
71 _CMU_HFPERCLKDIV_HFPERCLKDIV_SHIFT));
\r
72 /* Drive spi at max 7Mhz or half clockrate if core freq < 14Mhz */
\r
79 spidiv = (clk) / (div) - 256;
\r
82 /* Never allow higher frequency than specified, round up 1/4 div */
\r
83 if (spidiv & 0x3f) spidiv += 0x40;
\r
85 usart->CLKDIV = spidiv;
\r
86 usart->CTRL = USART_CTRL_SYNC;
\r
87 usart->CMD = USART_CMD_CLEARRX | USART_CMD_CLEARTX;
\r
88 usart->ROUTE = USART_ROUTE_TXPEN | USART_ROUTE_RXPEN | USART_ROUTE_CLKPEN;
\r
89 usart->CMD = USART_CMD_MASTEREN | USART_CMD_TXEN | USART_CMD_RXEN;
\r
92 /**************************************************************************//**
\r
93 * @brief Disables GPIO pins and USART2 from FPGA register access
\r
94 *****************************************************************************/
\r
95 static void spiDisable(void)
\r
97 USART_TypeDef *usart = USART2;
\r
98 GPIO_TypeDef *gpio = GPIO;
\r
100 /* Disable USART2 */
\r
101 usart->CTRL = _USART_CTRL_RESETVALUE;
\r
102 usart->ROUTE = _USART_ROUTE_RESETVALUE;
\r
103 usart->CMD = USART_CMD_MASTERDIS | USART_CMD_TXDIS | USART_CMD_RXDIS;
\r
105 /* Disable SPI pins */
\r
106 gpio->P[2].MODEH &= ~(_GPIO_P_MODEH_MODE13_MASK);
\r
107 gpio->P[2].MODEL &= ~(_GPIO_P_MODEL_MODE2_MASK |
\r
108 _GPIO_P_MODEL_MODE3_MASK |
\r
109 _GPIO_P_MODEL_MODE4_MASK |
\r
110 _GPIO_P_MODEL_MODE5_MASK);
\r
113 /**************************************************************************//**
\r
114 * @brief Performs USART2 SPI Transfer
\r
115 *****************************************************************************/
\r
116 static uint16_t spiAccess(uint8_t spiadr, uint8_t rw, uint16_t spidata)
\r
118 USART_TypeDef *usart = USART2;
\r
119 GPIO_TypeDef *gpio = GPIO;
\r
122 clear_bit(gpio->P[2].DOUT, 5);
\r
125 usart->TXDATA = (spiadr & 0x3) | rw << 3;
\r
126 while (!(usart->STATUS & USART_STATUS_TXC)) ;
\r
127 tmp = (usart->RXDATA) << 0;
\r
130 usart->TXDATA = spidata & 0xFF;
\r
131 while (!(usart->STATUS & USART_STATUS_TXC)) ;
\r
132 tmp = (usart->RXDATA);
\r
135 usart->TXDATA = spidata >> 8;
\r
136 while (!(usart->STATUS & USART_STATUS_TXC)) ;
\r
137 tmp |= (usart->RXDATA) << 8;
\r
139 gpio->P[2].DOUT |= (1 << 5);
\r
144 /**************************************************************************//**
\r
145 * @brief Performs USART2 SPI write to FPGA register
\r
146 * @param spiadr Address of register
\r
147 * @param spidata Data to write
\r
148 *****************************************************************************/
\r
149 static void spiWrite(uint8_t spiadr, uint16_t spidata)
\r
151 spiAccess(spiadr, 0, spidata);
\r
154 /**************************************************************************//**
\r
155 * @brief Performs USART2 SPI read from FPGA register
\r
156 * @param spiadr Address of register
\r
157 * @param spidata Dummy data
\r
158 *****************************************************************************/
\r
159 static uint16_t spiRead(uint8_t spiadr, uint16_t spidata)
\r
161 return spiAccess(spiadr, 1, spidata);
\r
164 /**************************************************************************//**
\r
165 * @brief Initializes DVK register access
\r
166 *****************************************************************************/
\r
167 void DVK_SPI_init(void)
\r
172 /* Read "board control Magic" register to verify SPI is up and running */
\r
173 /* if not FPGA is configured to be in EBI mode */
\r
175 spiMagic = DVK_SPI_readRegister(BC_MAGIC);
\r
176 if (spiMagic != BC_MAGIC_VALUE)
\r
178 /* Development Kit is configured to use EBI mode, restart of kit required */
\r
179 /* to use USART2-SPI for configuration */
\r
185 /**************************************************************************//**
\r
186 * @brief Disable and free up resources used by SPI board control access
\r
187 *****************************************************************************/
\r
188 void DVK_SPI_disable(void)
\r
193 /**************************************************************************//**
\r
194 * @brief Perform read from DVK board control register
\r
195 * @param addr Address of register to read from
\r
196 *****************************************************************************/
\r
197 uint16_t DVK_SPI_readRegister(volatile uint16_t *addr)
\r
201 if (addr != lastAddr)
\r
203 spiWrite(0x00, 0xFFFF & ((uint32_t) addr)); /*LSBs of address*/
\r
204 spiWrite(0x01, 0xFF & ((uint32_t) addr >> 16)); /*MSBs of address*/
\r
205 spiWrite(0x02, (0x0C000000 & (uint32_t) addr) >> 26); /*Chip select*/
\r
208 data = spiRead(0x03, 0);
\r
209 data = spiRead(0x03, 0);
\r
214 /**************************************************************************//**
\r
215 * @brief Perform write to DVK board control register
\r
216 * @param addr Address of register to write to
\r
217 * @param data 16-bit to write into register
\r
218 *****************************************************************************/
\r
219 void DVK_SPI_writeRegister(volatile uint16_t *addr, uint16_t data)
\r
221 if (addr != lastAddr)
\r
223 spiWrite(0x00, 0xFFFF & ((uint32_t) addr)); /*LSBs of address*/
\r
224 spiWrite(0x01, 0xFF & ((uint32_t) addr >> 16)); /*MSBs of address*/
\r
225 spiWrite(0x02, (0x0C000000 & (uint32_t) addr) >> 26); /*Chip select*/
\r
227 spiWrite(0x03, data); /*Data*/
\r