gpio-mockup.c (8a68ea00a62e7ec33e9e4e7f3d9c2a845943c58d) | gpio-mockup.c (e2ff7408953f6fe8a341b31ed2d848f73606bbf4) |
---|---|
1/* 2 * GPIO Testing Device Driver 3 * 4 * Copyright (C) 2014 Kamlakant Patel <kamlakant.patel@broadcom.com> 5 * Copyright (C) 2015-2016 Bamvor Jian Zhang <bamvor.zhangjian@linaro.org> 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by the 9 * Free Software Foundation; either version 2 of the License, or (at your 10 * option) any later version. 11 * 12 */ 13 14#include <linux/init.h> 15#include <linux/module.h> 16#include <linux/gpio/driver.h> 17#include <linux/platform_device.h> 18#include <linux/slab.h> | 1/* 2 * GPIO Testing Device Driver 3 * 4 * Copyright (C) 2014 Kamlakant Patel <kamlakant.patel@broadcom.com> 5 * Copyright (C) 2015-2016 Bamvor Jian Zhang <bamvor.zhangjian@linaro.org> 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by the 9 * Free Software Foundation; either version 2 of the License, or (at your 10 * option) any later version. 11 * 12 */ 13 14#include <linux/init.h> 15#include <linux/module.h> 16#include <linux/gpio/driver.h> 17#include <linux/platform_device.h> 18#include <linux/slab.h> |
19#include <linux/interrupt.h> 20#include <linux/irq.h> 21#include <linux/irq_work.h> |
|
19 20#define GPIO_MOCKUP_NAME "gpio-mockup" 21#define GPIO_MOCKUP_MAX_GC 10 22 23enum { 24 DIR_IN = 0, 25 DIR_OUT, 26}; 27 28/* 29 * struct gpio_pin_status - structure describing a GPIO status 30 * @dir: Configures direction of gpio as "in" or "out", 0=in, 1=out 31 * @value: Configures status of the gpio as 0(low) or 1(high) 32 */ 33struct gpio_mockup_line_status { 34 int dir; 35 bool value; 36}; 37 | 22 23#define GPIO_MOCKUP_NAME "gpio-mockup" 24#define GPIO_MOCKUP_MAX_GC 10 25 26enum { 27 DIR_IN = 0, 28 DIR_OUT, 29}; 30 31/* 32 * struct gpio_pin_status - structure describing a GPIO status 33 * @dir: Configures direction of gpio as "in" or "out", 0=in, 1=out 34 * @value: Configures status of the gpio as 0(low) or 1(high) 35 */ 36struct gpio_mockup_line_status { 37 int dir; 38 bool value; 39}; 40 |
41struct gpio_mockup_irq_context { 42 struct irq_work work; 43 int irq; 44}; 45 |
|
38struct gpio_mockup_chip { 39 struct gpio_chip gc; 40 struct gpio_mockup_line_status *lines; | 46struct gpio_mockup_chip { 47 struct gpio_chip gc; 48 struct gpio_mockup_line_status *lines; |
49 struct gpio_mockup_irq_context irq_ctx; |
|
41}; 42 43static int gpio_mockup_ranges[GPIO_MOCKUP_MAX_GC << 1]; 44static int gpio_mockup_params_nr; 45module_param_array(gpio_mockup_ranges, int, &gpio_mockup_params_nr, 0400); 46 47static bool gpio_mockup_named_lines; 48module_param_named(gpio_mockup_named_lines, --- 61 unchanged lines hidden (view full) --- 110 return -ENOMEM; 111 } 112 113 gc->names = (const char *const *)names; 114 115 return 0; 116} 117 | 50}; 51 52static int gpio_mockup_ranges[GPIO_MOCKUP_MAX_GC << 1]; 53static int gpio_mockup_params_nr; 54module_param_array(gpio_mockup_ranges, int, &gpio_mockup_params_nr, 0400); 55 56static bool gpio_mockup_named_lines; 57module_param_named(gpio_mockup_named_lines, --- 61 unchanged lines hidden (view full) --- 119 return -ENOMEM; 120 } 121 122 gc->names = (const char *const *)names; 123 124 return 0; 125} 126 |
127static int gpio_mockup_to_irq(struct gpio_chip *chip, unsigned int offset) 128{ 129 return chip->irq_base + offset; 130} 131 132/* 133 * While we should generally support irqmask and irqunmask, this driver is 134 * for testing purposes only so we don't care. 135 */ 136static void gpio_mockup_irqmask(struct irq_data *d) { } 137static void gpio_mockup_irqunmask(struct irq_data *d) { } 138 139static struct irq_chip gpio_mockup_irqchip = { 140 .name = GPIO_MOCKUP_NAME, 141 .irq_mask = gpio_mockup_irqmask, 142 .irq_unmask = gpio_mockup_irqunmask, 143}; 144 145static void gpio_mockup_handle_irq(struct irq_work *work) 146{ 147 struct gpio_mockup_irq_context *irq_ctx; 148 149 irq_ctx = container_of(work, struct gpio_mockup_irq_context, work); 150 handle_simple_irq(irq_to_desc(irq_ctx->irq)); 151} 152 153static int gpio_mockup_irqchip_setup(struct device *dev, 154 struct gpio_mockup_chip *chip) 155{ 156 struct gpio_chip *gc = &chip->gc; 157 int irq_base, i; 158 159 irq_base = irq_alloc_descs(-1, 0, gc->ngpio, 0); 160 if (irq_base < 0) 161 return irq_base; 162 163 gc->irq_base = irq_base; 164 gc->irqchip = &gpio_mockup_irqchip; 165 166 for (i = 0; i < gc->ngpio; i++) { 167 irq_set_chip(irq_base + i, gc->irqchip); 168 irq_set_handler(irq_base + i, &handle_simple_irq); 169 irq_modify_status(irq_base + i, 170 IRQ_NOREQUEST | IRQ_NOAUTOEN, IRQ_NOPROBE); 171 } 172 173 init_irq_work(&chip->irq_ctx.work, gpio_mockup_handle_irq); 174 175 return 0; 176} 177 |
|
118static int gpio_mockup_add(struct device *dev, 119 struct gpio_mockup_chip *chip, 120 const char *name, int base, int ngpio) 121{ 122 struct gpio_chip *gc = &chip->gc; 123 int ret; 124 125 gc->base = base; 126 gc->ngpio = ngpio; 127 gc->label = name; 128 gc->owner = THIS_MODULE; 129 gc->parent = dev; 130 gc->get = gpio_mockup_get; 131 gc->set = gpio_mockup_set; 132 gc->direction_output = gpio_mockup_dirout; 133 gc->direction_input = gpio_mockup_dirin; 134 gc->get_direction = gpio_mockup_get_direction; | 178static int gpio_mockup_add(struct device *dev, 179 struct gpio_mockup_chip *chip, 180 const char *name, int base, int ngpio) 181{ 182 struct gpio_chip *gc = &chip->gc; 183 int ret; 184 185 gc->base = base; 186 gc->ngpio = ngpio; 187 gc->label = name; 188 gc->owner = THIS_MODULE; 189 gc->parent = dev; 190 gc->get = gpio_mockup_get; 191 gc->set = gpio_mockup_set; 192 gc->direction_output = gpio_mockup_dirout; 193 gc->direction_input = gpio_mockup_dirin; 194 gc->get_direction = gpio_mockup_get_direction; |
195 gc->to_irq = gpio_mockup_to_irq; |
|
135 136 chip->lines = devm_kzalloc(dev, sizeof(*chip->lines) * gc->ngpio, 137 GFP_KERNEL); 138 if (!chip->lines) 139 return -ENOMEM; 140 141 if (gpio_mockup_named_lines) { 142 ret = gpio_mockup_name_lines(dev, chip); 143 if (ret) 144 return ret; 145 } 146 | 196 197 chip->lines = devm_kzalloc(dev, sizeof(*chip->lines) * gc->ngpio, 198 GFP_KERNEL); 199 if (!chip->lines) 200 return -ENOMEM; 201 202 if (gpio_mockup_named_lines) { 203 ret = gpio_mockup_name_lines(dev, chip); 204 if (ret) 205 return ret; 206 } 207 |
208 ret = gpio_mockup_irqchip_setup(dev, chip); 209 if (ret) 210 return ret; 211 |
|
147 return devm_gpiochip_add_data(dev, &chip->gc, chip); 148} 149 150static int gpio_mockup_probe(struct platform_device *pdev) 151{ 152 struct gpio_mockup_chip *chips; 153 struct device *dev = &pdev->dev; 154 int ret, i, base, ngpio; --- 40 unchanged lines hidden (view full) --- 195 196 dev_info(dev, "gpio<%d..%d> add successful!", 197 base, base + ngpio); 198 } 199 200 return 0; 201} 202 | 212 return devm_gpiochip_add_data(dev, &chip->gc, chip); 213} 214 215static int gpio_mockup_probe(struct platform_device *pdev) 216{ 217 struct gpio_mockup_chip *chips; 218 struct device *dev = &pdev->dev; 219 int ret, i, base, ngpio; --- 40 unchanged lines hidden (view full) --- 260 261 dev_info(dev, "gpio<%d..%d> add successful!", 262 base, base + ngpio); 263 } 264 265 return 0; 266} 267 |
268static int gpio_mockup_remove(struct platform_device *pdev) 269{ 270 struct gpio_mockup_chip *chips; 271 int i; 272 273 chips = platform_get_drvdata(pdev); 274 275 for (i = 0; i < gpio_mockup_params_nr >> 1; i++) 276 irq_free_descs(chips[i].gc.irq_base, chips[i].gc.ngpio); 277 278 return 0; 279} 280 |
|
203static struct platform_driver gpio_mockup_driver = { 204 .driver = { 205 .name = GPIO_MOCKUP_NAME, 206 }, 207 .probe = gpio_mockup_probe, | 281static struct platform_driver gpio_mockup_driver = { 282 .driver = { 283 .name = GPIO_MOCKUP_NAME, 284 }, 285 .probe = gpio_mockup_probe, |
286 .remove = gpio_mockup_remove, |
|
208}; 209 210static struct platform_device *pdev; 211static int __init mock_device_init(void) 212{ 213 int err; 214 215 pdev = platform_device_alloc(GPIO_MOCKUP_NAME, -1); --- 31 unchanged lines hidden --- | 287}; 288 289static struct platform_device *pdev; 290static int __init mock_device_init(void) 291{ 292 int err; 293 294 pdev = platform_device_alloc(GPIO_MOCKUP_NAME, -1); --- 31 unchanged lines hidden --- |