]>
Commit | Line | Data |
---|---|---|
b30de3cc GL |
1 | /* |
2 | * Copyright (C) 2009 | |
3 | * Guennadi Liakhovetski, DENX Software Engineering, <lg@denx.de> | |
4 | * | |
d8e0ca85 SB |
5 | * Copyright (C) 2011 |
6 | * Stefano Babic, DENX Software Engineering, <sbabic@denx.de> | |
7 | * | |
1a459660 | 8 | * SPDX-License-Identifier: GPL-2.0+ |
b30de3cc GL |
9 | */ |
10 | #include <common.h> | |
c4ea1424 | 11 | #include <asm/arch/imx-regs.h> |
d8e0ca85 | 12 | #include <asm/gpio.h> |
c4ea1424 | 13 | #include <asm/io.h> |
e53bcd94 | 14 | #include <errno.h> |
b30de3cc | 15 | |
d8e0ca85 SB |
16 | enum mxc_gpio_direction { |
17 | MXC_GPIO_DIRECTION_IN, | |
18 | MXC_GPIO_DIRECTION_OUT, | |
19 | }; | |
20 | ||
8d28c211 | 21 | #define GPIO_TO_PORT(n) (n / 32) |
d8e0ca85 | 22 | |
b30de3cc GL |
23 | /* GPIO port description */ |
24 | static unsigned long gpio_ports[] = { | |
c4ea1424 SB |
25 | [0] = GPIO1_BASE_ADDR, |
26 | [1] = GPIO2_BASE_ADDR, | |
27 | [2] = GPIO3_BASE_ADDR, | |
e71c39de | 28 | #if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \ |
5ea6d7c8 | 29 | defined(CONFIG_MX53) || defined(CONFIG_MX6) |
c4ea1424 SB |
30 | [3] = GPIO4_BASE_ADDR, |
31 | #endif | |
5ea6d7c8 | 32 | #if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6) |
01643ec1 LHR |
33 | [4] = GPIO5_BASE_ADDR, |
34 | [5] = GPIO6_BASE_ADDR, | |
e71c39de | 35 | #endif |
5ea6d7c8 | 36 | #if defined(CONFIG_MX53) || defined(CONFIG_MX6) |
01643ec1 LHR |
37 | [6] = GPIO7_BASE_ADDR, |
38 | #endif | |
b30de3cc GL |
39 | }; |
40 | ||
d8e0ca85 SB |
41 | static int mxc_gpio_direction(unsigned int gpio, |
42 | enum mxc_gpio_direction direction) | |
b30de3cc | 43 | { |
be282554 | 44 | unsigned int port = GPIO_TO_PORT(gpio); |
c4ea1424 | 45 | struct gpio_regs *regs; |
b30de3cc GL |
46 | u32 l; |
47 | ||
48 | if (port >= ARRAY_SIZE(gpio_ports)) | |
365d6070 | 49 | return -1; |
b30de3cc GL |
50 | |
51 | gpio &= 0x1f; | |
52 | ||
c4ea1424 SB |
53 | regs = (struct gpio_regs *)gpio_ports[port]; |
54 | ||
55 | l = readl(®s->gpio_dir); | |
56 | ||
b30de3cc | 57 | switch (direction) { |
c4ea1424 | 58 | case MXC_GPIO_DIRECTION_OUT: |
b30de3cc GL |
59 | l |= 1 << gpio; |
60 | break; | |
c4ea1424 | 61 | case MXC_GPIO_DIRECTION_IN: |
b30de3cc GL |
62 | l &= ~(1 << gpio); |
63 | } | |
c4ea1424 | 64 | writel(l, ®s->gpio_dir); |
b30de3cc GL |
65 | |
66 | return 0; | |
67 | } | |
68 | ||
365d6070 | 69 | int gpio_set_value(unsigned gpio, int value) |
b30de3cc | 70 | { |
be282554 | 71 | unsigned int port = GPIO_TO_PORT(gpio); |
c4ea1424 | 72 | struct gpio_regs *regs; |
b30de3cc GL |
73 | u32 l; |
74 | ||
75 | if (port >= ARRAY_SIZE(gpio_ports)) | |
365d6070 | 76 | return -1; |
b30de3cc GL |
77 | |
78 | gpio &= 0x1f; | |
79 | ||
c4ea1424 SB |
80 | regs = (struct gpio_regs *)gpio_ports[port]; |
81 | ||
82 | l = readl(®s->gpio_dr); | |
b30de3cc GL |
83 | if (value) |
84 | l |= 1 << gpio; | |
85 | else | |
86 | l &= ~(1 << gpio); | |
c4ea1424 | 87 | writel(l, ®s->gpio_dr); |
365d6070 JH |
88 | |
89 | return 0; | |
b30de3cc | 90 | } |
7d27cd08 | 91 | |
365d6070 | 92 | int gpio_get_value(unsigned gpio) |
7d27cd08 | 93 | { |
be282554 | 94 | unsigned int port = GPIO_TO_PORT(gpio); |
c4ea1424 | 95 | struct gpio_regs *regs; |
365d6070 | 96 | u32 val; |
7d27cd08 SB |
97 | |
98 | if (port >= ARRAY_SIZE(gpio_ports)) | |
365d6070 | 99 | return -1; |
7d27cd08 SB |
100 | |
101 | gpio &= 0x1f; | |
102 | ||
c4ea1424 SB |
103 | regs = (struct gpio_regs *)gpio_ports[port]; |
104 | ||
5dafa454 | 105 | val = (readl(®s->gpio_psr) >> gpio) & 0x01; |
7d27cd08 | 106 | |
365d6070 | 107 | return val; |
7d27cd08 | 108 | } |
d8e0ca85 | 109 | |
365d6070 | 110 | int gpio_request(unsigned gpio, const char *label) |
d8e0ca85 | 111 | { |
be282554 | 112 | unsigned int port = GPIO_TO_PORT(gpio); |
d8e0ca85 | 113 | if (port >= ARRAY_SIZE(gpio_ports)) |
365d6070 | 114 | return -1; |
d8e0ca85 SB |
115 | return 0; |
116 | } | |
117 | ||
365d6070 | 118 | int gpio_free(unsigned gpio) |
d8e0ca85 | 119 | { |
365d6070 | 120 | return 0; |
d8e0ca85 SB |
121 | } |
122 | ||
365d6070 | 123 | int gpio_direction_input(unsigned gpio) |
d8e0ca85 | 124 | { |
365d6070 | 125 | return mxc_gpio_direction(gpio, MXC_GPIO_DIRECTION_IN); |
d8e0ca85 SB |
126 | } |
127 | ||
365d6070 | 128 | int gpio_direction_output(unsigned gpio, int value) |
d8e0ca85 | 129 | { |
365d6070 | 130 | int ret = mxc_gpio_direction(gpio, MXC_GPIO_DIRECTION_OUT); |
d8e0ca85 SB |
131 | |
132 | if (ret < 0) | |
133 | return ret; | |
134 | ||
d71c9c9f | 135 | return gpio_set_value(gpio, value); |
d8e0ca85 | 136 | } |