1 /* 2 * GPIO driver for Ingenic JZ4730. 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_jz4730_irq_pin : public Hw::Gpio_irq_pin 47 { 48 unsigned _pin; 49 Hw::Register_block<32> _regs; 50 51 // Convenience method for obtaining the bit corresponding to a pin. 52 53 l4_uint32_t _pin_bit(unsigned pin) 54 { return 1 << (pin & 31); } 55 56 void write_reg_pin(unsigned reg); 57 58 // Convenience methods for clearing and setting bits in the absence of 59 // dedicated registers. 60 61 void clear_reg_pin(unsigned reg); 62 void set_reg_pin(unsigned reg); 63 void clear_reg_pins(uint32_t reg_upper, uint32_t reg_lower); 64 void set_reg_pins(uint32_t reg_upper, uint32_t reg_lower, uint8_t value); 65 66 public: 67 Gpio_jz4730_irq_pin(unsigned pin, Hw::Register_block<32> const ®s); 68 69 void do_mask(); 70 void do_unmask(); 71 bool do_set_mode(unsigned mode); 72 int clear(); 73 bool enabled(); 74 }; 75 76 class Gpio_jz4730_chip : public Hw::Gpio_chip 77 { 78 private: 79 Hw::Register_block<32> _regs; 80 81 l4_addr_t _start; 82 unsigned _nr_pins; 83 struct gpio_port *_pull_config; 84 85 // Convenience method for obtaining the bit corresponding to a pin. 86 87 l4_uint32_t _pin_bit(unsigned pin) 88 { return 1 << (pin & 31); } 89 90 // Convenience method for obtaining the bit position of a pin. 91 92 unsigned _pin_shift(unsigned pin) 93 { return pin % 32; } 94 95 // Permit only "aligned" accesses to registers. 96 97 unsigned _reg_offset_check(unsigned pin_offset) const 98 { 99 switch (pin_offset) 100 { 101 case 0: 102 return 0; 103 104 default: 105 throw -L4_EINVAL; 106 } 107 } 108 109 // General configuration register updates. 110 111 void _config(unsigned bitmap, unsigned mode); 112 113 // General pull-up register updates. 114 115 void _config_pull(unsigned bitmap, unsigned mode); 116 117 // General pad register updates. 118 119 void _config_pad(unsigned bitmap, unsigned func, unsigned value); 120 121 // Paired register field access. 122 123 void _get_pin_value(unsigned pin, uint32_t reg_upper, uint32_t reg_lower, 124 unsigned *value); 125 126 public: 127 Gpio_jz4730_chip(l4_addr_t start, uint8_t port_number); 128 129 // Obtain the number of pins. 130 131 unsigned nr_pins() const { return _nr_pins; } 132 133 // Unnecessary operations. 134 135 void request(unsigned) {} 136 void free(unsigned) {} 137 138 // Configuration methods. 139 140 void setup(unsigned pin, unsigned mode, int value = 0); 141 void config_pull(unsigned pin, unsigned mode); 142 void config_pad(unsigned pin, unsigned func, unsigned value); 143 void config_get(unsigned pin, unsigned reg, unsigned *value); 144 void config_pad_get(unsigned pin, unsigned *func, unsigned *value); 145 146 // Multiple pin configuration methods. 147 148 void multi_setup(Pin_slice const &mask, unsigned mode, unsigned outvalues = 0); 149 void multi_config_pull(Pin_slice const &mask, unsigned mode); 150 void multi_config_pad(Pin_slice const &mask, unsigned func, unsigned value = 0); 151 void multi_set(Pin_slice const &mask, unsigned data); 152 unsigned multi_get(unsigned offset); 153 154 // IRQ pin configuration. 155 156 Hw::Gpio_irq_pin *get_irq(unsigned pin); 157 158 // Pin/port data methods. 159 160 int get(unsigned pin); 161 void set(unsigned pin, int value); 162 163 private: 164 void config(unsigned pin, unsigned mode); 165 }; 166 167 #endif /* __cplusplus */ 168 169 170 171 /* C language interface. */ 172 173 EXTERN_C_BEGIN 174 175 void *jz4730_gpio_init(l4_addr_t start, uint8_t port_number); 176 177 void jz4730_gpio_setup(void *gpio, unsigned pin, unsigned mode, int value); 178 void jz4730_gpio_config_pull(void *gpio, unsigned pin, unsigned mode); 179 void jz4730_gpio_config_pad(void *gpio, unsigned pin, unsigned func, unsigned value); 180 void jz4730_gpio_config_get(void *gpio, unsigned pin, unsigned reg, unsigned *value); 181 void jz4730_gpio_config_pad_get(void *gpio, unsigned pin, unsigned *func, unsigned *value); 182 183 void jz4730_gpio_multi_setup(void *gpio, Pin_slice const *mask, unsigned mode, unsigned outvalues); 184 void jz4730_gpio_multi_config_pull(void *gpio, Pin_slice const *mask, unsigned mode); 185 void jz4730_gpio_multi_config_pad(void *gpio, Pin_slice const *mask, unsigned func, unsigned value); 186 void jz4730_gpio_multi_set(void *gpio, Pin_slice const *mask, unsigned data); 187 unsigned jz4730_gpio_multi_get(void *gpio, unsigned offset); 188 189 int jz4730_gpio_get(void *gpio, unsigned pin); 190 void jz4730_gpio_set(void *gpio, unsigned pin, int value); 191 192 void *jz4730_gpio_get_irq(void *gpio, unsigned pin); 193 bool jz4730_gpio_irq_set_mode(void *gpio_irq, unsigned mode); 194 195 EXTERN_C_END