1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) 2016 Stefan Roese <sr@denx.de> 4 */ 5 6 #include <common.h> 7 #include <dm.h> 8 #include <asm/gpio.h> 9 #include <asm/io.h> 10 #include <errno.h> 11 12 #define MVEBU_GPIOS_PER_BANK 32 13 14 struct mvebu_gpio_regs { 15 u32 data_out; 16 u32 io_conf; 17 u32 blink_en; 18 u32 in_pol; 19 u32 data_in; 20 }; 21 22 struct mvebu_gpio_priv { 23 struct mvebu_gpio_regs *regs; 24 char name[2]; 25 }; 26 27 static int mvebu_gpio_direction_input(struct udevice *dev, unsigned int gpio) 28 { 29 struct mvebu_gpio_priv *priv = dev_get_priv(dev); 30 struct mvebu_gpio_regs *regs = priv->regs; 31 32 setbits_le32(®s->io_conf, BIT(gpio)); 33 34 return 0; 35 } 36 37 static int mvebu_gpio_direction_output(struct udevice *dev, unsigned gpio, 38 int value) 39 { 40 struct mvebu_gpio_priv *priv = dev_get_priv(dev); 41 struct mvebu_gpio_regs *regs = priv->regs; 42 43 if (value) 44 setbits_le32(®s->data_out, BIT(gpio)); 45 else 46 clrbits_le32(®s->data_out, BIT(gpio)); 47 clrbits_le32(®s->io_conf, BIT(gpio)); 48 49 return 0; 50 } 51 52 static int mvebu_gpio_get_function(struct udevice *dev, unsigned gpio) 53 { 54 struct mvebu_gpio_priv *priv = dev_get_priv(dev); 55 struct mvebu_gpio_regs *regs = priv->regs; 56 u32 val; 57 58 val = readl(®s->io_conf) & BIT(gpio); 59 if (val) 60 return GPIOF_INPUT; 61 else 62 return GPIOF_OUTPUT; 63 } 64 65 static int mvebu_gpio_set_value(struct udevice *dev, unsigned gpio, 66 int value) 67 { 68 struct mvebu_gpio_priv *priv = dev_get_priv(dev); 69 struct mvebu_gpio_regs *regs = priv->regs; 70 71 if (value) 72 setbits_le32(®s->data_out, BIT(gpio)); 73 else 74 clrbits_le32(®s->data_out, BIT(gpio)); 75 76 return 0; 77 } 78 79 static int mvebu_gpio_get_value(struct udevice *dev, unsigned gpio) 80 { 81 struct mvebu_gpio_priv *priv = dev_get_priv(dev); 82 struct mvebu_gpio_regs *regs = priv->regs; 83 84 return !!(readl(®s->data_in) & BIT(gpio)); 85 } 86 87 static int mvebu_gpio_probe(struct udevice *dev) 88 { 89 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 90 struct mvebu_gpio_priv *priv = dev_get_priv(dev); 91 92 priv->regs = (struct mvebu_gpio_regs *)devfdt_get_addr(dev); 93 uc_priv->gpio_count = MVEBU_GPIOS_PER_BANK; 94 priv->name[0] = 'A' + dev->req_seq; 95 uc_priv->bank_name = priv->name; 96 97 return 0; 98 } 99 100 static const struct dm_gpio_ops mvebu_gpio_ops = { 101 .direction_input = mvebu_gpio_direction_input, 102 .direction_output = mvebu_gpio_direction_output, 103 .get_function = mvebu_gpio_get_function, 104 .get_value = mvebu_gpio_get_value, 105 .set_value = mvebu_gpio_set_value, 106 }; 107 108 static const struct udevice_id mvebu_gpio_ids[] = { 109 { .compatible = "marvell,orion-gpio" }, 110 { } 111 }; 112 113 U_BOOT_DRIVER(gpio_mvebu) = { 114 .name = "gpio_mvebu", 115 .id = UCLASS_GPIO, 116 .of_match = mvebu_gpio_ids, 117 .ops = &mvebu_gpio_ops, 118 .probe = mvebu_gpio_probe, 119 .priv_auto_alloc_size = sizeof(struct mvebu_gpio_priv), 120 }; 121