Skip to content

Commit

Permalink
Address review comments
Browse files Browse the repository at this point in the history
Use size_t instead of uint32_t wherever appropriate
Use unsigned int instead of uint32_t wherever appropriate
Use *num_rxpkts as inout to indicate size of rx buf
Add assert() to check inputs in sanity check function
Simplify txrx functions
Rm pl022_init() and integrate it into pl022_configure()
Add panic() to error checking in pl022_configure()
  • Loading branch information
Victor Chong committed Jul 9, 2016
1 parent 92d681a commit 4c1bfb2
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 129 deletions.
203 changes: 86 additions & 117 deletions core/drivers/pl022_spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include <gpio.h>
#include <initcall.h>
#include <io.h>
#include <kernel/panic.h>
#include <kernel/tee_time.h>
#include <trace.h>
#include <util.h>
Expand All @@ -40,8 +41,8 @@
#define SSPCR1 0x004
#define SSPDR 0x008
#define SSPSR 0x00C
#define SSPCPSR 0x010
#define SSPIMSC 0x014
#define SSPCPSR 0x010
#define SSPIMSC 0x014
#define SSPRIS 0x018
#define SSPMIS 0x01C
#define SSPICR 0x020
Expand All @@ -53,10 +54,10 @@
#define SSPB2BTRANS 0x030

/* test registers */
#define SSPTCR 0x080
#define SSPTCR 0x080
#define SSPITIP 0x084
#define SSPITOP 0x088
#define SSPTDR 0x08C
#define SSPTDR 0x08C

#define SSPPeriphID0 0xFE0
#define SSPPeriphID1 0xFE4
Expand All @@ -69,29 +70,29 @@
#define SSPPCellID3 0xFFC

/* spi register masks */
#define SSPCR0_SCR SHIFT_U32(0xFF, 8)
#define SSPCR0_SPH SHIFT_U32(1, 7)
#define SSPCR0_SPH1 SHIFT_U32(1, 7)
#define SSPCR0_SPH0 SHIFT_U32(0, 7)
#define SSPCR0_SPO SHIFT_U32(1, 6)
#define SSPCR0_SPO1 SHIFT_U32(1, 6)
#define SSPCR0_SPO0 SHIFT_U32(0, 6)
#define SSPCR0_FRF SHIFT_U32(3, 4)
#define SSPCR0_SCR SHIFT_U32(0xFF, 8)
#define SSPCR0_SPH SHIFT_U32(1, 7)
#define SSPCR0_SPH1 SHIFT_U32(1, 7)
#define SSPCR0_SPH0 SHIFT_U32(0, 7)
#define SSPCR0_SPO SHIFT_U32(1, 6)
#define SSPCR0_SPO1 SHIFT_U32(1, 6)
#define SSPCR0_SPO0 SHIFT_U32(0, 6)
#define SSPCR0_FRF SHIFT_U32(3, 4)
#define SSPCR0_FRF_SPI SHIFT_U32(0, 4)
#define SSPCR0_DSS SHIFT_U32(0xFF, 0)
#define SSPCR0_DSS SHIFT_U32(0xFF, 0)
#define SSPCR0_DSS_16BIT SHIFT_U32(0xF, 0)
#define SSPCR0_DSS_8BIT SHIFT_U32(7, 0)
#define SSPCR0_DSS_8BIT SHIFT_U32(7, 0)

#define SSPCR1_SOD SHIFT_U32(1, 3)
#define SSPCR1_SOD SHIFT_U32(1, 3)
#define SSPCR1_SOD_ENABLE SHIFT_U32(1, 3)
#define SSPCR1_SOD_DISABLE SHIFT_U32(0, 3)
#define SSPCR1_MS SHIFT_U32(1, 2)
#define SSPCR1_MS_SLAVE SHIFT_U32(1, 2)
#define SSPCR1_MS SHIFT_U32(1, 2)
#define SSPCR1_MS_SLAVE SHIFT_U32(1, 2)
#define SSPCR1_MS_MASTER SHIFT_U32(0, 2)
#define SSPCR1_SSE SHIFT_U32(1, 1)
#define SSPCR1_SSE SHIFT_U32(1, 1)
#define SSPCR1_SSE_ENABLE SHIFT_U32(1, 1)
#define SSPCR1_SSE_DISABLE SHIFT_U32(0, 1)
#define SSPCR1_LBM SHIFT_U32(1, 0)
#define SSPCR1_LBM SHIFT_U32(1, 0)
#define SSPCR1_LBM_YES SHIFT_U32(1, 0)
#define SSPCR1_LBM_NO SHIFT_U32(0, 0)

