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