1 /* 2 * GPIO driver for Ingenic X1600. 3 * (See below for additional copyright and licensing notices.) 4 * 5 * Copyright (C) 2017, 2018, 2023, 2024 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 * Subject to other copyrights, being derived from the bcm2835.cc and 24 * omap.cc GPIO driver implementations. 25 * 26 * This file is part of TUD:OS and distributed under the terms of the 27 * GNU General Public License 2. 28 * Please see the COPYING-GPL-2 file for details. 29 */ 30 31 #pragma once 32 33 #include <l4/sys/err.h> 34 #include <l4/sys/types.h> 35 #include <stdint.h> 36 #include "gpio.h" 37 38 39 40 #ifdef __cplusplus 41 42 #include <l4/devices/hw_mmio_register_block.h> 43 44 // GPIO device control. 45 46 class Gpio_x1600_irq_pin : public Hw::Gpio_irq_pin 47 { 48 unsigned _pin; 49 50 // Register blocks for the conventional and optional shadow registers. 51 52 Hw::Register_block<32> _regs, _shadow_regs; 53 uint8_t _port_number; 54 bool _shadow; 55 56 // Convenience method for obtaining the bit corresponding to a pin. 57 58 l4_uint32_t _pin_bit(unsigned pin) 59 { return 1 << (pin & 31); } 60 61 void write_reg_pin(unsigned reg); 62 63 public: 64 Gpio_x1600_irq_pin(unsigned pin, Hw::Register_block<32> const ®s, 65 Hw::Register_block<32> const &shadow_regs, 66 uint8_t port_number); 67 68 Gpio_x1600_irq_pin(unsigned pin, Hw::Register_block<32> const ®s); 69 70 void do_mask(); 71 void do_unmask(); 72 bool do_set_mode(unsigned mode); 73 int clear(); 74 bool enabled(); 75 }; 76 77 class Gpio_x1600_chip : public Hw::Gpio_chip 78 { 79 private: 80 // Register blocks for the conventional and optional shadow registers. 81 82 Hw::Register_block<32> _regs, _shadow_regs; 83 84 l4_addr_t _start, _end; 85 unsigned _nr_pins; 86 l4_uint32_t _pull_ups, _pull_downs; 87 88 // Optional shadow port configuration. 89 90 l4_addr_t _shadow_start, _shadow_end; 91 uint8_t _port_number; 92 bool _shadow; 93 94 // Convenience method for obtaining the bit corresponding to a pin. 95 96 l4_uint32_t _pin_bit(unsigned pin) 97 { return 1 << (pin & 31); } 98 99 // Convenience method for obtaining the bit position of a pin. 100 101 unsigned _pin_shift(unsigned pin) 102 { return pin % 32; } 103 104 // Permit only "aligned" accesses to registers. 105 106 unsigned _reg_offset_check(unsigned pin_offset) const 107 { 108 switch (pin_offset) 109 { 110 case 0: 111 return 0; 112 113 default: 114 throw -L4_EINVAL; 115 } 116 } 117 118 void write_reg_pin(unsigned reg, unsigned pin); 119 120 public: 121 Gpio_x1600_chip(l4_addr_t start, l4_addr_t end, 122 unsigned nr_pins, 123 l4_uint32_t pull_ups, l4_uint32_t pull_downs, 124 l4_addr_t shadow_start = 0, l4_addr_t shadow_end = 0, 125 uint8_t port_number = 0); 126 127 // Obtain the number of pins. 128 129 unsigned nr_pins() const { return _nr_pins; } 130 131 // Unnecessary operations. 132 133 void request(unsigned) {} 134 void free(unsigned) {} 135 136 // Configuration methods. 137 138 void setup(unsigned pin, unsigned mode, int value = 0); 139 void config_pull(unsigned pin, unsigned mode); 140 void config_pad(unsigned pin, unsigned func, unsigned value); 141 void config_get(unsigned pin, unsigned reg, unsigned *value); 142 void config_pad_get(unsigned pin, unsigned *func, unsigned *value); 143 144 // Multiple pin configuration methods. 145 146 void multi_setup(Pin_slice const &mask, unsigned mode, unsigned outvalues = 0); 147 void multi_config_pad(Pin_slice const &mask, unsigned func, unsigned value = 0); 148 void multi_set(Pin_slice const &mask, unsigned data); 149 unsigned multi_get(unsigned offset); 150 151 // IRQ pin configuration. 152 153 Hw::Gpio_irq_pin *get_irq(unsigned pin); 154 155 // Pin/port data methods. 156 157 int get(unsigned pin); 158 void set(unsigned pin, int value); 159 160 private: 161 void config(unsigned pin, unsigned mode); 162 }; 163 164 #endif /* __cplusplus */ 165 166 167 168 /* C language interface. */ 169 170 EXTERN_C_BEGIN 171 172 void *x1600_gpio_init(l4_addr_t start, l4_addr_t end, unsigned pins, 173 l4_uint32_t pull_ups, l4_uint32_t pull_downs); 174 175 void *x1600_gpio_init_shadow(l4_addr_t start, l4_addr_t end, unsigned pins, 176 l4_uint32_t pull_ups, l4_uint32_t pull_downs, 177 l4_addr_t shadow_start, l4_addr_t shadow_end, 178 uint8_t port_number); 179 180 void x1600_gpio_setup(void *gpio, unsigned pin, unsigned mode, int value); 181 void x1600_gpio_config_pull(void *gpio, unsigned pin, unsigned mode); 182 void x1600_gpio_config_pad(void *gpio, unsigned pin, unsigned func, unsigned value); 183 void x1600_gpio_config_get(void *gpio, unsigned pin, unsigned reg, unsigned *value); 184 void x1600_gpio_config_pad_get(void *gpio, unsigned pin, unsigned *func, unsigned *value); 185 186 void x1600_gpio_multi_setup(void *gpio, Pin_slice const *mask, unsigned mode, unsigned outvalues); 187 void x1600_gpio_multi_config_pad(void *gpio, Pin_slice const *mask, unsigned func, unsigned value); 188 void x1600_gpio_multi_set(void *gpio, Pin_slice const *mask, unsigned data); 189 unsigned x1600_gpio_multi_get(void *gpio, unsigned offset); 190 191 int x1600_gpio_get(void *gpio, unsigned pin); 192 void x1600_gpio_set(void *gpio, unsigned pin, int value); 193 194 void *x1600_gpio_get_irq(void *gpio, unsigned pin); 195 bool x1600_gpio_irq_set_mode(void *gpio_irq, unsigned mode); 196 197 EXTERN_C_END