Expand Down Expand Up @@ -120,7 +121,7 @@
#define SSPMIS_RTMIS SHIFT_U32(1, 1)
#define SSPMIS_RORMIS SHIFT_U32(1, 0)

#define SSPICR_RTIC SHIFT_U32(1, 1)
#define SSPICR_RTIC SHIFT_U32(1, 1)
#define SSPICR_RORIC SHIFT_U32(1, 0)

#define SSPDMACR_TXDMAE SHIFT_U32(1, 1)
Expand Down Expand Up @@ -148,10 +149,11 @@
#define MASK_4 0xF
/* spi register masks */

#define SSP_CPSDVR_MAX 254
#define SSP_CPSDVR_MIN 2
#define SSP_CPSDVR_MAX 254
#define SSP_CPSDVR_MIN 2
#define SSP_SCR_MAX 255
#define SSP_SCR_MIN 0
#define SSP_DATASIZE_MAX 16

enum pl022_data_size {
PL022_DATA_SIZE4 = 0x3,
Expand All @@ -177,163 +179,125 @@ enum pl022_spi_mode {
};

static void pl022_txrx8(struct spi_chip *chip, uint8_t *wdat,
uint8_t *rdat, uint32_t num_txpkts, uint32_t *num_rxpkts)
uint8_t *rdat, size_t num_txpkts, size_t *num_rxpkts)
{
uint32_t i, j = 0;
size_t i = 0, j = 0;
struct pl022_data *pd = container_of(chip, struct pl022_data, chip);

gpio_set_value(pd->cs_gpio_pin, GPIO_LEVEL_LOW);

for (i = 0; i < num_txpkts; i++) {
if (read32(pd->base + SSPSR) & SSPSR_TNF) {
while (i < num_txpkts) {
if (read8(pd->base + SSPSR) & SSPSR_TNF)
/* tx 1 packet */
write8(wdat[i], pd->base + SSPDR);

/* rx 1 packet */
if (read32(pd->base + SSPSR) & SSPSR_RNE)
rdat[j++] = read8(pd->base + SSPDR);

} else {
DMSG("TX FIFO full.. waiting..\n");
while ((read32(pd->base + SSPSR) & SSPSR_TNF) == 0)
tee_time_wait(1);

DMSG("TX FIFO available.. resuming..\n");
i--; /* retry current packet in next loop */
}
write8(wdat[i++], pd->base + SSPDR);
}

do {
while (read32(pd->base + SSPSR) & SSPSR_RNE)
while ((read8(pd->base + SSPSR) & SSPSR_RNE)
&& (j < *num_rxpkts))
rdat[j++] = read8(pd->base + SSPDR);
} while ((read8(pd->base + SSPSR) & SSPSR_BSY) && (j < *num_rxpkts));

} while (read32(pd->base + SSPSR) & SSPSR_BSY);
*num_rxpkts = j;

gpio_set_value(pd->cs_gpio_pin, GPIO_LEVEL_HIGH);
*num_rxpkts = j;
}

