]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
704d9a64 SR |
2 | /* |
3 | * Copyright (C) 2016 Stefan Roese <sr@denx.de> | |
704d9a64 SR |
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 | ||
704d9a64 SR |
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 | ||
b23005ce SR |
43 | if (value) |
44 | setbits_le32(®s->data_out, BIT(gpio)); | |
45 | else | |
46 | clrbits_le32(®s->data_out, BIT(gpio)); | |
704d9a64 SR |
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 | ||
a821c4af | 92 | priv->regs = (struct mvebu_gpio_regs *)devfdt_get_addr(dev); |
704d9a64 SR |
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 | }; |