lpc176x: Add support for ssp1 (#2393)
Signed-off-by: Andrey Kovalev <aka@pxe.ru>
This commit is contained in:
parent
b70416167b
commit
b3c3b61387
|
@ -30,6 +30,7 @@ uint16_t gpio_adc_read(struct gpio_adc g);
|
||||||
void gpio_adc_cancel_sample(struct gpio_adc g);
|
void gpio_adc_cancel_sample(struct gpio_adc g);
|
||||||
|
|
||||||
struct spi_config {
|
struct spi_config {
|
||||||
|
void *spi;
|
||||||
uint32_t cr0, cpsr;
|
uint32_t cr0, cpsr;
|
||||||
};
|
};
|
||||||
struct spi_config spi_setup(uint32_t bus, uint8_t mode, uint32_t rate);
|
struct spi_config spi_setup(uint32_t bus, uint8_t mode, uint32_t rate);
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
#define PCLK_TIMER0 1
|
#define PCLK_TIMER0 1
|
||||||
#define PCLK_UART0 3
|
#define PCLK_UART0 3
|
||||||
|
#define PCLK_SSP1 10
|
||||||
#define PCLK_ADC 12
|
#define PCLK_ADC 12
|
||||||
#define PCLK_I2C1 19
|
#define PCLK_I2C1 19
|
||||||
#define PCLK_SSP0 21
|
#define PCLK_SSP0 21
|
||||||
|
|
|
@ -9,42 +9,55 @@
|
||||||
#include "internal.h" // gpio_peripheral
|
#include "internal.h" // gpio_peripheral
|
||||||
#include "sched.h" // sched_shutdown
|
#include "sched.h" // sched_shutdown
|
||||||
|
|
||||||
|
struct spi_info {
|
||||||
|
LPC_SSP_TypeDef *spi;
|
||||||
|
uint8_t miso_pin, mosi_pin, sck_pin, pclk;
|
||||||
|
};
|
||||||
|
|
||||||
DECL_ENUMERATION("spi_bus", "ssp0", 0);
|
DECL_ENUMERATION("spi_bus", "ssp0", 0);
|
||||||
DECL_CONSTANT_STR("BUS_PINS_ssp0", "P0.17,P0.18,P0.15");
|
DECL_CONSTANT_STR("BUS_PINS_ssp0", "P0.17,P0.18,P0.15");
|
||||||
|
DECL_ENUMERATION("spi_bus", "ssp1", 1);
|
||||||
|
DECL_CONSTANT_STR("BUS_PINS_ssp1", "P0.8,P0.9,P0.7");
|
||||||
|
|
||||||
|
static const struct spi_info spi_bus[] = {
|
||||||
|
{ LPC_SSP0, GPIO(0, 17), GPIO(0, 18), GPIO(0, 15), PCLK_SSP0 },
|
||||||
|
{ LPC_SSP1, GPIO(0, 8), GPIO(0, 9), GPIO(0, 7), PCLK_SSP1 },
|
||||||
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
spi_init(void)
|
spi_init(uint32_t bus)
|
||||||
{
|
{
|
||||||
static int have_run_init;
|
static int have_run_init[ARRAY_SIZE(spi_bus)];
|
||||||
if (have_run_init)
|
if (have_run_init[bus])
|
||||||
return;
|
return;
|
||||||
have_run_init = 1;
|
have_run_init[bus] = 1;
|
||||||
|
|
||||||
// Configure MISO0, MOSI0, SCK0 pins
|
// Configure MISO0, MOSI0, SCK0 pins
|
||||||
gpio_peripheral(GPIO(0, 17), 2, 0);
|
gpio_peripheral(spi_bus[bus].miso_pin, 2, 0);
|
||||||
gpio_peripheral(GPIO(0, 18), 2, 0);
|
gpio_peripheral(spi_bus[bus].mosi_pin, 2, 0);
|
||||||
gpio_peripheral(GPIO(0, 15), 2, 0);
|
gpio_peripheral(spi_bus[bus].sck_pin, 2, 0);
|
||||||
|
|
||||||
// Setup clock
|
// Setup clock
|
||||||
enable_pclock(PCLK_SSP0);
|
enable_pclock(spi_bus[bus].pclk);
|
||||||
|
|
||||||
// Set initial registers
|
// Set initial registers
|
||||||
LPC_SSP0->CR0 = 0x07;
|
LPC_SSP_TypeDef *spi = spi_bus[bus].spi;
|
||||||
LPC_SSP0->CPSR = 254;
|
spi->CR0 = 0x07;
|
||||||
LPC_SSP0->CR1 = 1<<1;
|
spi->CPSR = 254;
|
||||||
|
spi->CR1 = 1<<1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct spi_config
|
struct spi_config
|
||||||
spi_setup(uint32_t bus, uint8_t mode, uint32_t rate)
|
spi_setup(uint32_t bus, uint8_t mode, uint32_t rate)
|
||||||
{
|
{
|
||||||
if (bus)
|
if (bus >= ARRAY_SIZE(spi_bus))
|
||||||
shutdown("Invalid spi_setup parameters");
|
shutdown("Invalid spi_setup parameters");
|
||||||
|
|
||||||
// Make sure bus is enabled
|
// Make sure bus is enabled
|
||||||
spi_init();
|
spi_init(bus);
|
||||||
|
|
||||||
// Setup clock rate and mode
|
// Setup clock rate and mode
|
||||||
struct spi_config res = {0, 0};
|
struct spi_config res = {spi_bus[bus].spi, 0, 0};
|
||||||
uint32_t pclk = SystemCoreClock;
|
uint32_t pclk = SystemCoreClock;
|
||||||
uint32_t div = DIV_ROUND_UP(pclk/2, rate) << 1;
|
uint32_t div = DIV_ROUND_UP(pclk/2, rate) << 1;
|
||||||
res.cpsr = div < 2 ? 2 : (div > 254 ? 254 : div);
|
res.cpsr = div < 2 ? 2 : (div > 254 ? 254 : div);
|
||||||
|
@ -56,31 +69,33 @@ spi_setup(uint32_t bus, uint8_t mode, uint32_t rate)
|
||||||
void
|
void
|
||||||
spi_prepare(struct spi_config config)
|
spi_prepare(struct spi_config config)
|
||||||
{
|
{
|
||||||
LPC_SSP0->CR0 = config.cr0;
|
LPC_SSP_TypeDef *spi = config.spi;
|
||||||
LPC_SSP0->CPSR = config.cpsr;
|
spi->CR0 = config.cr0;
|
||||||
|
spi->CPSR = config.cpsr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
spi_transfer(struct spi_config config, uint8_t receive_data
|
spi_transfer(struct spi_config config, uint8_t receive_data
|
||||||
, uint8_t len, uint8_t *data)
|
, uint8_t len, uint8_t *data)
|
||||||
{
|
{
|
||||||
|
LPC_SSP_TypeDef *spi = config.spi;
|
||||||
if (receive_data) {
|
if (receive_data) {
|
||||||
while (len--) {
|
while (len--) {
|
||||||
LPC_SSP0->DR = *data;
|
spi->DR = *data;
|
||||||
// wait for read data to be ready
|
// wait for read data to be ready
|
||||||
while (!(LPC_SSP0->SR & (1<<2)))
|
while (!(spi->SR & (1<<2)))
|
||||||
;
|
;
|
||||||
// get data
|
// get data
|
||||||
*data++ = LPC_SSP0->DR;
|
*data++ = spi->DR;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
while (len--) {
|
while (len--) {
|
||||||
LPC_SSP0->DR = *data++;
|
spi->DR = *data++;
|
||||||
// wait for read data to be ready
|
// wait for read data to be ready
|
||||||
while (!(LPC_SSP0->SR & (1<<2)))
|
while (!(spi->SR & (1<<2)))
|
||||||
;
|
;
|
||||||
// read data (to clear receive fifo)
|
// read data (to clear receive fifo)
|
||||||
LPC_SSP0->DR;
|
spi->DR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue