1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * GPIO driver for the ACCES 104-DIO-48E series 4 * Copyright (C) 2016 William Breathitt Gray 5 * 6 * This driver supports the following ACCES devices: 104-DIO-48E and 7 * 104-DIO-24E. 8 */ 9 #include <linux/bits.h> 10 #include <linux/device.h> 11 #include <linux/err.h> 12 #include <linux/i8254.h> 13 #include <linux/ioport.h> 14 #include <linux/irq.h> 15 #include <linux/isa.h> 16 #include <linux/kernel.h> 17 #include <linux/module.h> 18 #include <linux/moduleparam.h> 19 #include <linux/regmap.h> 20 #include <linux/spinlock.h> 21 #include <linux/types.h> 22 23 #include "gpio-i8255.h" 24 25 MODULE_IMPORT_NS(I8255); 26 27 #define DIO48E_EXTENT 16 28 #define MAX_NUM_DIO48E max_num_isa_dev(DIO48E_EXTENT) 29 30 static unsigned int base[MAX_NUM_DIO48E]; 31 static unsigned int num_dio48e; 32 module_param_hw_array(base, uint, ioport, &num_dio48e, 0); 33 MODULE_PARM_DESC(base, "ACCES 104-DIO-48E base addresses"); 34 35 static unsigned int irq[MAX_NUM_DIO48E]; 36 static unsigned int num_irq; 37 module_param_hw_array(irq, uint, irq, &num_irq, 0); 38 MODULE_PARM_DESC(irq, "ACCES 104-DIO-48E interrupt line numbers"); 39 40 #define DIO48E_ENABLE_INTERRUPT 0xB 41 #define DIO48E_DISABLE_INTERRUPT DIO48E_ENABLE_INTERRUPT 42 #define DIO48E_ENABLE_COUNTER_TIMER_ADDRESSING 0xD 43 #define DIO48E_DISABLE_COUNTER_TIMER_ADDRESSING DIO48E_ENABLE_COUNTER_TIMER_ADDRESSING 44 #define DIO48E_CLEAR_INTERRUPT 0xF 45 46 #define DIO48E_NUM_PPI 2 47 48 static const struct regmap_range dio48e_wr_ranges[] = { 49 regmap_reg_range(0x0, 0x9), regmap_reg_range(0xB, 0xB), 50 regmap_reg_range(0xD, 0xD), regmap_reg_range(0xF, 0xF), 51 }; 52 static const struct regmap_range dio48e_rd_ranges[] = { 53 regmap_reg_range(0x0, 0x2), regmap_reg_range(0x4, 0x6), 54 regmap_reg_range(0xB, 0xB), regmap_reg_range(0xD, 0xD), 55 regmap_reg_range(0xF, 0xF), 56 }; 57 static const struct regmap_range dio48e_volatile_ranges[] = { 58 i8255_volatile_regmap_range(0x0), i8255_volatile_regmap_range(0x4), 59 regmap_reg_range(0xB, 0xB), regmap_reg_range(0xD, 0xD), 60 regmap_reg_range(0xF, 0xF), 61 }; 62 static const struct regmap_range dio48e_precious_ranges[] = { 63 regmap_reg_range(0xB, 0xB), regmap_reg_range(0xD, 0xD), 64 regmap_reg_range(0xF, 0xF), 65 }; 66 static const struct regmap_access_table dio48e_wr_table = { 67 .yes_ranges = dio48e_wr_ranges, 68 .n_yes_ranges = ARRAY_SIZE(dio48e_wr_ranges), 69 }; 70 static const struct regmap_access_table dio48e_rd_table = { 71 .yes_ranges = dio48e_rd_ranges, 72 .n_yes_ranges = ARRAY_SIZE(dio48e_rd_ranges), 73 }; 74 static const struct regmap_access_table dio48e_volatile_table = { 75 .yes_ranges = dio48e_volatile_ranges, 76 .n_yes_ranges = ARRAY_SIZE(dio48e_volatile_ranges), 77 }; 78 static const struct regmap_access_table dio48e_precious_table = { 79 .yes_ranges = dio48e_precious_ranges, 80 .n_yes_ranges = ARRAY_SIZE(dio48e_precious_ranges), 81 }; 82 83 static const struct regmap_range pit_wr_ranges[] = { 84 regmap_reg_range(0x0, 0x3), 85 }; 86 static const struct regmap_range pit_rd_ranges[] = { 87 regmap_reg_range(0x0, 0x2), 88 }; 89 static const struct regmap_access_table pit_wr_table = { 90 .yes_ranges = pit_wr_ranges, 91 .n_yes_ranges = ARRAY_SIZE(pit_wr_ranges), 92 }; 93 static const struct regmap_access_table pit_rd_table = { 94 .yes_ranges = pit_rd_ranges, 95 .n_yes_ranges = ARRAY_SIZE(pit_rd_ranges), 96 }; 97 98 /* only bit 3 on each respective Port C supports interrupts */ 99 #define DIO48E_REGMAP_IRQ(_ppi) \ 100 [19 + (_ppi) * 24] = { \ 101 .mask = BIT(_ppi), \ 102 .type = { .types_supported = IRQ_TYPE_EDGE_RISING }, \ 103 } 104 105 static const struct regmap_irq dio48e_regmap_irqs[] = { 106 DIO48E_REGMAP_IRQ(0), DIO48E_REGMAP_IRQ(1), 107 }; 108 109 /** 110 * struct dio48e_gpio - GPIO device private data structure 111 * @lock: synchronization lock to prevent I/O race conditions 112 * @map: Regmap for the device 113 * @regs: virtual mapping for device registers 114 * @flags: IRQ flags saved during locking 115 * @irq_mask: Current IRQ mask state on the device 116 */ 117 struct dio48e_gpio { 118 raw_spinlock_t lock; 119 struct regmap *map; 120 void __iomem *regs; 121 unsigned long flags; 122 unsigned int irq_mask; 123 }; 124 125 static void dio48e_regmap_lock(void *lock_arg) __acquires(&dio48egpio->lock) 126 { 127 struct dio48e_gpio *const dio48egpio = lock_arg; 128 unsigned long flags; 129 130 raw_spin_lock_irqsave(&dio48egpio->lock, flags); 131 dio48egpio->flags = flags; 132 } 133 134 static void dio48e_regmap_unlock(void *lock_arg) __releases(&dio48egpio->lock) 135 { 136 struct dio48e_gpio *const dio48egpio = lock_arg; 137 138 raw_spin_unlock_irqrestore(&dio48egpio->lock, dio48egpio->flags); 139 } 140 141 static void pit_regmap_lock(void *lock_arg) __acquires(&dio48egpio->lock) 142 { 143 struct dio48e_gpio *const dio48egpio = lock_arg; 144 unsigned long flags; 145 146 raw_spin_lock_irqsave(&dio48egpio->lock, flags); 147 dio48egpio->flags = flags; 148 149 iowrite8(0x00, dio48egpio->regs + DIO48E_ENABLE_COUNTER_TIMER_ADDRESSING); 150 } 151 152 static void pit_regmap_unlock(void *lock_arg) __releases(&dio48egpio->lock) 153 { 154 struct dio48e_gpio *const dio48egpio = lock_arg; 155 156 ioread8(dio48egpio->regs + DIO48E_DISABLE_COUNTER_TIMER_ADDRESSING); 157 158 raw_spin_unlock_irqrestore(&dio48egpio->lock, dio48egpio->flags); 159 } 160 161 static int dio48e_handle_mask_sync(const int index, 162 const unsigned int mask_buf_def, 163 const unsigned int mask_buf, 164 void *const irq_drv_data) 165 { 166 struct dio48e_gpio *const dio48egpio = irq_drv_data; 167 const unsigned int prev_mask = dio48egpio->irq_mask; 168 int err; 169 unsigned int val; 170 171 /* exit early if no change since the previous mask */ 172 if (mask_buf == prev_mask) 173 return 0; 174 175 /* remember the current mask for the next mask sync */ 176 dio48egpio->irq_mask = mask_buf; 177 178 /* if all previously masked, enable interrupts when unmasking */ 179 if (prev_mask == mask_buf_def) { 180 err = regmap_write(dio48egpio->map, DIO48E_CLEAR_INTERRUPT, 0x00); 181 if (err) 182 return err; 183 return regmap_write(dio48egpio->map, DIO48E_ENABLE_INTERRUPT, 0x00); 184 } 185 186 /* if all are currently masked, disable interrupts */ 187 if (mask_buf == mask_buf_def) 188 return regmap_read(dio48egpio->map, DIO48E_DISABLE_INTERRUPT, &val); 189 190 return 0; 191 } 192 193 #define DIO48E_NGPIO 48 194 static const char *dio48e_names[DIO48E_NGPIO] = { 195 "PPI Group 0 Port A 0", "PPI Group 0 Port A 1", "PPI Group 0 Port A 2", 196 "PPI Group 0 Port A 3", "PPI Group 0 Port A 4", "PPI Group 0 Port A 5", 197 "PPI Group 0 Port A 6", "PPI Group 0 Port A 7", "PPI Group 0 Port B 0", 198 "PPI Group 0 Port B 1", "PPI Group 0 Port B 2", "PPI Group 0 Port B 3", 199 "PPI Group 0 Port B 4", "PPI Group 0 Port B 5", "PPI Group 0 Port B 6", 200 "PPI Group 0 Port B 7", "PPI Group 0 Port C 0", "PPI Group 0 Port C 1", 201 "PPI Group 0 Port C 2", "PPI Group 0 Port C 3", "PPI Group 0 Port C 4", 202 "PPI Group 0 Port C 5", "PPI Group 0 Port C 6", "PPI Group 0 Port C 7", 203 "PPI Group 1 Port A 0", "PPI Group 1 Port A 1", "PPI Group 1 Port A 2", 204 "PPI Group 1 Port A 3", "PPI Group 1 Port A 4", "PPI Group 1 Port A 5", 205 "PPI Group 1 Port A 6", "PPI Group 1 Port A 7", "PPI Group 1 Port B 0", 206 "PPI Group 1 Port B 1", "PPI Group 1 Port B 2", "PPI Group 1 Port B 3", 207 "PPI Group 1 Port B 4", "PPI Group 1 Port B 5", "PPI Group 1 Port B 6", 208 "PPI Group 1 Port B 7", "PPI Group 1 Port C 0", "PPI Group 1 Port C 1", 209 "PPI Group 1 Port C 2", "PPI Group 1 Port C 3", "PPI Group 1 Port C 4", 210 "PPI Group 1 Port C 5", "PPI Group 1 Port C 6", "PPI Group 1 Port C 7" 211 }; 212 213 static int dio48e_irq_init_hw(struct regmap *const map) 214 { 215 unsigned int val; 216 217 /* Disable IRQ by default */ 218 return regmap_read(map, DIO48E_DISABLE_INTERRUPT, &val); 219 } 220 221 static int dio48e_probe(struct device *dev, unsigned int id) 222 { 223 const char *const name = dev_name(dev); 224 struct i8255_regmap_config config = {}; 225 void __iomem *regs; 226 struct regmap *map; 227 struct regmap_config dio48e_regmap_config; 228 struct regmap_config pit_regmap_config; 229 struct i8254_regmap_config pit_config; 230 int err; 231 struct regmap_irq_chip *chip; 232 struct dio48e_gpio *dio48egpio; 233 struct regmap_irq_chip_data *chip_data; 234 235 if (!devm_request_region(dev, base[id], DIO48E_EXTENT, name)) { 236 dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n", 237 base[id], base[id] + DIO48E_EXTENT); 238 return -EBUSY; 239 } 240 241 dio48egpio = devm_kzalloc(dev, sizeof(*dio48egpio), GFP_KERNEL); 242 if (!dio48egpio) 243 return -ENOMEM; 244 245 regs = devm_ioport_map(dev, base[id], DIO48E_EXTENT); 246 if (!regs) 247 return -ENOMEM; 248 249 dio48egpio->regs = regs; 250 251 raw_spin_lock_init(&dio48egpio->lock); 252 253 dio48e_regmap_config = (struct regmap_config) { 254 .reg_bits = 8, 255 .reg_stride = 1, 256 .val_bits = 8, 257 .lock = dio48e_regmap_lock, 258 .unlock = dio48e_regmap_unlock, 259 .lock_arg = dio48egpio, 260 .io_port = true, 261 .wr_table = &dio48e_wr_table, 262 .rd_table = &dio48e_rd_table, 263 .volatile_table = &dio48e_volatile_table, 264 .precious_table = &dio48e_precious_table, 265 .cache_type = REGCACHE_FLAT, 266 }; 267 268 map = devm_regmap_init_mmio(dev, regs, &dio48e_regmap_config); 269 if (IS_ERR(map)) 270 return dev_err_probe(dev, PTR_ERR(map), 271 "Unable to initialize register map\n"); 272 273 dio48egpio->map = map; 274 275 pit_regmap_config = (struct regmap_config) { 276 .name = "i8254", 277 .reg_bits = 8, 278 .reg_stride = 1, 279 .val_bits = 8, 280 .lock = pit_regmap_lock, 281 .unlock = pit_regmap_unlock, 282 .lock_arg = dio48egpio, 283 .io_port = true, 284 .wr_table = &pit_wr_table, 285 .rd_table = &pit_rd_table, 286 }; 287 288 pit_config.map = devm_regmap_init_mmio(dev, regs, &pit_regmap_config); 289 if (IS_ERR(pit_config.map)) 290 return dev_err_probe(dev, PTR_ERR(pit_config.map), 291 "Unable to initialize i8254 register map\n"); 292 293 chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); 294 if (!chip) 295 return -ENOMEM; 296 297 chip->name = name; 298 chip->mask_base = DIO48E_ENABLE_INTERRUPT; 299 chip->ack_base = DIO48E_CLEAR_INTERRUPT; 300 chip->no_status = true; 301 chip->num_regs = 1; 302 chip->irqs = dio48e_regmap_irqs; 303 chip->num_irqs = ARRAY_SIZE(dio48e_regmap_irqs); 304 chip->handle_mask_sync = dio48e_handle_mask_sync; 305 chip->irq_drv_data = dio48egpio; 306 307 /* Initialize to prevent spurious interrupts before we're ready */ 308 err = dio48e_irq_init_hw(map); 309 if (err) 310 return err; 311 312 err = devm_regmap_add_irq_chip(dev, map, irq[id], 0, 0, chip, &chip_data); 313 if (err) 314 return dev_err_probe(dev, err, "IRQ registration failed\n"); 315 316 pit_config.parent = dev; 317 318 err = devm_i8254_regmap_register(dev, &pit_config); 319 if (err) 320 return err; 321 322 config.parent = dev; 323 config.map = map; 324 config.num_ppi = DIO48E_NUM_PPI; 325 config.names = dio48e_names; 326 config.domain = regmap_irq_get_domain(chip_data); 327 328 return devm_i8255_regmap_register(dev, &config); 329 } 330 331 static struct isa_driver dio48e_driver = { 332 .probe = dio48e_probe, 333 .driver = { 334 .name = "104-dio-48e" 335 }, 336 }; 337 module_isa_driver_with_irq(dio48e_driver, num_dio48e, num_irq); 338 339 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>"); 340 MODULE_DESCRIPTION("ACCES 104-DIO-48E GPIO driver"); 341 MODULE_LICENSE("GPL v2"); 342 MODULE_IMPORT_NS(I8254); 343