150 lines
4.4 KiB
C
150 lines
4.4 KiB
C
/****************************************************************************
|
|
* drivers/modem/alt1250/altmdm_spi.c
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership. The
|
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
|
* "License"); you may not use this file except in compliance with the
|
|
* License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
* License for the specific language governing permissions and limitations
|
|
* under the License.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Included Files
|
|
****************************************************************************/
|
|
|
|
#include <nuttx/config.h>
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <arpa/inet.h>
|
|
|
|
#include <nuttx/modem/alt1250.h>
|
|
|
|
#include "altmdm_spi.h"
|
|
|
|
/****************************************************************************
|
|
* Public Functions
|
|
****************************************************************************/
|
|
|
|
void altmdm_spipkt_init(FAR altmdm_spipkt_t *pkt)
|
|
{
|
|
pkt->header = 0;
|
|
pkt->buffer = NULL;
|
|
pkt->buff_size = 0;
|
|
}
|
|
|
|
void altmdm_set_spipkt_rxbuffer(FAR altmdm_spipkt_t *pkt, FAR void *buf,
|
|
uint16_t sz)
|
|
{
|
|
pkt->buffer = buf;
|
|
pkt->buff_size = sz;
|
|
}
|
|
|
|
void altmdm_set_spipkt_txbuffer(FAR altmdm_spipkt_t *pkt, FAR void *buf,
|
|
uint16_t sz)
|
|
{
|
|
uint16_t total_sz;
|
|
|
|
if (sz <= ALTSPI_MAX_PKTSIZE)
|
|
{
|
|
sz &= ALTSPI_PKT_SIZEMASK;
|
|
total_sz = (sz + (ALTSPI_PKT_WORDSIZE - 1)) &
|
|
~(ALTSPI_PKT_WORDSIZE - 1);
|
|
pkt->header = (total_sz << ALTSPI_PKT_TOTALSIZE_POS) + sz;
|
|
pkt->buffer = buf;
|
|
pkt->buff_size = sz;
|
|
}
|
|
}
|
|
|
|
void altmdm_overwrite_body_size(FAR altmdm_spipkt_t *pkt, uint16_t sz)
|
|
{
|
|
uint16_t total_sz;
|
|
|
|
if (sz <= ALTSPI_MAX_PKTSIZE)
|
|
{
|
|
sz &= ALTSPI_PKT_SIZEMASK;
|
|
total_sz = (sz + (ALTSPI_PKT_WORDSIZE - 1)) &
|
|
~(ALTSPI_PKT_WORDSIZE - 1);
|
|
pkt->header = (pkt->header & ALTSPI_STATUSMASK) |
|
|
((total_sz << ALTSPI_PKT_TOTALSIZE_POS) + sz);
|
|
}
|
|
}
|
|
|
|
void altmdm_set_sleeppkt(FAR altmdm_spipkt_t *pkt)
|
|
{
|
|
altmdm_set_spipkt_txbuffer(pkt, NULL, 0);
|
|
pkt->header |= ALTSPI_SLEEP_BIT;
|
|
}
|
|
|
|
void altmdm_set_retrypkt(FAR altmdm_spipkt_t *pkt)
|
|
{
|
|
pkt->header |= ALTSPI_BUFFFULL_BIT;
|
|
}
|
|
|
|
bool altmdm_is_valid_spipkt_header(FAR altmdm_spipkt_t *pkt)
|
|
{
|
|
uint16_t actual_size;
|
|
uint16_t total_size;
|
|
|
|
actual_size = pkt_actual_size(pkt);
|
|
total_size = pkt_total_size(pkt);
|
|
|
|
return ((actual_size <= ALTSPI_MAX_PKTSIZE) &&
|
|
(actual_size <= pkt->buff_size) &&
|
|
(((actual_size + (ALTSPI_PKT_WORDSIZE - 1)) & ~(ALTSPI_PKT_WORDSIZE - 1))
|
|
== total_size));
|
|
}
|
|
|
|
bool altmdm_is_sleeppkt_ok(FAR altmdm_spipkt_t *pkt)
|
|
{
|
|
return (strncmp(pkt->buffer, "OKOK", 4) == 0);
|
|
}
|
|
|
|
void altmdm_do_hdr_transaction(FAR struct spi_dev_s *spidev,
|
|
FAR const struct alt1250_lower_s *lower, FAR altmdm_spipkt_t *tx_pkt,
|
|
FAR altmdm_spipkt_t *rx_pkt)
|
|
{
|
|
/* Alt1250 is network endian, so swap tx header value. */
|
|
|
|
tx_pkt->header = htonl(tx_pkt->header);
|
|
|
|
SPI_EXCHANGE(spidev, &tx_pkt->header, &rx_pkt->header, ALTSPI_PKT_HDRSIZE);
|
|
|
|
/* Get correct endian values after exchanged */
|
|
|
|
rx_pkt->header = ntohl(rx_pkt->header);
|
|
tx_pkt->header = ntohl(tx_pkt->header);
|
|
|
|
m_info("Header TRX done. rx: 0x%08lx, tx: 0x%08lx\n",
|
|
rx_pkt->header, tx_pkt->header);
|
|
}
|
|
|
|
void altmdm_do_body_transaction(FAR struct spi_dev_s *spidev,
|
|
FAR const struct alt1250_lower_s *lower, FAR altmdm_spipkt_t *tx_pkt,
|
|
FAR altmdm_spipkt_t *rx_pkt)
|
|
{
|
|
size_t exchange_size;
|
|
|
|
/* Larger size is exchange size */
|
|
|
|
exchange_size = pkt_total_size(tx_pkt) > pkt_total_size(rx_pkt)
|
|
? pkt_total_size(tx_pkt) : pkt_total_size(rx_pkt);
|
|
|
|
SPI_EXCHANGE(spidev, tx_pkt->buffer, rx_pkt->buffer, exchange_size);
|
|
|
|
m_info("Body TRX done. ex size: %d, rx size: %d/%d, tx size: %d/%d\n",
|
|
exchange_size, pkt_actual_size(rx_pkt), pkt_total_size(rx_pkt),
|
|
pkt_actual_size(tx_pkt), pkt_total_size(tx_pkt));
|
|
}
|