root/drivers/media/pci/solo6x10/solo6x10-gpio.c

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

DEFINITIONS

This source file includes following definitions.
  1. solo_gpio_mode
  2. solo_gpio_set
  3. solo_gpio_clear
  4. solo_gpio_config
  5. solo_gpiochip_get_direction
  6. solo_gpiochip_direction_input
  7. solo_gpiochip_direction_output
  8. solo_gpiochip_get
  9. solo_gpiochip_set
  10. solo_gpio_init
  11. solo_gpio_exit

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
   4  *
   5  * Original author:
   6  * Ben Collins <bcollins@ubuntu.com>
   7  *
   8  * Additional work by:
   9  * John Brooks <john.brooks@bluecherry.net>
  10  */
  11 
  12 #include <linux/kernel.h>
  13 #include <linux/fs.h>
  14 #include <linux/delay.h>
  15 #include <linux/uaccess.h>
  16 
  17 #include "solo6x10.h"
  18 
  19 static void solo_gpio_mode(struct solo_dev *solo_dev,
  20                            unsigned int port_mask, unsigned int mode)
  21 {
  22         int port;
  23         unsigned int ret;
  24 
  25         ret = solo_reg_read(solo_dev, SOLO_GPIO_CONFIG_0);
  26 
  27         /* To set gpio */
  28         for (port = 0; port < 16; port++) {
  29                 if (!((1 << port) & port_mask))
  30                         continue;
  31 
  32                 ret &= (~(3 << (port << 1)));
  33                 ret |= ((mode & 3) << (port << 1));
  34         }
  35 
  36         solo_reg_write(solo_dev, SOLO_GPIO_CONFIG_0, ret);
  37 
  38         /* To set extended gpio - sensor */
  39         ret = solo_reg_read(solo_dev, SOLO_GPIO_CONFIG_1);
  40 
  41         for (port = 0; port < 16; port++) {
  42                 if (!((1UL << (port + 16)) & port_mask))
  43                         continue;
  44 
  45                 if (!mode)
  46                         ret &= ~(1UL << port);
  47                 else
  48                         ret |= 1UL << port;
  49         }
  50 
  51         /* Enable GPIO[31:16] */
  52         ret |= 0xffff0000;
  53 
  54         solo_reg_write(solo_dev, SOLO_GPIO_CONFIG_1, ret);
  55 }
  56 
  57 static void solo_gpio_set(struct solo_dev *solo_dev, unsigned int value)
  58 {
  59         solo_reg_write(solo_dev, SOLO_GPIO_DATA_OUT,
  60                        solo_reg_read(solo_dev, SOLO_GPIO_DATA_OUT) | value);
  61 }
  62 
  63 static void solo_gpio_clear(struct solo_dev *solo_dev, unsigned int value)
  64 {
  65         solo_reg_write(solo_dev, SOLO_GPIO_DATA_OUT,
  66                        solo_reg_read(solo_dev, SOLO_GPIO_DATA_OUT) & ~value);
  67 }
  68 
  69 static void solo_gpio_config(struct solo_dev *solo_dev)
  70 {
  71         /* Video reset */
  72         solo_gpio_mode(solo_dev, 0x30, 1);
  73         solo_gpio_clear(solo_dev, 0x30);
  74         udelay(100);
  75         solo_gpio_set(solo_dev, 0x30);
  76         udelay(100);
  77 
  78         /* Warning: Don't touch the next line unless you're sure of what
  79          * you're doing: first four gpio [0-3] are used for video. */
  80         solo_gpio_mode(solo_dev, 0x0f, 2);
  81 
  82         /* We use bit 8-15 of SOLO_GPIO_CONFIG_0 for relay purposes */
  83         solo_gpio_mode(solo_dev, 0xff00, 1);
  84 
  85         /* Initially set relay status to 0 */
  86         solo_gpio_clear(solo_dev, 0xff00);
  87 
  88         /* Set input pins direction */
  89         solo_gpio_mode(solo_dev, 0xffff0000, 0);
  90 }
  91 
  92 #ifdef CONFIG_GPIOLIB
  93 /* Pins 0-7 are not exported, because it seems from code above they are
  94  * used for internal purposes. So offset 0 corresponds to pin 8, therefore
  95  * offsets 0-7 are relay GPIOs, 8-23 - input GPIOs.
  96  */
  97 static int solo_gpiochip_get_direction(struct gpio_chip *chip,
  98                                        unsigned int offset)
  99 {
 100         int ret, mode;
 101         struct solo_dev *solo_dev = gpiochip_get_data(chip);
 102 
 103         if (offset < 8) {
 104                 ret = solo_reg_read(solo_dev, SOLO_GPIO_CONFIG_0);
 105                 mode = 3 & (ret >> ((offset + 8) * 2));
 106         } else {
 107                 ret = solo_reg_read(solo_dev, SOLO_GPIO_CONFIG_1);
 108                 mode =  1 & (ret >> (offset - 8));
 109         }
 110 
 111         if (!mode)
 112                 return 1;
 113         else if (mode == 1)
 114                 return 0;
 115 
 116         return -1;
 117 }
 118 
 119 static int solo_gpiochip_direction_input(struct gpio_chip *chip,
 120                                          unsigned int offset)
 121 {
 122         return -1;
 123 }
 124 
 125 static int solo_gpiochip_direction_output(struct gpio_chip *chip,
 126                                           unsigned int offset, int value)
 127 {
 128         return -1;
 129 }
 130 
 131 static int solo_gpiochip_get(struct gpio_chip *chip,
 132                                                 unsigned int offset)
 133 {
 134         int ret;
 135         struct solo_dev *solo_dev = gpiochip_get_data(chip);
 136 
 137         ret = solo_reg_read(solo_dev, SOLO_GPIO_DATA_IN);
 138 
 139         return 1 & (ret >> (offset + 8));
 140 }
 141 
 142 static void solo_gpiochip_set(struct gpio_chip *chip,
 143                                                 unsigned int offset, int value)
 144 {
 145         struct solo_dev *solo_dev = gpiochip_get_data(chip);
 146 
 147         if (value)
 148                 solo_gpio_set(solo_dev, 1 << (offset + 8));
 149         else
 150                 solo_gpio_clear(solo_dev, 1 << (offset + 8));
 151 }
 152 #endif
 153 
 154 int solo_gpio_init(struct solo_dev *solo_dev)
 155 {
 156 #ifdef CONFIG_GPIOLIB
 157         int ret;
 158 #endif
 159 
 160         solo_gpio_config(solo_dev);
 161 #ifdef CONFIG_GPIOLIB
 162         solo_dev->gpio_dev.label = SOLO6X10_NAME"_gpio";
 163         solo_dev->gpio_dev.parent = &solo_dev->pdev->dev;
 164         solo_dev->gpio_dev.owner = THIS_MODULE;
 165         solo_dev->gpio_dev.base = -1;
 166         solo_dev->gpio_dev.ngpio = 24;
 167         solo_dev->gpio_dev.can_sleep = 0;
 168 
 169         solo_dev->gpio_dev.get_direction = solo_gpiochip_get_direction;
 170         solo_dev->gpio_dev.direction_input = solo_gpiochip_direction_input;
 171         solo_dev->gpio_dev.direction_output = solo_gpiochip_direction_output;
 172         solo_dev->gpio_dev.get = solo_gpiochip_get;
 173         solo_dev->gpio_dev.set = solo_gpiochip_set;
 174 
 175         ret = gpiochip_add_data(&solo_dev->gpio_dev, solo_dev);
 176 
 177         if (ret) {
 178                 solo_dev->gpio_dev.label = NULL;
 179                 return -1;
 180         }
 181 #endif
 182         return 0;
 183 }
 184 
 185 void solo_gpio_exit(struct solo_dev *solo_dev)
 186 {
 187 #ifdef CONFIG_GPIOLIB
 188         if (solo_dev->gpio_dev.label) {
 189                 gpiochip_remove(&solo_dev->gpio_dev);
 190                 solo_dev->gpio_dev.label = NULL;
 191         }
 192 #endif
 193         solo_gpio_clear(solo_dev, 0x30);
 194         solo_gpio_config(solo_dev);
 195 }

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