uboot/drivers/pinctrl/pinctrl-apple.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2021 Mark Kettenis <kettenis@openbsd.org>
   4 */
   5
   6#include <common.h>
   7#include <dm.h>
   8#include <dm/device-internal.h>
   9#include <dm/pinctrl.h>
  10#include <dt-bindings/pinctrl/apple.h>
  11#include <asm/io.h>
  12#include <asm-generic/gpio.h>
  13#include <linux/bitfield.h>
  14
  15struct apple_pinctrl_priv {
  16        void *base;
  17        int pin_count;
  18};
  19
  20#define REG_GPIO(x)     (4 * (x))
  21#define  REG_GPIO_DATA          BIT(0)
  22#define  REG_GPIO_MODE          GENMASK(3, 1)
  23#define  REG_GPIO_OUT           1
  24#define  REG_GPIO_PERIPH        GENMASK(6, 5)
  25#define  REG_GPIO_INPUT_ENABLE  BIT(9)
  26
  27static void apple_pinctrl_config_pin(struct apple_pinctrl_priv *priv,
  28                                     unsigned pin, u32 clr, u32 set)
  29{
  30        unsigned reg = REG_GPIO(pin);
  31        u32 old, new;
  32
  33        old = readl(priv->base + REG_GPIO(pin));
  34        new = (old & ~clr) | set;
  35        writel(new, priv->base + reg);
  36}
  37
  38static int apple_gpio_get_value(struct udevice *dev, unsigned offset)
  39{
  40        struct apple_pinctrl_priv *priv = dev_get_priv(dev->parent);
  41
  42        return !!(readl(priv->base + REG_GPIO(offset)) & REG_GPIO_DATA);
  43}
  44
  45static int apple_gpio_set_value(struct udevice *dev, unsigned offset,
  46                                int value)
  47{
  48        struct apple_pinctrl_priv *priv = dev_get_priv(dev->parent);
  49
  50        apple_pinctrl_config_pin(priv, offset, REG_GPIO_DATA,
  51                                 value ? REG_GPIO_DATA : 0);
  52        return 0;
  53}
  54
  55static int apple_gpio_get_direction(struct udevice *dev, unsigned offset)
  56{
  57        struct apple_pinctrl_priv *priv = dev_get_priv(dev->parent);
  58        u32 reg = readl(priv->base + REG_GPIO(offset));
  59
  60        if (FIELD_GET(REG_GPIO_MODE, reg) == REG_GPIO_OUT)
  61                return GPIOF_OUTPUT;
  62        else
  63                return GPIOF_INPUT;
  64}
  65
  66static int apple_gpio_direction_input(struct udevice *dev, unsigned offset)
  67{
  68        struct apple_pinctrl_priv *priv = dev_get_priv(dev->parent);
  69
  70        apple_pinctrl_config_pin(priv, offset,
  71                                 REG_GPIO_PERIPH | REG_GPIO_MODE,
  72                                 REG_GPIO_INPUT_ENABLE);
  73        return 0;
  74}
  75
  76static int apple_gpio_direction_output(struct udevice *dev, unsigned offset,
  77                                       int value)
  78{
  79        struct apple_pinctrl_priv *priv = dev_get_priv(dev->parent);
  80        u32 set = (value ? REG_GPIO_DATA : 0);
  81
  82        apple_pinctrl_config_pin(priv, offset, REG_GPIO_DATA |
  83                                 REG_GPIO_PERIPH | REG_GPIO_MODE,
  84                                 set | FIELD_PREP(REG_GPIO_MODE, REG_GPIO_OUT));
  85        return 0;
  86}
  87
  88static int apple_gpio_probe(struct udevice *dev)
  89{
  90        struct apple_pinctrl_priv *priv = dev_get_priv(dev->parent);
  91        struct gpio_dev_priv *uc_priv;
  92
  93        uc_priv = dev_get_uclass_priv(dev);
  94        uc_priv->bank_name = "gpio";
  95        uc_priv->gpio_count = priv->pin_count;
  96
  97        return 0;
  98}
  99
 100static struct dm_gpio_ops apple_gpio_ops = {
 101        .get_value = apple_gpio_get_value,
 102        .set_value = apple_gpio_set_value,
 103        .get_function = apple_gpio_get_direction,
 104        .direction_input = apple_gpio_direction_input,
 105        .direction_output = apple_gpio_direction_output,
 106};
 107
 108static struct driver apple_gpio_driver = {
 109        .name = "apple_gpio",
 110        .id = UCLASS_GPIO,
 111        .probe = apple_gpio_probe,
 112        .ops = &apple_gpio_ops,
 113};
 114
 115static int apple_pinctrl_get_pins_count(struct udevice *dev)
 116{
 117        struct apple_pinctrl_priv *priv = dev_get_priv(dev);
 118
 119        return priv->pin_count;
 120}
 121
 122static const char *apple_pinctrl_get_pin_name(struct udevice *dev,
 123                                              unsigned selector)
 124{
 125        static char pin_name[PINNAME_SIZE];
 126
 127        snprintf(pin_name, PINNAME_SIZE, "pin%d", selector);
 128        return pin_name;
 129}
 130
 131static int apple_pinctrl_get_pin_muxing(struct udevice *dev, unsigned selector,
 132                                        char *buf, int size)
 133{
 134        struct apple_pinctrl_priv *priv = dev_get_priv(dev);
 135
 136        if (readl(priv->base + REG_GPIO(selector)) & REG_GPIO_PERIPH)
 137                strncpy(buf, "periph", size);
 138        else
 139                strncpy(buf, "gpio", size);
 140        return 0;
 141}
 142
 143static int apple_pinctrl_pinmux_set(struct udevice *dev, unsigned pin_selector,
 144                                    unsigned func_selector)
 145{
 146        struct apple_pinctrl_priv *priv = dev_get_priv(dev);
 147
 148        apple_pinctrl_config_pin(priv, pin_selector,
 149                                 REG_GPIO_DATA | REG_GPIO_MODE,
 150                                 FIELD_PREP(REG_GPIO_PERIPH, func_selector) |
 151                                 REG_GPIO_INPUT_ENABLE);
 152        return 0;
 153}
 154
 155static int apple_pinctrl_pinmux_property_set(struct udevice *dev,
 156                                             u32 pinmux_group)
 157{
 158        unsigned pin_selector = APPLE_PIN(pinmux_group);
 159        unsigned func_selector = APPLE_FUNC(pinmux_group);
 160        int ret;
 161
 162        ret = apple_pinctrl_pinmux_set(dev, pin_selector, func_selector);
 163        return ret ? ret : pin_selector;
 164}
 165
 166static int apple_pinctrl_probe(struct udevice *dev)
 167{
 168        struct apple_pinctrl_priv *priv = dev_get_priv(dev);
 169        struct ofnode_phandle_args args;
 170        struct udevice *child;
 171
 172        priv->base = dev_read_addr_ptr(dev);
 173        if (!priv->base)
 174                return -EINVAL;
 175
 176        if (!dev_read_phandle_with_args(dev, "gpio-ranges",
 177                                        NULL, 3, 0, &args))
 178                priv->pin_count = args.args[2];
 179
 180        device_bind(dev, &apple_gpio_driver, "apple_gpio", NULL,
 181                    dev_ofnode(dev), &child);
 182
 183        return 0;
 184}
 185
 186static struct pinctrl_ops apple_pinctrl_ops = {
 187        .set_state = pinctrl_generic_set_state,
 188        .get_pins_count = apple_pinctrl_get_pins_count,
 189        .get_pin_name = apple_pinctrl_get_pin_name,
 190        .pinmux_set = apple_pinctrl_pinmux_set,
 191        .pinmux_property_set = apple_pinctrl_pinmux_property_set,
 192        .get_pin_muxing = apple_pinctrl_get_pin_muxing,
 193};
 194
 195static const struct udevice_id apple_pinctrl_ids[] = {
 196        { .compatible = "apple,pinctrl" },
 197        { /* sentinel */ }
 198};
 199
 200U_BOOT_DRIVER(pinctrl_apple) = {
 201        .name = "apple_pinctrl",
 202        .id = UCLASS_PINCTRL,
 203        .of_match = apple_pinctrl_ids,
 204        .priv_auto = sizeof(struct apple_pinctrl_priv),
 205        .ops = &apple_pinctrl_ops,
 206        .probe = apple_pinctrl_probe,
 207};
 208