root/drivers/gpio/gpio-loongson.c

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

DEFINITIONS

This source file includes following definitions.
  1. loongson_gpio_get_value
  2. loongson_gpio_set_value
  3. loongson_gpio_direction_input
  4. loongson_gpio_direction_output
  5. loongson_gpio_probe
  6. loongson_gpio_setup

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  *  Loongson-2F/3A/3B GPIO Support
   4  *
   5  *  Copyright (c) 2008 Richard Liu,  STMicroelectronics  <richard.liu@st.com>
   6  *  Copyright (c) 2008-2010 Arnaud Patard <apatard@mandriva.com>
   7  *  Copyright (c) 2013 Hongbing Hu <huhb@lemote.com>
   8  *  Copyright (c) 2014 Huacai Chen <chenhc@lemote.com>
   9  */
  10 
  11 #include <linux/kernel.h>
  12 #include <linux/init.h>
  13 #include <linux/module.h>
  14 #include <linux/spinlock.h>
  15 #include <linux/err.h>
  16 #include <linux/gpio/driver.h>
  17 #include <linux/platform_device.h>
  18 #include <linux/bitops.h>
  19 #include <asm/types.h>
  20 #include <loongson.h>
  21 
  22 #define STLS2F_N_GPIO           4
  23 #define STLS3A_N_GPIO           16
  24 
  25 #ifdef CONFIG_CPU_LOONGSON3
  26 #define LOONGSON_N_GPIO STLS3A_N_GPIO
  27 #else
  28 #define LOONGSON_N_GPIO STLS2F_N_GPIO
  29 #endif
  30 
  31 /*
  32  * Offset into the register where we read lines, we write them from offset 0.
  33  * This offset is the only thing that stand between us and using
  34  * GPIO_GENERIC.
  35  */
  36 #define LOONGSON_GPIO_IN_OFFSET 16
  37 
  38 static DEFINE_SPINLOCK(gpio_lock);
  39 
  40 static int loongson_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
  41 {
  42         u32 val;
  43 
  44         spin_lock(&gpio_lock);
  45         val = LOONGSON_GPIODATA;
  46         spin_unlock(&gpio_lock);
  47 
  48         return !!(val & BIT(gpio + LOONGSON_GPIO_IN_OFFSET));
  49 }
  50 
  51 static void loongson_gpio_set_value(struct gpio_chip *chip,
  52                 unsigned gpio, int value)
  53 {
  54         u32 val;
  55 
  56         spin_lock(&gpio_lock);
  57         val = LOONGSON_GPIODATA;
  58         if (value)
  59                 val |= BIT(gpio);
  60         else
  61                 val &= ~BIT(gpio);
  62         LOONGSON_GPIODATA = val;
  63         spin_unlock(&gpio_lock);
  64 }
  65 
  66 static int loongson_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
  67 {
  68         u32 temp;
  69 
  70         spin_lock(&gpio_lock);
  71         temp = LOONGSON_GPIOIE;
  72         temp |= BIT(gpio);
  73         LOONGSON_GPIOIE = temp;
  74         spin_unlock(&gpio_lock);
  75 
  76         return 0;
  77 }
  78 
  79 static int loongson_gpio_direction_output(struct gpio_chip *chip,
  80                 unsigned gpio, int level)
  81 {
  82         u32 temp;
  83 
  84         loongson_gpio_set_value(chip, gpio, level);
  85         spin_lock(&gpio_lock);
  86         temp = LOONGSON_GPIOIE;
  87         temp &= ~BIT(gpio);
  88         LOONGSON_GPIOIE = temp;
  89         spin_unlock(&gpio_lock);
  90 
  91         return 0;
  92 }
  93 
  94 static int loongson_gpio_probe(struct platform_device *pdev)
  95 {
  96         struct gpio_chip *gc;
  97         struct device *dev = &pdev->dev;
  98 
  99         gc = devm_kzalloc(dev, sizeof(*gc), GFP_KERNEL);
 100         if (!gc)
 101                 return -ENOMEM;
 102 
 103         gc->label = "loongson-gpio-chip";
 104         gc->base = 0;
 105         gc->ngpio = LOONGSON_N_GPIO;
 106         gc->get = loongson_gpio_get_value;
 107         gc->set = loongson_gpio_set_value;
 108         gc->direction_input = loongson_gpio_direction_input;
 109         gc->direction_output = loongson_gpio_direction_output;
 110 
 111         return gpiochip_add_data(gc, NULL);
 112 }
 113 
 114 static struct platform_driver loongson_gpio_driver = {
 115         .driver = {
 116                 .name = "loongson-gpio",
 117         },
 118         .probe = loongson_gpio_probe,
 119 };
 120 
 121 static int __init loongson_gpio_setup(void)
 122 {
 123         struct platform_device *pdev;
 124         int ret;
 125 
 126         ret = platform_driver_register(&loongson_gpio_driver);
 127         if (ret) {
 128                 pr_err("error registering loongson GPIO driver\n");
 129                 return ret;
 130         }
 131 
 132         pdev = platform_device_register_simple("loongson-gpio", -1, NULL, 0);
 133         return PTR_ERR_OR_ZERO(pdev);
 134 }
 135 postcore_initcall(loongson_gpio_setup);

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