Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'gpio-v5.1-updates-for-linus-part-2' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux into devel

gpio: updates for v5.1 - part 2

- gpio-mockup updates improving the user-space testing interface and
adding line state tracking for correct edge interrupts
- interrupt simulator patch exposing the irq type configuration to
users

+176 -29
+164 -29
drivers/gpio/gpio-mockup.c
··· 47 47 struct gpio_mockup_line_status { 48 48 int dir; 49 49 int value; 50 + int pull; 50 51 }; 51 52 52 53 struct gpio_mockup_chip { ··· 55 54 struct gpio_mockup_line_status *lines; 56 55 struct irq_sim irqsim; 57 56 struct dentry *dbg_dir; 57 + struct mutex lock; 58 58 }; 59 59 60 60 struct gpio_mockup_dbgfs_private { 61 61 struct gpio_mockup_chip *chip; 62 62 struct gpio_desc *desc; 63 - int offset; 63 + unsigned int offset; 64 64 }; 65 65 66 66 static int gpio_mockup_ranges[GPIO_MOCKUP_MAX_RANGES]; ··· 84 82 return gpio_mockup_ranges[index * 2 + 1]; 85 83 } 86 84 87 - static int gpio_mockup_get(struct gpio_chip *gc, unsigned int offset) 85 + static int __gpio_mockup_get(struct gpio_mockup_chip *chip, 86 + unsigned int offset) 88 87 { 89 - struct gpio_mockup_chip *chip = gpiochip_get_data(gc); 90 - 91 88 return chip->lines[offset].value; 92 89 } 93 90 91 + static int gpio_mockup_get(struct gpio_chip *gc, unsigned int offset) 92 + { 93 + struct gpio_mockup_chip *chip = gpiochip_get_data(gc); 94 + int val; 95 + 96 + mutex_lock(&chip->lock); 97 + val = __gpio_mockup_get(chip, offset); 98 + mutex_unlock(&chip->lock); 99 + 100 + return val; 101 + } 102 + 103 + static int gpio_mockup_get_multiple(struct gpio_chip *gc, 104 + unsigned long *mask, unsigned long *bits) 105 + { 106 + struct gpio_mockup_chip *chip = gpiochip_get_data(gc); 107 + unsigned int bit, val; 108 + 109 + mutex_lock(&chip->lock); 110 + for_each_set_bit(bit, mask, gc->ngpio) { 111 + val = __gpio_mockup_get(chip, bit); 112 + __assign_bit(bit, bits, val); 113 + } 114 + mutex_unlock(&chip->lock); 115 + 116 + return 0; 117 + } 118 + 119 + static void __gpio_mockup_set(struct gpio_mockup_chip *chip, 120 + unsigned int offset, int value) 121 + { 122 + chip->lines[offset].value = !!value; 123 + } 124 + 94 125 static void gpio_mockup_set(struct gpio_chip *gc, 95 - unsigned int offset, int value) 126 + unsigned int offset, int value) 96 127 { 97 128 struct gpio_mockup_chip *chip = gpiochip_get_data(gc); 98 129 99 - chip->lines[offset].value = !!value; 130 + mutex_lock(&chip->lock); 131 + __gpio_mockup_set(chip, offset, value); 132 + mutex_unlock(&chip->lock); 100 133 } 101 134 102 135 static void gpio_mockup_set_multiple(struct gpio_chip *gc, 103 136 unsigned long *mask, unsigned long *bits) 104 137 { 138 + struct gpio_mockup_chip *chip = gpiochip_get_data(gc); 105 139 unsigned int bit; 106 140 141 + mutex_lock(&chip->lock); 107 142 for_each_set_bit(bit, mask, gc->ngpio) 108 - gpio_mockup_set(gc, bit, test_bit(bit, bits)); 109 - 143 + __gpio_mockup_set(chip, bit, test_bit(bit, bits)); 144 + mutex_unlock(&chip->lock); 110 145 } 111 146 112 147 static int gpio_mockup_dirout(struct gpio_chip *gc, ··· 151 112 { 152 113 struct gpio_mockup_chip *chip = gpiochip_get_data(gc); 153 114 154 - gpio_mockup_set(gc, offset, value); 115 + mutex_lock(&chip->lock); 155 116 chip->lines[offset].dir = GPIO_MOCKUP_DIR_OUT; 117 + __gpio_mockup_set(chip, offset, value); 118 + mutex_unlock(&chip->lock); 156 119 157 120 return 0; 158 121 } ··· 163 122 { 164 123 struct gpio_mockup_chip *chip = gpiochip_get_data(gc); 165 124 125 + mutex_lock(&chip->lock); 166 126 chip->lines[offset].dir = GPIO_MOCKUP_DIR_IN; 127 + mutex_unlock(&chip->lock); 167 128 168 129 return 0; 169 130 } ··· 173 130 static int gpio_mockup_get_direction(struct gpio_chip *gc, unsigned int offset) 174 131 { 175 132 struct gpio_mockup_chip *chip = gpiochip_get_data(gc); 133 + int direction; 176 134 177 - return !chip->lines[offset].dir; 135 + mutex_lock(&chip->lock); 136 + direction = !chip->lines[offset].dir; 137 + mutex_unlock(&chip->lock); 138 + 139 + return direction; 178 140 } 179 141 180 142 static int gpio_mockup_to_irq(struct gpio_chip *gc, unsigned int offset) ··· 189 141 return irq_sim_irqnum(&chip->irqsim, offset); 190 142 } 191 143 192 - static ssize_t gpio_mockup_event_write(struct file *file, 193 - const char __user *usr_buf, 194 - size_t size, loff_t *ppos) 144 + static void gpio_mockup_free(struct gpio_chip *gc, unsigned int offset) 145 + { 146 + struct gpio_mockup_chip *chip = gpiochip_get_data(gc); 147 + 148 + __gpio_mockup_set(chip, offset, chip->lines[offset].pull); 149 + } 150 + 151 + static ssize_t gpio_mockup_debugfs_read(struct file *file, 152 + char __user *usr_buf, 153 + size_t size, loff_t *ppos) 195 154 { 196 155 struct gpio_mockup_dbgfs_private *priv; 197 156 struct gpio_mockup_chip *chip; 198 157 struct seq_file *sfile; 158 + struct gpio_chip *gc; 159 + char buf[3]; 160 + int val, rv; 161 + 162 + if (*ppos != 0) 163 + return 0; 164 + 165 + sfile = file->private_data; 166 + priv = sfile->private; 167 + chip = priv->chip; 168 + gc = &chip->gc; 169 + 170 + val = gpio_mockup_get(gc, priv->offset); 171 + snprintf(buf, sizeof(buf), "%d\n", val); 172 + 173 + rv = copy_to_user(usr_buf, buf, sizeof(buf)); 174 + if (rv) 175 + return rv; 176 + 177 + return sizeof(buf) - 1; 178 + } 179 + 180 + static ssize_t gpio_mockup_debugfs_write(struct file *file, 181 + const char __user *usr_buf, 182 + size_t size, loff_t *ppos) 183 + { 184 + struct gpio_mockup_dbgfs_private *priv; 185 + int rv, val, curr, irq, irq_type; 186 + struct gpio_mockup_chip *chip; 187 + struct seq_file *sfile; 199 188 struct gpio_desc *desc; 200 - int rv, val; 189 + struct gpio_chip *gc; 190 + struct irq_sim *sim; 191 + 192 + if (*ppos != 0) 193 + return -EINVAL; 201 194 202 195 rv = kstrtoint_from_user(usr_buf, size, 0, &val); 203 196 if (rv) ··· 248 159 249 160 sfile = file->private_data; 250 161 priv = sfile->private; 251 - desc = priv->desc; 252 162 chip = priv->chip; 163 + gc = &chip->gc; 164 + desc = &gc->gpiodev->descs[priv->offset]; 165 + sim = &chip->irqsim; 253 166 254 - gpiod_set_value_cansleep(desc, val); 255 - irq_sim_fire(&chip->irqsim, priv->offset); 167 + mutex_lock(&chip->lock); 168 + 169 + if (test_bit(FLAG_REQUESTED, &desc->flags) && 170 + !test_bit(FLAG_IS_OUT, &desc->flags)) { 171 + curr = __gpio_mockup_get(chip, priv->offset); 172 + if (curr == val) 173 + goto out; 174 + 175 + irq = irq_sim_irqnum(sim, priv->offset); 176 + irq_type = irq_get_trigger_type(irq); 177 + 178 + if ((val == 1 && (irq_type & IRQ_TYPE_EDGE_RISING)) || 179 + (val == 0 && (irq_type & IRQ_TYPE_EDGE_FALLING))) 180 + irq_sim_fire(sim, priv->offset); 181 + } 182 + 183 + /* Change the value unless we're actively driving the line. */ 184 + if (!test_bit(FLAG_REQUESTED, &desc->flags) || 185 + !test_bit(FLAG_IS_OUT, &desc->flags)) 186 + __gpio_mockup_set(chip, priv->offset, val); 187 + 188 + out: 189 + chip->lines[priv->offset].pull = val; 190 + mutex_unlock(&chip->lock); 256 191 257 192 return size; 258 193 } 259 194 260 - static int gpio_mockup_event_open(struct inode *inode, struct file *file) 195 + static int gpio_mockup_debugfs_open(struct inode *inode, struct file *file) 261 196 { 262 197 return single_open(file, NULL, inode->i_private); 263 198 } 264 199 265 - static const struct file_operations gpio_mockup_event_ops = { 200 + /* 201 + * Each mockup chip is represented by a directory named after the chip's device 202 + * name under /sys/kernel/debug/gpio-mockup/. Each line is represented by 203 + * a file using the line's offset as the name under the chip's directory. 204 + * 205 + * Reading from the line's file yields the current *value*, writing to the 206 + * line's file changes the current *pull*. Default pull for mockup lines is 207 + * down. 208 + * 209 + * Examples: 210 + * - when a line pulled down is requested in output mode and driven high, its 211 + * value will return to 0 once it's released 212 + * - when the line is requested in output mode and driven high, writing 0 to 213 + * the corresponding debugfs file will change the pull to down but the 214 + * reported value will still be 1 until the line is released 215 + * - line requested in input mode always reports the same value as its pull 216 + * configuration 217 + * - when the line is requested in input mode and monitored for events, writing 218 + * the same value to the debugfs file will be a noop, while writing the 219 + * opposite value will generate a dummy interrupt with an appropriate edge 220 + */ 221 + static const struct file_operations gpio_mockup_debugfs_ops = { 266 222 .owner = THIS_MODULE, 267 - .open = gpio_mockup_event_open, 268 - .write = gpio_mockup_event_write, 223 + .open = gpio_mockup_debugfs_open, 224 + .read = gpio_mockup_debugfs_read, 225 + .write = gpio_mockup_debugfs_write, 269 226 .llseek = no_llseek, 270 227 }; 271 228 ··· 319 184 struct gpio_mockup_chip *chip) 320 185 { 321 186 struct gpio_mockup_dbgfs_private *priv; 322 - struct dentry *evfile, *link; 187 + struct dentry *evfile; 323 188 struct gpio_chip *gc; 324 189 const char *devname; 325 190 char *name; ··· 330 195 331 196 chip->dbg_dir = debugfs_create_dir(devname, gpio_mockup_dbg_dir); 332 197 if (IS_ERR_OR_NULL(chip->dbg_dir)) 333 - goto err; 334 - 335 - link = debugfs_create_symlink(gc->label, gpio_mockup_dbg_dir, devname); 336 - if (IS_ERR_OR_NULL(link)) 337 198 goto err; 338 199 339 200 for (i = 0; i < gc->ngpio; i++) { ··· 346 215 priv->desc = &gc->gpiodev->descs[i]; 347 216 348 217 evfile = debugfs_create_file(name, 0200, chip->dbg_dir, priv, 349 - &gpio_mockup_event_ops); 218 + &gpio_mockup_debugfs_ops); 350 219 if (IS_ERR_OR_NULL(evfile)) 351 220 goto err; 352 221 } ··· 354 223 return; 355 224 356 225 err: 357 - dev_err(dev, "error creating debugfs event files\n"); 226 + dev_err(dev, "error creating debugfs files\n"); 358 227 } 359 228 360 229 static int gpio_mockup_name_lines(struct device *dev, ··· 414 283 return -ENOMEM; 415 284 } 416 285 286 + mutex_init(&chip->lock); 287 + 417 288 gc = &chip->gc; 418 289 gc->base = base; 419 290 gc->ngpio = ngpio; ··· 424 291 gc->parent = dev; 425 292 gc->get = gpio_mockup_get; 426 293 gc->set = gpio_mockup_set; 294 + gc->get_multiple = gpio_mockup_get_multiple; 427 295 gc->set_multiple = gpio_mockup_set_multiple; 428 296 gc->direction_output = gpio_mockup_dirout; 429 297 gc->direction_input = gpio_mockup_dirin; 430 298 gc->get_direction = gpio_mockup_get_direction; 431 299 gc->to_irq = gpio_mockup_to_irq; 300 + gc->free = gpio_mockup_free; 432 301 433 302 chip->lines = devm_kcalloc(dev, gc->ngpio, 434 303 sizeof(*chip->lines), GFP_KERNEL); ··· 504 369 return -EINVAL; 505 370 } 506 371 507 - gpio_mockup_dbg_dir = debugfs_create_dir("gpio-mockup-event", NULL); 372 + gpio_mockup_dbg_dir = debugfs_create_dir("gpio-mockup", NULL); 508 373 if (IS_ERR_OR_NULL(gpio_mockup_dbg_dir)) 509 374 gpio_mockup_err("error creating debugfs directory\n"); 510 375
+12
kernel/irq/irq_sim.c
··· 25 25 irq_ctx->enabled = true; 26 26 } 27 27 28 + static int irq_sim_set_type(struct irq_data *data, unsigned int type) 29 + { 30 + /* We only support rising and falling edge trigger types. */ 31 + if (type & ~IRQ_TYPE_EDGE_BOTH) 32 + return -EINVAL; 33 + 34 + irqd_set_trigger_type(data, type); 35 + 36 + return 0; 37 + } 38 + 28 39 static struct irq_chip irq_sim_irqchip = { 29 40 .name = "irq_sim", 30 41 .irq_mask = irq_sim_irqmask, 31 42 .irq_unmask = irq_sim_irqunmask, 43 + .irq_set_type = irq_sim_set_type, 32 44 }; 33 45 34 46 static void irq_sim_handle_irq(struct irq_work *work)