1.1 --- a/pkg/devices/lib/gpio/include/gpio-x1600.h Fri Feb 23 22:53:30 2024 +0100
1.2 +++ b/pkg/devices/lib/gpio/include/gpio-x1600.h Mon Feb 26 16:18:13 2024 +0100
1.3 @@ -2,7 +2,7 @@
1.4 * GPIO driver for Ingenic X1600.
1.5 * (See below for additional copyright and licensing notices.)
1.6 *
1.7 - * Copyright (C) 2017, 2018, 2023 Paul Boddie <paul@boddie.org.uk>
1.8 + * Copyright (C) 2017, 2018, 2023, 2024 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 @@ -46,7 +46,12 @@
1.13 class Gpio_x1600_irq_pin : public Hw::Gpio_irq_pin
1.14 {
1.15 unsigned _pin;
1.16 - Hw::Register_block<32> _regs;
1.17 +
1.18 + // Register blocks for the conventional and optional shadow registers.
1.19 +
1.20 + Hw::Register_block<32> _regs, _shadow_regs;
1.21 + uint8_t _port_number;
1.22 + bool _shadow;
1.23
1.24 // Convenience method for obtaining the bit corresponding to a pin.
1.25
1.26 @@ -56,6 +61,10 @@
1.27 void write_reg_pin(unsigned reg);
1.28
1.29 public:
1.30 + Gpio_x1600_irq_pin(unsigned pin, Hw::Register_block<32> const ®s,
1.31 + Hw::Register_block<32> const &shadow_regs,
1.32 + uint8_t port_number);
1.33 +
1.34 Gpio_x1600_irq_pin(unsigned pin, Hw::Register_block<32> const ®s);
1.35
1.36 void do_mask();
1.37 @@ -68,12 +77,20 @@
1.38 class Gpio_x1600_chip : public Hw::Gpio_chip
1.39 {
1.40 private:
1.41 - Hw::Register_block<32> _regs;
1.42 + // Register blocks for the conventional and optional shadow registers.
1.43 +
1.44 + Hw::Register_block<32> _regs, _shadow_regs;
1.45
1.46 l4_addr_t _start, _end;
1.47 unsigned _nr_pins;
1.48 l4_uint32_t _pull_ups, _pull_downs;
1.49
1.50 + // Optional shadow port configuration.
1.51 +
1.52 + l4_addr_t _shadow_start, _shadow_end;
1.53 + uint8_t _port_number;
1.54 + bool _shadow;
1.55 +
1.56 // Convenience method for obtaining the bit corresponding to a pin.
1.57
1.58 l4_uint32_t _pin_bit(unsigned pin)
1.59 @@ -98,10 +115,14 @@
1.60 }
1.61 }
1.62
1.63 + void write_reg_pin(unsigned reg, unsigned pin);
1.64 +
1.65 public:
1.66 Gpio_x1600_chip(l4_addr_t start, l4_addr_t end,
1.67 - unsigned nr_pins,
1.68 - l4_uint32_t pull_ups, l4_uint32_t pull_downs);
1.69 + unsigned nr_pins,
1.70 + l4_uint32_t pull_ups, l4_uint32_t pull_downs,
1.71 + l4_addr_t shadow_start = 0, l4_addr_t shadow_end = 0,
1.72 + uint8_t port_number = 0);
1.73
1.74 // Obtain the number of pins.
1.75
1.76 @@ -149,7 +170,12 @@
1.77 EXTERN_C_BEGIN
1.78
1.79 void *x1600_gpio_init(l4_addr_t start, l4_addr_t end, unsigned pins,
1.80 - l4_uint32_t pull_ups, l4_uint32_t pull_downs);
1.81 + l4_uint32_t pull_ups, l4_uint32_t pull_downs);
1.82 +
1.83 +void *x1600_gpio_init_shadow(l4_addr_t start, l4_addr_t end, unsigned pins,
1.84 + l4_uint32_t pull_ups, l4_uint32_t pull_downs,
1.85 + l4_addr_t shadow_start, l4_addr_t shadow_end,
1.86 + uint8_t port_number);
1.87
1.88 void x1600_gpio_setup(void *gpio, unsigned pin, unsigned mode, int value);
1.89 void x1600_gpio_config_pull(void *gpio, unsigned pin, unsigned mode);
2.1 --- a/pkg/devices/lib/gpio/src/x1600.cc Fri Feb 23 22:53:30 2024 +0100
2.2 +++ b/pkg/devices/lib/gpio/src/x1600.cc Mon Feb 26 16:18:13 2024 +0100
2.3 @@ -106,8 +106,15 @@
2.4
2.5 // IRQ control for each GPIO pin.
2.6
2.7 +Gpio_x1600_irq_pin::Gpio_x1600_irq_pin(unsigned pin, Hw::Register_block<32> const ®s,
2.8 + Hw::Register_block<32> const &shadow_regs,
2.9 + uint8_t port_number)
2.10 +: _pin(pin), _regs(regs), _shadow_regs(shadow_regs), _port_number(port_number),
2.11 + _shadow(true)
2.12 +{}
2.13 +
2.14 Gpio_x1600_irq_pin::Gpio_x1600_irq_pin(unsigned pin, Hw::Register_block<32> const ®s)
2.15 -: _pin(pin), _regs(regs)
2.16 +: _pin(pin), _regs(regs), _shadow(false)
2.17 {}
2.18
2.19 void
2.20 @@ -116,7 +123,10 @@
2.21 // Write the pin bit to the register, setting or clearing the pin
2.22 // depending on the register chosen.
2.23
2.24 - _regs[reg] = _pin_bit(_pin);
2.25 + if (_shadow)
2.26 + _shadow_regs[reg] = _pin_bit(_pin);
2.27 + else
2.28 + _regs[reg] = _pin_bit(_pin);
2.29 }
2.30
2.31 void Gpio_x1600_irq_pin::do_mask()
2.32 @@ -142,11 +152,10 @@
2.33 // not atomic, that's why we first mask the IRQ and if it was
2.34 // enabled we unmask it after we have changed the mode
2.35
2.36 - /* NOTE: The X1600 provides a special port Z that allows changes to be made
2.37 - and then committed atomically using PzGID2LD. This is not currently
2.38 - used. */
2.39 + // The X1600 provides a special port Z that allows changes to be made and then
2.40 + // committed atomically using PzGID2LD.
2.41
2.42 - if (enabled())
2.43 + if (!_shadow && enabled())
2.44 do_mask();
2.45
2.46 // Do the PxINT, PxPAT1 and PxPAT0 configuration.
2.47 @@ -178,7 +187,9 @@
2.48 return false;
2.49 }
2.50
2.51 - if (enabled())
2.52 + if (_shadow)
2.53 + _shadow_regs[Shadow_transfer] = _port_number;
2.54 + else if (enabled())
2.55 do_unmask();
2.56
2.57 return true;
2.58 @@ -205,13 +216,37 @@
2.59 // Initialise the GPIO controller.
2.60
2.61 Gpio_x1600_chip::Gpio_x1600_chip(l4_addr_t start, l4_addr_t end,
2.62 - unsigned nr_pins,
2.63 - l4_uint32_t pull_ups, l4_uint32_t pull_downs)
2.64 + unsigned nr_pins,
2.65 + l4_uint32_t pull_ups, l4_uint32_t pull_downs,
2.66 + l4_addr_t shadow_start, l4_addr_t shadow_end,
2.67 + uint8_t port_number)
2.68 : _start(start), _end(end),
2.69 _nr_pins(nr_pins),
2.70 - _pull_ups(pull_ups), _pull_downs(pull_downs)
2.71 + _pull_ups(pull_ups), _pull_downs(pull_downs),
2.72 + _shadow_start(shadow_start), _shadow_end(shadow_end),
2.73 + _port_number(port_number)
2.74 {
2.75 _regs = new Hw::Mmio_register_block<32>(_start);
2.76 +
2.77 + if (_shadow_start)
2.78 + {
2.79 + _shadow_regs = new Hw::Mmio_register_block<32>(_shadow_start);
2.80 + _shadow = true;
2.81 + }
2.82 + else
2.83 + _shadow = false;
2.84 +}
2.85 +
2.86 +void
2.87 +Gpio_x1600_chip::write_reg_pin(unsigned reg, unsigned pin)
2.88 +{
2.89 + // Write the pin bit to the register, setting or clearing the pin
2.90 + // depending on the register chosen.
2.91 +
2.92 + if (_shadow)
2.93 + _shadow_regs[reg] = _pin_bit(pin);
2.94 + else
2.95 + _regs[reg] = _pin_bit(pin);
2.96 }
2.97
2.98 // Return the value of a pin.
2.99 @@ -281,22 +316,25 @@
2.100 switch (mode)
2.101 {
2.102 case Input:
2.103 - _regs[Port_int_clear] = _pin_bit(pin);
2.104 - _regs[Port_gpio_set] = _pin_bit(pin);
2.105 - _regs[Port_dir_set] = _pin_bit(pin);
2.106 + write_reg_pin(Port_int_clear, pin);
2.107 + write_reg_pin(Port_gpio_set, pin);
2.108 + write_reg_pin(Port_dir_set, pin);
2.109 break;
2.110 case Output:
2.111 - _regs[Port_int_clear] = _pin_bit(pin);
2.112 - _regs[Port_gpio_set] = _pin_bit(pin);
2.113 - _regs[Port_dir_clear] = _pin_bit(pin);
2.114 + write_reg_pin(Port_int_clear, pin);
2.115 + write_reg_pin(Port_gpio_set, pin);
2.116 + write_reg_pin(Port_dir_clear, pin);
2.117 break;
2.118 case Irq:
2.119 - _regs[Port_int_set] = _pin_bit(pin);
2.120 + write_reg_pin(Port_int_set, pin);
2.121 // Other details depend on the actual trigger mode.
2.122 break;
2.123 default:
2.124 break;
2.125 }
2.126 +
2.127 + if (_shadow)
2.128 + _shadow_regs[Shadow_transfer] = _port_number;
2.129 }
2.130
2.131 // Pull-up/down configuration for a pin.
2.132 @@ -342,22 +380,25 @@
2.133 // Support two different outputs.
2.134
2.135 case Hw::Gpio_chip::Function_gpio:
2.136 - _regs[Port_int_clear] = _pin_bit(pin);
2.137 - _regs[Port_gpio_set] = _pin_bit(pin);
2.138 - _regs[value & 1 ? Port_data_set : Port_data_clear] = _pin_bit(pin);
2.139 + write_reg_pin(Port_int_clear, pin);
2.140 + write_reg_pin(Port_gpio_set, pin);
2.141 + write_reg_pin(value & 1 ? Port_data_set : Port_data_clear, pin);
2.142 break;
2.143
2.144 // Support four different device functions.
2.145
2.146 case Hw::Gpio_chip::Function_alt:
2.147 - _regs[Port_int_clear] = _pin_bit(pin);
2.148 - _regs[Port_gpio_clear] = _pin_bit(pin);
2.149 - _regs[value & 2 ? Port_group1_set : Port_group1_clear] = _pin_bit(pin);
2.150 - _regs[value & 1 ? Port_group0_set : Port_group0_clear] = _pin_bit(pin);
2.151 + write_reg_pin(Port_int_clear, pin);
2.152 + write_reg_pin(Port_gpio_clear, pin);
2.153 + write_reg_pin(value & 2 ? Port_group1_set : Port_group1_clear, pin);
2.154 + write_reg_pin(value & 1 ? Port_group0_set : Port_group0_clear, pin);
2.155 break;
2.156 default:
2.157 throw -L4_EINVAL;
2.158 }
2.159 +
2.160 + if (_shadow)
2.161 + _shadow_regs[Shadow_transfer] = _port_number;
2.162 }
2.163
2.164 // Obtain a pin's configuration from a register in the supplied value.
2.165 @@ -418,7 +459,10 @@
2.166 if (pin >= _nr_pins)
2.167 throw -L4_EINVAL;
2.168
2.169 - return new Gpio_x1600_irq_pin(pin, _regs);
2.170 + if (_shadow)
2.171 + return new Gpio_x1600_irq_pin(pin, _regs, _shadow_regs, _port_number);
2.172 + else
2.173 + return new Gpio_x1600_irq_pin(pin, _regs);
2.174 }
2.175
2.176 // Pin function configuration for multiple pins.
2.177 @@ -448,11 +492,20 @@
2.178 // C language interface functions.
2.179
2.180 void *x1600_gpio_init(l4_addr_t start, l4_addr_t end, unsigned pins,
2.181 - l4_uint32_t pull_ups, l4_uint32_t pull_downs)
2.182 + l4_uint32_t pull_ups, l4_uint32_t pull_downs)
2.183 {
2.184 return (void *) new Gpio_x1600_chip(start, end, pins, pull_ups, pull_downs);
2.185 }
2.186
2.187 +void *x1600_gpio_init_shadow(l4_addr_t start, l4_addr_t end, unsigned pins,
2.188 + l4_uint32_t pull_ups, l4_uint32_t pull_downs,
2.189 + l4_addr_t shadow_start, l4_addr_t shadow_end,
2.190 + uint8_t port_number)
2.191 +{
2.192 + return (void *) new Gpio_x1600_chip(start, end, pins, pull_ups, pull_downs,
2.193 + shadow_start, shadow_end, port_number);
2.194 +}
2.195 +
2.196 void x1600_gpio_setup(void *gpio, unsigned pin, unsigned mode, int value)
2.197 {
2.198 static_cast<Gpio_x1600_chip *>(gpio)->setup(pin, mode, value);
3.1 --- a/pkg/landfall-examples/Control Fri Feb 23 22:53:30 2024 +0100
3.2 +++ b/pkg/landfall-examples/Control Mon Feb 26 16:18:13 2024 +0100
3.3 @@ -1,3 +1,3 @@
3.4 provides: landfall-examples
3.5 -requires: crtn l4re l4re_c mag-gfx devices
3.6 +requires: crtn l4re l4re_c mag-gfx devices libfsclient libfsserver
3.7 Maintainer: paul@boddie.org.uk
4.1 --- a/pkg/landfall-examples/hw_info/common.h Fri Feb 23 22:53:30 2024 +0100
4.2 +++ b/pkg/landfall-examples/hw_info/common.h Mon Feb 26 16:18:13 2024 +0100
4.3 @@ -102,7 +102,12 @@
4.4 /* GPIO adapter functions. */
4.5
4.6 void *gpio_init(l4_addr_t start, l4_addr_t end, unsigned pins,
4.7 - l4_uint32_t pull_ups, l4_uint32_t pull_downs);
4.8 + l4_uint32_t pull_ups, l4_uint32_t pull_downs);
4.9 +
4.10 +void *gpio_init_shadow(l4_addr_t start, l4_addr_t end, unsigned pins,
4.11 + l4_uint32_t pull_ups, l4_uint32_t pull_downs,
4.12 + l4_addr_t shadow_start, l4_addr_t shadow_end,
4.13 + uint8_t port_number);
4.14
4.15 void gpio_setup(void *gpio, unsigned pin, unsigned mode, int value);
4.16
5.1 --- a/pkg/landfall-examples/hw_info/hw_info.c Fri Feb 23 22:53:30 2024 +0100
5.2 +++ b/pkg/landfall-examples/hw_info/hw_info.c Mon Feb 26 16:18:13 2024 +0100
5.3 @@ -2006,8 +2006,11 @@
5.4 printf("GPIO at 0x%lx...0x%lx.\n", gpio_base, gpio_base_end);
5.5
5.6 for (port = 0; port < num_gpio_ports; port++)
5.7 - gpio[port] = gpio_init(gpio_base + port * 0x100, gpio_base + (port + 1) * 0x100,
5.8 - 32, gpio_ports[port].pull_ups, gpio_ports[port].pull_downs);
5.9 + gpio[port] = gpio_init_shadow(gpio_base + port * 0x100, gpio_base + (port + 1) * 0x100,
5.10 + 32,
5.11 + gpio_ports[port].pull_ups, gpio_ports[port].pull_downs,
5.12 + gpio_base + 0x700, gpio_base + 0x700,
5.13 + port);
5.14
5.15 printf("Access I2C...\n");
5.16
6.1 --- a/pkg/landfall-examples/hw_info/jz4780.c Fri Feb 23 22:53:30 2024 +0100
6.2 +++ b/pkg/landfall-examples/hw_info/jz4780.c Mon Feb 26 16:18:13 2024 +0100
6.3 @@ -193,6 +193,15 @@
6.4 return jz4780_gpio_init(start, end, pins, pull_ups, pull_downs);
6.5 }
6.6
6.7 +void *gpio_init_shadow(l4_addr_t start, l4_addr_t end, unsigned pins,
6.8 + l4_uint32_t pull_ups, l4_uint32_t pull_downs,
6.9 + l4_addr_t shadow_start, l4_addr_t shadow_end,
6.10 + uint8_t port_number)
6.11 +{
6.12 + (void) shadow_start; (void) shadow_end; (void) port_number;
6.13 + return jz4780_gpio_init(start, end, pins, pull_ups, pull_downs);
6.14 +}
6.15 +
6.16 void gpio_setup(void *gpio, unsigned pin, unsigned mode, int value)
6.17 {
6.18 jz4780_gpio_setup(gpio, pin, mode, value);
7.1 --- a/pkg/landfall-examples/hw_info/x1600.c Fri Feb 23 22:53:30 2024 +0100
7.2 +++ b/pkg/landfall-examples/hw_info/x1600.c Mon Feb 26 16:18:13 2024 +0100
7.3 @@ -182,6 +182,15 @@
7.4 return x1600_gpio_init(start, end, pins, pull_ups, pull_downs);
7.5 }
7.6
7.7 +void *gpio_init_shadow(l4_addr_t start, l4_addr_t end, unsigned pins,
7.8 + l4_uint32_t pull_ups, l4_uint32_t pull_downs,
7.9 + l4_addr_t shadow_start, l4_addr_t shadow_end,
7.10 + uint8_t port_number)
7.11 +{
7.12 + return x1600_gpio_init_shadow(start, end, pins, pull_ups, pull_downs,
7.13 + shadow_start, shadow_end, port_number);
7.14 +}
7.15 +
7.16 void gpio_setup(void *gpio, unsigned pin, unsigned mode, int value)
7.17 {
7.18 x1600_gpio_setup(gpio, pin, mode, value);