1 /* 2 * Perform SPI communication using the JZ4780 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-jz4780.h> 33 #include <l4/devices/dma-jz4780.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_jz4780_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_jz4780_chip *_cpm; 48 Dma_jz4780_channel *_dma; 49 enum Dma_jz4780_request_type _request_type; 50 uint64_t _frequency; 51 52 /* Common utilities. */ 53 54 void configure_transfer(uint8_t char_size); 55 56 void wait_busy(); 57 58 public: 59 explicit Spi_jz4780_channel(l4_addr_t spi_start, l4_addr_t start, 60 enum Clock_identifiers clock, 61 Cpm_jz4780_chip *cpm, 62 Dma_jz4780_channel *dma, 63 enum Dma_jz4780_request_type request_type, 64 uint64_t frequency); 65 66 /* Convenience operations. */ 67 68 virtual uint32_t send(uint32_t bytes, const uint8_t data[]); 69 70 virtual uint32_t send_dc(uint32_t bytes, const uint8_t data[], const int dc[], 71 uint8_t char_size, bool big_endian = true); 72 73 uint32_t send_units(uint32_t bytes, const uint8_t data[], uint8_t unit_size, 74 uint8_t char_size, bool big_endian = true); 75 76 /* DMA operations. */ 77 78 uint32_t transfer(l4_addr_t vaddr, l4re_dma_space_dma_addr_t paddr, 79 uint32_t count, uint8_t unit_size, uint8_t char_size, 80 l4_addr_t desc_vaddr = 0, 81 l4re_dma_space_dma_addr_t desc_paddr = 0); 82 }; 83 84 /* SPI peripheral. */ 85 86 class Spi_jz4780_chip 87 { 88 private: 89 l4_addr_t _spi_start, _start, _end; 90 Cpm_jz4780_chip *_cpm; 91 92 public: 93 explicit Spi_jz4780_chip(l4_addr_t spi_start, l4_addr_t start, l4_addr_t end, Cpm_jz4780_chip *cpm); 94 95 Spi_jz4780_channel *get_channel(uint8_t channel, Dma_jz4780_channel *dma, uint64_t frequency); 96 }; 97 98 #endif /* __cplusplus */ 99 100 101 102 /* C language interface. */ 103 104 EXTERN_C_BEGIN 105 106 void *jz4780_spi_init(l4_addr_t spi_start, l4_addr_t start, l4_addr_t end, 107 void *cpm); 108 109 void *jz4780_spi_get_channel(void *spi, uint8_t channel, void *dma, uint64_t frequency); 110 111 uint32_t jz4780_spi_send(void *channel, uint32_t bytes, const uint8_t data[]); 112 113 uint32_t jz4780_spi_send_dc(void *channel, uint32_t bytes, const uint8_t data[], 114 const int dc[], uint8_t char_size, int big_endian); 115 116 uint32_t jz4780_spi_send_units(void *channel, uint32_t bytes, const uint8_t data[], 117 uint8_t unit_size, uint8_t char_size, int big_endian); 118 119 uint32_t jz4780_spi_transfer(void *channel, l4_addr_t vaddr, 120 l4re_dma_space_dma_addr_t paddr, uint32_t count, 121 uint8_t unit_size, uint8_t char_size); 122 123 uint32_t jz4780_spi_transfer_descriptor(void *channel, l4_addr_t vaddr, 124 l4re_dma_space_dma_addr_t paddr, 125 uint32_t count, uint8_t unit_size, 126 uint8_t char_size, l4_addr_t desc_vaddr, 127 l4re_dma_space_dma_addr_t desc_paddr); 128 129 EXTERN_C_END