1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/pkg/devices/lib/spi/src/hybrid.cc Thu Nov 09 18:40:31 2023 +0100
1.3 @@ -0,0 +1,119 @@
1.4 +/*
1.5 + * Perform SPI communication using a suitable abstraction augmented with
1.6 + * explicit manipulation of a control signal.
1.7 + *
1.8 + * Copyright (C) 2023 Paul Boddie <paul@boddie.org.uk>
1.9 + *
1.10 + * This program is free software; you can redistribute it and/or
1.11 + * modify it under the terms of the GNU General Public License as
1.12 + * published by the Free Software Foundation; either version 2 of
1.13 + * the License, or (at your option) any later version.
1.14 + *
1.15 + * This program is distributed in the hope that it will be useful,
1.16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.18 + * GNU General Public License for more details.
1.19 + *
1.20 + * You should have received a copy of the GNU General Public License
1.21 + * along with this program; if not, write to the Free Software
1.22 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
1.23 + * Boston, MA 02110-1301, USA
1.24 + */
1.25 +
1.26 +#include <l4/devices/spi-hybrid.h>
1.27 +
1.28 +
1.29 +
1.30 +Spi_hybrid::Spi_hybrid(Spi_channel_base *channel,
1.31 + Hw::Gpio_chip *control_device, int control_pin,
1.32 + int control_alt_func)
1.33 +: _channel(channel),
1.34 + _control_device(control_device),
1.35 + _control_pin(control_pin),
1.36 + _control_alt_func(control_alt_func)
1.37 +{
1.38 +}
1.39 +
1.40 +Spi_channel_base *Spi_hybrid::get_channel()
1.41 +{
1.42 + return _channel;
1.43 +}
1.44 +
1.45 +void Spi_hybrid::acquire_control(bool asserted)
1.46 +{
1.47 + _control_device->setup(_control_pin, Hw::Gpio_chip::Output, asserted ? 1 : 0);
1.48 +}
1.49 +
1.50 +void Spi_hybrid::release_control()
1.51 +{
1.52 + if (_control_alt_func >= 0)
1.53 + _control_device->config_pad(_control_pin, Hw::Gpio_chip::Function_alt, _control_alt_func);
1.54 + else
1.55 + _control_device->setup(_control_pin, Hw::Gpio_chip::Input, 0);
1.56 +}
1.57 +
1.58 +/* Send a byte sequence. */
1.59 +
1.60 +uint32_t Spi_hybrid::send(uint32_t bytes, const uint8_t data[])
1.61 +{
1.62 + return _channel->send(bytes, data);
1.63 +}
1.64 +
1.65 +/* Send a byte sequence with control information. */
1.66 +
1.67 +uint32_t Spi_hybrid::send_dc(uint32_t bytes, const uint8_t data[], const int dc[])
1.68 +{
1.69 + return _channel->send_dc(bytes, data, dc);
1.70 +}
1.71 +
1.72 +/* Send a sequence of units having the given character size. */
1.73 +
1.74 +uint32_t Spi_hybrid::send_units(uint32_t bytes, const uint8_t data[],
1.75 + uint8_t unit_size, uint8_t char_size)
1.76 +{
1.77 + return _channel->send_units(bytes, data, unit_size, char_size);
1.78 +}
1.79 +
1.80 +
1.81 +
1.82 +/* C language interface. */
1.83 +
1.84 +void *spi_hybrid_get_channel(void *channel, void *control_chip, int control_pin,
1.85 + int control_alt_func)
1.86 +{
1.87 + return (void *) new Spi_hybrid(reinterpret_cast<Spi_channel_base *>(channel),
1.88 + reinterpret_cast<Hw::Gpio_chip *>(control_chip),
1.89 + control_pin, control_alt_func);
1.90 +}
1.91 +
1.92 +void *spi_hybrid_get_raw_channel(void *channel)
1.93 +{
1.94 + return static_cast<Spi_hybrid *>(channel)->get_channel();
1.95 +}
1.96 +
1.97 +void spi_hybrid_acquire_control(void *channel, int level)
1.98 +{
1.99 + static_cast<Spi_hybrid *>(channel)->acquire_control(level);
1.100 +}
1.101 +
1.102 +void spi_hybrid_release_control(void *channel)
1.103 +{
1.104 + static_cast<Spi_hybrid *>(channel)->release_control();
1.105 +}
1.106 +
1.107 +uint32_t spi_hybrid_send(void *channel, uint32_t bytes, const uint8_t data[])
1.108 +{
1.109 + return static_cast<Spi_hybrid *>(channel)->send(bytes, data);
1.110 +}
1.111 +
1.112 +uint32_t spi_hybrid_send_dc(void *channel, uint32_t bytes, const uint8_t data[],
1.113 + const int dc[])
1.114 +{
1.115 + return static_cast<Spi_hybrid *>(channel)->send_dc(bytes, data, dc);
1.116 +}
1.117 +
1.118 +uint32_t spi_hybrid_send_units(void *channel, uint32_t bytes, const uint8_t data[],
1.119 + uint8_t unit_size, uint8_t char_size)
1.120 +{
1.121 + return static_cast<Spi_hybrid *>(channel)->send_units(bytes, data, unit_size, char_size);
1.122 +}