root/drivers/gpio/gpio-janz-ttl.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ttl_get_value
  2. ttl_set_value
  3. ttl_write_reg
  4. ttl_setup_device
  5. ttl_probe

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Janz MODULbus VMOD-TTL GPIO Driver
   4  *
   5  * Copyright (c) 2010 Ira W. Snyder <iws@ovro.caltech.edu>
   6  */
   7 
   8 #include <linux/kernel.h>
   9 #include <linux/module.h>
  10 #include <linux/init.h>
  11 #include <linux/interrupt.h>
  12 #include <linux/delay.h>
  13 #include <linux/platform_device.h>
  14 #include <linux/io.h>
  15 #include <linux/gpio/driver.h>
  16 #include <linux/slab.h>
  17 #include <linux/bitops.h>
  18 
  19 #include <linux/mfd/janz.h>
  20 
  21 #define DRV_NAME "janz-ttl"
  22 
  23 #define PORTA_DIRECTION         0x23
  24 #define PORTB_DIRECTION         0x2B
  25 #define PORTC_DIRECTION         0x06
  26 #define PORTA_IOCTL             0x24
  27 #define PORTB_IOCTL             0x2C
  28 #define PORTC_IOCTL             0x07
  29 
  30 #define MASTER_INT_CTL          0x00
  31 #define MASTER_CONF_CTL         0x01
  32 
  33 #define CONF_PAE                BIT(2)
  34 #define CONF_PBE                BIT(7)
  35 #define CONF_PCE                BIT(4)
  36 
  37 struct ttl_control_regs {
  38         __be16 portc;
  39         __be16 portb;
  40         __be16 porta;
  41         __be16 control;
  42 };
  43 
  44 struct ttl_module {
  45         struct gpio_chip gpio;
  46 
  47         /* base address of registers */
  48         struct ttl_control_regs __iomem *regs;
  49 
  50         u8 portc_shadow;
  51         u8 portb_shadow;
  52         u8 porta_shadow;
  53 
  54         spinlock_t lock;
  55 };
  56 
  57 static int ttl_get_value(struct gpio_chip *gpio, unsigned offset)
  58 {
  59         struct ttl_module *mod = dev_get_drvdata(gpio->parent);
  60         u8 *shadow;
  61         int ret;
  62 
  63         if (offset < 8) {
  64                 shadow = &mod->porta_shadow;
  65         } else if (offset < 16) {
  66                 shadow = &mod->portb_shadow;
  67                 offset -= 8;
  68         } else {
  69                 shadow = &mod->portc_shadow;
  70                 offset -= 16;
  71         }
  72 
  73         spin_lock(&mod->lock);
  74         ret = *shadow & BIT(offset);
  75         spin_unlock(&mod->lock);
  76         return !!ret;
  77 }
  78 
  79 static void ttl_set_value(struct gpio_chip *gpio, unsigned offset, int value)
  80 {
  81         struct ttl_module *mod = dev_get_drvdata(gpio->parent);
  82         void __iomem *port;
  83         u8 *shadow;
  84 
  85         if (offset < 8) {
  86                 port = &mod->regs->porta;
  87                 shadow = &mod->porta_shadow;
  88         } else if (offset < 16) {
  89                 port = &mod->regs->portb;
  90                 shadow = &mod->portb_shadow;
  91                 offset -= 8;
  92         } else {
  93                 port = &mod->regs->portc;
  94                 shadow = &mod->portc_shadow;
  95                 offset -= 16;
  96         }
  97 
  98         spin_lock(&mod->lock);
  99         if (value)
 100                 *shadow |= BIT(offset);
 101         else
 102                 *shadow &= ~BIT(offset);
 103 
 104         iowrite16be(*shadow, port);
 105         spin_unlock(&mod->lock);
 106 }
 107 
 108 static void ttl_write_reg(struct ttl_module *mod, u8 reg, u16 val)
 109 {
 110         iowrite16be(reg, &mod->regs->control);
 111         iowrite16be(val, &mod->regs->control);
 112 }
 113 
 114 static void ttl_setup_device(struct ttl_module *mod)
 115 {
 116         /* reset the device to a known state */
 117         iowrite16be(0x0000, &mod->regs->control);
 118         iowrite16be(0x0001, &mod->regs->control);
 119         iowrite16be(0x0000, &mod->regs->control);
 120 
 121         /* put all ports in open-drain mode */
 122         ttl_write_reg(mod, PORTA_IOCTL, 0x00ff);
 123         ttl_write_reg(mod, PORTB_IOCTL, 0x00ff);
 124         ttl_write_reg(mod, PORTC_IOCTL, 0x000f);
 125 
 126         /* set all ports as outputs */
 127         ttl_write_reg(mod, PORTA_DIRECTION, 0x0000);
 128         ttl_write_reg(mod, PORTB_DIRECTION, 0x0000);
 129         ttl_write_reg(mod, PORTC_DIRECTION, 0x0000);
 130 
 131         /* set all ports to drive zeroes */
 132         iowrite16be(0x0000, &mod->regs->porta);
 133         iowrite16be(0x0000, &mod->regs->portb);
 134         iowrite16be(0x0000, &mod->regs->portc);
 135 
 136         /* enable all ports */
 137         ttl_write_reg(mod, MASTER_CONF_CTL, CONF_PAE | CONF_PBE | CONF_PCE);
 138 }
 139 
 140 static int ttl_probe(struct platform_device *pdev)
 141 {
 142         struct janz_platform_data *pdata;
 143         struct ttl_module *mod;
 144         struct gpio_chip *gpio;
 145         int ret;
 146 
 147         pdata = dev_get_platdata(&pdev->dev);
 148         if (!pdata) {
 149                 dev_err(&pdev->dev, "no platform data\n");
 150                 return -ENXIO;
 151         }
 152 
 153         mod = devm_kzalloc(&pdev->dev, sizeof(*mod), GFP_KERNEL);
 154         if (!mod)
 155                 return -ENOMEM;
 156 
 157         platform_set_drvdata(pdev, mod);
 158         spin_lock_init(&mod->lock);
 159 
 160         /* get access to the MODULbus registers for this module */
 161         mod->regs = devm_platform_ioremap_resource(pdev, 0);
 162         if (IS_ERR(mod->regs))
 163                 return PTR_ERR(mod->regs);
 164 
 165         ttl_setup_device(mod);
 166 
 167         /* Initialize the GPIO data structures */
 168         gpio = &mod->gpio;
 169         gpio->parent = &pdev->dev;
 170         gpio->label = pdev->name;
 171         gpio->get = ttl_get_value;
 172         gpio->set = ttl_set_value;
 173         gpio->owner = THIS_MODULE;
 174 
 175         /* request dynamic allocation */
 176         gpio->base = -1;
 177         gpio->ngpio = 20;
 178 
 179         ret = devm_gpiochip_add_data(&pdev->dev, gpio, NULL);
 180         if (ret) {
 181                 dev_err(&pdev->dev, "unable to add GPIO chip\n");
 182                 return ret;
 183         }
 184 
 185         return 0;
 186 }
 187 
 188 static struct platform_driver ttl_driver = {
 189         .driver         = {
 190                 .name   = DRV_NAME,
 191         },
 192         .probe          = ttl_probe,
 193 };
 194 
 195 module_platform_driver(ttl_driver);
 196 
 197 MODULE_AUTHOR("Ira W. Snyder <iws@ovro.caltech.edu>");
 198 MODULE_DESCRIPTION("Janz MODULbus VMOD-TTL Driver");
 199 MODULE_LICENSE("GPL");
 200 MODULE_ALIAS("platform:janz-ttl");

/* [<][>][^][v][top][bottom][index][help] */