1 /* 2 * Perform SPI communication using a suitable abstraction augmented with 3 * explicit manipulation of a control signal. 4 * 5 * Copyright (C) 2023 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 #include <l4/devices/spi-hybrid.h> 24 25 26 27 Spi_hybrid::Spi_hybrid(Spi_channel_base *channel, 28 Hw::Gpio_chip *control_device, int control_pin, 29 int control_alt_func) 30 : _channel(channel), 31 _control_device(control_device), 32 _control_pin(control_pin), 33 _control_alt_func(control_alt_func) 34 { 35 } 36 37 Spi_channel_base *Spi_hybrid::get_channel() 38 { 39 return _channel; 40 } 41 42 void Spi_hybrid::acquire_control(bool asserted) 43 { 44 _control_device->setup(_control_pin, Hw::Gpio_chip::Output, asserted ? 1 : 0); 45 } 46 47 void Spi_hybrid::release_control() 48 { 49 if (_control_alt_func >= 0) 50 _control_device->config_pad(_control_pin, Hw::Gpio_chip::Function_alt, _control_alt_func); 51 else 52 _control_device->setup(_control_pin, Hw::Gpio_chip::Input, 0); 53 } 54 55 /* Send a byte sequence. */ 56 57 uint32_t Spi_hybrid::send(uint32_t bytes, const uint8_t data[]) 58 { 59 return _channel->send(bytes, data); 60 } 61 62 /* Send a byte sequence with control information. */ 63 64 uint32_t Spi_hybrid::send_dc(uint32_t bytes, const uint8_t data[], const int dc[]) 65 { 66 return _channel->send_dc(bytes, data, dc); 67 } 68 69 /* Send a sequence of units having the given character size. */ 70 71 uint32_t Spi_hybrid::send_units(uint32_t bytes, const uint8_t data[], 72 uint8_t unit_size, uint8_t char_size) 73 { 74 return _channel->send_units(bytes, data, unit_size, char_size); 75 } 76 77 78 79 /* C language interface. */ 80 81 void *spi_hybrid_get_channel(void *channel, void *control_chip, int control_pin, 82 int control_alt_func) 83 { 84 return (void *) new Spi_hybrid(reinterpret_cast<Spi_channel_base *>(channel), 85 reinterpret_cast<Hw::Gpio_chip *>(control_chip), 86 control_pin, control_alt_func); 87 } 88 89 void *spi_hybrid_get_raw_channel(void *channel) 90 { 91 return static_cast<Spi_hybrid *>(channel)->get_channel(); 92 } 93 94 void spi_hybrid_acquire_control(void *channel, int level) 95 { 96 static_cast<Spi_hybrid *>(channel)->acquire_control(level); 97 } 98 99 void spi_hybrid_release_control(void *channel) 100 { 101 static_cast<Spi_hybrid *>(channel)->release_control(); 102 } 103 104 uint32_t spi_hybrid_send(void *channel, uint32_t bytes, const uint8_t data[]) 105 { 106 return static_cast<Spi_hybrid *>(channel)->send(bytes, data); 107 } 108 109 uint32_t spi_hybrid_send_dc(void *channel, uint32_t bytes, const uint8_t data[], 110 const int dc[]) 111 { 112 return static_cast<Spi_hybrid *>(channel)->send_dc(bytes, data, dc); 113 } 114 115 uint32_t spi_hybrid_send_units(void *channel, uint32_t bytes, const uint8_t data[], 116 uint8_t unit_size, uint8_t char_size) 117 { 118 return static_cast<Spi_hybrid *>(channel)->send_units(bytes, data, unit_size, char_size); 119 }