blob: 491bd66a0437f1e3b79e83ff4693989bd6865bcf [file] [log] [blame]
/* Copyright 2014 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef __CROS_EC_USART_H
#define __CROS_EC_USART_H
/* STM32 USART driver for Chrome EC */
#include "common.h"
#include "consumer.h"
#include "producer.h"
#include "queue.h"
#include <stdint.h>
/*
* Per-USART state stored in RAM. This structure will be zero initialized by
* BSS init.
*/
struct usart_state {
/*
* Counter of bytes received and then dropped because of lack of space
* in the RX queue.
*/
uint32_t rx_dropped;
/*
* Counter of the number of times an receive overrun condition is
* detected. This will not usually be a count of the number of bytes
* that were lost due to overrun conditions.
*/
uint32_t rx_overrun;
};
struct usart_config;
struct usart_hw_ops {
/*
* The generic USART initialization code calls this function to allow
* the variant HW specific code to perform any initialization. This
* function is called before the USART is enabled, and should among
* other things enable the USARTs interrupt.
*/
void (*enable)(struct usart_config const *config);
/*
* The generic USART shutdown code calls this function, allowing the
* variant specific code an opportunity to do any variant specific
* shutdown tasks.
*/
void (*disable)(struct usart_config const *config);
};
/*
* The usart_rx/usart_tx structures contain functions pointers for the
* interrupt handler and producer/consumer operations required to implement a
* particular RX/TX strategy.
*
* These structures are defined by the various RX/TX implementations, and are
* used to initialize the usart_config structure to configure the USART driver
* for interrupt or DMA based transfer.
*/
struct usart_rx {
void (*init)(struct usart_config const *config);
void (*interrupt)(struct usart_config const *config);
/*
* Print to the console any per-strategy diagnostic information, this
* is used by the usart_info command. This can be NULL if there is
* nothing interesting to display.
*/
void (*info)(struct usart_config const *config);
struct producer_ops producer_ops;
};
struct usart_tx {
void (*init)(struct usart_config const *config);
void (*interrupt)(struct usart_config const *config);
/*
* Print to the console any per-strategy diagnostic information, this
* is used by the usart_info command. This can be NULL if there is
* nothing interesting to display.
*/
void (*info)(struct usart_config const *config);
struct consumer_ops consumer_ops;
};
extern struct usart_rx const usart_rx_interrupt;
extern struct usart_tx const usart_tx_interrupt;
/*
* Per-USART hardware configuration stored in flash. Instances of this
* structure are provided by each variants driver, one per physical USART.
*/
struct usart_hw_config {
int index;
intptr_t base;
int irq;
uint32_t volatile *clock_register;
uint32_t clock_enable;
struct usart_hw_ops const *ops;
};
/*
* Compile time Per-USART configuration stored in flash. Instances of this
* structure are provided by the user of the USART. This structure binds
* together all information required to operate a USART.
*/
struct usart_config {
/*
* Pointer to USART HW configuration. There is one HW configuration
* per physical USART.
*/
struct usart_hw_config const *hw;
struct usart_rx const *rx;
struct usart_tx const *tx;
/*
* Pointer to USART state structure. The state structure maintains per
* USART information.
*/
struct usart_state volatile *state;
/*
* Baud rate for USART.
*/
int baud;
/* Other flags (rx/tx inversion, half-duplex). */
#define USART_CONFIG_FLAG_RX_INV BIT(0)
#define USART_CONFIG_FLAG_TX_INV BIT(1)
#define USART_CONFIG_FLAG_HDSEL BIT(2)
unsigned int flags;
struct consumer consumer;
struct producer producer;
};
/*
* Convenience macro for defining USARTs and their associated state and buffers.
* NAME is used to construct the names of the usart_state struct, and
* usart_config struct, the latter is just called NAME.
*
* HW is the name of the usart_hw_config provided by the variant specific code.
*
* RX_QUEUE and TX_QUEUE are the names of the RX and TX queues that this USART
* should write to and read from respectively.
*/
/*
* The following assertions can not be made because they require access to
* non-const fields, but should be kept in mind.
*
* BUILD_ASSERT(RX_QUEUE.unit_bytes == 1);
* BUILD_ASSERT(TX_QUEUE.unit_bytes == 1);
*/
#define USART_CONFIG(HW, RX, TX, BAUD, FLAGS, RX_QUEUE, TX_QUEUE) \
((struct usart_config const) { \
.hw = &HW, \
.rx = &RX, \
.tx = &TX, \
.state = &((struct usart_state){}), \
.baud = BAUD, \
.flags = FLAGS, \
.consumer = { \
.queue = &TX_QUEUE, \
.ops = &TX.consumer_ops, \
}, \
.producer = { \
.queue = &RX_QUEUE, \
.ops = &RX.producer_ops, \
}, \
})
/*
* Initialize the given USART. Once init is finished the USART streams are
* available for operating on.
*/
void usart_init(struct usart_config const *config);
/*
* Shutdown the given USART.
*/
void usart_shutdown(struct usart_config const *config);
/*
* Handle a USART interrupt. The per-variant USART code creates bindings
* for the variants interrupts to call this generic USART interrupt handler
* with the appropriate usart_config.
*/
void usart_interrupt(struct usart_config const *config);
/*
* Trigger tx interrupt to process tx data. Calling this function will set
* TXIEIE of USART HW instance and trigger associated IRQ.
*/
void usart_tx_start(struct usart_config const *config);
/*
* These are HW specific baud rate calculation and setting functions that the
* peripheral variant code uses during initialization and clock frequency
* change. The baud rate divisor input frequency is passed in Hertz.
*/
void usart_set_baud_f0_l(struct usart_config const *config, int baud,
int frequency_hz);
void usart_set_baud_f(struct usart_config const *config, int baud,
int frequency_hz);
/*
* Allow specification of parity for this usart.
* parity is 0: none, 1: odd, 2: even.
*/
void usart_set_parity(struct usart_config const *config, int parity);
/*
* Check parity for this usart.
* parity is 0: none, 1: odd, 2: even.
*/
int usart_get_parity(struct usart_config const *config);
/*
* Set baud rate for this usart. Note that baud rate will get reset on
* core frequency change, so this only makes sense if the board never
* goes to deep idle.
*/
void usart_set_baud(struct usart_config const *config, int baud);
/*
* Different families provide different ways of clearing the transmit complete
* flag. This function will be provided by the family specific implementation.
*/
void usart_clear_tc(struct usart_config const *config);
/*
* Each family implementation provides the usart_get_configs function to access
* a read only list of the configs that are currently enabled.
*/
struct usart_configs {
/*
* The family's usart_config array, entries in the array for disabled
* configs will be NULL, enabled configs will point to the usart_config
* that was enabled. And the following will be true:
*
* configs[i]->hw->index == i;
*/
struct usart_config const * const *configs;
/*
* The total possible number of configs that this family supports.
* This will be the same as the number of usart_hw structs that the
* family provides in its family specific usart header.
*/
size_t count;
};
struct usart_configs usart_get_configs(void);
/*
* This usart_tx structure contains function pointer to interrupt
* handler implemented to send host response. Generic queue based
* interrupt handler is not used for usart host transport.
*/
extern struct usart_tx const usart_host_command_tx_interrupt;
#endif /* __CROS_EC_USART_H */