Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * GPIO driver for the Diamond Systems GPIO-MM
0004  * Copyright (C) 2016 William Breathitt Gray
0005  *
0006  * This driver supports the following Diamond Systems devices: GPIO-MM and
0007  * GPIO-MM-12.
0008  */
0009 #include <linux/device.h>
0010 #include <linux/errno.h>
0011 #include <linux/gpio/driver.h>
0012 #include <linux/io.h>
0013 #include <linux/ioport.h>
0014 #include <linux/isa.h>
0015 #include <linux/kernel.h>
0016 #include <linux/module.h>
0017 #include <linux/moduleparam.h>
0018 
0019 #include "gpio-i8255.h"
0020 
0021 MODULE_IMPORT_NS(I8255);
0022 
0023 #define GPIOMM_EXTENT 8
0024 #define MAX_NUM_GPIOMM max_num_isa_dev(GPIOMM_EXTENT)
0025 
0026 static unsigned int base[MAX_NUM_GPIOMM];
0027 static unsigned int num_gpiomm;
0028 module_param_hw_array(base, uint, ioport, &num_gpiomm, 0);
0029 MODULE_PARM_DESC(base, "Diamond Systems GPIO-MM base addresses");
0030 
0031 #define GPIOMM_NUM_PPI 2
0032 
0033 /**
0034  * struct gpiomm_gpio - GPIO device private data structure
0035  * @chip:       instance of the gpio_chip
0036  * @ppi_state:      Programmable Peripheral Interface group states
0037  * @ppi:        Programmable Peripheral Interface groups
0038  */
0039 struct gpiomm_gpio {
0040     struct gpio_chip chip;
0041     struct i8255_state ppi_state[GPIOMM_NUM_PPI];
0042     struct i8255 __iomem *ppi;
0043 };
0044 
0045 static int gpiomm_gpio_get_direction(struct gpio_chip *chip,
0046     unsigned int offset)
0047 {
0048     struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip);
0049 
0050     if (i8255_get_direction(gpiommgpio->ppi_state, offset))
0051         return GPIO_LINE_DIRECTION_IN;
0052 
0053     return GPIO_LINE_DIRECTION_OUT;
0054 }
0055 
0056 static int gpiomm_gpio_direction_input(struct gpio_chip *chip,
0057     unsigned int offset)
0058 {
0059     struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip);
0060 
0061     i8255_direction_input(gpiommgpio->ppi, gpiommgpio->ppi_state, offset);
0062 
0063     return 0;
0064 }
0065 
0066 static int gpiomm_gpio_direction_output(struct gpio_chip *chip,
0067     unsigned int offset, int value)
0068 {
0069     struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip);
0070 
0071     i8255_direction_output(gpiommgpio->ppi, gpiommgpio->ppi_state, offset,
0072                    value);
0073 
0074     return 0;
0075 }
0076 
0077 static int gpiomm_gpio_get(struct gpio_chip *chip, unsigned int offset)
0078 {
0079     struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip);
0080 
0081     return i8255_get(gpiommgpio->ppi, offset);
0082 }
0083 
0084 static int gpiomm_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask,
0085     unsigned long *bits)
0086 {
0087     struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip);
0088 
0089     i8255_get_multiple(gpiommgpio->ppi, mask, bits, chip->ngpio);
0090 
0091     return 0;
0092 }
0093 
0094 static void gpiomm_gpio_set(struct gpio_chip *chip, unsigned int offset,
0095     int value)
0096 {
0097     struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip);
0098 
0099     i8255_set(gpiommgpio->ppi, gpiommgpio->ppi_state, offset, value);
0100 }
0101 
0102 static void gpiomm_gpio_set_multiple(struct gpio_chip *chip,
0103     unsigned long *mask, unsigned long *bits)
0104 {
0105     struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip);
0106 
0107     i8255_set_multiple(gpiommgpio->ppi, gpiommgpio->ppi_state, mask, bits,
0108                chip->ngpio);
0109 }
0110 
0111 #define GPIOMM_NGPIO 48
0112 static const char *gpiomm_names[GPIOMM_NGPIO] = {
0113     "Port 1A0", "Port 1A1", "Port 1A2", "Port 1A3", "Port 1A4", "Port 1A5",
0114     "Port 1A6", "Port 1A7", "Port 1B0", "Port 1B1", "Port 1B2", "Port 1B3",
0115     "Port 1B4", "Port 1B5", "Port 1B6", "Port 1B7", "Port 1C0", "Port 1C1",
0116     "Port 1C2", "Port 1C3", "Port 1C4", "Port 1C5", "Port 1C6", "Port 1C7",
0117     "Port 2A0", "Port 2A1", "Port 2A2", "Port 2A3", "Port 2A4", "Port 2A5",
0118     "Port 2A6", "Port 2A7", "Port 2B0", "Port 2B1", "Port 2B2", "Port 2B3",
0119     "Port 2B4", "Port 2B5", "Port 2B6", "Port 2B7", "Port 2C0", "Port 2C1",
0120     "Port 2C2", "Port 2C3", "Port 2C4", "Port 2C5", "Port 2C6", "Port 2C7",
0121 };
0122 
0123 static void gpiomm_init_dio(struct i8255 __iomem *const ppi,
0124                 struct i8255_state *const ppi_state)
0125 {
0126     const unsigned long ngpio = 24;
0127     const unsigned long mask = GENMASK(ngpio - 1, 0);
0128     const unsigned long bits = 0;
0129     unsigned long i;
0130 
0131     /* Initialize all GPIO to output 0 */
0132     for (i = 0; i < GPIOMM_NUM_PPI; i++) {
0133         i8255_mode0_output(&ppi[i]);
0134         i8255_set_multiple(&ppi[i], &ppi_state[i], &mask, &bits, ngpio);
0135     }
0136 }
0137 
0138 static int gpiomm_probe(struct device *dev, unsigned int id)
0139 {
0140     struct gpiomm_gpio *gpiommgpio;
0141     const char *const name = dev_name(dev);
0142     int err;
0143 
0144     gpiommgpio = devm_kzalloc(dev, sizeof(*gpiommgpio), GFP_KERNEL);
0145     if (!gpiommgpio)
0146         return -ENOMEM;
0147 
0148     if (!devm_request_region(dev, base[id], GPIOMM_EXTENT, name)) {
0149         dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
0150             base[id], base[id] + GPIOMM_EXTENT);
0151         return -EBUSY;
0152     }
0153 
0154     gpiommgpio->ppi = devm_ioport_map(dev, base[id], GPIOMM_EXTENT);
0155     if (!gpiommgpio->ppi)
0156         return -ENOMEM;
0157 
0158     gpiommgpio->chip.label = name;
0159     gpiommgpio->chip.parent = dev;
0160     gpiommgpio->chip.owner = THIS_MODULE;
0161     gpiommgpio->chip.base = -1;
0162     gpiommgpio->chip.ngpio = GPIOMM_NGPIO;
0163     gpiommgpio->chip.names = gpiomm_names;
0164     gpiommgpio->chip.get_direction = gpiomm_gpio_get_direction;
0165     gpiommgpio->chip.direction_input = gpiomm_gpio_direction_input;
0166     gpiommgpio->chip.direction_output = gpiomm_gpio_direction_output;
0167     gpiommgpio->chip.get = gpiomm_gpio_get;
0168     gpiommgpio->chip.get_multiple = gpiomm_gpio_get_multiple;
0169     gpiommgpio->chip.set = gpiomm_gpio_set;
0170     gpiommgpio->chip.set_multiple = gpiomm_gpio_set_multiple;
0171 
0172     i8255_state_init(gpiommgpio->ppi_state, GPIOMM_NUM_PPI);
0173     gpiomm_init_dio(gpiommgpio->ppi, gpiommgpio->ppi_state);
0174 
0175     err = devm_gpiochip_add_data(dev, &gpiommgpio->chip, gpiommgpio);
0176     if (err) {
0177         dev_err(dev, "GPIO registering failed (%d)\n", err);
0178         return err;
0179     }
0180 
0181     return 0;
0182 }
0183 
0184 static struct isa_driver gpiomm_driver = {
0185     .probe = gpiomm_probe,
0186     .driver = {
0187         .name = "gpio-mm"
0188     },
0189 };
0190 
0191 module_isa_driver(gpiomm_driver, num_gpiomm);
0192 
0193 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
0194 MODULE_DESCRIPTION("Diamond Systems GPIO-MM GPIO driver");
0195 MODULE_LICENSE("GPL v2");