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