1 /* 2 * Perform SPI communication using the SPI peripheral. 3 * 4 * Copyright (C) 2023, 2024 Paul Boddie <paul@boddie.org.uk> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation; either version 2 of 9 * the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA 20 */ 21 22 #pragma once 23 24 #include <l4/re/c/dma_space.h> 25 #include <l4/sys/types.h> 26 #include <stdint.h> 27 28 29 30 #ifdef __cplusplus 31 32 #include <l4/devices/cpm-generic.h> 33 #include <l4/devices/dma-generic.h> 34 #include <l4/devices/hw_mmio_register_block.h> 35 #include <l4/devices/spi.h> 36 37 /* SPI peripheral channel. */ 38 39 class Spi_channel : public Spi_channel_base 40 { 41 Hw::Register_block<32> _regs; 42 43 /* Initialisation parameters. */ 44 45 l4_addr_t _spi_start; 46 enum Clock_identifiers _clock; 47 Cpm_chip *_cpm; 48 Dma_channel *_dma; 49 int _request_type; 50 uint64_t _frequency; 51 52 /* Common utilities. */ 53 54 void configure_transfer(uint8_t char_size); 55 void wait_busy(); 56 57 public: 58 explicit Spi_channel(l4_addr_t spi_start, l4_addr_t start, 59 enum Clock_identifiers clock, 60 Cpm_chip *cpm, 61 Dma_channel *dma, 62 int request_type, 63 uint64_t frequency); 64 65 /* Convenience operations. */ 66 67 virtual uint32_t send(uint32_t bytes, const uint8_t data[]); 68 69 virtual uint32_t send_dc(uint32_t bytes, const uint8_t data[], const int dc[], 70 uint8_t char_size, bool big_endian = true); 71 72 uint32_t send_units(uint32_t bytes, const uint8_t data[], uint8_t unit_size, 73 uint8_t char_size, bool big_endian = true); 74 75 /* DMA operations. */ 76 77 uint32_t transfer(l4_addr_t vaddr, l4re_dma_space_dma_addr_t paddr, 78 uint32_t count, uint8_t unit_size, uint8_t char_size, 79 l4_addr_t desc_vaddr = 0, 80 l4re_dma_space_dma_addr_t desc_paddr = 0); 81 }; 82 83 /* SPI peripheral. */ 84 85 class Spi_chip 86 { 87 protected: 88 l4_addr_t _spi_start, _start, _end; 89 Cpm_chip *_cpm; 90 91 virtual unsigned int num_channels() = 0; 92 93 virtual Spi_channel *_get_channel(uint8_t channel, Dma_channel *dma, 94 uint64_t frequency) = 0; 95 96 public: 97 explicit Spi_chip(l4_addr_t spi_start, l4_addr_t start, l4_addr_t end, Cpm_chip *cpm); 98 99 Spi_channel *get_channel(uint8_t channel, Dma_channel *dma, uint64_t frequency); 100 }; 101 102 #endif /* __cplusplus */