fbdev: imsttfb: Fix use after free bug in imsttfb_probe
[linux-block.git] / drivers / gpio / gpio-gpio-mm.c
CommitLineData
1802d0be 1// SPDX-License-Identifier: GPL-2.0-only
6ea5dcdf
WBG
2/*
3 * GPIO driver for the Diamond Systems GPIO-MM
4 * Copyright (C) 2016 William Breathitt Gray
5 *
6ea5dcdf
WBG
6 * This driver supports the following Diamond Systems devices: GPIO-MM and
7 * GPIO-MM-12.
8 */
6ea5dcdf
WBG
9#include <linux/device.h>
10#include <linux/errno.h>
6ea5dcdf
WBG
11#include <linux/ioport.h>
12#include <linux/isa.h>
13#include <linux/kernel.h>
14#include <linux/module.h>
15#include <linux/moduleparam.h>
1c05004f
WBG
16#include <linux/regmap.h>
17#include <linux/types.h>
949506dc
WBG
18
19#include "gpio-i8255.h"
20
21MODULE_IMPORT_NS(I8255);
6ea5dcdf
WBG
22
23#define GPIOMM_EXTENT 8
24#define MAX_NUM_GPIOMM max_num_isa_dev(GPIOMM_EXTENT)
25
26static unsigned int base[MAX_NUM_GPIOMM];
27static unsigned int num_gpiomm;
d759f906 28module_param_hw_array(base, uint, ioport, &num_gpiomm, 0);
6ea5dcdf
WBG
29MODULE_PARM_DESC(base, "Diamond Systems GPIO-MM base addresses");
30
949506dc
WBG
31#define GPIOMM_NUM_PPI 2
32
1c05004f
WBG
33static const struct regmap_range gpiomm_volatile_ranges[] = {
34 i8255_volatile_regmap_range(0x0), i8255_volatile_regmap_range(0x4),
35};
36static const struct regmap_access_table gpiomm_volatile_table = {
37 .yes_ranges = gpiomm_volatile_ranges,
38 .n_yes_ranges = ARRAY_SIZE(gpiomm_volatile_ranges),
39};
40static const struct regmap_config gpiomm_regmap_config = {
41 .reg_bits = 8,
42 .reg_stride = 1,
43 .val_bits = 8,
44 .io_port = true,
45 .max_register = 0x7,
46 .volatile_table = &gpiomm_volatile_table,
47 .cache_type = REGCACHE_FLAT,
6ea5dcdf 48};
65502a12 49
210b4bde
WBG
50#define GPIOMM_NGPIO 48
51static const char *gpiomm_names[GPIOMM_NGPIO] = {
52 "Port 1A0", "Port 1A1", "Port 1A2", "Port 1A3", "Port 1A4", "Port 1A5",
53 "Port 1A6", "Port 1A7", "Port 1B0", "Port 1B1", "Port 1B2", "Port 1B3",
54 "Port 1B4", "Port 1B5", "Port 1B6", "Port 1B7", "Port 1C0", "Port 1C1",
55 "Port 1C2", "Port 1C3", "Port 1C4", "Port 1C5", "Port 1C6", "Port 1C7",
56 "Port 2A0", "Port 2A1", "Port 2A2", "Port 2A3", "Port 2A4", "Port 2A5",
57 "Port 2A6", "Port 2A7", "Port 2B0", "Port 2B1", "Port 2B2", "Port 2B3",
58 "Port 2B4", "Port 2B5", "Port 2B6", "Port 2B7", "Port 2C0", "Port 2C1",
59 "Port 2C2", "Port 2C3", "Port 2C4", "Port 2C5", "Port 2C6", "Port 2C7",
60};
61
6ea5dcdf
WBG
62static int gpiomm_probe(struct device *dev, unsigned int id)
63{
6ea5dcdf 64 const char *const name = dev_name(dev);
1c05004f
WBG
65 struct i8255_regmap_config config = {};
66 void __iomem *regs;
6ea5dcdf
WBG
67
68 if (!devm_request_region(dev, base[id], GPIOMM_EXTENT, name)) {
69 dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
70 base[id], base[id] + GPIOMM_EXTENT);
71 return -EBUSY;
72 }
73
1c05004f
WBG
74 regs = devm_ioport_map(dev, base[id], GPIOMM_EXTENT);
75 if (!regs)
54c8e251
WBG
76 return -ENOMEM;
77
1c05004f
WBG
78 config.map = devm_regmap_init_mmio(dev, regs, &gpiomm_regmap_config);
79 if (IS_ERR(config.map))
80 return dev_err_probe(dev, PTR_ERR(config.map),
81 "Unable to initialize register map\n");
82
83 config.parent = dev;
84 config.num_ppi = GPIOMM_NUM_PPI;
85 config.names = gpiomm_names;
6ea5dcdf 86
1c05004f 87 return devm_i8255_regmap_register(dev, &config);
6ea5dcdf
WBG
88}
89
6ea5dcdf
WBG
90static struct isa_driver gpiomm_driver = {
91 .probe = gpiomm_probe,
92 .driver = {
93 .name = "gpio-mm"
94 },
6ea5dcdf
WBG
95};
96
97module_isa_driver(gpiomm_driver, num_gpiomm);
98
99MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
100MODULE_DESCRIPTION("Diamond Systems GPIO-MM GPIO driver");
101MODULE_LICENSE("GPL v2");