|
| 1 | +/* |
| 2 | + * Copyright (c) 2017 Intel Corporation |
| 3 | + * |
| 4 | + * SPDX-License-Identifier: Apache-2.0 |
| 5 | + */ |
| 6 | + |
| 7 | +/** |
| 8 | + * @file |
| 9 | + * @brief Private API for SPI drivers |
| 10 | + */ |
| 11 | + |
| 12 | +#ifndef __SPI_DRIVER_COMMON_H__ |
| 13 | +#define __SPI_DRIVER_COMMON_H__ |
| 14 | + |
| 15 | +#include <gpio.h> |
| 16 | +#include <spi.h> |
| 17 | + |
| 18 | +#ifdef __cplusplus |
| 19 | +extern "C" { |
| 20 | +#endif |
| 21 | + |
| 22 | +struct spi_context { |
| 23 | + struct spi_config *config; |
| 24 | + |
| 25 | + const struct spi_buf **current_tx; |
| 26 | + struct spi_buf **current_rx; |
| 27 | + |
| 28 | + void *tx_buf; |
| 29 | + u32_t tx_len; |
| 30 | + void *rx_buf; |
| 31 | + u32_t rx_len; |
| 32 | +}; |
| 33 | + |
| 34 | +static inline bool spi_context_configured(struct spi_context *ctx, |
| 35 | + struct spi_config *config) |
| 36 | +{ |
| 37 | + return !!(ctx->config == config); |
| 38 | +} |
| 39 | + |
| 40 | +static inline void spi_context_cs_configure(struct spi_context *ctx) |
| 41 | +{ |
| 42 | + if (ctx->config->cs) { |
| 43 | + gpio_pin_configure(ctx->config->cs->gpio_dev, |
| 44 | + ctx->config->cs->gpio_pin, GPIO_DIR_OUT); |
| 45 | + gpio_pin_write(ctx->config->cs->gpio_dev, |
| 46 | + ctx->config->cs->gpio_pin, 1); |
| 47 | + } |
| 48 | +} |
| 49 | + |
| 50 | +static inline void spi_context_cs_control(struct spi_context *ctx, bool on) |
| 51 | +{ |
| 52 | + if (ctx->config->cs) { |
| 53 | + if (on) { |
| 54 | + gpio_pin_write(ctx->config->cs->gpio_dev, |
| 55 | + ctx->config->cs->gpio_pin, 0); |
| 56 | + k_busy_wait(ctx->config->cs->delay); |
| 57 | + } else { |
| 58 | + k_busy_wait(ctx->config->cs->delay); |
| 59 | + gpio_pin_write(ctx->config->cs->gpio_dev, |
| 60 | + ctx->config->cs->gpio_pin, 1); |
| 61 | + } |
| 62 | + } |
| 63 | +} |
| 64 | + |
| 65 | +static inline void spi_context_buffers_setup(struct spi_context *ctx, |
| 66 | + const struct spi_buf **tx_bufs, |
| 67 | + struct spi_buf **rx_bufs, |
| 68 | + uint8_t dfs) |
| 69 | +{ |
| 70 | + SYS_LOG_DBG("tx_bufs %p (%p) - rx_bufs %p (%p) - %u", |
| 71 | + tx_bufs, tx_bufs ? *tx_bufs : NULL, |
| 72 | + rx_bufs, rx_bufs ? *rx_bufs : NULL, dfs); |
| 73 | + |
| 74 | + ctx->current_tx = tx_bufs; |
| 75 | + ctx->current_rx = rx_bufs; |
| 76 | + |
| 77 | + if (*tx_bufs) { |
| 78 | + ctx->tx_buf = (*tx_bufs)->buf; |
| 79 | + ctx->tx_len = (*tx_bufs)->len/dfs; |
| 80 | + } else { |
| 81 | + ctx->tx_buf = NULL; |
| 82 | + ctx->tx_len = 0; |
| 83 | + } |
| 84 | + |
| 85 | + if (*rx_bufs) { |
| 86 | + ctx->rx_buf = (*rx_bufs)->buf; |
| 87 | + ctx->rx_len = (*rx_bufs)->len/dfs; |
| 88 | + } else { |
| 89 | + ctx->rx_buf = NULL; |
| 90 | + ctx->rx_len = 0; |
| 91 | + } |
| 92 | + |
| 93 | + SYS_LOG_DBG("current_tx %p, current_rx %p," |
| 94 | + " tx buf/len %p/%u, rx buf/len %p/%u", |
| 95 | + ctx->current_tx, ctx->current_rx, |
| 96 | + ctx->tx_buf, ctx->tx_len, ctx->rx_buf, ctx->rx_len); |
| 97 | +} |
| 98 | + |
| 99 | +static ALWAYS_INLINE |
| 100 | +void spi_context_update_tx(struct spi_context *ctx, uint8_t dfs) |
| 101 | +{ |
| 102 | + if (!ctx->tx_len) { |
| 103 | + return; |
| 104 | + } |
| 105 | + |
| 106 | + ctx->tx_len--; |
| 107 | + if (!ctx->tx_len) { |
| 108 | + ctx->current_tx++; |
| 109 | + if (*ctx->current_tx) { |
| 110 | + ctx->tx_buf = (*ctx->current_tx)->buf; |
| 111 | + ctx->tx_len = (*ctx->current_tx)->len/dfs; |
| 112 | + } else { |
| 113 | + ctx->tx_buf = NULL; |
| 114 | + } |
| 115 | + } else if (ctx->tx_buf) { |
| 116 | + ctx->tx_buf += dfs; |
| 117 | + } |
| 118 | + |
| 119 | + SYS_LOG_DBG("tx buf/len %p/%u", ctx->tx_buf, ctx->tx_len); |
| 120 | +} |
| 121 | + |
| 122 | +static ALWAYS_INLINE |
| 123 | +bool spi_context_tx_on(struct spi_context *ctx) |
| 124 | +{ |
| 125 | + return !!(ctx->tx_buf || ctx->tx_len); |
| 126 | +} |
| 127 | + |
| 128 | +static ALWAYS_INLINE |
| 129 | +void spi_context_update_rx(struct spi_context *ctx, uint8_t dfs) |
| 130 | +{ |
| 131 | + if (!ctx->rx_len) { |
| 132 | + return; |
| 133 | + } |
| 134 | + |
| 135 | + ctx->rx_len--; |
| 136 | + if (!ctx->rx_len) { |
| 137 | + ctx->current_rx++; |
| 138 | + if (*ctx->current_rx) { |
| 139 | + ctx->rx_buf = (*ctx->current_rx)->buf; |
| 140 | + ctx->rx_len = (*ctx->current_rx)->len/dfs; |
| 141 | + } else { |
| 142 | + ctx->rx_buf = NULL; |
| 143 | + } |
| 144 | + } else if (ctx->rx_buf) { |
| 145 | + ctx->rx_buf += dfs; |
| 146 | + } |
| 147 | + |
| 148 | + SYS_LOG_DBG("rx buf/len %p/%u", ctx->rx_buf, ctx->rx_len); |
| 149 | +} |
| 150 | + |
| 151 | +static ALWAYS_INLINE |
| 152 | +bool spi_context_rx_on(struct spi_context *ctx) |
| 153 | +{ |
| 154 | + return !!(ctx->rx_buf || ctx->rx_len); |
| 155 | +} |
| 156 | + |
| 157 | +#ifdef __cplusplus |
| 158 | +} |
| 159 | +#endif |
| 160 | + |
| 161 | +#endif /* __SPI_DRIVER_COMMON_H__ */ |
0 commit comments