1.1 --- a/pkg/devices/lib/gpio/include/gpio-jz4730.h Fri Sep 22 21:56:34 2023 +0200
1.2 +++ b/pkg/devices/lib/gpio/include/gpio-jz4730.h Sun Sep 24 01:53:43 2023 +0200
1.3 @@ -2,7 +2,7 @@
1.4 * GPIO driver for Ingenic JZ4730.
1.5 * (See below for additional copyright and licensing notices.)
1.6 *
1.7 - * Copyright (C) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
1.8 + * Copyright (C) 2017, 2018, 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 @@ -117,6 +117,11 @@
1.13
1.14 void _config_pad(unsigned bitmap, unsigned func, unsigned value);
1.15
1.16 + // Paired register field access.
1.17 +
1.18 + void _get_pin_value(unsigned pin, uint32_t reg_upper, uint32_t reg_lower,
1.19 + unsigned *value);
1.20 +
1.21 public:
1.22 Gpio_jz4730_chip(l4_addr_t start, l4_addr_t end,
1.23 unsigned nr_pins);
1.24 @@ -136,6 +141,7 @@
1.25 void config_pull(unsigned pin, unsigned mode);
1.26 void config_pad(unsigned pin, unsigned func, unsigned value);
1.27 void config_get(unsigned pin, unsigned reg, unsigned *value);
1.28 + void config_pad_get(unsigned pin, unsigned *func, unsigned *value);
1.29
1.30 // Multiple pin configuration methods.
1.31
1.32 @@ -172,6 +178,7 @@
1.33 void jz4730_gpio_config_pull(void *gpio, unsigned pin, unsigned mode);
1.34 void jz4730_gpio_config_pad(void *gpio, unsigned pin, unsigned func, unsigned value);
1.35 void jz4730_gpio_config_get(void *gpio, unsigned pin, unsigned reg, unsigned *value);
1.36 +void jz4730_gpio_config_pad_get(void *gpio, unsigned pin, unsigned *func, unsigned *value);
1.37
1.38 void jz4730_gpio_multi_setup(void *gpio, Pin_slice const *mask, unsigned mode, unsigned outvalues);
1.39 void jz4730_gpio_multi_config_pull(void *gpio, Pin_slice const *mask, unsigned mode);
2.1 --- a/pkg/devices/lib/gpio/include/gpio-jz4740.h Fri Sep 22 21:56:34 2023 +0200
2.2 +++ b/pkg/devices/lib/gpio/include/gpio-jz4740.h Sun Sep 24 01:53:43 2023 +0200
2.3 @@ -2,7 +2,7 @@
2.4 * GPIO driver for Ingenic JZ4740.
2.5 * (See below for additional copyright and licensing notices.)
2.6 *
2.7 - * Copyright (C) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
2.8 + * Copyright (C) 2017, 2018, 2023 Paul Boddie <paul@boddie.org.uk>
2.9 *
2.10 * This program is free software; you can redistribute it and/or
2.11 * modify it under the terms of the GNU General Public License as
2.12 @@ -128,6 +128,7 @@
2.13 void config_pull(unsigned pin, unsigned mode);
2.14 void config_pad(unsigned pin, unsigned func, unsigned value);
2.15 void config_get(unsigned pin, unsigned reg, unsigned *value);
2.16 + void config_pad_get(unsigned pin, unsigned *func, unsigned *value);
2.17
2.18 // Multiple pin configuration methods.
2.19
2.20 @@ -164,6 +165,7 @@
2.21 void jz4740_gpio_config_pull(void *gpio, unsigned pin, unsigned mode);
2.22 void jz4740_gpio_config_pad(void *gpio, unsigned pin, unsigned func, unsigned value);
2.23 void jz4740_gpio_config_get(void *gpio, unsigned pin, unsigned reg, unsigned *value);
2.24 +void jz4740_gpio_config_pad_get(void *gpio, unsigned pin, unsigned *func, unsigned *value);
2.25
2.26 void jz4740_gpio_multi_setup(void *gpio, Pin_slice const *mask, unsigned mode, unsigned outvalues);
2.27 void jz4740_gpio_multi_config_pull(void *gpio, Pin_slice const *mask, unsigned mode);
3.1 --- a/pkg/devices/lib/gpio/include/gpio-jz4780.h Fri Sep 22 21:56:34 2023 +0200
3.2 +++ b/pkg/devices/lib/gpio/include/gpio-jz4780.h Sun Sep 24 01:53:43 2023 +0200
3.3 @@ -2,7 +2,7 @@
3.4 * GPIO driver for Ingenic JZ4780.
3.5 * (See below for additional copyright and licensing notices.)
3.6 *
3.7 - * Copyright (C) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
3.8 + * Copyright (C) 2017, 2018, 2023 Paul Boddie <paul@boddie.org.uk>
3.9 *
3.10 * This program is free software; you can redistribute it and/or
3.11 * modify it under the terms of the GNU General Public License as
3.12 @@ -118,6 +118,7 @@
3.13 void config_pull(unsigned pin, unsigned mode);
3.14 void config_pad(unsigned pin, unsigned func, unsigned value);
3.15 void config_get(unsigned pin, unsigned reg, unsigned *value);
3.16 + void config_pad_get(unsigned pin, unsigned *func, unsigned *value);
3.17
3.18 // Multiple pin configuration methods.
3.19
3.20 @@ -154,6 +155,7 @@
3.21 void jz4780_gpio_config_pull(void *gpio, unsigned pin, unsigned mode);
3.22 void jz4780_gpio_config_pad(void *gpio, unsigned pin, unsigned func, unsigned value);
3.23 void jz4780_gpio_config_get(void *gpio, unsigned pin, unsigned reg, unsigned *value);
3.24 +void jz4780_gpio_config_pad_get(void *gpio, unsigned pin, unsigned *func, unsigned *value);
3.25
3.26 void jz4780_gpio_multi_setup(void *gpio, Pin_slice const *mask, unsigned mode, unsigned outvalues);
3.27 void jz4780_gpio_multi_config_pad(void *gpio, Pin_slice const *mask, unsigned func, unsigned value);
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/pkg/devices/lib/gpio/include/gpio-x1600.h Sun Sep 24 01:53:43 2023 +0200
4.3 @@ -0,0 +1,171 @@
4.4 +/*
4.5 + * GPIO driver for Ingenic X1600.
4.6 + * (See below for additional copyright and licensing notices.)
4.7 + *
4.8 + * Copyright (C) 2017, 2018, 2023 Paul Boddie <paul@boddie.org.uk>
4.9 + *
4.10 + * This program is free software; you can redistribute it and/or
4.11 + * modify it under the terms of the GNU General Public License as
4.12 + * published by the Free Software Foundation; either version 2 of
4.13 + * the License, or (at your option) any later version.
4.14 + *
4.15 + * This program is distributed in the hope that it will be useful,
4.16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
4.17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4.18 + * GNU General Public License for more details.
4.19 + *
4.20 + * You should have received a copy of the GNU General Public License
4.21 + * along with this program; if not, write to the Free Software
4.22 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
4.23 + * Boston, MA 02110-1301, USA
4.24 + *
4.25 + *
4.26 + * Subject to other copyrights, being derived from the bcm2835.cc and
4.27 + * omap.cc GPIO driver implementations.
4.28 + *
4.29 + * This file is part of TUD:OS and distributed under the terms of the
4.30 + * GNU General Public License 2.
4.31 + * Please see the COPYING-GPL-2 file for details.
4.32 + */
4.33 +
4.34 +#pragma once
4.35 +
4.36 +#include <l4/sys/err.h>
4.37 +#include <l4/sys/types.h>
4.38 +#include <stdint.h>
4.39 +#include "gpio.h"
4.40 +
4.41 +
4.42 +
4.43 +#ifdef __cplusplus
4.44 +
4.45 +#include <l4/devices/hw_mmio_register_block.h>
4.46 +
4.47 +// GPIO device control.
4.48 +
4.49 +class Gpio_x1600_irq_pin : public Hw::Gpio_irq_pin
4.50 +{
4.51 + unsigned _pin;
4.52 + Hw::Register_block<32> _regs;
4.53 +
4.54 + // Convenience method for obtaining the bit corresponding to a pin.
4.55 +
4.56 + l4_uint32_t _pin_bit(unsigned pin)
4.57 + { return 1 << (pin & 31); }
4.58 +
4.59 + void write_reg_pin(unsigned reg);
4.60 +
4.61 +public:
4.62 + Gpio_x1600_irq_pin(unsigned pin, Hw::Register_block<32> const ®s);
4.63 +
4.64 + void do_mask();
4.65 + void do_unmask();
4.66 + bool do_set_mode(unsigned mode);
4.67 + int clear();
4.68 + bool enabled();
4.69 +};
4.70 +
4.71 +class Gpio_x1600_chip : public Hw::Gpio_chip
4.72 +{
4.73 +private:
4.74 + Hw::Register_block<32> _regs;
4.75 +
4.76 + l4_addr_t _start, _end;
4.77 + unsigned _nr_pins;
4.78 + l4_uint32_t _pull_ups, _pull_downs;
4.79 +
4.80 + // Convenience method for obtaining the bit corresponding to a pin.
4.81 +
4.82 + l4_uint32_t _pin_bit(unsigned pin)
4.83 + { return 1 << (pin & 31); }
4.84 +
4.85 + // Convenience method for obtaining the bit position of a pin.
4.86 +
4.87 + unsigned _pin_shift(unsigned pin)
4.88 + { return pin % 32; }
4.89 +
4.90 + // Permit only "aligned" accesses to registers.
4.91 +
4.92 + unsigned _reg_offset_check(unsigned pin_offset) const
4.93 + {
4.94 + switch (pin_offset)
4.95 + {
4.96 + case 0:
4.97 + return 0;
4.98 +
4.99 + default:
4.100 + throw -L4_EINVAL;
4.101 + }
4.102 + }
4.103 +
4.104 +public:
4.105 + Gpio_x1600_chip(l4_addr_t start, l4_addr_t end,
4.106 + unsigned nr_pins,
4.107 + l4_uint32_t pull_ups, l4_uint32_t pull_downs);
4.108 +
4.109 + // Obtain the number of pins.
4.110 +
4.111 + unsigned nr_pins() const { return _nr_pins; }
4.112 +
4.113 + // Unnecessary operations.
4.114 +
4.115 + void request(unsigned) {}
4.116 + void free(unsigned) {}
4.117 +
4.118 + // Configuration methods.
4.119 +
4.120 + void setup(unsigned pin, unsigned mode, int value = 0);
4.121 + void config_pull(unsigned pin, unsigned mode);
4.122 + void config_pad(unsigned pin, unsigned func, unsigned value);
4.123 + void config_get(unsigned pin, unsigned reg, unsigned *value);
4.124 + void config_pad_get(unsigned pin, unsigned *func, unsigned *value);
4.125 +
4.126 + // Multiple pin configuration methods.
4.127 +
4.128 + void multi_setup(Pin_slice const &mask, unsigned mode, unsigned outvalues = 0);
4.129 + void multi_config_pad(Pin_slice const &mask, unsigned func, unsigned value = 0);
4.130 + void multi_set(Pin_slice const &mask, unsigned data);
4.131 + unsigned multi_get(unsigned offset);
4.132 +
4.133 + // IRQ pin configuration.
4.134 +
4.135 + Hw::Gpio_irq_pin *get_irq(unsigned pin);
4.136 +
4.137 + // Pin/port data methods.
4.138 +
4.139 + int get(unsigned pin);
4.140 + void set(unsigned pin, int value);
4.141 +
4.142 +private:
4.143 + void config(unsigned pin, unsigned mode);
4.144 +};
4.145 +
4.146 +#endif /* __cplusplus */
4.147 +
4.148 +
4.149 +
4.150 +/* C language interface. */
4.151 +
4.152 +EXTERN_C_BEGIN
4.153 +
4.154 +void *x1600_gpio_init(l4_addr_t start, l4_addr_t end, unsigned pins,
4.155 + l4_uint32_t pull_ups, l4_uint32_t pull_downs);
4.156 +
4.157 +void x1600_gpio_setup(void *gpio, unsigned pin, unsigned mode, int value);
4.158 +void x1600_gpio_config_pull(void *gpio, unsigned pin, unsigned mode);
4.159 +void x1600_gpio_config_pad(void *gpio, unsigned pin, unsigned func, unsigned value);
4.160 +void x1600_gpio_config_get(void *gpio, unsigned pin, unsigned reg, unsigned *value);
4.161 +void x1600_gpio_config_pad_get(void *gpio, unsigned pin, unsigned *func, unsigned *value);
4.162 +
4.163 +void x1600_gpio_multi_setup(void *gpio, Pin_slice const *mask, unsigned mode, unsigned outvalues);
4.164 +void x1600_gpio_multi_config_pad(void *gpio, Pin_slice const *mask, unsigned func, unsigned value);
4.165 +void x1600_gpio_multi_set(void *gpio, Pin_slice const *mask, unsigned data);
4.166 +unsigned x1600_gpio_multi_get(void *gpio, unsigned offset);
4.167 +
4.168 +int x1600_gpio_get(void *gpio, unsigned pin);
4.169 +void x1600_gpio_set(void *gpio, unsigned pin, int value);
4.170 +
4.171 +void *x1600_gpio_get_irq(void *gpio, unsigned pin);
4.172 +bool x1600_gpio_irq_set_mode(void *gpio_irq, unsigned mode);
4.173 +
4.174 +EXTERN_C_END
5.1 --- a/pkg/devices/lib/gpio/include/gpio.h Fri Sep 22 21:56:34 2023 +0200
5.2 +++ b/pkg/devices/lib/gpio/include/gpio.h Sun Sep 24 01:53:43 2023 +0200
5.3 @@ -2,7 +2,7 @@
5.4 * GPIO driver definitions.
5.5 * (See below for additional copyright and licensing notices.)
5.6 *
5.7 - * Copyright (C) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
5.8 + * Copyright (C) 2017, 2018, 2023 Paul Boddie <paul@boddie.org.uk>
5.9 *
5.10 * This program is free software; you can redistribute it and/or
5.11 * modify it under the terms of the GNU General Public License as
5.12 @@ -80,6 +80,7 @@
5.13 {
5.14 Function_gpio,
5.15 Function_alt,
5.16 + Function_irq,
5.17 };
5.18
5.19 virtual void request(unsigned pin) = 0;
5.20 @@ -123,6 +124,14 @@
5.21 virtual void config_get(unsigned pin, unsigned func, unsigned *value) = 0;
5.22
5.23 /**
5.24 + * \brief Get platform specific pad configuration.
5.25 + * \param pin the pin to configure.
5.26 + * \param func a platform specific sub-function of a pad to be configured
5.27 + * \param value a platform specific value for the given sub-function.
5.28 + */
5.29 + virtual void config_pad_get(unsigned pin, unsigned *func, unsigned *value) = 0;
5.30 +
5.31 + /**
5.32 * \brief Get the value of the given pin (generic API).
5.33 * \param pin the pin to read the value from.
5.34 */
5.35 @@ -210,6 +219,7 @@
5.36 {
5.37 Function_gpio,
5.38 Function_alt,
5.39 + Function_irq,
5.40 };
5.41
5.42 #endif /* __cplusplus */
6.1 --- a/pkg/devices/lib/gpio/src/Makefile Fri Sep 22 21:56:34 2023 +0200
6.2 +++ b/pkg/devices/lib/gpio/src/Makefile Sun Sep 24 01:53:43 2023 +0200
6.3 @@ -4,7 +4,7 @@
6.4 TARGET = libgpio.o.a libgpio.o.so
6.5 PC_FILENAME := libdrivers-gpio
6.6
6.7 -SRC_CC := jz4730.cc jz4740.cc jz4780.cc
6.8 +SRC_CC := jz4730.cc jz4740.cc jz4780.cc x1600.cc
6.9
6.10 PRIVATE_INCDIR += $(PKGDIR)/lib/gpio/include
6.11
7.1 --- a/pkg/devices/lib/gpio/src/jz4730.cc Fri Sep 22 21:56:34 2023 +0200
7.2 +++ b/pkg/devices/lib/gpio/src/jz4730.cc Sun Sep 24 01:53:43 2023 +0200
7.3 @@ -2,7 +2,7 @@
7.4 * GPIO driver for Ingenic JZ4730.
7.5 * (See below for additional copyright and licensing notices.)
7.6 *
7.7 - * Copyright (C) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
7.8 + * Copyright (C) 2017, 2018, 2023 Paul Boddie <paul@boddie.org.uk>
7.9 *
7.10 * This program is free software; you can redistribute it and/or
7.11 * modify it under the terms of the GNU General Public License as
7.12 @@ -46,6 +46,7 @@
7.13 Irq_detect_lower = 0x018, // PxGPDLR
7.14 Irq_detect_upper = 0x01c, // PxGPDUR
7.15 Irq_enable = 0x020, // PxGPIER
7.16 + Irq_mask = 0x024, // PxGPIM
7.17 Irq_flag = 0x028, // PxGPFR
7.18 };
7.19
7.20 @@ -70,8 +71,6 @@
7.21 }
7.22 }
7.23
7.24 -
7.25 -
7.26 // IRQ control for each GPIO pin.
7.27
7.28 Gpio_jz4730_irq_pin::Gpio_jz4730_irq_pin(unsigned pin, Hw::Register_block<32> const ®s)
7.29 @@ -129,6 +128,9 @@
7.30 {
7.31 // Set the interrupt bit in the PxGPIER register.
7.32
7.33 + /* NOTE: This should use the Irq_mask/PxGPIM register, with the enable
7.34 + register actually setting IRQ mode. */
7.35 +
7.36 clear_reg_pin(Irq_enable);
7.37 }
7.38
7.39 @@ -137,6 +139,9 @@
7.40 // Set the interrupt bit in the PxGPIER register, first also clearing the
7.41 // flag bit in the PxGPFR register to allow interrupts to be delivered.
7.42
7.43 + /* NOTE: This should use the Irq_mask/PxGPIM register, with the enable
7.44 + register actually setting IRQ mode. */
7.45 +
7.46 clear_reg_pin(Irq_flag);
7.47 set_reg_pin(Irq_enable);
7.48 }
7.49 @@ -306,19 +311,23 @@
7.50 Gpio_jz4730_chip::_config(unsigned bitmap, unsigned mode)
7.51 {
7.52 uint32_t upper_mask, lower_mask;
7.53 - unsigned bitmap_values = bitmap;
7.54
7.55 switch (mode)
7.56 {
7.57 case Input:
7.58 case Irq:
7.59 - // Clear the direction flags below.
7.60 - bitmap_values = 0;
7.61 - // Fall through to the next case to complete the operation.
7.62 + // Clear the direction flags.
7.63 + _regs[Port_direction] = _regs[Port_direction] & ~bitmap;
7.64 +
7.65 + // Clear the port function for the bits.
7.66 + _get_bitmaps(bitmap, 3, &upper_mask, &lower_mask);
7.67 + _regs[Port_function_upper] = (_regs[Port_function_upper] & ~upper_mask);
7.68 + _regs[Port_function_lower] = (_regs[Port_function_lower] & ~lower_mask);
7.69 + break;
7.70
7.71 case Output:
7.72 - // Clear the flags if set immediately above; otherwise, set them.
7.73 - _regs[Port_direction] = (_regs[Port_direction] & ~bitmap) | bitmap_values;
7.74 + // Set the direction flags.
7.75 + _regs[Port_direction] = _regs[Port_direction] | bitmap;
7.76
7.77 // Clear the port function for the bits.
7.78 _get_bitmaps(bitmap, 3, &upper_mask, &lower_mask);
7.79 @@ -382,12 +391,15 @@
7.80 {
7.81 case Hw::Gpio_chip::Function_alt:
7.82 _get_bitmaps(bitmap, value, &upper, &lower);
7.83 - // Fall through to the next case to complete the operation.
7.84 + _get_bitmaps(bitmap, 3, &upper_mask, &lower_mask);
7.85 + _regs[Port_function_upper] = (_regs[Port_function_upper] & ~upper_mask) | upper;
7.86 + _regs[Port_function_lower] = (_regs[Port_function_lower] & ~lower_mask) | lower;
7.87 + break;
7.88
7.89 case Hw::Gpio_chip::Function_gpio:
7.90 _get_bitmaps(bitmap, 3, &upper_mask, &lower_mask);
7.91 - _regs[Port_function_upper] = (_regs[Port_function_upper] & ~upper_mask) | upper;
7.92 - _regs[Port_function_lower] = (_regs[Port_function_lower] & ~lower_mask) | lower;
7.93 + _regs[Port_function_upper] = _regs[Port_function_upper] & ~upper_mask;
7.94 + _regs[Port_function_lower] = _regs[Port_function_lower] & ~lower_mask;
7.95 break;
7.96
7.97 default:
7.98 @@ -406,6 +418,62 @@
7.99 *value = (_regs[reg] >> _pin_shift(pin)) & 1;
7.100 }
7.101
7.102 +// Return function and function-specific configuration for a pin.
7.103 +
7.104 +void
7.105 +Gpio_jz4730_chip::config_pad_get(unsigned pin, unsigned *func, unsigned *value)
7.106 +{
7.107 + unsigned detect, direction, pin_function, interrupt;
7.108 +
7.109 + // Get the pin function using the awkward register pairing.
7.110 +
7.111 + _get_pin_value(pin, Port_function_upper, Port_function_lower, &pin_function);
7.112 +
7.113 + if (pin_function)
7.114 + {
7.115 + *func = Hw::Gpio_chip::Function_alt;
7.116 + *value = pin_function;
7.117 + return;
7.118 + }
7.119 +
7.120 + config_get(pin, Irq_enable, &interrupt);
7.121 +
7.122 + if (interrupt)
7.123 + {
7.124 + _get_pin_value(pin, Irq_detect_upper, Irq_detect_lower, &detect);
7.125 +
7.126 + *func = Hw::Gpio_chip::Function_irq;
7.127 +
7.128 + switch (detect)
7.129 + {
7.130 + case 0: *value = L4_IRQ_F_LEVEL_LOW; break;
7.131 + case 1: *value = L4_IRQ_F_LEVEL_HIGH; break;
7.132 + case 2: *value = L4_IRQ_F_NEG_EDGE; break;
7.133 + default: case 3: *value = L4_IRQ_F_POS_EDGE; break;
7.134 + }
7.135 + return;
7.136 + }
7.137 +
7.138 + config_get(pin, Port_direction, &direction);
7.139 +
7.140 + *func = Hw::Gpio_chip::Function_gpio;
7.141 + *value = direction ? Output : Input;
7.142 +}
7.143 +
7.144 +void
7.145 +Gpio_jz4730_chip::_get_pin_value(unsigned pin, uint32_t reg_upper,
7.146 + uint32_t reg_lower, unsigned *value)
7.147 +{
7.148 + uint8_t pin_out;
7.149 +
7.150 + if (pin >= _nr_pins)
7.151 + throw -L4_EINVAL;
7.152 +
7.153 + uint32_t reg = _select_bank_for_pin(reg_upper, reg_lower, pin, &pin_out);
7.154 +
7.155 + *value = (_regs[reg] & (3 << (pin_out << 1))) >> (pin_out << 1);
7.156 +}
7.157 +
7.158 // Obtain an IRQ abstraction for a pin.
7.159
7.160 Hw::Gpio_irq_pin *
7.161 @@ -473,6 +541,11 @@
7.162 static_cast<Gpio_jz4730_chip *>(gpio)->config_get(pin, reg, value);
7.163 }
7.164
7.165 +void jz4730_gpio_config_pad_get(void *gpio, unsigned pin, unsigned *func, unsigned *value)
7.166 +{
7.167 + static_cast<Gpio_jz4730_chip *>(gpio)->config_pad_get(pin, func, value);
7.168 +}
7.169 +
7.170 void jz4730_gpio_multi_setup(void *gpio, Pin_slice const *mask, unsigned mode, unsigned outvalues)
7.171 {
7.172 static_cast<Gpio_jz4730_chip *>(gpio)->multi_setup(*mask, mode, outvalues);
8.1 --- a/pkg/devices/lib/gpio/src/jz4740.cc Fri Sep 22 21:56:34 2023 +0200
8.2 +++ b/pkg/devices/lib/gpio/src/jz4740.cc Sun Sep 24 01:53:43 2023 +0200
8.3 @@ -2,7 +2,7 @@
8.4 * GPIO driver for Ingenic JZ4740.
8.5 * (See below for additional copyright and licensing notices.)
8.6 *
8.7 - * Copyright (C) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
8.8 + * Copyright (C) 2017, 2018, 2023 Paul Boddie <paul@boddie.org.uk>
8.9 *
8.10 * This program is free software; you can redistribute it and/or
8.11 * modify it under the terms of the GNU General Public License as
8.12 @@ -339,6 +339,38 @@
8.13 *value = (_regs[reg] >> _pin_shift(pin)) & 1;
8.14 }
8.15
8.16 +// Return function and function-specific configuration for a pin.
8.17 +
8.18 +void
8.19 +Gpio_jz4740_chip::config_pad_get(unsigned pin, unsigned *func, unsigned *value)
8.20 +{
8.21 + unsigned direction, function, select, trigger;
8.22 +
8.23 + config_get(pin, Port_function, &function);
8.24 + config_get(pin, Port_select, &select);
8.25 + config_get(pin, Port_dir, &direction);
8.26 +
8.27 + if (function)
8.28 + {
8.29 + *func = Hw::Gpio_chip::Function_alt;
8.30 + *value = select;
8.31 + return;
8.32 + }
8.33 +
8.34 + if (select)
8.35 + {
8.36 + config_get(pin, Port_trigger, &trigger);
8.37 +
8.38 + *func = Hw::Gpio_chip::Function_irq;
8.39 + *value = (trigger ? (direction ? L4_IRQ_F_POS_EDGE : L4_IRQ_F_NEG_EDGE)
8.40 + : (direction ? L4_IRQ_F_LEVEL_HIGH : L4_IRQ_F_LEVEL_LOW));
8.41 + return;
8.42 + }
8.43 +
8.44 + *func = Hw::Gpio_chip::Function_gpio;
8.45 + *value = direction ? Input : Output;
8.46 +}
8.47 +
8.48 // Obtain an IRQ abstraction for a pin.
8.49
8.50 Hw::Gpio_irq_pin *
8.51 @@ -406,6 +438,11 @@
8.52 static_cast<Gpio_jz4740_chip *>(gpio)->config_get(pin, reg, value);
8.53 }
8.54
8.55 +void jz4740_gpio_config_pad_get(void *gpio, unsigned pin, unsigned *func, unsigned *value)
8.56 +{
8.57 + static_cast<Gpio_jz4740_chip *>(gpio)->config_pad_get(pin, func, value);
8.58 +}
8.59 +
8.60 void jz4740_gpio_multi_setup(void *gpio, Pin_slice const *mask, unsigned mode, unsigned outvalues)
8.61 {
8.62 static_cast<Gpio_jz4740_chip *>(gpio)->multi_setup(*mask, mode, outvalues);
9.1 --- a/pkg/devices/lib/gpio/src/jz4780.cc Fri Sep 22 21:56:34 2023 +0200
9.2 +++ b/pkg/devices/lib/gpio/src/jz4780.cc Sun Sep 24 01:53:43 2023 +0200
9.3 @@ -2,7 +2,7 @@
9.4 * GPIO driver for Ingenic JZ4780.
9.5 * (See below for additional copyright and licensing notices.)
9.6 *
9.7 - * Copyright (C) 2017 Paul Boddie <paul@boddie.org.uk>
9.8 + * Copyright (C) 2017, 2023 Paul Boddie <paul@boddie.org.uk>
9.9 *
9.10 * This program is free software; you can redistribute it and/or
9.11 * modify it under the terms of the GNU General Public License as
9.12 @@ -47,20 +47,20 @@
9.13 */
9.14
9.15 enum Regs
9.16 -{
9.17 +{
9.18 Pin_level = 0x000, // PxPIN (read-only)
9.19 -
9.20 +
9.21 Port_int = 0x010, // PxINT
9.22 Port_int_set = 0x014, // PxINTS
9.23 Port_int_clear = 0x018, // PxINTC
9.24 -
9.25 +
9.26 Irq_mask = 0x020, // PxMSK (for PxINT == 1)
9.27 Irq_mask_set = 0x024, // PxMSKS
9.28 Irq_mask_clear = 0x028, // PxMSKC
9.29 Port_gpio = 0x020, // PxMSK (for PxINT == 0)
9.30 Port_gpio_set = 0x024, // PxMSKS
9.31 Port_gpio_clear = 0x028, // PxMSKC
9.32 -
9.33 +
9.34 Port_trigger = 0x030, // PxPAT1 (for PxINT == 1)
9.35 Port_trigger_set = 0x034, // PxPAT1S
9.36 Port_trigger_clear = 0x038, // PxPAT1C
9.37 @@ -70,7 +70,7 @@
9.38 Port_group1 = 0x030, // PxPAT1 (for PxINT == 0, PxMSK == 0)
9.39 Port_group1_set = 0x034, // PxPAT1S
9.40 Port_group1_clear = 0x038, // PxPAT1C
9.41 -
9.42 +
9.43 Port_level = 0x040, // PxPAT0 (for PxINT == 1)
9.44 Port_level_set = 0x044, // PxPAT0S
9.45 Port_level_clear = 0x048, // PxPAT0C
9.46 @@ -80,10 +80,10 @@
9.47 Port_group0 = 0x040, // PxPAT0 (for PxINT == 0, PxMSK == 0)
9.48 Port_group0_set = 0x044, // PxPAT0S
9.49 Port_group0_clear = 0x048, // PxPAT0C
9.50 -
9.51 +
9.52 Irq_flag = 0x050, // PxFLG (read-only)
9.53 Irq_flag_clear = 0x058, // PxFLGC
9.54 -
9.55 +
9.56 Pull_disable = 0x070, // PxPE
9.57 Pull_disable_set = 0x074, // PxPES
9.58 Pull_disable_clear = 0x078, // PxPEC
9.59 @@ -317,7 +317,7 @@
9.60 if (pin >= _nr_pins)
9.61 throw -L4_EINVAL;
9.62
9.63 - if (value > 1)
9.64 + if (value > 3)
9.65 throw -L4_EINVAL;
9.66
9.67 switch (func)
9.68 @@ -354,6 +354,45 @@
9.69 *value = (_regs[reg] >> _pin_shift(pin)) & 1;
9.70 }
9.71
9.72 +// Return function and function-specific configuration for a pin.
9.73 +
9.74 +void
9.75 +Gpio_jz4780_chip::config_pad_get(unsigned pin, unsigned *func, unsigned *value)
9.76 +{
9.77 + unsigned direction, gpio, group0, group1, interrupt, level, trigger;
9.78 +
9.79 + config_get(pin, Port_int, &interrupt);
9.80 +
9.81 + if (interrupt)
9.82 + {
9.83 + config_get(pin, Port_trigger, &trigger);
9.84 + config_get(pin, Port_level, &level);
9.85 +
9.86 + *func = Hw::Gpio_chip::Function_irq;
9.87 + *value = (trigger ? (level ? L4_IRQ_F_POS_EDGE : L4_IRQ_F_NEG_EDGE)
9.88 + : (level ? L4_IRQ_F_LEVEL_HIGH : L4_IRQ_F_LEVEL_LOW));
9.89 + return;
9.90 + }
9.91 +
9.92 + config_get(pin, Port_gpio, &gpio);
9.93 +
9.94 + if (gpio)
9.95 + {
9.96 + config_get(pin, Port_dir, &direction);
9.97 +
9.98 + *func = Hw::Gpio_chip::Function_gpio;
9.99 + *value = direction ? Input : Output;
9.100 + return;
9.101 + }
9.102 +
9.103 + *func = Hw::Gpio_chip::Function_alt;
9.104 +
9.105 + config_get(pin, Port_group0, &group0);
9.106 + config_get(pin, Port_group1, &group1);
9.107 +
9.108 + *value = (group1 << 1) | group0;
9.109 +}
9.110 +
9.111 // Obtain an IRQ abstraction for a pin.
9.112
9.113 Hw::Gpio_irq_pin *
9.114 @@ -417,6 +456,11 @@
9.115 static_cast<Gpio_jz4780_chip *>(gpio)->config_get(pin, reg, value);
9.116 }
9.117
9.118 +void jz4780_gpio_config_pad_get(void *gpio, unsigned pin, unsigned *func, unsigned *value)
9.119 +{
9.120 + static_cast<Gpio_jz4780_chip *>(gpio)->config_pad_get(pin, func, value);
9.121 +}
9.122 +
9.123 void jz4780_gpio_multi_setup(void *gpio, Pin_slice const *mask, unsigned mode, unsigned outvalues)
9.124 {
9.125 static_cast<Gpio_jz4780_chip *>(gpio)->multi_setup(*mask, mode, outvalues);
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/pkg/devices/lib/gpio/src/x1600.cc Sun Sep 24 01:53:43 2023 +0200
10.3 @@ -0,0 +1,519 @@
10.4 +/*
10.5 + * GPIO driver for Ingenic X1600.
10.6 + * (See below for additional copyright and licensing notices.)
10.7 + *
10.8 + * Copyright (C) 2017, 2023 Paul Boddie <paul@boddie.org.uk>
10.9 + *
10.10 + * This program is free software; you can redistribute it and/or
10.11 + * modify it under the terms of the GNU General Public License as
10.12 + * published by the Free Software Foundation; either version 2 of
10.13 + * the License, or (at your option) any later version.
10.14 + *
10.15 + * This program is distributed in the hope that it will be useful,
10.16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
10.17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10.18 + * GNU General Public License for more details.
10.19 + *
10.20 + * You should have received a copy of the GNU General Public License
10.21 + * along with this program; if not, write to the Free Software
10.22 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
10.23 + * Boston, MA 02110-1301, USA
10.24 + *
10.25 + *
10.26 + * Subject to other copyrights, being derived from the bcm2835.cc and
10.27 + * omap.cc GPIO driver implementations.
10.28 + *
10.29 + * This file is part of TUD:OS and distributed under the terms of the
10.30 + * GNU General Public License 2.
10.31 + * Please see the COPYING-GPL-2 file for details.
10.32 + */
10.33 +
10.34 +#include <l4/sys/icu.h>
10.35 +#include <l4/util/util.h>
10.36 +#include <l4/devices/hw_mmio_register_block.h>
10.37 +
10.38 +#include "gpio-x1600.h"
10.39 +
10.40 +/*
10.41 +GPIO register offsets (x in A..D).
10.42 +
10.43 +Register summary:
10.44 +
10.45 +PxINT 0 (function/GPIO) 1 (interrupt)
10.46 +PxMSK 0 (function) 1 (GPIO) 0 (IRQ enable)/1 (IRQ disable)
10.47 +PxPAT1 0 (function 0/1) 1 (function 2/3) 0 (output) 1 (input) 0 (level trigger) 1 (edge trigger)
10.48 +PxPAT0 0 (function 0) 0 (function 2) 0 (output value 0) 0 (low level) 0 (falling edge)
10.49 + 1 (function 1) 1 (function 3) 1 (output value 1) 1 (high level) 1 (rising edge)
10.50 +*/
10.51 +
10.52 +enum Regs
10.53 +{
10.54 + Pin_level = 0x000, // PxPINL (read-only)
10.55 +
10.56 + Port_int = 0x010, // PxINT
10.57 + Port_int_set = 0x014, // PxINTS
10.58 + Port_int_clear = 0x018, // PxINTC
10.59 +
10.60 + Irq_mask = 0x020, // PxMSK (for PxINT == 1)
10.61 + Irq_mask_set = 0x024, // PxMSKS
10.62 + Irq_mask_clear = 0x028, // PxMSKC
10.63 + Port_gpio = 0x020, // PxMSK (for PxINT == 0)
10.64 + Port_gpio_set = 0x024, // PxMSKS
10.65 + Port_gpio_clear = 0x028, // PxMSKC
10.66 +
10.67 + Port_trigger = 0x030, // PxPAT1 (for PxINT == 1)
10.68 + Port_trigger_set = 0x034, // PxPAT1S
10.69 + Port_trigger_clear = 0x038, // PxPAT1C
10.70 + Port_dir = 0x030, // PxPAT1 (for PxINT == 0, PxMSK == 1)
10.71 + Port_dir_set = 0x034, // PxPAT1S
10.72 + Port_dir_clear = 0x038, // PxPAT1C
10.73 + Port_group1 = 0x030, // PxPAT1 (for PxINT == 0, PxMSK == 0)
10.74 + Port_group1_set = 0x034, // PxPAT1S
10.75 + Port_group1_clear = 0x038, // PxPAT1C
10.76 +
10.77 + Port_level = 0x040, // PxPAT0 (for PxINT == 1)
10.78 + Port_level_set = 0x044, // PxPAT0S
10.79 + Port_level_clear = 0x048, // PxPAT0C
10.80 + Port_data = 0x040, // PxPAT0 (for PxINT == 0, PxMSK == 1, PxPAT1 == 0)
10.81 + Port_data_set = 0x044, // PxPAT0S
10.82 + Port_data_clear = 0x048, // PxPAT0C
10.83 + Port_group0 = 0x040, // PxPAT0 (for PxINT == 0, PxMSK == 0)
10.84 + Port_group0_set = 0x044, // PxPAT0S
10.85 + Port_group0_clear = 0x048, // PxPAT0C
10.86 +
10.87 + Irq_flag = 0x050, // PxFLG (read-only)
10.88 + Irq_flag_clear = 0x058, // PxFLGC
10.89 +
10.90 + // Only the following registers differ from the JZ4780. The dual-edge
10.91 + // registers being added to the X1600, with the pull-up/down registers being
10.92 + // relocated.
10.93 +
10.94 + Pull_edge = 0x070, // PxEDG
10.95 + Pull_edge_set = 0x074, // PxEDGS
10.96 + Pull_edge_clear = 0x078, // PxEDGC
10.97 +
10.98 + Pull_disable = 0x080, // PxPE
10.99 + Pull_disable_set = 0x084, // PxPES
10.100 + Pull_disable_clear = 0x088, // PxPEC
10.101 +
10.102 + // The shadow port Z is available at offset 0x700 and supports the INTS, INTC,
10.103 + // MSKS, MSKC, PAT1S, PAT1C, PAT0S, PAT0C registers, along with the following.
10.104 +
10.105 + Shadow_transfer = 0x0f0, // PzGID2LD
10.106 +};
10.107 +
10.108 +
10.109 +
10.110 +// IRQ control for each GPIO pin.
10.111 +
10.112 +Gpio_x1600_irq_pin::Gpio_x1600_irq_pin(unsigned pin, Hw::Register_block<32> const ®s)
10.113 +: _pin(pin), _regs(regs)
10.114 +{}
10.115 +
10.116 +void
10.117 +Gpio_x1600_irq_pin::write_reg_pin(unsigned reg)
10.118 +{
10.119 + // Write the pin bit to the register, setting or clearing the pin
10.120 + // depending on the register chosen.
10.121 +
10.122 + _regs[reg] = _pin_bit(_pin);
10.123 +}
10.124 +
10.125 +void Gpio_x1600_irq_pin::do_mask()
10.126 +{
10.127 + // Set the interrupt bit in the PxIM register.
10.128 +
10.129 + write_reg_pin(Irq_mask_set);
10.130 +}
10.131 +
10.132 +void Gpio_x1600_irq_pin::do_unmask()
10.133 +{
10.134 + // Clear the interrupt bit in the PxIM register, first also clearing the
10.135 + // flag bit in the PxFLG register to allow interrupts to be delivered.
10.136 +
10.137 + write_reg_pin(Irq_flag_clear);
10.138 + write_reg_pin(Irq_mask_clear);
10.139 +}
10.140 +
10.141 +bool Gpio_x1600_irq_pin::do_set_mode(unsigned mode)
10.142 +{
10.143 + // Standard comment found for this method:
10.144 + // this operation touches multiple mmio registers and is thus
10.145 + // not atomic, that's why we first mask the IRQ and if it was
10.146 + // enabled we unmask it after we have changed the mode
10.147 +
10.148 + /* NOTE: The X1600 provides a special port Z that allows changes to be made
10.149 + and then committed atomically using PzGID2LD. This is not currently
10.150 + used. */
10.151 +
10.152 + if (enabled())
10.153 + do_mask();
10.154 +
10.155 + // Do the PxINT, PxPAT1 and PxPAT0 configuration.
10.156 +
10.157 + switch(mode)
10.158 + {
10.159 + case L4_IRQ_F_LEVEL_HIGH:
10.160 + write_reg_pin(Port_int_set);
10.161 + write_reg_pin(Port_trigger_clear);
10.162 + write_reg_pin(Port_level_set);
10.163 + break;
10.164 + case L4_IRQ_F_LEVEL_LOW:
10.165 + write_reg_pin(Port_int_set);
10.166 + write_reg_pin(Port_trigger_clear);
10.167 + write_reg_pin(Port_level_clear);
10.168 + break;
10.169 + case L4_IRQ_F_POS_EDGE:
10.170 + write_reg_pin(Port_int_set);
10.171 + write_reg_pin(Port_trigger_set);
10.172 + write_reg_pin(Port_level_set);
10.173 + break;
10.174 + case L4_IRQ_F_NEG_EDGE:
10.175 + write_reg_pin(Port_int_set);
10.176 + write_reg_pin(Port_trigger_set);
10.177 + write_reg_pin(Port_level_clear);
10.178 + break;
10.179 +
10.180 + default:
10.181 + return false;
10.182 + }
10.183 +
10.184 + if (enabled())
10.185 + do_unmask();
10.186 +
10.187 + return true;
10.188 +}
10.189 +
10.190 +int Gpio_x1600_irq_pin::clear()
10.191 +{
10.192 + // Obtain the flag status for the pin, clearing it if set.
10.193 +
10.194 + l4_uint32_t e = _regs[Irq_flag] & (1UL << _pin);
10.195 + if (e)
10.196 + _regs[Irq_flag_clear] = e;
10.197 +
10.198 + return (e >> _pin);
10.199 +}
10.200 +
10.201 +bool Gpio_x1600_irq_pin::enabled()
10.202 +{
10.203 + return true;
10.204 +}
10.205 +
10.206 +
10.207 +
10.208 +// Initialise the GPIO controller.
10.209 +
10.210 +Gpio_x1600_chip::Gpio_x1600_chip(l4_addr_t start, l4_addr_t end,
10.211 + unsigned nr_pins,
10.212 + l4_uint32_t pull_ups, l4_uint32_t pull_downs)
10.213 +: _start(start), _end(end),
10.214 + _nr_pins(nr_pins),
10.215 + _pull_ups(pull_ups), _pull_downs(pull_downs)
10.216 +{
10.217 + _regs = new Hw::Mmio_register_block<32>(_start);
10.218 +}
10.219 +
10.220 +// Return the value of a pin.
10.221 +
10.222 +int
10.223 +Gpio_x1600_chip::get(unsigned pin)
10.224 +{
10.225 + if (pin >= _nr_pins)
10.226 + throw -L4_EINVAL;
10.227 +
10.228 + l4_uint32_t val = _regs[Pin_level];
10.229 + return (val >> _pin_shift(pin)) & 1;
10.230 +}
10.231 +
10.232 +// Return multiple pin values.
10.233 +
10.234 +unsigned
10.235 +Gpio_x1600_chip::multi_get(unsigned offset)
10.236 +{
10.237 + _reg_offset_check(offset);
10.238 + return _regs[Pin_level];
10.239 +}
10.240 +
10.241 +// Set the value of a pin.
10.242 +
10.243 +void
10.244 +Gpio_x1600_chip::set(unsigned pin, int value)
10.245 +{
10.246 + if (pin >= _nr_pins)
10.247 + throw -L4_EINVAL;
10.248 +
10.249 + l4_uint32_t reg_set = value ? Port_data_set : Port_data_clear;
10.250 + _regs[reg_set] = _pin_bit(pin);
10.251 +}
10.252 +
10.253 +// Set multiple pin values.
10.254 +
10.255 +void
10.256 +Gpio_x1600_chip::multi_set(Pin_slice const &mask, unsigned data)
10.257 +{
10.258 + _reg_offset_check(mask.offset);
10.259 + if (mask.mask & data)
10.260 + _regs[Port_data_set] = (mask.mask & data);
10.261 + if (mask.mask & ~data)
10.262 + _regs[Port_data_clear] = (mask.mask & ~data);
10.263 +}
10.264 +
10.265 +// Set a pin up with the given mode and value (if appropriate).
10.266 +
10.267 +void
10.268 +Gpio_x1600_chip::setup(unsigned pin, unsigned mode, int value)
10.269 +{
10.270 + if (pin >= _nr_pins)
10.271 + throw -L4_EINVAL;
10.272 +
10.273 + config(pin, mode);
10.274 +
10.275 + if (mode == Output)
10.276 + set(pin, value);
10.277 +}
10.278 +
10.279 +// Configuration of a pin using the generic input/output/IRQ mode.
10.280 +
10.281 +void
10.282 +Gpio_x1600_chip::config(unsigned pin, unsigned mode)
10.283 +{
10.284 + switch (mode)
10.285 + {
10.286 + case Input:
10.287 + _regs[Port_int_clear] = _pin_bit(pin);
10.288 + _regs[Port_gpio_set] = _pin_bit(pin);
10.289 + _regs[Port_dir_set] = _pin_bit(pin);
10.290 + break;
10.291 + case Output:
10.292 + _regs[Port_int_clear] = _pin_bit(pin);
10.293 + _regs[Port_gpio_set] = _pin_bit(pin);
10.294 + _regs[Port_dir_clear] = _pin_bit(pin);
10.295 + break;
10.296 + case Irq:
10.297 + _regs[Port_int_set] = _pin_bit(pin);
10.298 + // Other details depend on the actual trigger mode.
10.299 + break;
10.300 + default:
10.301 + break;
10.302 + }
10.303 +}
10.304 +
10.305 +// Pull-up/down configuration for a pin.
10.306 +
10.307 +void
10.308 +Gpio_x1600_chip::config_pull(unsigned pin, unsigned mode)
10.309 +{
10.310 + if (pin >= _nr_pins)
10.311 + throw -L4_EINVAL;
10.312 +
10.313 + switch (mode)
10.314 + {
10.315 + case Pull_none:
10.316 + _regs[Pull_disable_set] = _pin_bit(pin);
10.317 + break;
10.318 + case Pull_down:
10.319 + if (_pin_bit(pin) & _pull_downs)
10.320 + _regs[Pull_disable_clear] = _pin_bit(pin);
10.321 + break;
10.322 + case Pull_up:
10.323 + if (_pin_bit(pin) & _pull_ups)
10.324 + _regs[Pull_disable_clear] = _pin_bit(pin);
10.325 + break;
10.326 + default:
10.327 + // Invalid pull-up/down mode for pin.
10.328 + throw -L4_EINVAL;
10.329 + }
10.330 +}
10.331 +
10.332 +// Pin function configuration.
10.333 +
10.334 +void
10.335 +Gpio_x1600_chip::config_pad(unsigned pin, unsigned func, unsigned value)
10.336 +{
10.337 + if (pin >= _nr_pins)
10.338 + throw -L4_EINVAL;
10.339 +
10.340 + if (value > 3)
10.341 + throw -L4_EINVAL;
10.342 +
10.343 + switch (func)
10.344 + {
10.345 + // Support two different outputs.
10.346 +
10.347 + case Hw::Gpio_chip::Function_gpio:
10.348 + _regs[Port_int_clear] = _pin_bit(pin);
10.349 + _regs[Port_gpio_set] = _pin_bit(pin);
10.350 + _regs[value & 1 ? Port_data_set : Port_data_clear] = _pin_bit(pin);
10.351 + break;
10.352 +
10.353 + // Support four different device functions.
10.354 +
10.355 + case Hw::Gpio_chip::Function_alt:
10.356 + _regs[Port_int_clear] = _pin_bit(pin);
10.357 + _regs[Port_gpio_clear] = _pin_bit(pin);
10.358 + _regs[value & 2 ? Port_group1_set : Port_group1_clear] = _pin_bit(pin);
10.359 + _regs[value & 1 ? Port_group0_set : Port_group0_clear] = _pin_bit(pin);
10.360 + break;
10.361 + default:
10.362 + throw -L4_EINVAL;
10.363 + }
10.364 +}
10.365 +
10.366 +// Obtain a pin's configuration from a register in the supplied value.
10.367 +
10.368 +void
10.369 +Gpio_x1600_chip::config_get(unsigned pin, unsigned reg, unsigned *value)
10.370 +{
10.371 + if (pin >= _nr_pins)
10.372 + throw -L4_EINVAL;
10.373 +
10.374 + *value = (_regs[reg] >> _pin_shift(pin)) & 1;
10.375 +}
10.376 +
10.377 +// Return function and function-specific configuration for a pin.
10.378 +
10.379 +void
10.380 +Gpio_x1600_chip::config_pad_get(unsigned pin, unsigned *func, unsigned *value)
10.381 +{
10.382 + unsigned direction, gpio, group0, group1, interrupt, level, trigger;
10.383 +
10.384 + config_get(pin, Port_int, &interrupt);
10.385 +
10.386 + if (interrupt)
10.387 + {
10.388 + config_get(pin, Port_trigger, &trigger);
10.389 + config_get(pin, Port_level, &level);
10.390 +
10.391 + *func = Hw::Gpio_chip::Function_irq;
10.392 + *value = (trigger ? (level ? L4_IRQ_F_POS_EDGE : L4_IRQ_F_NEG_EDGE)
10.393 + : (level ? L4_IRQ_F_LEVEL_HIGH : L4_IRQ_F_LEVEL_LOW));
10.394 + return;
10.395 + }
10.396 +
10.397 + config_get(pin, Port_gpio, &gpio);
10.398 +
10.399 + if (gpio)
10.400 + {
10.401 + config_get(pin, Port_dir, &direction);
10.402 +
10.403 + *func = Hw::Gpio_chip::Function_gpio;
10.404 + *value = direction ? Input : Output;
10.405 + return;
10.406 + }
10.407 +
10.408 + *func = Hw::Gpio_chip::Function_alt;
10.409 +
10.410 + config_get(pin, Port_group0, &group0);
10.411 + config_get(pin, Port_group1, &group1);
10.412 +
10.413 + *value = (group1 << 1) | group0;
10.414 +}
10.415 +
10.416 +// Obtain an IRQ abstraction for a pin.
10.417 +
10.418 +Hw::Gpio_irq_pin *
10.419 +Gpio_x1600_chip::get_irq(unsigned pin)
10.420 +{
10.421 + if (pin >= _nr_pins)
10.422 + throw -L4_EINVAL;
10.423 +
10.424 + return new Gpio_x1600_irq_pin(pin, _regs);
10.425 +}
10.426 +
10.427 +// Pin function configuration for multiple pins.
10.428 +
10.429 +void
10.430 +Gpio_x1600_chip::multi_config_pad(Pin_slice const &mask, unsigned func, unsigned val)
10.431 +{
10.432 + unsigned m = mask.mask;
10.433 + for (unsigned pin = mask.offset; pin < _nr_pins; ++pin, m >>= 1)
10.434 + if (m & 1)
10.435 + config_pad(pin, func, val);
10.436 +}
10.437 +
10.438 +// Set up multiple pins with the given mode.
10.439 +
10.440 +void
10.441 +Gpio_x1600_chip::multi_setup(Pin_slice const &mask, unsigned mode, unsigned outvalues)
10.442 +{
10.443 + unsigned m = mask.mask;
10.444 + for (unsigned pin = mask.offset; pin < _nr_pins; ++pin, m >>= 1, outvalues >>= 1)
10.445 + if (m & 1)
10.446 + setup(pin, mode, outvalues & 1);
10.447 +}
10.448 +
10.449 +
10.450 +
10.451 +// C language interface functions.
10.452 +
10.453 +void *x1600_gpio_init(l4_addr_t start, l4_addr_t end, unsigned pins,
10.454 + l4_uint32_t pull_ups, l4_uint32_t pull_downs)
10.455 +{
10.456 + return (void *) new Gpio_x1600_chip(start, end, pins, pull_ups, pull_downs);
10.457 +}
10.458 +
10.459 +void x1600_gpio_setup(void *gpio, unsigned pin, unsigned mode, int value)
10.460 +{
10.461 + static_cast<Gpio_x1600_chip *>(gpio)->setup(pin, mode, value);
10.462 +}
10.463 +
10.464 +void x1600_gpio_config_pull(void *gpio, unsigned pin, unsigned mode)
10.465 +{
10.466 + static_cast<Gpio_x1600_chip *>(gpio)->config_pull(pin, mode);
10.467 +}
10.468 +
10.469 +void x1600_gpio_config_pad(void *gpio, unsigned pin, unsigned func, unsigned value)
10.470 +{
10.471 + static_cast<Gpio_x1600_chip *>(gpio)->config_pad(pin, func, value);
10.472 +}
10.473 +
10.474 +void x1600_gpio_config_get(void *gpio, unsigned pin, unsigned reg, unsigned *value)
10.475 +{
10.476 + static_cast<Gpio_x1600_chip *>(gpio)->config_get(pin, reg, value);
10.477 +}
10.478 +
10.479 +void x1600_gpio_config_pad_get(void *gpio, unsigned pin, unsigned *func, unsigned *value)
10.480 +{
10.481 + static_cast<Gpio_x1600_chip *>(gpio)->config_pad_get(pin, func, value);
10.482 +}
10.483 +
10.484 +void x1600_gpio_multi_setup(void *gpio, Pin_slice const *mask, unsigned mode, unsigned outvalues)
10.485 +{
10.486 + static_cast<Gpio_x1600_chip *>(gpio)->multi_setup(*mask, mode, outvalues);
10.487 +}
10.488 +
10.489 +void x1600_gpio_multi_config_pad(void *gpio, Pin_slice const *mask, unsigned func, unsigned value)
10.490 +{
10.491 + static_cast<Gpio_x1600_chip *>(gpio)->multi_config_pad(*mask, func, value);
10.492 +}
10.493 +
10.494 +void x1600_gpio_multi_set(void *gpio, Pin_slice const *mask, unsigned data)
10.495 +{
10.496 + static_cast<Gpio_x1600_chip *>(gpio)->multi_set(*mask, data);
10.497 +}
10.498 +
10.499 +unsigned x1600_gpio_multi_get(void *gpio, unsigned offset)
10.500 +{
10.501 + return static_cast<Gpio_x1600_chip *>(gpio)->multi_get(offset);
10.502 +}
10.503 +
10.504 +int x1600_gpio_get(void *gpio, unsigned pin)
10.505 +{
10.506 + return static_cast<Gpio_x1600_chip *>(gpio)->get(pin);
10.507 +}
10.508 +
10.509 +void x1600_gpio_set(void *gpio, unsigned pin, int value)
10.510 +{
10.511 + static_cast<Gpio_x1600_chip *>(gpio)->set(pin, value);
10.512 +}
10.513 +
10.514 +void *x1600_gpio_get_irq(void *gpio, unsigned pin)
10.515 +{
10.516 + return (void *) static_cast<Gpio_x1600_chip *>(gpio)->get_irq(pin);
10.517 +}
10.518 +
10.519 +bool x1600_gpio_irq_set_mode(void *gpio_irq, unsigned mode)
10.520 +{
10.521 + return static_cast<Hw::Gpio_irq_pin *>(gpio_irq)->do_set_mode(mode);
10.522 +}