static void pl022_txrx16(struct spi_chip *chip, uint16_t *wdat,
uint16_t *rdat, uint32_t num_txpkts, uint32_t *num_rxpkts)
uint16_t *rdat, size_t num_txpkts, size_t *num_rxpkts)
{
uint32_t i, j = 0;
size_t i = 0, j = 0;
struct pl022_data *pd = container_of(chip, struct pl022_data, chip);

gpio_set_value(pd->cs_gpio_pin, GPIO_LEVEL_LOW);

for (i = 0; i < num_txpkts; i++) {
if (read32(pd->base + SSPSR) & SSPSR_TNF) {
while (i < num_txpkts) {
if (read8(pd->base + SSPSR) & SSPSR_TNF)
/* tx 1 packet */
write16(wdat[i], pd->base + SSPDR);

/* rx 1 packet */
if (read32(pd->base + SSPSR) & SSPSR_RNE)
rdat[j++] = read16(pd->base + SSPDR);

} else {
DMSG("TX FIFO full.. waiting..\n");
while ((read32(pd->base + SSPSR) & SSPSR_TNF) == 0)
tee_time_wait(1);

DMSG("TX FIFO available.. resuming..\n");
i--; /* retry current packet in next loop */
}
write16(wdat[i++], pd->base + SSPDR);
}

do {
while (read32(pd->base + SSPSR) & SSPSR_RNE)
while ((read8(pd->base + SSPSR) & SSPSR_RNE)
&& (j < *num_rxpkts))
rdat[j++] = read16(pd->base + SSPDR);
} while ((read8(pd->base + SSPSR) & SSPSR_BSY) && (j < *num_rxpkts));

} while (read32(pd->base + SSPSR) & SSPSR_BSY);
*num_rxpkts = j;

gpio_set_value(pd->cs_gpio_pin, GPIO_LEVEL_HIGH);
*num_rxpkts = j;
}

static void pl022_tx8(struct spi_chip *chip, uint8_t *wdat,
uint32_t num_txpkts)
size_t num_txpkts)
{
uint32_t i;
size_t i = 0;
struct pl022_data *pd = container_of(chip, struct pl022_data, chip);

gpio_set_value(pd->cs_gpio_pin, GPIO_LEVEL_LOW);

for (i = 0; i < num_txpkts; i++) {
if (read32(pd->base + SSPSR) & SSPSR_TNF) {
while (i < num_txpkts) {
if (read8(pd->base + SSPSR) & SSPSR_TNF)
/* tx 1 packet */
write8(wdat[i], pd->base + SSPDR);
} else {
DMSG("TX FIFO full.. waiting..\n");
while ((read32(pd->base + SSPSR) & SSPSR_TNF) == 0)
tee_time_wait(1);

DMSG("TX FIFO available.. resuming..\n");
i--; /* retry current packet in next loop */
}
write8(wdat[i++], pd->base + SSPDR);
}

gpio_set_value(pd->cs_gpio_pin, GPIO_LEVEL_HIGH);
}

static void pl022_tx16(struct spi_chip *chip, uint16_t *wdat,
uint32_t num_txpkts)
size_t num_txpkts)
{
uint32_t i;
size_t i = 0;
struct pl022_data *pd = container_of(chip, struct pl022_data, chip);

gpio_set_value(pd->cs_gpio_pin, GPIO_LEVEL_LOW);

for (i = 0; i < num_txpkts; i++) {
if (read32(pd->base + SSPSR) & SSPSR_TNF) {
while (i < num_txpkts) {
if (read8(pd->base + SSPSR) & SSPSR_TNF)
/* tx 1 packet */
write16(wdat[i], pd->base + SSPDR);
} else {
DMSG("TX FIFO full.. waiting..\n");
while ((read32(pd->base + SSPSR) & SSPSR_TNF) == 0)
tee_time_wait(1);

DMSG("TX FIFO available.. resuming..\n");
i--; /* retry current packet in next loop */
}
write16(wdat[i++], pd->base + SSPDR);
}

gpio_set_value(pd->cs_gpio_pin, GPIO_LEVEL_HIGH);
}

static void pl022_rx8(struct spi_chip *chip, uint8_t *rdat,
uint32_t *num_rxpkts)
size_t *num_rxpkts)
{
uint32_t j = 0;
size_t j = 0;
struct pl022_data *pd = container_of(chip, struct pl022_data, chip);

gpio_set_value(pd->cs_gpio_pin, GPIO_LEVEL_LOW);

do {
while (read32(pd->base + SSPSR) & SSPSR_RNE)
while ((read8(pd->base + SSPSR) & SSPSR_RNE)
&& (j < *num_rxpkts))
rdat[j++] = read8(pd->base + SSPDR);
} while ((read8(pd->base + SSPSR) & SSPSR_BSY) && (j < *num_rxpkts));

} while (read32(pd->base + SSPSR) & SSPSR_BSY);
*num_rxpkts = j;

gpio_set_value(pd->cs_gpio_pin, GPIO_LEVEL_HIGH);
*num_rxpkts = j;
}

