1.1 --- a/pkg/devices/lib/gpio/src/x1600.cc Fri Feb 23 22:53:30 2024 +0100
1.2 +++ b/pkg/devices/lib/gpio/src/x1600.cc Mon Feb 26 16:18:13 2024 +0100
1.3 @@ -106,8 +106,15 @@
1.4
1.5 // IRQ control for each GPIO pin.
1.6
1.7 +Gpio_x1600_irq_pin::Gpio_x1600_irq_pin(unsigned pin, Hw::Register_block<32> const ®s,
1.8 + Hw::Register_block<32> const &shadow_regs,
1.9 + uint8_t port_number)
1.10 +: _pin(pin), _regs(regs), _shadow_regs(shadow_regs), _port_number(port_number),
1.11 + _shadow(true)
1.12 +{}
1.13 +
1.14 Gpio_x1600_irq_pin::Gpio_x1600_irq_pin(unsigned pin, Hw::Register_block<32> const ®s)
1.15 -: _pin(pin), _regs(regs)
1.16 +: _pin(pin), _regs(regs), _shadow(false)
1.17 {}
1.18
1.19 void
1.20 @@ -116,7 +123,10 @@
1.21 // Write the pin bit to the register, setting or clearing the pin
1.22 // depending on the register chosen.
1.23
1.24 - _regs[reg] = _pin_bit(_pin);
1.25 + if (_shadow)
1.26 + _shadow_regs[reg] = _pin_bit(_pin);
1.27 + else
1.28 + _regs[reg] = _pin_bit(_pin);
1.29 }
1.30
1.31 void Gpio_x1600_irq_pin::do_mask()
1.32 @@ -142,11 +152,10 @@
1.33 // not atomic, that's why we first mask the IRQ and if it was
1.34 // enabled we unmask it after we have changed the mode
1.35
1.36 - /* NOTE: The X1600 provides a special port Z that allows changes to be made
1.37 - and then committed atomically using PzGID2LD. This is not currently
1.38 - used. */
1.39 + // The X1600 provides a special port Z that allows changes to be made and then
1.40 + // committed atomically using PzGID2LD.
1.41
1.42 - if (enabled())
1.43 + if (!_shadow && enabled())
1.44 do_mask();
1.45
1.46 // Do the PxINT, PxPAT1 and PxPAT0 configuration.
1.47 @@ -178,7 +187,9 @@
1.48 return false;
1.49 }
1.50
1.51 - if (enabled())
1.52 + if (_shadow)
1.53 + _shadow_regs[Shadow_transfer] = _port_number;
1.54 + else if (enabled())
1.55 do_unmask();
1.56
1.57 return true;
1.58 @@ -205,13 +216,37 @@
1.59 // Initialise the GPIO controller.
1.60
1.61 Gpio_x1600_chip::Gpio_x1600_chip(l4_addr_t start, l4_addr_t end,
1.62 - unsigned nr_pins,
1.63 - l4_uint32_t pull_ups, l4_uint32_t pull_downs)
1.64 + unsigned nr_pins,
1.65 + l4_uint32_t pull_ups, l4_uint32_t pull_downs,
1.66 + l4_addr_t shadow_start, l4_addr_t shadow_end,
1.67 + uint8_t port_number)
1.68 : _start(start), _end(end),
1.69 _nr_pins(nr_pins),
1.70 - _pull_ups(pull_ups), _pull_downs(pull_downs)
1.71 + _pull_ups(pull_ups), _pull_downs(pull_downs),
1.72 + _shadow_start(shadow_start), _shadow_end(shadow_end),
1.73 + _port_number(port_number)
1.74 {
1.75 _regs = new Hw::Mmio_register_block<32>(_start);
1.76 +
1.77 + if (_shadow_start)
1.78 + {
1.79 + _shadow_regs = new Hw::Mmio_register_block<32>(_shadow_start);
1.80 + _shadow = true;
1.81 + }
1.82 + else
1.83 + _shadow = false;
1.84 +}
1.85 +
1.86 +void
1.87 +Gpio_x1600_chip::write_reg_pin(unsigned reg, unsigned pin)
1.88 +{
1.89 + // Write the pin bit to the register, setting or clearing the pin
1.90 + // depending on the register chosen.
1.91 +
1.92 + if (_shadow)
1.93 + _shadow_regs[reg] = _pin_bit(pin);
1.94 + else
1.95 + _regs[reg] = _pin_bit(pin);
1.96 }
1.97
1.98 // Return the value of a pin.
1.99 @@ -281,22 +316,25 @@
1.100 switch (mode)
1.101 {
1.102 case Input:
1.103 - _regs[Port_int_clear] = _pin_bit(pin);
1.104 - _regs[Port_gpio_set] = _pin_bit(pin);
1.105 - _regs[Port_dir_set] = _pin_bit(pin);
1.106 + write_reg_pin(Port_int_clear, pin);
1.107 + write_reg_pin(Port_gpio_set, pin);
1.108 + write_reg_pin(Port_dir_set, pin);
1.109 break;
1.110 case Output:
1.111 - _regs[Port_int_clear] = _pin_bit(pin);
1.112 - _regs[Port_gpio_set] = _pin_bit(pin);
1.113 - _regs[Port_dir_clear] = _pin_bit(pin);
1.114 + write_reg_pin(Port_int_clear, pin);
1.115 + write_reg_pin(Port_gpio_set, pin);
1.116 + write_reg_pin(Port_dir_clear, pin);
1.117 break;
1.118 case Irq:
1.119 - _regs[Port_int_set] = _pin_bit(pin);
1.120 + write_reg_pin(Port_int_set, pin);
1.121 // Other details depend on the actual trigger mode.
1.122 break;
1.123 default:
1.124 break;
1.125 }
1.126 +
1.127 + if (_shadow)
1.128 + _shadow_regs[Shadow_transfer] = _port_number;
1.129 }
1.130
1.131 // Pull-up/down configuration for a pin.
1.132 @@ -342,22 +380,25 @@
1.133 // Support two different outputs.
1.134
1.135 case Hw::Gpio_chip::Function_gpio:
1.136 - _regs[Port_int_clear] = _pin_bit(pin);
1.137 - _regs[Port_gpio_set] = _pin_bit(pin);
1.138 - _regs[value & 1 ? Port_data_set : Port_data_clear] = _pin_bit(pin);
1.139 + write_reg_pin(Port_int_clear, pin);
1.140 + write_reg_pin(Port_gpio_set, pin);
1.141 + write_reg_pin(value & 1 ? Port_data_set : Port_data_clear, pin);
1.142 break;
1.143
1.144 // Support four different device functions.
1.145
1.146 case Hw::Gpio_chip::Function_alt:
1.147 - _regs[Port_int_clear] = _pin_bit(pin);
1.148 - _regs[Port_gpio_clear] = _pin_bit(pin);
1.149 - _regs[value & 2 ? Port_group1_set : Port_group1_clear] = _pin_bit(pin);
1.150 - _regs[value & 1 ? Port_group0_set : Port_group0_clear] = _pin_bit(pin);
1.151 + write_reg_pin(Port_int_clear, pin);
1.152 + write_reg_pin(Port_gpio_clear, pin);
1.153 + write_reg_pin(value & 2 ? Port_group1_set : Port_group1_clear, pin);
1.154 + write_reg_pin(value & 1 ? Port_group0_set : Port_group0_clear, pin);
1.155 break;
1.156 default:
1.157 throw -L4_EINVAL;
1.158 }
1.159 +
1.160 + if (_shadow)
1.161 + _shadow_regs[Shadow_transfer] = _port_number;
1.162 }
1.163
1.164 // Obtain a pin's configuration from a register in the supplied value.
1.165 @@ -418,7 +459,10 @@
1.166 if (pin >= _nr_pins)
1.167 throw -L4_EINVAL;
1.168
1.169 - return new Gpio_x1600_irq_pin(pin, _regs);
1.170 + if (_shadow)
1.171 + return new Gpio_x1600_irq_pin(pin, _regs, _shadow_regs, _port_number);
1.172 + else
1.173 + return new Gpio_x1600_irq_pin(pin, _regs);
1.174 }
1.175
1.176 // Pin function configuration for multiple pins.
1.177 @@ -448,11 +492,20 @@
1.178 // C language interface functions.
1.179
1.180 void *x1600_gpio_init(l4_addr_t start, l4_addr_t end, unsigned pins,
1.181 - l4_uint32_t pull_ups, l4_uint32_t pull_downs)
1.182 + l4_uint32_t pull_ups, l4_uint32_t pull_downs)
1.183 {
1.184 return (void *) new Gpio_x1600_chip(start, end, pins, pull_ups, pull_downs);
1.185 }
1.186
1.187 +void *x1600_gpio_init_shadow(l4_addr_t start, l4_addr_t end, unsigned pins,
1.188 + l4_uint32_t pull_ups, l4_uint32_t pull_downs,
1.189 + l4_addr_t shadow_start, l4_addr_t shadow_end,
1.190 + uint8_t port_number)
1.191 +{
1.192 + return (void *) new Gpio_x1600_chip(start, end, pins, pull_ups, pull_downs,
1.193 + shadow_start, shadow_end, port_number);
1.194 +}
1.195 +
1.196 void x1600_gpio_setup(void *gpio, unsigned pin, unsigned mode, int value)
1.197 {
1.198 static_cast<Gpio_x1600_chip *>(gpio)->setup(pin, mode, value);