blob: 712293fbfe5c5f4d769d2bdc5195f23398e85e57 [file] [log] [blame]
/****************************************************************************
* arch/arm/src/tlsr82/tlsr82_spi_console.c
*
* SPDX-License-Identifier: Apache-2.0
*
* 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/arch.h>
#include <nuttx/irq.h>
#include <assert.h>
#include <debug.h>
#include <execinfo.h>
#include <nuttx/compiler.h>
#include <nuttx/board.h>
#include <nuttx/serial/serial.h>
#include <arch/board/board.h>
#include "arm_internal.h"
#include "tlsr82_gpio.h"
#include "hardware/tlsr82_spi.h"
#include "hardware/tlsr82_clock.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define CONFIG_TLSR82_SPI_CS_ON 1
#define SPI_WAIT_BUSY(t, _timeout_) \
do \
{ \
t = 0; \
while ((SPI_CTRL_REG & SPI_CTRL_BUSY) && (t < (_timeout_))) \
{ \
t++; \
} \
} \
while (0)
#ifdef CONFIG_TLSR82_SPI_CS_ON
# define TLSR82_SPI_CS_HIGH SPI_CS_HIGH
# define TLSR82_SPI_CS_LOW SPI_CS_LOW
#else
# define TLSR82_SPI_CS_HIGH 0
# define TLSR82_SPI_CS_LOW 0
#endif
/****************************************************************************
* Private Types
****************************************************************************/
struct spi_console_dev_s
{
uint32_t clkdiv;
uint32_t pin_mosi;
uint32_t pin_miso;
uint32_t pin_sck;
uint32_t pin_cs;
uint32_t cpol;
uint32_t cpha;
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
#ifdef CONFIG_TLSR82_SPI_SYSLOG
static inline void spi_putc(char ch);
#endif
static ssize_t spi_console_read(struct file *filep, char *buffer,
size_t buflen);
static ssize_t spi_console_write(struct file *filep,
const char *buffer, size_t buflen);
static int spi_console_ioctl(struct file *filep, int cmd,
unsigned long arg);
/****************************************************************************
* Private Data
****************************************************************************/
static struct spi_console_dev_s g_console_dev =
{
.clkdiv = 2,
.pin_mosi = GPIO_PIN_PA2 | GPIO_AF_MUX0,
.pin_miso = GPIO_PIN_PA3 | GPIO_AF_MUX0,
.pin_sck = GPIO_PIN_PD7 | GPIO_AF_MUX0,
.pin_cs = GPIO_PIN_PD2 | GPIO_AF_MUX0,
.cpol = 0,
.cpha = 0,
};
static const struct file_operations g_consoleops =
{
NULL, /* open */
NULL, /* close */
spi_console_read, /* read */
spi_console_write, /* write */
NULL, /* seek */
spi_console_ioctl, /* ioctl */
};
/****************************************************************************
* Inline Functions
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: gpio_console_ioctl
****************************************************************************/
static int spi_console_ioctl(struct file *filep, int cmd,
unsigned long arg)
{
return -ENOTTY;
}
/****************************************************************************
* Name: gpio_console_read
****************************************************************************/
static ssize_t spi_console_read(struct file *filep, char *buffer,
size_t buflen)
{
return 0;
}
/****************************************************************************
* Name: gpio_console_write
****************************************************************************/
static ssize_t spi_console_write(struct file *filep,
const char *buffer, size_t buflen)
{
int i;
/* Pull low the CS pin */
TLSR82_SPI_CS_LOW;
/* Enable SPI output and set status to write */
BM_CLR(SPI_CTRL_REG, SPI_CTRL_OUT_OFF);
BM_CLR(SPI_CTRL_REG, SPI_CTRL_RW_STA);
for (i = 0; i < buflen; i++)
{
SPI_DATA_REG = buffer[i];
while (SPI_CTRL_REG & SPI_CTRL_BUSY);
}
/* Pull high the CS pin */
TLSR82_SPI_CS_HIGH;
return buflen;
}
/****************************************************************************
* Name: spi_putc
*
* Description:
* Directly output a char by spi per
*
* Parameters:
* dev - Pointer to the driver state structure.
* handler - Callback to be invoked on timer interrupt.
* arg - Argument to be passed to the handler callback.
*
* Returned Values:
* Zero (OK) is returned on success; A negated errno value is returned
* to indicate the nature of any failure.
*
****************************************************************************/
#ifdef CONFIG_TLSR82_SPI_SYSLOG
static inline void spi_putc(char ch)
{
int t;
TLSR82_SPI_CS_LOW;
BM_CLR(SPI_CTRL_REG, SPI_CTRL_OUT_OFF);
BM_CLR(SPI_CTRL_REG, SPI_CTRL_RW_STA);
SPI_DATA_REG = ch;
SPI_WAIT_BUSY(t, 100);
TLSR82_SPI_CS_HIGH;
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: spi_console_init
****************************************************************************/
/****************************************************************************
* Name: spi_console_early_init
*
* Description:
* SPI early init, after this, the spi can be used for syslog before the
* console register, used for debug.
*
* Parameters:
* void
*
* Returned Values:
* void
*
****************************************************************************/
void spi_console_early_init(void)
{
/* SPI I2C multiplex config:
* 1. Enable the SPI and I2C for GroupA and GroupD;
* 2. Enable the PD7 SPI function;
* 3. Disable the PD7 I2C function;
*/
BM_SET(SPI_I2C_GROUP_REG, SPI_I2C_GROUPA_EN);
BM_SET(SPI_I2C_GROUP_REG, SPI_I2C_GROUPD_EN);
BM_SET(SPI_I2C_PIN_REG, SPI_PD7_SPI_EN);
BM_CLR(SPI_I2C_PIN_REG, I2C_PD7_I2C_EN);
/* GPIO config, the miso pin config can be removed */
tlsr82_gpioconfig(g_console_dev.pin_miso);
tlsr82_gpioconfig(g_console_dev.pin_mosi);
tlsr82_gpioconfig(g_console_dev.pin_sck);
tlsr82_gpioconfig(g_console_dev.pin_cs);
/* Pull-up the cs pin */
SPI_CS_HIGH;
/* Enable SPI clock source; */
BM_SET(CLK_EN1_REG, CLK_EN1_SPI);
/* Config the SPI clkdiv = 2,
* SpiClosk = SystemClock / ((clkdiv + 1) * 2)
* = 4MHz
*/
SPI_CLK_REG = 0;
BM_SET(SPI_CLK_REG, 2);
/* Enable SPI clock and config SPI as master; */
BM_SET(SPI_CLK_REG, SPI_CLK_EN);
BM_SET(SPI_CTRL_REG, SPI_CTRL_MASTER_EN);
/* CPOL = 0, CPHA = 0 */
SPI_MODE_REG = SPI_MODE_REG & (~0x3);
}
/****************************************************************************
* Name: spi_console_init
*
* Description:
* SPI as the console, only support write, the printf() will output by
* spi, used for debug.
*
* Parameters:
* void
*
* Returned Values:
* void
*
****************************************************************************/
void spi_console_init(void)
{
int ret;
/* Driver register */
ret = register_driver("/dev/console", &g_consoleops, 0666, NULL);
if (ret < 0)
{
syslog(LOG_DEBUG, "register spi_console failed\n");
}
}
/****************************************************************************
* Name: up_putc
*
* Description:
* Provide priority, low-level access to support OS debug
* writes. When the SPI is used for syslog output, the up_putc() should be
* implemented by spi.
*
****************************************************************************/
#ifdef CONFIG_TLSR82_SPI_SYSLOG
void up_putc(int ch)
{
spi_putc((uint8_t)ch);
}
#endif