static void pl022_rx16(struct spi_chip *chip, uint16_t *rdat,
uint32_t *num_rxpkts)
size_t *num_rxpkts)
{
uint32_t j = 0;
size_t j = 0;
struct pl022_data *pd = container_of(chip, struct pl022_data, chip);

gpio_set_value(pd->cs_gpio_pin, GPIO_LEVEL_LOW);

do {
while (read32(pd->base + SSPSR) & SSPSR_RNE)
while ((read8(pd->base + SSPSR) & SSPSR_RNE)
&& (j < *num_rxpkts))
rdat[j++] = read16(pd->base + SSPDR);
} while ((read8(pd->base + SSPSR) & SSPSR_BSY) && (j < *num_rxpkts));

} while (read32(pd->base + SSPSR) & SSPSR_BSY);
*num_rxpkts = j;

gpio_set_value(pd->cs_gpio_pin, GPIO_LEVEL_HIGH);
*num_rxpkts = j;
}

static void pl022_print_peri_id(struct pl022_data *pd __maybe_unused)
Expand All @@ -358,6 +322,15 @@ static void pl022_print_cell_id(struct pl022_data *pd __maybe_unused)

static void pl022_sanity_check(struct pl022_data *pd)
{
assert(pd);
assert(pd->chip.ops);
assert(pd->base);
assert(pd->cs_gpio_base);
assert(pd->clk_hz);
assert(pd->speed_hz && pd->speed_hz <= pd->clk_hz/2);
assert(pd->mode <= SPI_MODE3);
assert(pd->data_size_bits == 8 || pd->data_size_bits == 16);

DMSG("SSPB2BTRANS: Expected: 0x2. Read: 0x%x\n",
read32(pd->base + SSPB2BTRANS));
pl022_print_peri_id(pd);
Expand All @@ -373,7 +346,7 @@ static inline uint32_t pl022_calc_freq(struct pl022_data *pd,
static void pl022_calc_clk_divisors(struct pl022_data *pd,
uint8_t *cpsdvr, uint8_t *scr)
{
uint32_t freq1 = 0, freq2 = 0;
unsigned int freq1 = 0, freq2 = 0;
uint8_t tmp_cpsdvr1, tmp_scr1, tmp_cpsdvr2 = 0, tmp_scr2 = 0;

for (tmp_scr1 = SSP_SCR_MIN; tmp_scr1 < SSP_SCR_MAX; tmp_scr1++) {
Expand Down Expand Up @@ -426,11 +399,21 @@ static void pl022_flush_fifo(struct pl022_data *pd)
} while (read32(pd->base + SSPSR) & SSPSR_BSY);
}

static const struct spi_ops pl022_ops = {
.txrx8 = pl022_txrx8,
.txrx16 = pl022_txrx16,
.tx8 = pl022_tx8,
.tx16 = pl022_tx16,
.rx8 = pl022_rx8,
.rx16 = pl022_rx16,
};

void pl022_configure(struct pl022_data *pd)
{
uint16_t mode, data_size;
uint8_t cpsdvr, scr, lbm;

pd->chip.ops = &pl022_ops;
pl022_sanity_check(pd);
pl022_calc_clk_divisors(pd, &cpsdvr, &scr);

Expand All @@ -454,7 +437,7 @@ void pl022_configure(struct pl022_data *pd)
break;
default:
EMSG("Invalid spi mode: %u\n", pd->mode);
return;
panic();
}

switch (pd->data_size_bits) {
Expand All @@ -468,7 +451,7 @@ void pl022_configure(struct pl022_data *pd)
break;
default:
EMSG("Unsupported data size: %u bits\n", pd->data_size_bits);
return;
panic();
}

if (pd->loopback) {
Expand Down Expand Up @@ -516,17 +499,3 @@ void pl022_end(struct pl022_data *pd)
io_mask8(pd->base + SSPCR1, SSPCR1_SSE_DISABLE, SSPCR1_SSE);
}

static const struct spi_ops pl022_ops = {
.txrx8 = pl022_txrx8,
.txrx16 = pl022_txrx16,
.tx8 = pl022_tx8,
.tx16 = pl022_tx16,
.rx8 = pl022_rx8,
.rx16 = pl022_rx16,
};

void pl022_init(struct pl022_data *pd)
{
pd->chip.ops = &pl022_ops;
}

Loading

0 comments on commit 4c1bfb2

Please sign in to comment.