drivers/modem/altair: Update altair modem driver

- Add board specific logic to altair modem dirver
- Fix issue that SPI4 RX frequency violated AC Spec
- Remove dummy buffer in altair driver
- Fix priority of SPI transfer task is too low
- Remove unnecessary configuration
- Modify timeout value for RX ready
- Fix minor bugs
This commit is contained in:
SPRESENSE 2020-07-27 13:49:53 +09:00 committed by Alin Jerpelea
parent 524f18c4cd
commit 500ead8101
14 changed files with 634 additions and 1718 deletions

View File

@ -44,7 +44,6 @@ endif
ifeq ($(CONFIG_MODEM_ALTMDM),y)
CSRCS += cxd56_altmdm.c
CSRCS += cxd56_altmdm_spi.c
endif
ifeq ($(CONFIG_BOARDCTL_UNIQUEID),y)

View File

@ -39,6 +39,9 @@
#include <nuttx/config.h>
#if defined(CONFIG_MODEM_ALTMDM) && defined(CONFIG_CXD56_LTE) && \
defined(CONFIG_CXD56_GPIO_IRQ) && defined(CONFIG_CXD56_SPI)
#include <stdio.h>
#include <debug.h>
#include <errno.h>
@ -47,277 +50,405 @@
#include <nuttx/spi/spi.h>
#include <nuttx/modem/altmdm.h>
#if defined(CONFIG_MODEM_ALTMDM) && defined(CONFIG_CXD56_GPIO_IRQ)
#include <arch/board/board.h>
#include <arch/board/cxd56_altmdm.h>
#include "cxd56_spi.h"
#include "cxd56_dmac.h"
#include "cxd56_gpio.h"
#include "cxd56_gpioint.h"
#include "cxd56_pinconfig.h"
#endif
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#if defined(CONFIG_MODEM_ALTMDM) && defined(CONFIG_CXD56_GPIO_IRQ)
#define ALTMDM_SHUTDOWN (PIN_SPI2_MISO)
#define MODEM_WAKEUP (PIN_SPI2_MOSI)
#define MASTER_REQUEST (PIN_RTC_IRQ_OUT)
#define SLAVE_REQUEST (PIN_SPI2_SCK)
#define LTE_POWER_BUTTON (PIN_AP_CLK)
#define NUM_OF_PINS (sizeof(pincfg) / sizeof(struct altmdm_pincfg))
#if !defined(CONFIG_MODEM_ALTMDM_MAX_PACKET_SIZE)
# error CONFIG_MODEM_ALTMDM_MAX_PACKET_SIZE is not set
#endif
#if defined(CONFIG_CXD56_LTE_SPI4)
# define SPI_CH (4)
# define SPI_MAXFREQUENCY (9750000)
# if defined(CONFIG_CXD56_LTE_SPI4_DMAC)
# define DMA_TXCH (2)
# define DMA_RXCH (3)
# define DMA_TXCHCHG (CXD56_DMA_PERIPHERAL_SPI4_TX)
# define DMA_RXCHCFG (CXD56_DMA_PERIPHERAL_SPI4_RX)
# endif
#elif defined(CONFIG_CXD56_LTE_SPI5)
# define SPI_CH (5)
# define SPI_MAXFREQUENCY (13000000)
# if defined(CONFIG_CXD56_LTE_SPI5_DMAC)
# define DMA_TXCH (4)
# define DMA_RXCH (5)
# define DMA_TXCHCHG (CXD56_DMA_PERIPHERAL_SPI5_TX)
# define DMA_RXCHCFG (CXD56_DMA_PERIPHERAL_SPI5_RX)
# endif
#else
# error "Select LTE SPI 4 or 5"
#endif
/****************************************************************************
* Private Types
* Private Function Prototypes
****************************************************************************/
#if defined(CONFIG_MODEM_ALTMDM) && defined(CONFIG_CXD56_GPIO_IRQ)
struct altmdm_pincfg
{
uint32_t pin;
bool input_enable;
bool init_val;
};
#endif
static void altmdm_poweron(void);
static void altmdm_poweroff(void);
static void altmdm_sready_irqattach(bool attach, xcpt_t handler);
static void altmdm_sready_irqenable(bool enable);
static bool altmdm_sready(void);
static void altmdm_master_request(bool request);
static void altmdm_wakeup(bool wakeup);
static uint32_t altmdm_spi_maxfreq(void);
/****************************************************************************
* Private Data
****************************************************************************/
#if defined(CONFIG_MODEM_ALTMDM) && defined(CONFIG_CXD56_GPIO_IRQ)
static const struct altmdm_pincfg pincfg[] =
static void *g_devhandle = NULL;
static const struct altmdm_lower_s g_altmdm_lower =
{
{MODEM_WAKEUP, false, false}, /* out, low */
{MASTER_REQUEST, false, false}, /* out, low */
{SLAVE_REQUEST, true, false}, /* in, low */
.poweron = altmdm_poweron,
.poweroff = altmdm_poweroff,
.sready_irqattach = altmdm_sready_irqattach,
.sready_irqenable = altmdm_sready_irqenable,
.sready = altmdm_sready,
.master_request = altmdm_master_request,
.wakeup = altmdm_wakeup,
.spi_maxfreq = altmdm_spi_maxfreq
};
#endif
#if defined(CONFIG_MODEM_ALTMDM) && defined(CONFIG_CXD56_GPIO_IRQ)
/****************************************************************************
* Public Functions
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: board_altmdm_poweron
* Name: spi_pincontrol
*
* Description:
* Configure the SPI pin
*
* Input Parameter:
* bus - SPI bus number to control
* on - true: enable pin, false: disable pin
*
****************************************************************************/
static void spi_pincontrol(int bus, bool on)
{
switch (bus)
{
#ifdef CONFIG_CXD56_SPI4
case 4:
if (on)
{
CXD56_PIN_CONFIGS(PINCONFS_SPI4);
}
else
{
CXD56_PIN_CONFIGS(PINCONFS_SPI4_GPIO);
}
break;
#endif /* CONFIG_CXD56_SPI4 */
#ifdef CONFIG_CXD56_SPI5
case 5:
#ifdef CONFIG_CXD56_SPI5_PINMAP_EMMC
if (on)
{
CXD56_PIN_CONFIGS(PINCONFS_EMMCA_SPI5);
}
else
{
CXD56_PIN_CONFIGS(PINCONFS_EMMCA_GPIO);
}
#endif /* CONFIG_CXD56_SPI5_PINMAP_EMMC */
#ifdef CONFIG_CXD56_SPI5_PINMAP_SDIO
if (on)
{
CXD56_PIN_CONFIGS(PINCONFS_SDIOA_SPI5);
}
else
{
CXD56_PIN_CONFIGS(PINCONFS_SDIOA_GPIO);
}
#endif /* CONFIG_CXD56_SPI5_PINMAP_SDIO */
break;
#endif /* CONFIG_CXD56_SPI5 */
default:
break;
}
}
/****************************************************************************
* Name: altmdm_poweron
*
* Description:
* Power on the Altair modem device on the board.
*
****************************************************************************/
void board_altmdm_poweron(void)
static void altmdm_poweron(void)
{
int i;
/* power on altair modem device */
/* Power on altair modem device */
board_altmdm_poweron();
cxd56_gpio_config(ALTMDM_SHUTDOWN, false);
cxd56_gpio_write(ALTMDM_SHUTDOWN, true);
/* Input enable */
cxd56_gpio_config(LTE_POWER_BUTTON, false);
cxd56_gpio_write(LTE_POWER_BUTTON, true);
cxd56_gpio_config(ALTMDM_SLAVE_REQ, true);
board_power_control(POWER_LTE, true);
/* Output enable */
for (i = 0; i < NUM_OF_PINS; i++)
{
/* input pin: input enable */
cxd56_gpio_config(ALTMDM_MASTER_REQ, false);
cxd56_gpio_config(ALTMDM_WAKEUP, false);
cxd56_gpio_config(pincfg[i].pin, pincfg[i].input_enable);
/* Write a default value for output pin */
/* if it is an output pin, write a default value */
if (pincfg[i].input_enable == false)
{
cxd56_gpio_write(pincfg[i].pin, pincfg[i].init_val);
}
}
cxd56_gpio_write(ALTMDM_MASTER_REQ, false);
cxd56_gpio_write(ALTMDM_WAKEUP, false);
/* Slave request seems to float in Lite Hibernation and becomes HIGH at
* some times when it should stay LOW.
*/
cxd56_pin_config(PINCONF_SET(SLAVE_REQUEST,
cxd56_pin_config(PINCONF_SET(ALTMDM_SLAVE_REQ,
PINCONF_MODE0,
PINCONF_INPUT_ENABLE,
PINCONF_DRIVE_NORMAL, PINCONF_PULLDOWN));
/* enable the SPI pin */
spi_pincontrol(SPI_CH, true);
}
/****************************************************************************
* Name: board_altmdm_poweroff
* Name: altmdm_poweroff
*
* Description:
* Power off the Altair modem device on the board.
*
****************************************************************************/
void board_altmdm_poweroff(void)
static void altmdm_poweroff(void)
{
int i;
/* disable the SPI pin */
for (i = 0; i < NUM_OF_PINS; i++)
{
/* input disable, output disable(Hi-z) */
spi_pincontrol(SPI_CH, false);
cxd56_gpio_config(pincfg[i].pin, false);
}
/* Input disable */
cxd56_gpio_config(ALTMDM_SLAVE_REQ, false);
/* Output disable(Hi-z) */
cxd56_gpio_config(ALTMDM_MASTER_REQ, false);
cxd56_gpio_config(ALTMDM_WAKEUP, false);
/* power off Altair modem device */
cxd56_gpio_write(ALTMDM_SHUTDOWN, true);
board_power_control(POWER_LTE, false);
cxd56_gpio_write(ALTMDM_SHUTDOWN, false);
cxd56_gpio_write(LTE_POWER_BUTTON, false);
board_altmdm_poweroff();
}
/****************************************************************************
* Name: board_altmdm_gpio_write
* Name: altmdm_sready_irqattach
*
* Description:
* Write GPIO pin.
* Register Slave-Request GPIO irq.
*
****************************************************************************/
void board_altmdm_gpio_write(uint32_t pin, bool value)
static void altmdm_sready_irqattach(bool attach, xcpt_t handler)
{
if (pin < NUM_OF_PINS)
uint32_t pol = GPIOINT_LEVEL_HIGH;
uint32_t nf = GPIOINT_NOISE_FILTER_DISABLE;
if (attach)
{
if (pincfg[pin].input_enable == false)
{
cxd56_gpio_write(pincfg[pin].pin, value);
}
}
}
/* Attach then enable the new interrupt handler */
/****************************************************************************
* Name: board_altmdm_gpio_read
*
* Description:
* Read GPIO pin.
*
****************************************************************************/
bool board_altmdm_gpio_read(uint32_t pin)
{
bool val = false;
if (pin < NUM_OF_PINS)
{
if (pincfg[pin].input_enable == true)
{
val = cxd56_gpio_read(pincfg[pin].pin);
}
}
return val;
}
/****************************************************************************
* Name: board_altmdm_gpio_irq
*
* Description:
* Register GPIO irq.
*
****************************************************************************/
void board_altmdm_gpio_irq(uint32_t pin, uint32_t polarity,
uint32_t noise_filter, xcpt_t irqhandler)
{
uint32_t pol;
uint32_t nf;
switch (polarity)
{
case ALTMDM_GPIOINT_LEVEL_HIGH:
pol = GPIOINT_LEVEL_HIGH;
break;
case ALTMDM_GPIOINT_LEVEL_LOW:
pol = GPIOINT_LEVEL_LOW;
break;
case ALTMDM_GPIOINT_EDGE_RISE:
pol = GPIOINT_EDGE_RISE;
break;
case ALTMDM_GPIOINT_EDGE_FALL:
pol = GPIOINT_EDGE_FALL;
break;
case ALTMDM_GPIOINT_EDGE_BOTH:
pol = GPIOINT_EDGE_BOTH;
break;
default:
return;
break;
}
if (noise_filter == ALTMDM_GPIOINT_NOISE_FILTER_ENABLE)
{
nf = GPIOINT_NOISE_FILTER_ENABLE;
cxd56_gpioint_config(ALTMDM_SLAVE_REQ,
(GPIOINT_TOGGLE_MODE_MASK | nf | pol),
handler, NULL);
}
else
{
nf = GPIOINT_NOISE_FILTER_DISABLE;
}
/* Disable the interrupt handler */
if (pin < NUM_OF_PINS)
{
if (pincfg[pin].input_enable == true)
{
if (irqhandler)
{
/* Attach then enable the new interrupt handler */
cxd56_gpioint_config(pincfg[pin].pin,
(GPIOINT_TOGGLE_MODE_MASK | nf | pol),
irqhandler, NULL);
}
}
cxd56_gpioint_config(ALTMDM_SLAVE_REQ, 0, NULL, NULL);
}
}
/****************************************************************************
* Name: board_altmdm_gpio_int_control
* Name: altmdm_sready_irqenable
*
* Description:
* Enable or disable GPIO interrupt.
* Enable or disable Slave-Request GPIO interrupt.
*
****************************************************************************/
void board_altmdm_gpio_int_control(uint32_t pin, bool en)
static void altmdm_sready_irqenable(bool enable)
{
if (pin < NUM_OF_PINS)
if (enable)
{
if (pincfg[pin].input_enable == true)
{
if (en)
{
/* enable interrupt */
/* enable interrupt */
cxd56_gpioint_enable(pincfg[pin].pin);
}
else
{
/* disable interrupt */
cxd56_gpioint_enable(ALTMDM_SLAVE_REQ);
}
else
{
/* disable interrupt */
cxd56_gpioint_disable(pincfg[pin].pin);
}
}
cxd56_gpioint_disable(ALTMDM_SLAVE_REQ);
}
}
/****************************************************************************
* Name: altmdm_sready
*
* Description:
* Read Slave-Request GPIO pin.
*
****************************************************************************/
static bool altmdm_sready(void)
{
return cxd56_gpio_read(ALTMDM_SLAVE_REQ);
}
/****************************************************************************
* Name: altmdm_master_request
*
* Description:
* Write Master-Request GPIO pin.
*
****************************************************************************/
static void altmdm_master_request(bool request)
{
cxd56_gpio_write(ALTMDM_MASTER_REQ, request);
}
/****************************************************************************
* Name: altmdm_wakeup
*
* Description:
* Write Modme-Wakeup GPIO pin.
*
****************************************************************************/
static void altmdm_wakeup(bool wakeup)
{
cxd56_gpio_write(ALTMDM_WAKEUP, wakeup);
}
/****************************************************************************
* Name: altmdm_spi_maxfreq
*
* Description:
* Get the maximum SPI clock frequency.
*
****************************************************************************/
static uint32_t altmdm_spi_maxfreq(void)
{
return SPI_MAXFREQUENCY;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: board_altmdm_initialize
*
* Description:
* Initialize Altair modem
*
****************************************************************************/
int board_altmdm_initialize(FAR const char *devpath)
{
FAR struct spi_dev_s *spi;
#if defined(CONFIG_CXD56_LTE_SPI4_DMAC) || defined(CONFIG_CXD56_LTE_SPI5_DMAC)
DMA_HANDLE hdl;
dma_config_t conf;
#endif
m_info("Initializing ALTMDM..\n");
if (!g_devhandle)
{
/* Initialize spi deivce */
spi = cxd56_spibus_initialize(SPI_CH);
if (!spi)
{
m_err("ERROR: Failed to initialize spi%d.\n", SPI_CH);
return -ENODEV;
}
#if defined(CONFIG_CXD56_LTE_SPI4_DMAC) || defined(CONFIG_CXD56_LTE_SPI5_DMAC)
hdl = cxd56_dmachannel(DMA_TXCH,
CONFIG_MODEM_ALTMDM_MAX_PACKET_SIZE);
if (hdl)
{
conf.channel_cfg = DMA_TXCHCHG;
conf.dest_width = CXD56_DMAC_WIDTH8;
conf.src_width = CXD56_DMAC_WIDTH8;
cxd56_spi_dmaconfig(SPI_CH, CXD56_SPI_DMAC_CHTYPE_TX, hdl,
&conf);
}
hdl = cxd56_dmachannel(DMA_RXCH,
CONFIG_MODEM_ALTMDM_MAX_PACKET_SIZE);
if (hdl)
{
conf.channel_cfg = DMA_RXCHCFG;
conf.dest_width = CXD56_DMAC_WIDTH8;
conf.src_width = CXD56_DMAC_WIDTH8;
cxd56_spi_dmaconfig(SPI_CH, CXD56_SPI_DMAC_CHTYPE_RX, hdl,
&conf);
}
#endif
spi_pincontrol(SPI_CH, false);
g_devhandle = altmdm_register(devpath, spi, &g_altmdm_lower);
if (!g_devhandle)
{
m_err("ERROR: Failed to register altmdm driver.\n");
return -ENODEV;
}
board_altmdm_poweroff();
}
return OK;
}
/****************************************************************************
* Name: board_altmdm_uninitialize
*
* Description:
* Uninitialize Altair modem
*
****************************************************************************/
int board_altmdm_uninitialize(void)
{
m_info("Uninitializing ALTMDM..\n");
if (g_devhandle)
{
altmdm_unregister(g_devhandle);
g_devhandle = NULL;
}
return OK;
}
#endif

View File

@ -1,279 +0,0 @@
/****************************************************************************
* boards/arm/cxd56xx/common/src/cxd56_altmdm_spi.c
*
* Copyright 2018 Sony Semiconductor Solutions Corporation
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name of Sony Semiconductor Solutions Corporation nor
* the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#if defined(CONFIG_CXD56_SPI) && defined(CONFIG_MODEM_ALTMDM) && defined(CONFIG_CXD56_LTE)
#include <stdio.h>
#include <debug.h>
#include <errno.h>
#include <nuttx/board.h>
#include <nuttx/spi/spi.h>
#include <nuttx/modem/altmdm.h>
#include <arch/board/cxd56_altmdm.h>
#include "cxd56_spi.h"
#include "cxd56_dmac.h"
#include "cxd56_pinconfig.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#if defined(CONFIG_CXD56_LTE_SPI4)
# define SPI_CH (4)
# if defined(CONFIG_CXD56_LTE_SPI4_DMAC)
# define DMA_TXCH (2)
# define DMA_RXCH (3)
# define DMA_TXCHCHG (CXD56_DMA_PERIPHERAL_SPI4_TX)
# define DMA_RXCHCFG (CXD56_DMA_PERIPHERAL_SPI4_RX)
# if !defined(CONFIG_MODEM_ALTMDM_MAX_PACKET_SIZE)
# error CONFIG_MODEM_ALTMDM_MAX_PACKET_SIZE is not set
# endif
# endif
#elif defined(CONFIG_CXD56_LTE_SPI5)
# define SPI_CH (5)
# if defined(CONFIG_CXD56_LTE_SPI5_DMAC)
# define DMA_TXCH (4)
# define DMA_RXCH (5)
# define DMA_TXCHCHG (CXD56_DMA_PERIPHERAL_SPI5_TX)
# define DMA_RXCHCFG (CXD56_DMA_PERIPHERAL_SPI5_RX)
# if !defined(CONFIG_MODEM_ALTMDM_MAX_PACKET_SIZE)
# error CONFIG_MODEM_ALTMDM_MAX_PACKET_SIZE is not set
# endif
# endif
#else
# error "Select LTE SPI 4 or 5"
#endif
/****************************************************************************
* Private Data
****************************************************************************/
static void *g_devhandle = NULL;
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: spi_pincontrol
*
* Description:
* Configure the SPI pin
*
* Input Parameter:
* on - true: enable pin, false: disable pin
*
****************************************************************************/
static void spi_pincontrol(int bus, bool on)
{
switch (bus)
{
#ifdef CONFIG_CXD56_SPI4
case 4:
if (on)
{
CXD56_PIN_CONFIGS(PINCONFS_SPI4);
}
else
{
CXD56_PIN_CONFIGS(PINCONFS_SPI4_GPIO);
}
break;
#endif /* CONFIG_CXD56_SPI4 */
#ifdef CONFIG_CXD56_SPI5
case 5:
#ifdef CONFIG_CXD56_SPI5_PINMAP_EMMC
if (on)
{
CXD56_PIN_CONFIGS(PINCONFS_EMMCA_SPI5);
}
else
{
CXD56_PIN_CONFIGS(PINCONFS_EMMCA_GPIO);
}
#endif /* CONFIG_CXD56_SPI5_PINMAP_EMMC */
#ifdef CONFIG_CXD56_SPI5_PINMAP_SDIO
if (on)
{
CXD56_PIN_CONFIGS(PINCONFS_SDIOA_SPI5);
}
else
{
CXD56_PIN_CONFIGS(PINCONFS_SDIOA_GPIO);
}
#endif /* CONFIG_CXD56_SPI5_PINMAP_SDIO */
break;
#endif /* CONFIG_CXD56_SPI5 */
default:
break;
}
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: board_altmdm_initialize
*
* Description:
* Initialize Altair modem
*
****************************************************************************/
int board_altmdm_initialize(FAR const char *devpath)
{
FAR struct spi_dev_s *spi;
int spi_ch = SPI_CH;
#if defined(CONFIG_CXD56_LTE_SPI4_DMAC) || defined(CONFIG_CXD56_LTE_SPI5_DMAC)
DMA_HANDLE hdl;
dma_config_t conf;
#endif
m_info("Initializing ALTMDM..\n");
if (!g_devhandle)
{
/* Initialize spi device */
spi = cxd56_spibus_initialize(spi_ch);
if (!spi)
{
m_err("ERROR: Failed to initialize spi%d.\n", spi_ch);
return -ENODEV;
}
#if defined(CONFIG_CXD56_LTE_SPI4_DMAC) || defined(CONFIG_CXD56_LTE_SPI5_DMAC)
hdl = cxd56_dmachannel(DMA_TXCH, CONFIG_MODEM_ALTMDM_MAX_PACKET_SIZE);
if (hdl)
{
conf.channel_cfg = DMA_TXCHCHG;
conf.dest_width = CXD56_DMAC_WIDTH8;
conf.src_width = CXD56_DMAC_WIDTH8;
cxd56_spi_dmaconfig(spi_ch, CXD56_SPI_DMAC_CHTYPE_TX, hdl, &conf);
}
hdl = cxd56_dmachannel(DMA_RXCH, CONFIG_MODEM_ALTMDM_MAX_PACKET_SIZE);
if (hdl)
{
conf.channel_cfg = DMA_RXCHCFG;
conf.dest_width = CXD56_DMAC_WIDTH8;
conf.src_width = CXD56_DMAC_WIDTH8;
cxd56_spi_dmaconfig(spi_ch, CXD56_SPI_DMAC_CHTYPE_RX, hdl, &conf);
}
#endif
spi_pincontrol(spi_ch, false);
g_devhandle = altmdm_register(devpath, spi);
if (!g_devhandle)
{
m_err("ERROR: Failed to register altmdm driver.\n");
return -ENODEV;
}
board_altmdm_poweroff();
}
return OK;
}
/****************************************************************************
* Name: board_altmdm_uninitialize
*
* Description:
* Uninitialize Altair modem
*
****************************************************************************/
int board_altmdm_uninitialize(void)
{
m_info("Uninitializing ALTMDM..\n");
if (g_devhandle)
{
altmdm_unregister(g_devhandle);
g_devhandle = NULL;
}
return OK;
}
/****************************************************************************
* Name: board_altmdm_power_control
*
* Description:
* Power on/off the Altair modem device on the board.
*
****************************************************************************/
void board_altmdm_power_control(bool en)
{
int spi_ch = SPI_CH;
if (en)
{
/* power on altair modem device */
board_altmdm_poweron();
/* enable the SPI pin */
spi_pincontrol(spi_ch, true);
}
else
{
/* disable the SPI pin */
spi_pincontrol(spi_ch, false);
/* power off Altair modem device */
board_altmdm_poweroff();
}
}
#endif /* CONFIG_CXD56_SPI && CONFIG_MODEM_ALTMDM */

View File

@ -255,6 +255,14 @@ enum board_power_device
#define BOARDIOC_USBDEV_SETNOTIFYSIG (BOARDIOC_USER+0x0001)
/* Altair modem device pin definitions **************************************/
#define ALTMDM_SLAVE_REQ PIN_SPI2_SCK
#define ALTMDM_MASTER_REQ PIN_RTC_IRQ_OUT
#define ALTMDM_WAKEUP PIN_SPI2_MOSI
#define ALTMDM_SHUTDOWN PIN_SPI2_MISO
#define ALTMDM_LTE_POWER_BUTTON PIN_AP_CLK
/****************************************************************************
* Public Types
****************************************************************************/

View File

@ -1,7 +1,7 @@
/****************************************************************************
* boards/arm/cxd56xx/spresense/include/cxd56_altmdm.h
*
* Copyright 2018 Sony Semiconductor Solutions Corporation
* Copyright 2018, 2019 Sony Semiconductor Solutions Corporation
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -41,42 +41,6 @@
****************************************************************************/
#include <nuttx/config.h>
#include <sys/boardctl.h>
#include <stdbool.h>
#include <nuttx/irq.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Altair modem gpio definitions ********************************************/
#if defined(CONFIG_MODEM_ALTMDM) && defined(CONFIG_CXD56_GPIO_IRQ)
/* definitions of gpio pin number */
#define ALTMDM_GPIO_MODEM_WAKEUP (0)
#define ALTMDM_GPIO_MASTER_REQ (1)
#define ALTMDM_GPIO_SLAVE_REQ (2)
/* definitions of gpio interrupt polarity */
#define ALTMDM_GPIOINT_LEVEL_HIGH (0)
#define ALTMDM_GPIOINT_LEVEL_LOW (1)
#define ALTMDM_GPIOINT_EDGE_RISE (2)
#define ALTMDM_GPIOINT_EDGE_FALL (3)
#define ALTMDM_GPIOINT_EDGE_BOTH (4)
/* definitions of gpio interrupt noise filter */
#define ALTMDM_GPIOINT_NOISE_FILTER_ENABLE (0)
#define ALTMDM_GPIOINT_NOISE_FILTER_DISABLE (1)
#endif
/****************************************************************************
* Public Types
****************************************************************************/
#ifndef __ASSEMBLY__
@ -97,7 +61,7 @@ extern "C"
* Public Function Prototypes
****************************************************************************/
#if defined(CONFIG_MODEM_ALTMDM) && defined(CONFIG_CXD56_GPIO_IRQ)
#if defined(CONFIG_MODEM_ALTMDM)
/****************************************************************************
* Name: board_altmdm_initialize
@ -119,16 +83,6 @@ int board_altmdm_initialize(FAR const char *devpath);
int board_altmdm_uninitialize(void);
/****************************************************************************
* Name: board_altmdm_power_control
*
* Description:
* Power on/off the Altair modem device on the board.
*
****************************************************************************/
void board_altmdm_power_control(bool en);
/****************************************************************************
* Name: board_altmdm_poweron
*
@ -149,47 +103,6 @@ void board_altmdm_poweron(void);
void board_altmdm_poweroff(void);
/****************************************************************************
* Name: board_altmdm_gpio_write
*
* Description:
* Write GPIO pin.
*
****************************************************************************/
void board_altmdm_gpio_write(uint32_t pin, bool value);
/****************************************************************************
* Name: board_altmdm_gpio_read
*
* Description:
* Read GPIO pin.
*
****************************************************************************/
bool board_altmdm_gpio_read(uint32_t pin);
/****************************************************************************
* Name: board_altmdm_gpio_irq
*
* Description:
* Register GPIO irq.
*
****************************************************************************/
void board_altmdm_gpio_irq(uint32_t pin, uint32_t polarity,
uint32_t noise_filter, xcpt_t irqhandler);
/****************************************************************************
* Name: board_altmdm_gpio_int_control
*
* Description:
* Enable or disable GPIO interrupt.
*
****************************************************************************/
void board_altmdm_gpio_int_control(uint32_t pin, bool en);
#endif
#undef EXTERN

View File

@ -89,6 +89,10 @@ ifeq ($(CONFIG_USBDEV_COMPOSITE),y)
CSRCS += cxd56_composite.c
endif
ifeq ($(CONFIG_MODEM_ALTMDM),y)
CSRCS += cxd56_altmdm_power.c
endif
DEPPATH += --dep-path board
VPATH += :board
CFLAGS += $(shell $(INCDIR) "$(CC)" $(TOPDIR)$(DELIM)arch$(DELIM)$(CONFIG_ARCH)$(DELIM)src$(DELIM)board$(DELIM)board)

View File

@ -0,0 +1,101 @@
/****************************************************************************
* boards/arm/cxd56xx/spresense/src/cxd56_altmdm_power.c
*
* Copyright 2019 Sony Semiconductor Solutions Corporation
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name of Sony Semiconductor Solutions Corporation nor
* the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#if defined(CONFIG_MODEM_ALTMDM)
#include <stdio.h>
#include <debug.h>
#include <errno.h>
#include <nuttx/board.h>
#include <nuttx/spi/spi.h>
#include <nuttx/modem/altmdm.h>
#include <arch/board/board.h>
#include "cxd56_gpio.h"
#include "cxd56_pinconfig.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: board_altmdm_poweron
*
* Description:
* Power on the Altair modem device on the board.
*
****************************************************************************/
void board_altmdm_poweron(void)
{
/* Power on altair modem device */
cxd56_gpio_config(ALTMDM_SHUTDOWN, false);
cxd56_gpio_write(ALTMDM_SHUTDOWN, true);
cxd56_gpio_config(ALTMDM_LTE_POWER_BUTTON, false);
cxd56_gpio_write(ALTMDM_LTE_POWER_BUTTON, true);
board_power_control(POWER_LTE, true);
}
/****************************************************************************
* Name: board_altmdm_poweroff
*
* Description:
* Power off the Altair modem device on the board.
*
****************************************************************************/
void board_altmdm_poweroff(void)
{
/* Power off Altair modem device */
cxd56_gpio_write(ALTMDM_SHUTDOWN, true);
board_power_control(POWER_LTE, false);
cxd56_gpio_write(ALTMDM_SHUTDOWN, false);
cxd56_gpio_write(ALTMDM_LTE_POWER_BUTTON, false);
}
#endif

View File

@ -12,12 +12,10 @@ menuconfig MODEM_ALTMDM
if MODEM_ALTMDM
config MODEM_ALTMDM_PROTCOL_V2_1
bool "Enable SPI protocol version 2.1"
default y
depends on MODEM_ALTMDM
---help---
Support only this version.
config MODEM_ALTMDM_XFER_TASK_PRIORITY
int "transfer task priority"
default 170
range 1 255
config MODEM_ALTMDM_DEBUG
bool "Enable debug mode for Altair modem driver"

View File

@ -395,7 +395,8 @@ static int altmdm_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
*
****************************************************************************/
FAR void *altmdm_register(FAR const char *devpath, FAR struct spi_dev_s *dev)
FAR void *altmdm_register(FAR const char *devpath, FAR struct spi_dev_s *dev,
FAR const struct altmdm_lower_s *lower)
{
FAR struct altmdm_dev_s *priv;
int ret;
@ -410,6 +411,7 @@ FAR void *altmdm_register(FAR const char *devpath, FAR struct spi_dev_s *dev)
priv->spi = dev;
priv->path = strdup(devpath);
priv->lower = lower;
ret = altmdm_initialize(priv);
if (ret < 0)

View File

@ -58,6 +58,7 @@ struct altmdm_dev_s
struct altmdm_spi_dev_s spidev;
struct altmdm_sys_lock_s lock;
int poweron;
FAR const struct altmdm_lower_s *lower;
};
/****************************************************************************
@ -146,8 +147,6 @@ int altmdm_spi_readabort(FAR struct altmdm_dev_s *priv);
int altmdm_spi_sleepmodem(FAR struct altmdm_dev_s *priv);
#ifdef CONFIG_MODEM_ALTMDM_PROTCOL_V2_1
/****************************************************************************
* Name: altmdm_spi_setreceiverready
*
@ -178,8 +177,6 @@ int altmdm_spi_isreceiverready(FAR struct altmdm_dev_s *priv);
int altmdm_spi_clearreceiverready(FAR struct altmdm_dev_s *priv);
#endif
/****************************************************************************
* Name: altmdm_spi_gpioreadyisr
*

File diff suppressed because it is too large Load Diff

View File

@ -89,7 +89,8 @@ int altmdm_pm_uninit(FAR struct altmdm_dev_s *priv);
*
****************************************************************************/
int altmdm_pm_wakeup(FAR struct altmdm_dev_s *priv);
int altmdm_pm_wakeup(FAR struct altmdm_dev_s *priv,
CODE int (*wait_fn)(FAR struct altmdm_dev_s *priv, uint32_t timeout_ms));
/****************************************************************************
* Name: altmdm_pm_notify_reset
@ -101,19 +102,6 @@ int altmdm_pm_wakeup(FAR struct altmdm_dev_s *priv);
int altmdm_pm_notify_reset(FAR struct altmdm_dev_s *priv);
#ifdef CONFIG_MODEM_ALTMDM_PROTCOL_V2_1
/****************************************************************************
* Name: altmdm_pm_callgpiohandler
*
* Description:
* Call Device to Host GPIO interrupt handler.
*
****************************************************************************/
int altmdm_pm_callgpiohandler(FAR struct altmdm_dev_s *priv);
#endif
/****************************************************************************
* Name: altmdm_pm_registercb
*

View File

@ -73,7 +73,12 @@
EVENT_SV_TIMER_EXP)
#define EVENT_TRANS_WAIT (EVENT_TXREQ | EVENT_RXREQ | EVENT_RXBUFRDY | \
EVENT_SLEEPREQ | EVENT_SV_TIMER_EXP | EVENT_EXIT)
#define XFER_TASK_PRI (90)
#if defined(CONFIG_MODEM_ALTMDM_XFER_TASK_PRIORITY)
# define XFER_TASK_PRI (CONFIG_MODEM_ALTMDM_XFER_TASK_PRIORITY)
#else
# define XFER_TASK_PRI (170)
#endif
#define XFER_TASK_STKSIZE (1536)
#define XFER_TASK_NAME "altmdm_xfer_task"
#if defined(CONFIG_MODEM_ALTMDM_MAX_PACKET_SIZE)
@ -92,7 +97,8 @@
/* Timeout is counted in units of millisecond. */
#define WAIT_RXREQ_TIMEOUT (1000)
#define WAIT_RXREQ_TIMEOUT (5)
#define WAIT_RXREQ_HEADER_TIMEOUT (5 * 1000)
#define WAIT_XFERRDY_TIMEOUT (25 * 1000)
#if defined(CONFIG_MODEM_ALTMDM_SLEEP_TIMER_VAL)
# if (CONFIG_MODEM_ALTMDM_SLEEP_TIMER_VAL < 20)
@ -104,11 +110,7 @@
#endif
#define WRITE_WAIT_TIMEOUT (ALTMDM_SYS_FLAG_TMOFEVR)
#define SREQ_WAIT_TIMEOUT (ALTMDM_SYS_FLAG_TMOFEVR)
#define SPI_MAXFREQUENCY (13000000) /* 13MHz. */
#define GPIO_SREQ_INT_POLARITY (ALTMDM_GPIOINT_LEVEL_HIGH)
#define GPIO_SREQ_INT_NOISE_FILTER (ALTMDM_GPIOINT_NOISE_FILTER_DISABLE)
#define YIELD_TASK_NOBUFF (100 * 1000) /* microsecond */
/* Defines for transfer mode */
@ -161,8 +163,6 @@
****************************************************************************/
static struct altmdm_dev_s *g_privdata = NULL;
static char g_tmp_rxbuff[MAX_PKT_SIZE];
static char g_tmp_txbuff[MAX_PKT_SIZE];
/****************************************************************************
* Private Functions
@ -181,8 +181,13 @@ static void svtimer_handler(int signo, FAR siginfo_t * info,
{
FAR struct altmdm_dev_s *priv =
(FAR struct altmdm_dev_s *)(info->si_value.sival_ptr);
struct altmdm_sys_flagstate_s flag_status;
altmdm_sys_setflag(&priv->spidev.xfer_flag, EVENT_SV_TIMER_EXP);
altmdm_sys_referflag(&priv->spidev.xfer_flag, &flag_status);
if (!(flag_status.flag_pattern & EVENT_SV_TIMER_EXP))
{
altmdm_sys_setflag(&priv->spidev.xfer_flag, EVENT_SV_TIMER_EXP);
}
}
/****************************************************************************
@ -293,7 +298,8 @@ static int get_dmasize(FAR struct altmdm_dev_s *priv, int data_size)
*
****************************************************************************/
static int wait_receiverready(FAR struct altmdm_dev_s *priv)
static int wait_receiverready(FAR struct altmdm_dev_s *priv,
uint32_t timeout_ms)
{
int ret;
uint32_t ptn;
@ -301,7 +307,7 @@ static int wait_receiverready(FAR struct altmdm_dev_s *priv)
ret = altmdm_sys_waitflag(&spidev->xfer_flag, EVENT_RXREQ,
ALTMDM_SYS_FLAG_WMODEOR, &ptn,
WAIT_RXREQ_TIMEOUT);
timeout_ms);
if (ret != 0)
{
m_err("receiver ready timeout.\n");
@ -802,6 +808,9 @@ static int do_xferheader(FAR struct altmdm_dev_s *priv,
if ((is_sleepreq) || (is_txreq))
{
DEBUGASSERT(priv->lower);
priv->lower->master_request(true);
if (is_sleepreq)
{
set_txheader_sleepreq(priv);
@ -820,6 +829,7 @@ static int do_xferheader(FAR struct altmdm_dev_s *priv,
{
possibleofrx = false;
}
set_txheader_possibleofrx(priv, possibleofrx);
}
@ -829,7 +839,7 @@ static int do_xferheader(FAR struct altmdm_dev_s *priv,
if ((!is_rxreq) && (!is_rcvrready))
{
ret = wait_receiverready(priv);
ret = wait_receiverready(priv, WAIT_RXREQ_HEADER_TIMEOUT);
if (ret < 0)
{
goto trans_header_error;
@ -840,8 +850,8 @@ static int do_xferheader(FAR struct altmdm_dev_s *priv,
dma_xfer_size = get_dmasize(priv, sizeof(struct altmdm_spi_xferhdr_s));
ret = do_dmaxfer(priv, (void *)&spidev->tx_param.header,
(void *)&spidev->rx_param.header, dma_xfer_size);
ret = do_dmaxfer(priv, (FAR void *)&spidev->tx_param.header,
(FAR void *)&spidev->rx_param.header, dma_xfer_size);
if (ret < 0)
{
goto trans_header_error;
@ -877,7 +887,7 @@ static int do_receivedata(FAR struct altmdm_dev_s *priv)
/* Wait for Receiver Ready to receive. */
ret = wait_receiverready(priv);
ret = wait_receiverready(priv, WAIT_RXREQ_TIMEOUT);
if (ret >= 0)
{
/* Get DMA transfer size */
@ -888,7 +898,7 @@ static int do_receivedata(FAR struct altmdm_dev_s *priv)
/* Do DMA transfer */
ret = do_dmaxfer(priv, (void *)g_tmp_txbuff, rxbuff, dma_xfer_size);
ret = do_dmaxfer(priv, NULL, rxbuff, dma_xfer_size);
}
if (ret < 0)
@ -916,7 +926,7 @@ static int do_senddata(FAR struct altmdm_dev_s *priv)
/* Wait for Receiver Ready to receive. */
ret = wait_receiverready(priv);
ret = wait_receiverready(priv, WAIT_RXREQ_TIMEOUT);
if (ret >= 0)
{
/* Get DMA transfer size */
@ -925,8 +935,8 @@ static int do_senddata(FAR struct altmdm_dev_s *priv)
/* Do DMA transfer */
ret = do_dmaxfer(priv, (void *)spidev->tx_param.buff_addr,
(void *)g_tmp_rxbuff, dma_xfer_size);
ret = do_dmaxfer(priv, (FAR void *)spidev->tx_param.buff_addr,
NULL, dma_xfer_size);
}
if (ret < 0)
@ -956,7 +966,7 @@ static int do_trxdata(FAR struct altmdm_dev_s *priv)
/* Wait for Receiver Ready to receive. */
ret = wait_receiverready(priv);
ret = wait_receiverready(priv, WAIT_RXREQ_TIMEOUT);
if (ret >= 0)
{
/* Choose the larger one. */
@ -978,7 +988,7 @@ static int do_trxdata(FAR struct altmdm_dev_s *priv)
/* Do DMA transfer */
ret = do_dmaxfer(priv, (void *)spidev->tx_param.buff_addr, rxbuff,
ret = do_dmaxfer(priv, (FAR void *)spidev->tx_param.buff_addr, rxbuff,
dma_xfer_size);
}
@ -1009,7 +1019,7 @@ static int do_receivedata_nobuff(FAR struct altmdm_dev_s *priv)
/* Wait for Receiver Ready to receive. */
ret = wait_receiverready(priv);
ret = wait_receiverready(priv, WAIT_RXREQ_TIMEOUT);
if (ret >= 0)
{
/* Get DMA transfer size */
@ -1018,8 +1028,7 @@ static int do_receivedata_nobuff(FAR struct altmdm_dev_s *priv)
/* Do DMA transfer */
ret = do_dmaxfer(priv, (void *)g_tmp_txbuff, (void *)g_tmp_rxbuff,
dma_xfer_size);
ret = do_dmaxfer(priv, NULL, NULL, dma_xfer_size);
}
if (ret < 0)
@ -1053,7 +1062,7 @@ static int do_trxdata_norxbuff(FAR struct altmdm_dev_s *priv)
/* Wait for Receiver Ready to receive. */
ret = wait_receiverready(priv);
ret = wait_receiverready(priv, WAIT_RXREQ_TIMEOUT);
if (ret >= 0)
{
/* Choose the larger one. */
@ -1073,8 +1082,8 @@ static int do_trxdata_norxbuff(FAR struct altmdm_dev_s *priv)
/* Do DMA transfer */
ret = do_dmaxfer(priv, (void *)spidev->tx_param.buff_addr,
(void *)g_tmp_rxbuff, dma_xfer_size);
ret = do_dmaxfer(priv, (FAR void *)spidev->tx_param.buff_addr,
NULL, dma_xfer_size);
}
if (ret < 0)
@ -1103,10 +1112,11 @@ static int do_receivesleepdata(FAR struct altmdm_dev_s *priv, FAR int *resp)
{
int ret;
int dma_xfer_size;
char rxbuff[UNIT_SIZE];
/* Wait for Receiver Ready to receive. */
ret = wait_receiverready(priv);
ret = wait_receiverready(priv, WAIT_RXREQ_TIMEOUT);
if (ret >= 0)
{
/* Get DMA transfer size */
@ -1115,8 +1125,7 @@ static int do_receivesleepdata(FAR struct altmdm_dev_s *priv, FAR int *resp)
/* Do DMA transfer */
ret = do_dmaxfer(priv, (void *)g_tmp_txbuff, (void *)g_tmp_rxbuff,
dma_xfer_size);
ret = do_dmaxfer(priv, NULL, (FAR void *)rxbuff, dma_xfer_size);
}
if (ret < 0)
@ -1127,10 +1136,10 @@ static int do_receivesleepdata(FAR struct altmdm_dev_s *priv, FAR int *resp)
else
{
m_info("[SRESP] 0x%02x,0x%02x,0x%02x,0x%02x\n",
g_tmp_rxbuff[0], g_tmp_rxbuff[1],
g_tmp_rxbuff[2], g_tmp_rxbuff[3]);
rxbuff[0], rxbuff[1],
rxbuff[2], rxbuff[3]);
if (!memcmp(g_tmp_rxbuff, "OK", 2))
if (!memcmp(rxbuff, "OK", 2))
{
*resp = SLEEP_OK;
}
@ -1156,10 +1165,11 @@ static int do_receivereset(FAR struct altmdm_dev_s *priv)
int ret;
int dma_xfer_size;
FAR struct altmdm_spi_dev_s *spidev = &priv->spidev;
char rxbuff[UNIT_SIZE];
/* Wait for Receiver Ready to receive. */
ret = wait_receiverready(priv);
ret = wait_receiverready(priv, WAIT_RXREQ_TIMEOUT);
if (ret >= 0)
{
/* Get DMA transfer size */
@ -1168,8 +1178,7 @@ static int do_receivereset(FAR struct altmdm_dev_s *priv)
/* Do DMA transfer */
ret = do_dmaxfer(priv, (void *)g_tmp_txbuff, (void *)g_tmp_rxbuff,
dma_xfer_size);
ret = do_dmaxfer(priv, NULL, (FAR void *)rxbuff, dma_xfer_size);
}
if (ret < 0)
@ -1183,7 +1192,7 @@ static int do_receivereset(FAR struct altmdm_dev_s *priv)
(spidev->rx_param.
status_info & (STAT_INF_GET_BOOTSTAT | STAT_INF_RESET)))
{
switch (g_tmp_rxbuff[0])
switch (rxbuff[0])
{
case RESET_BOOTSTAT_BOOTING:
altmdm_pm_set_bootstatus(priv,
@ -1197,9 +1206,9 @@ static int do_receivereset(FAR struct altmdm_dev_s *priv)
default:
m_err
("ERR:%04d Invalid payload of reset packet. %02x,%02x,%02x,%02x\n",
__LINE__, g_tmp_rxbuff[0], g_tmp_rxbuff[1], g_tmp_rxbuff[2],
g_tmp_rxbuff[3]);
("ERR:%04d Invalid payload of reset packet. " \
"%02x,%02x,%02x,%02x\n",
__LINE__, rxbuff[0], rxbuff[1], rxbuff[2], rxbuff[3]);
break;
}
}
@ -1235,19 +1244,15 @@ static int do_trxreset(FAR struct altmdm_dev_s *priv)
/* Wait for Receiver Ready to receive. */
ret = wait_receiverready(priv);
ret = wait_receiverready(priv, WAIT_RXREQ_TIMEOUT);
if (ret >= 0)
{
/* Choose the larger one. */
/* If a conflict occurs with the reset packet,
* the packet is transferred by the size specified
* by the receiving side. Discard the data on the sending side.
*/
if (spidev->tx_param.total_size < spidev->rx_param.total_size)
{
xfer_size = spidev->rx_param.total_size;
}
else
{
xfer_size = spidev->tx_param.total_size;
}
xfer_size = spidev->rx_param.total_size;
/* Get DMA transfer size */
@ -1255,8 +1260,7 @@ static int do_trxreset(FAR struct altmdm_dev_s *priv)
/* Do DMA transfer */
ret = do_dmaxfer(priv, (void *)spidev->tx_param.buff_addr,
(void *)g_tmp_rxbuff, dma_xfer_size);
ret = do_dmaxfer(priv, NULL, NULL, dma_xfer_size);
}
if (ret < 0)
@ -1280,7 +1284,7 @@ static int do_trxreset(FAR struct altmdm_dev_s *priv)
static int do_xfersleep(FAR struct altmdm_dev_s *priv, uint32_t is_rcvrready)
{
int ret;
int resp;
int resp = 0;
int is_reset = 0;
int total_size;
int actual_size;
@ -1307,6 +1311,9 @@ static int do_xfersleep(FAR struct altmdm_dev_s *priv, uint32_t is_rcvrready)
ret = SLEEP_NG;
}
DEBUGASSERT(priv && priv->lower);
priv->lower->master_request(false);
if (is_reset)
{
if (!priv->spidev.is_xferready)
@ -1331,7 +1338,8 @@ static int do_xfersleep(FAR struct altmdm_dev_s *priv, uint32_t is_rcvrready)
****************************************************************************/
static uint32_t decide_xfermode(FAR struct altmdm_dev_s *priv,
uint32_t is_rxreq, uint32_t is_txreq, int ret)
uint32_t is_rxreq, uint32_t is_txreq,
int ret)
{
int retval;
int is_reset;
@ -1556,6 +1564,13 @@ static void done_xfer(FAR struct altmdm_dev_s *priv, uint32_t xfer_mode,
}
altmdm_sys_setflag(&spidev->tx_param.done_flag, EVENT_TX_DONE);
/* Yield the CPU so that the upper layer can execute
* the receiving process.
*/
nxsig_usleep(YIELD_TASK_NOBUFF);
break;
case MODE_TRXHEADERFAILTXREQ:
@ -1596,8 +1611,16 @@ static void done_xfer(FAR struct altmdm_dev_s *priv, uint32_t xfer_mode,
altmdm_sys_setflag(&spidev->tx_param.done_flag, EVENT_TX_DONE);
break;
case MODE_TRXHEADERFAILRXREQ:
case MODE_RXDATANOBUFF:
/* Yield the CPU so that the upper layer can execute
* the receiving process.
*/
nxsig_usleep(YIELD_TASK_NOBUFF);
break;
case MODE_TRXHEADERFAILRXREQ:
case MODE_RXINVALID:
break;
@ -1703,8 +1726,8 @@ static int xfer_task(int argc, char *argv[])
}
else if (is_timerexp)
{
/* Case where modem spontaneously enters sleep state and
* timer is not stopped.
/* Case where modem spontaneously enters sleep state
* and timer is not stopped.
*/
modem_state = altmdm_pm_getinternalstate();
@ -1742,35 +1765,37 @@ static int xfer_task(int argc, char *argv[])
{
stop_svtimer(priv);
if (is_txreq)
{
/* Wakeup modem before data transfer */
/* Wakeup modem before data transfer */
res_code = altmdm_pm_wakeup(priv);
if (res_code == MODEM_PM_WAKEUP_FAIL)
{
done_xfer(priv, MODE_TXDATA, TRANS_WAITRCVRTMO);
start_svtimer(priv);
continue;
}
#ifdef CONFIG_MODEM_ALTMDM_PROTCOL_V2_1
else if (res_code == MODEM_PM_WAKEUP_DONE)
{
is_rcvrready = 1;
}
#endif
if (is_rxreq)
{
res_code = altmdm_pm_wakeup(priv, NULL);
}
else
{
res_code = altmdm_pm_wakeup(priv, wait_receiverready);
}
if (res_code == MODEM_PM_WAKEUP_FAIL)
{
done_xfer(priv, MODE_TXDATA, TRANS_WAITRCVRTMO);
start_svtimer(priv);
continue;
}
else if (res_code == MODEM_PM_WAKEUP_DONE)
{
is_rcvrready = 1;
}
/* transfer header */
ret = do_xferheader(priv, is_rxreq, is_txreq, 0, is_rcvrready);
#ifdef CONFIG_MODEM_ALTMDM_PROTCOL_V2_1
if (is_rcvrready)
{
is_rcvrready = 0;
}
#endif
xfer_mode = decide_xfermode(priv, is_rxreq, is_txreq, ret);
switch (xfer_mode)
@ -1817,6 +1842,12 @@ static int xfer_task(int argc, char *argv[])
break;
}
if (is_txreq)
{
DEBUGASSERT(priv->lower);
priv->lower->master_request(false);
}
m_info("m=%d\n", xfer_mode);
done_xfer(priv, xfer_mode, ret);
start_svtimer(priv);
@ -1849,25 +1880,10 @@ static int xfer_task(int argc, char *argv[])
int altmdm_spi_gpioreadyisr(int irq, FAR void *context, FAR void *arg)
{
uint32_t modem_state;
FAR struct altmdm_dev_s *priv = g_privdata;
FAR struct altmdm_spi_dev_s *spidev = &priv->spidev;
#ifdef CONFIG_MODEM_ALTMDM_PROTCOL_V2_1
modem_state = altmdm_pm_getinternalstate();
if ((modem_state == MODEM_PM_INTERNAL_STATE_GOING_TO_SLEEP) ||
(modem_state == MODEM_PM_INTERNAL_STATE_GOING_TO_WAKE) ||
(modem_state == MODEM_PM_INTERNAL_STATE_SLEEP))
{
altmdm_pm_callgpiohandler(priv);
}
else
{
altmdm_sys_setflag(&spidev->xfer_flag, EVENT_RXREQ);
}
#else
altmdm_sys_setflag(&spidev->xfer_flag, EVENT_RXREQ);
#endif
return 0;
}
@ -1891,7 +1907,6 @@ int altmdm_spi_init(FAR struct altmdm_dev_s *priv)
altmdm_pm_init(priv);
memset(&priv->spidev, 0, sizeof(struct altmdm_spi_dev_s));
memset(g_tmp_txbuff, 0, sizeof(g_tmp_txbuff));
priv->spidev.is_not_run = false;
priv->spidev.is_xferready = false;
@ -1906,14 +1921,18 @@ int altmdm_spi_init(FAR struct altmdm_dev_s *priv)
create_rxbufffifo(priv);
DEBUGASSERT(priv->lower);
/* SPI settings */
SPI_LOCK(priv->spi, true);
SPI_SETMODE(priv->spi, SPIDEV_MODE0);
SPI_SETBITS(priv->spi, 8);
SPI_SETFREQUENCY(priv->spi, SPI_MAXFREQUENCY);
SPI_SETFREQUENCY(priv->spi, priv->lower->spi_maxfreq());
SPI_LOCK(priv->spi, false);
priv->lower->sready_irqattach(true, altmdm_spi_gpioreadyisr);
priv->spidev.task_id = task_create(XFER_TASK_NAME, XFER_TASK_PRI,
XFER_TASK_STKSIZE, xfer_task, NULL);
if (priv->spidev.task_id == ERROR)
@ -1964,6 +1983,9 @@ int altmdm_spi_uninit(FAR struct altmdm_dev_s *priv)
destroy_rxbufffifo(priv);
DEBUGASSERT(priv->lower);
priv->lower->sready_irqattach(false, NULL);
/* Uninitialize modem power management driver */
altmdm_pm_uninit(priv);
@ -1981,6 +2003,9 @@ int altmdm_spi_uninit(FAR struct altmdm_dev_s *priv)
int altmdm_spi_enable(FAR struct altmdm_dev_s *priv)
{
DEBUGASSERT(priv && priv->lower);
priv->lower->sready_irqenable(true);
return 0;
}
@ -1996,6 +2021,9 @@ int altmdm_spi_disable(FAR struct altmdm_dev_s *priv)
{
FAR struct altmdm_spi_dev_s *spidev = &priv->spidev;
DEBUGASSERT(priv->lower);
priv->lower->sready_irqenable(false);
spidev->is_xferready = false;
return 0;
@ -2042,6 +2070,7 @@ ssize_t altmdm_spi_read(FAR struct altmdm_dev_s * priv,
m_info("rx buffer discard because of abort.%d\n", __LINE__);
free_rxbuffer(priv, rbuff);
}
rsize = -ECONNABORTED;
}
else
@ -2165,6 +2194,7 @@ again:
wsize = -EIO;
break;
}
m_info("%s: tx result: %d.\n", __func__, spidev->tx_param.result);
m_info("%s: write size: %d.\n", __func__, wsize);
}
@ -2250,8 +2280,6 @@ int altmdm_spi_sleepmodem(FAR struct altmdm_dev_s *priv)
return ret;
}
#ifdef CONFIG_MODEM_ALTMDM_PROTCOL_V2_1
/****************************************************************************
* Name: altmdm_spi_setreceiverready
*
@ -2307,6 +2335,5 @@ int altmdm_spi_clearreceiverready(FAR struct altmdm_dev_s *priv)
return 0;
}
#endif
#endif /* CONFIG_MODEM_ALTMDM */

View File

@ -45,6 +45,7 @@
#include <nuttx/spi/spi.h>
#include <queue.h>
#include <debug.h>
#include <nuttx/irq.h>
/****************************************************************************
* Pre-processor Definitions
@ -55,8 +56,8 @@
/* Non-standard debug that may be enabled just for testing the modem driver */
#ifdef CONFIG_MODEM_ALTMDM_DEBUG
# define m_err logerr
# define m_info loginfo
# define m_err _err
# define m_info _info
#else
# define m_err(x...)
# define m_info(x...)
@ -96,6 +97,18 @@ struct altmdm_pm_wakelock_s
int count;
};
struct altmdm_lower_s
{
void (*poweron)(void);
void (*poweroff)(void);
void (*sready_irqattach)(bool attach, xcpt_t handler);
void (*sready_irqenable)(bool enable);
bool (*sready)(void);
void (*master_request)(bool request);
void (*wakeup)(bool wakeup);
uint32_t (*spi_maxfreq)(void);
};
typedef void (*altmdm_pm_cbfunc_t) (uint32_t state);
/****************************************************************************
@ -120,13 +133,15 @@ extern "C"
* devpath - The full path to the driver to register. E.g., "/dev/altmdm".
* dev - An instance of the SPI interface to use to communicate with
* ALTMDM.
* lower - An instance of the lower interface.
*
* Returned Value:
* Not NULL on success; NULL on failure.
*
****************************************************************************/
FAR void *altmdm_register(FAR const char *devpath, FAR struct spi_dev_s *dev);
FAR void *altmdm_register(FAR const char *devpath, FAR struct spi_dev_s *dev,
FAR const struct altmdm_lower_s *lower);
/****************************************************************************
* Name: altmdm_unregister