uboot/drivers/gpio/msm_gpio.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Qualcomm GPIO driver
   4 *
   5 * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
   6 */
   7
   8#include <common.h>
   9#include <dm.h>
  10#include <errno.h>
  11#include <asm/global_data.h>
  12#include <asm/gpio.h>
  13#include <asm/io.h>
  14
  15DECLARE_GLOBAL_DATA_PTR;
  16
  17/* Register offsets */
  18#define GPIO_CONFIG_OFF(no)         ((no) * 0x1000)
  19#define GPIO_IN_OUT_OFF(no)         ((no) * 0x1000 + 0x4)
  20
  21/* OE */
  22#define GPIO_OE_DISABLE  (0x0 << 9)
  23#define GPIO_OE_ENABLE   (0x1 << 9)
  24#define GPIO_OE_MASK     (0x1 << 9)
  25
  26/* GPIO_IN_OUT register shifts. */
  27#define GPIO_IN          0
  28#define GPIO_OUT         1
  29
  30struct msm_gpio_bank {
  31        phys_addr_t base;
  32};
  33
  34static int msm_gpio_direction_input(struct udevice *dev, unsigned int gpio)
  35{
  36        struct msm_gpio_bank *priv = dev_get_priv(dev);
  37        phys_addr_t reg = priv->base + GPIO_CONFIG_OFF(gpio);
  38
  39        /* Disable OE bit */
  40        clrsetbits_le32(reg, GPIO_OE_MASK, GPIO_OE_DISABLE);
  41
  42        return 0;
  43}
  44
  45static int msm_gpio_set_value(struct udevice *dev, unsigned gpio, int value)
  46{
  47        struct msm_gpio_bank *priv = dev_get_priv(dev);
  48
  49        value = !!value;
  50        /* set value */
  51        writel(value << GPIO_OUT, priv->base + GPIO_IN_OUT_OFF(gpio));
  52
  53        return 0;
  54}
  55
  56static int msm_gpio_direction_output(struct udevice *dev, unsigned gpio,
  57                                     int value)
  58{
  59        struct msm_gpio_bank *priv = dev_get_priv(dev);
  60        phys_addr_t reg = priv->base + GPIO_CONFIG_OFF(gpio);
  61
  62        value = !!value;
  63        /* set value */
  64        writel(value << GPIO_OUT, priv->base + GPIO_IN_OUT_OFF(gpio));
  65        /* switch direction */
  66        clrsetbits_le32(reg, GPIO_OE_MASK, GPIO_OE_ENABLE);
  67
  68        return 0;
  69}
  70
  71static int msm_gpio_get_value(struct udevice *dev, unsigned gpio)
  72{
  73        struct msm_gpio_bank *priv = dev_get_priv(dev);
  74
  75        return !!(readl(priv->base + GPIO_IN_OUT_OFF(gpio)) >> GPIO_IN);
  76}
  77
  78static int msm_gpio_get_function(struct udevice *dev, unsigned offset)
  79{
  80        struct msm_gpio_bank *priv = dev_get_priv(dev);
  81
  82        if (readl(priv->base + GPIO_CONFIG_OFF(offset)) & GPIO_OE_ENABLE)
  83                return GPIOF_OUTPUT;
  84
  85        return GPIOF_INPUT;
  86}
  87
  88static const struct dm_gpio_ops gpio_msm_ops = {
  89        .direction_input        = msm_gpio_direction_input,
  90        .direction_output       = msm_gpio_direction_output,
  91        .get_value              = msm_gpio_get_value,
  92        .set_value              = msm_gpio_set_value,
  93        .get_function           = msm_gpio_get_function,
  94};
  95
  96static int msm_gpio_probe(struct udevice *dev)
  97{
  98        struct msm_gpio_bank *priv = dev_get_priv(dev);
  99
 100        priv->base = dev_read_addr(dev);
 101
 102        return priv->base == FDT_ADDR_T_NONE ? -EINVAL : 0;
 103}
 104
 105static int msm_gpio_of_to_plat(struct udevice *dev)
 106{
 107        struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
 108
 109        uc_priv->gpio_count = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
 110                                             "gpio-count", 0);
 111        uc_priv->bank_name = fdt_getprop(gd->fdt_blob, dev_of_offset(dev),
 112                                         "gpio-bank-name", NULL);
 113        if (uc_priv->bank_name == NULL)
 114                uc_priv->bank_name = "soc";
 115
 116        return 0;
 117}
 118
 119static const struct udevice_id msm_gpio_ids[] = {
 120        { .compatible = "qcom,msm8916-pinctrl" },
 121        { .compatible = "qcom,apq8016-pinctrl" },
 122        { .compatible = "qcom,ipq4019-pinctrl" },
 123        { .compatible = "qcom,sdm845-pinctrl" },
 124        { }
 125};
 126
 127U_BOOT_DRIVER(gpio_msm) = {
 128        .name   = "gpio_msm",
 129        .id     = UCLASS_GPIO,
 130        .of_match = msm_gpio_ids,
 131        .of_to_plat = msm_gpio_of_to_plat,
 132        .probe  = msm_gpio_probe,
 133        .ops    = &gpio_msm_ops,
 134        .priv_auto      = sizeof(struct msm_gpio_bank),
 135};
 136