]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
704d9a64 SR |
2 | /* |
3 | * Copyright (C) 2016 Stefan Roese <[email protected]> | |
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> | |
cd93d625 | 11 | #include <linux/bitops.h> |
704d9a64 | 12 | |
704d9a64 SR |
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 | ||
b23005ce SR |
44 | if (value) |
45 | setbits_le32(®s->data_out, BIT(gpio)); | |
46 | else | |
47 | clrbits_le32(®s->data_out, BIT(gpio)); | |
704d9a64 SR |
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 | ||
8613c8d8 | 93 | priv->regs = dev_read_addr_ptr(dev); |
704d9a64 | 94 | uc_priv->gpio_count = MVEBU_GPIOS_PER_BANK; |
fb0ea6a7 | 95 | priv->name[0] = 'A' + dev_seq(dev); |
704d9a64 SR |
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, | |
41575d8e | 120 | .priv_auto = sizeof(struct mvebu_gpio_priv), |
704d9a64 | 121 | }; |