bt: hci driver over spi: BlueNRG-MS read until IRQ pin goes low

According to BlueNRG-MS ref manual, SPI master shoul read  from
controller as long as IRQ pin is high.
Introduce a new loop within spi_rx_thread to do so. Since
it is now possible to enter read loop with nothing to read, set
a max attempts limit to be sure to exit the loop.

Signed-off-by: Erwan Gouriou <erwan.gouriou@linaro.org>
Signed-off-by: Christophe Priouzeau <christophe.priouzeau@st.com>
This commit is contained in:
Christophe Priouzeau 2018-06-26 13:30:26 +02:00 committed by Carles Cufí
commit 7b02e6dc55

View file

@ -99,6 +99,11 @@ void spi_dump_message(const u8_t *pre, u8_t *buf, u8_t size) {}
#if defined(CONFIG_BT_SPI_BLUENRG) #if defined(CONFIG_BT_SPI_BLUENRG)
static struct device *cs_dev; static struct device *cs_dev;
/* Define a limit when reading IRQ high */
/* It can be required to be increased for */
/* some particular cases. */
#define IRQ_HIGH_MAX_READ 3
static u8_t attempts;
#endif /* CONFIG_BT_SPI_BLUENRG */ #endif /* CONFIG_BT_SPI_BLUENRG */
static struct device *spi_dev; static struct device *spi_dev;
@ -168,7 +173,7 @@ static void bt_spi_handle_vendor_evt(u8_t *rxmsg)
* know the amount of byte to read. * know the amount of byte to read.
* (See section 5.2 of BlueNRG-MS datasheet) * (See section 5.2 of BlueNRG-MS datasheet)
*/ */
static int bt_spi_configure_cs(void) static int configure_cs(void)
{ {
cs_dev = device_get_binding(CONFIG_BT_SPI_CHIP_SELECT_DEV_NAME); cs_dev = device_get_binding(CONFIG_BT_SPI_CHIP_SELECT_DEV_NAME);
if (!cs_dev) { if (!cs_dev) {
@ -184,20 +189,50 @@ static int bt_spi_configure_cs(void)
return 0; return 0;
} }
static void bt_spi_kick_cs(void) static void kick_cs(void)
{ {
gpio_pin_write(cs_dev, GPIO_CS_PIN, 1); gpio_pin_write(cs_dev, GPIO_CS_PIN, 1);
gpio_pin_write(cs_dev, GPIO_CS_PIN, 0); gpio_pin_write(cs_dev, GPIO_CS_PIN, 0);
} }
static void bt_spi_release_cs(void) static void release_cs(void)
{ {
gpio_pin_write(cs_dev, GPIO_CS_PIN, 1); gpio_pin_write(cs_dev, GPIO_CS_PIN, 1);
} }
static bool irq_pin_high(void)
{
u32_t pin_state;
gpio_pin_read(irq_dev, GPIO_IRQ_PIN, &pin_state);
BT_DBG("IRQ Pin: %d", pin_state);
return pin_state;
}
static void init_irq_high_loop(void)
{
attempts = IRQ_HIGH_MAX_READ;
}
static bool exit_irq_high_loop(void)
{
/* Limit attempts on BlueNRG-MS as we might */
/* enter this loop with nothing to read */
attempts--;
return attempts;
}
#else #else
#define bt_spi_configure_cs(...) 0 #define configure_cs(...) 0
#define bt_spi_kick_cs(...) #define kick_cs(...)
#define bt_spi_release_cs(...) #define release_cs(...)
#define irq_pin_high(...) 0
#define init_irq_high_loop(...)
#define exit_irq_high_loop(...) 1
#endif #endif
static void bt_spi_rx_thread(void) static void bt_spi_rx_thread(void)
@ -220,11 +255,14 @@ static void bt_spi_rx_thread(void)
BT_DBG(""); BT_DBG("");
do { do {
bt_spi_kick_cs(); init_irq_high_loop();
do {
kick_cs();
ret = bt_spi_transceive(header_master, 5, ret = bt_spi_transceive(header_master, 5,
header_slave, 5); header_slave, 5);
} while ((header_slave[STATUS_HEADER_TOREAD] == 0 || } while ((((header_slave[STATUS_HEADER_TOREAD] == 0 ||
header_slave[STATUS_HEADER_TOREAD] == 0xFF) && !ret); header_slave[STATUS_HEADER_TOREAD] == 0xFF) &&
!ret)) && exit_irq_high_loop());
if (!ret) { if (!ret) {
size = header_slave[STATUS_HEADER_TOREAD]; size = header_slave[STATUS_HEADER_TOREAD];
@ -235,7 +273,7 @@ static void bt_spi_rx_thread(void)
} while (rxmsg[0] == 0 && ret == 0); } while (rxmsg[0] == 0 && ret == 0);
} }
bt_spi_release_cs(); release_cs();
gpio_pin_enable_callback(irq_dev, GPIO_IRQ_PIN); gpio_pin_enable_callback(irq_dev, GPIO_IRQ_PIN);
k_sem_give(&sem_busy); k_sem_give(&sem_busy);
@ -283,6 +321,9 @@ static void bt_spi_rx_thread(void)
} else { } else {
bt_recv(buf); bt_recv(buf);
} }
/* On BlueNRG-MS, host is expected to read */
/* as long as IRQ pin is high */
} while (irq_pin_high());
} }
} }
@ -326,7 +367,7 @@ static int bt_spi_send(struct net_buf *buf)
/* Poll sanity values until device has woken-up */ /* Poll sanity values until device has woken-up */
do { do {
bt_spi_kick_cs(); kick_cs();
ret = bt_spi_transceive(header, 5, rxmsg, 5); ret = bt_spi_transceive(header, 5, rxmsg, 5);
/* /*
@ -348,7 +389,7 @@ static int bt_spi_send(struct net_buf *buf)
} while (rxmsg[0] == 0 && !ret); } while (rxmsg[0] == 0 && !ret);
} }
bt_spi_release_cs(); release_cs();
if (ret) { if (ret) {
BT_ERR("Error %d", ret); BT_ERR("Error %d", ret);
@ -384,6 +425,9 @@ static int bt_spi_open(void)
/* Configure IRQ pin and the IRQ call-back/handler */ /* Configure IRQ pin and the IRQ call-back/handler */
gpio_pin_configure(irq_dev, GPIO_IRQ_PIN, gpio_pin_configure(irq_dev, GPIO_IRQ_PIN,
#if defined(CONFIG_BT_SPI_BLUENRG)
GPIO_PUD_PULL_DOWN |
#endif
GPIO_DIR_IN | GPIO_INT | GPIO_DIR_IN | GPIO_INT |
GPIO_INT_EDGE | GPIO_INT_ACTIVE_HIGH); GPIO_INT_EDGE | GPIO_INT_ACTIVE_HIGH);
@ -431,7 +475,7 @@ static int _bt_spi_init(struct device *unused)
return -EIO; return -EIO;
} }
if (bt_spi_configure_cs()) { if (configure_cs()) {
return -EIO; return -EIO;
} }