1 /* 2 * Perform SPI communication using a suitable abstraction augmented with 3 * explicit manipulation of a control signal. 4 * 5 * Copyright (C) 2023, 2024 Paul Boddie <paul@boddie.org.uk> 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License as 9 * published by the Free Software Foundation; either version 2 of 10 * the License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 20 * Boston, MA 02110-1301, USA 21 */ 22 23 #pragma once 24 25 #include <l4/re/c/dma_space.h> 26 #include <stdint.h> 27 28 29 30 #ifdef __cplusplus 31 32 #include <l4/devices/gpio.h> 33 #include <l4/devices/spi.h> 34 35 /* SPI channel abstraction. */ 36 37 class Spi_hybrid : public Spi_channel_base, public Spi_control_base 38 { 39 Spi_channel_base *_channel; 40 Hw::Gpio_chip *_control_device; 41 int _control_pin; 42 int _control_alt_func; 43 44 public: 45 explicit Spi_hybrid(Spi_channel_base *channel, 46 Hw::Gpio_chip *control_device, int control_pin, 47 int control_alt_func = -1); 48 49 Spi_channel_base *get_channel(); 50 51 void acquire_control(bool asserted); 52 53 void release_control(); 54 55 uint32_t send(uint32_t bytes, const uint8_t data[]); 56 57 uint32_t send_dc(uint32_t bytes, const uint8_t data[], const int dc[], 58 uint8_t char_size, bool big_endian = true); 59 60 uint32_t send_units(uint32_t bytes, const uint8_t data[], 61 uint8_t unit_size, uint8_t char_size, 62 bool big_endian = true); 63 64 uint32_t transfer(l4_addr_t vaddr, l4re_dma_space_dma_addr_t paddr, 65 uint32_t count, uint8_t unit_size, uint8_t char_size, 66 l4_addr_t desc_vaddr = 0, 67 l4re_dma_space_dma_addr_t desc_paddr = 0); 68 }; 69 70 #endif /* __cplusplus */ 71 72 73 74 /* C language interface. */ 75 76 EXTERN_C_BEGIN 77 78 void *spi_hybrid_get_channel(void *channel, void *control_chip, int control_pin, 79 int control_alt_func); 80 81 void *spi_hybrid_get_raw_channel(void *channel); 82 83 void spi_hybrid_acquire_control(void *channel, int asserted); 84 85 void spi_hybrid_release_control(void *channel); 86 87 uint32_t spi_hybrid_send(void *channel, uint32_t bytes, const uint8_t data[]); 88 89 uint32_t spi_hybrid_send_dc(void *channel, uint32_t bytes, const uint8_t data[], 90 const int dc[], uint8_t char_size, int big_endian); 91 92 uint32_t spi_hybrid_send_units(void *channel, uint32_t bytes, const uint8_t data[], 93 uint8_t unit_size, uint8_t char_size, int big_endian); 94 95 uint32_t spi_hybrid_transfer(void *channel, l4_addr_t vaddr, 96 l4re_dma_space_dma_addr_t paddr, uint32_t count, 97 uint8_t unit_size, uint8_t char_size); 98 99 uint32_t spi_hybrid_transfer_descriptor(void *channel, l4_addr_t vaddr, 100 l4re_dma_space_dma_addr_t paddr, 101 uint32_t count, uint8_t unit_size, 102 uint8_t char_size, l4_addr_t desc_vaddr, 103 l4re_dma_space_dma_addr_t desc_paddr); 104 105 EXTERN_C_END