1 /*******************************************************************************
2 * Copyright (C) 2015 Maxim Integrated Products, Inc., All Rights Reserved.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
18 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
22 * Except as contained in this notice, the name of Maxim Integrated
23 * Products, Inc. shall not be used except as stated in the Maxim Integrated
24 * Products, Inc. Branding Policy.
26 * The mere transfer of this software does not imply any licenses
27 * of trade secrets, proprietary technology, copyrights, patents,
28 * trademarks, maskwork rights, or any other form of intellectual
29 * property whatsoever. Maxim Integrated Products, Inc. retains all
31 *******************************************************************************
35 #include "mbed_assert.h"
39 #include "ioman_regs.h"
40 #include "clkman_regs.h"
41 #include "PeripheralPins.h"
43 #define DEFAULT_CHAR 8
44 #define DEFAULT_MODE 0
45 #define DEFAULT_FREQ 1000000
47 // Formatting settings
50 //******************************************************************************
51 void spi_init(spi_t
*obj
, PinName mosi
, PinName miso
, PinName sclk
, PinName ssel
)
53 // Make sure pins are pointing to the same SPI instance
54 SPIName spi_mosi
= (SPIName
)pinmap_peripheral(mosi
, PinMap_SPI_MOSI
);
55 SPIName spi_miso
= (SPIName
)pinmap_peripheral(miso
, PinMap_SPI_MISO
);
56 SPIName spi_sclk
= (SPIName
)pinmap_peripheral(sclk
, PinMap_SPI_SCLK
);
57 SPIName spi_ssel
= (SPIName
)pinmap_peripheral(ssel
, PinMap_SPI_SSEL
);
59 SPIName spi_data
= (SPIName
)pinmap_merge(spi_mosi
, spi_miso
);
62 // Give the application the option to manually control Slave Select
63 if((SPIName
)spi_ssel
!= (SPIName
)NC
) {
64 spi_cntl
= (SPIName
)pinmap_merge(spi_sclk
, spi_ssel
);
69 SPIName spi
= (SPIName
)pinmap_merge(spi_data
, spi_cntl
);
71 MBED_ASSERT((SPIName
)spi
!= (SPIName
)NC
);
73 // Set the obj pointer to the proper SPI Instance
74 obj
->spi
= (mxc_spi_regs_t
*)spi
;
76 // Set the SPI index and FIFOs
77 obj
->index
= MXC_SPI_BASE_TO_INSTANCE(obj
->spi
);
78 obj
->rxfifo
= MXC_SPI_GET_RXFIFO(obj
->index
);
79 obj
->txfifo
= MXC_SPI_GET_TXFIFO(obj
->index
);
82 pinmap_pinout(mosi
, PinMap_SPI_MOSI
);
83 pinmap_pinout(miso
, PinMap_SPI_MISO
);
84 pinmap_pinout(sclk
, PinMap_SPI_SCLK
);
85 pinmap_pinout(ssel
, PinMap_SPI_SSEL
);
87 // Enable SPI and FIFOs
88 obj
->spi
->gen_ctrl
= (MXC_F_SPI_GEN_CTRL_SPI_MSTR_EN
|
89 MXC_F_SPI_GEN_CTRL_TX_FIFO_EN
|
90 MXC_F_SPI_GEN_CTRL_RX_FIFO_EN
);
92 // Give instance the default settings
93 spi_format(obj
, DEFAULT_CHAR
, DEFAULT_MODE
, 0);
94 spi_frequency(obj
, DEFAULT_FREQ
);
97 //******************************************************************************
98 void spi_format(spi_t
*obj
, int bits
, int mode
, int slave
)
100 // Check the validity of the inputs
101 MBED_ASSERT(((bits
>= 1) && (bits
<= 32)) && ((mode
>= 0) && (mode
<= 3)));
103 // Only supports master mode
106 // Save formatting data
110 obj
->spi
->mstr_cfg
&= ~(MXC_F_SPI_MSTR_CFG_SPI_MODE
);
111 obj
->spi
->mstr_cfg
|= (mode
<< MXC_F_SPI_MSTR_CFG_SPI_MODE_POS
);
114 //******************************************************************************
115 void spi_frequency(spi_t
*obj
, int hz
)
117 // Maximum frequency is half the system frequency
118 MBED_ASSERT((unsigned int)hz
< (SystemCoreClock
/ 2));
119 unsigned clocks
= ((SystemCoreClock
/2)/(hz
));
121 // Figure out the divider ratio
123 while(clk_div
< 10) {
128 clocks
= clocks
>> 1;
131 // Turn on the SPI clock
132 if(obj
->index
== 0) {
133 MXC_CLKMAN
->clk_ctrl_3_spi0
= clk_div
;
134 } else if(obj
->index
== 1) {
135 MXC_CLKMAN
->clk_ctrl_4_spi1
= clk_div
;
136 } else if(obj
->index
== 2) {
137 MXC_CLKMAN
->clk_ctrl_5_spi2
= clk_div
;
142 // Set the number of clocks to hold sclk high and low
143 MXC_SET_FIELD(&obj
->spi
->mstr_cfg
, (MXC_F_SPI_MSTR_CFG_SCK_HI_CLK
| MXC_F_SPI_MSTR_CFG_SCK_LO_CLK
),
144 ((clocks
<< MXC_F_SPI_MSTR_CFG_SCK_HI_CLK_POS
) | (clocks
<< MXC_F_SPI_MSTR_CFG_SCK_LO_CLK_POS
)));
147 //******************************************************************************
148 int spi_master_write(spi_t
*obj
, int value
)
155 uint16_t header
= ((0x3 << MXC_F_SPI_FIFO_DIR_POS
) | // TX and RX
156 (0x0 << MXC_F_SPI_FIFO_UNIT_POS
) | // Send bits
157 (bits
<< MXC_F_SPI_FIFO_SIZE_POS
) | // Number of units
158 (0x1 << MXC_F_SPI_FIFO_DASS_POS
)); // Deassert SS
160 // Send the message header
161 obj
->txfifo
->txfifo_16
= header
;
165 obj
->txfifo
->txfifo_16
= (uint16_t)value
;
167 obj
->txfifo
->txfifo_32
= (uint32_t)value
;
176 while(((obj
->spi
->fifo_ctrl
& MXC_F_SPI_FIFO_CTRL_RX_FIFO_USED
)
177 >> MXC_F_SPI_FIFO_CTRL_RX_FIFO_USED_POS
) < 1) {}
179 result
|= (obj
->rxfifo
->rxfifo_8
<< (i
++*8));
186 //******************************************************************************
187 int spi_busy(spi_t
*obj
)
189 return !(obj
->spi
->intfl
& MXC_F_SPI_INTFL_TX_READY
);