1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
/*
* Freescale i.MX28 GPIO control code
*
* Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
* on behalf of DENX Software Engineering GmbH
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
#include <netdev.h>
#include <asm/errno.h>
#include <asm/io.h>
#include <asm/arch/iomux.h>
#include <asm/arch/imx-regs.h>
#if defined(CONFIG_MX23)
#define PINCTRL_BANKS 3
#define PINCTRL_DOUT(n) (0x0500 + ((n) * 0x10))
#define PINCTRL_DIN(n) (0x0600 + ((n) * 0x10))
#define PINCTRL_DOE(n) (0x0700 + ((n) * 0x10))
#define PINCTRL_PIN2IRQ(n) (0x0800 + ((n) * 0x10))
#define PINCTRL_IRQEN(n) (0x0900 + ((n) * 0x10))
#define PINCTRL_IRQSTAT(n) (0x0c00 + ((n) * 0x10))
#elif defined(CONFIG_MX28)
#define PINCTRL_BANKS 5
#define PINCTRL_DOUT(n) (0x0700 + ((n) * 0x10))
#define PINCTRL_DIN(n) (0x0900 + ((n) * 0x10))
#define PINCTRL_DOE(n) (0x0b00 + ((n) * 0x10))
#define PINCTRL_PIN2IRQ(n) (0x1000 + ((n) * 0x10))
#define PINCTRL_IRQEN(n) (0x1100 + ((n) * 0x10))
#define PINCTRL_IRQSTAT(n) (0x1400 + ((n) * 0x10))
#else
#error "Please select CONFIG_MX23 or CONFIG_MX28"
#endif
#define GPIO_INT_FALL_EDGE 0x0
#define GPIO_INT_LOW_LEV 0x1
#define GPIO_INT_RISE_EDGE 0x2
#define GPIO_INT_HIGH_LEV 0x3
#define GPIO_INT_LEV_MASK (1 << 0)
#define GPIO_INT_POL_MASK (1 << 1)
void mxs_gpio_init(void)
{
int i;
for (i = 0; i < PINCTRL_BANKS; i++) {
writel(0, MXS_PINCTRL_BASE + PINCTRL_PIN2IRQ(i));
writel(0, MXS_PINCTRL_BASE + PINCTRL_IRQEN(i));
/* Use SCT address here to clear the IRQSTAT bits */
writel(0xffffffff, MXS_PINCTRL_BASE + PINCTRL_IRQSTAT(i) + 8);
}
}
int gpio_get_value(int gp)
{
uint32_t bank = PAD_BANK(gp);
uint32_t offset = PINCTRL_DIN(bank);
struct mx28_register *reg =
(struct mx28_register *)(MXS_PINCTRL_BASE + offset);
return (readl(®->reg) >> PAD_PIN(gp)) & 1;
}
void gpio_set_value(int gp, int value)
{
uint32_t bank = PAD_BANK(gp);
uint32_t offset = PINCTRL_DOUT(bank);
struct mx28_register *reg =
(struct mx28_register *)(MXS_PINCTRL_BASE + offset);
if (value)
writel(1 << PAD_PIN(gp), ®->reg_set);
else
writel(1 << PAD_PIN(gp), ®->reg_clr);
}
int gpio_direction_input(int gp)
{
uint32_t bank = PAD_BANK(gp);
uint32_t offset = PINCTRL_DOE(bank);
struct mx28_register *reg =
(struct mx28_register *)(MXS_PINCTRL_BASE + offset);
writel(1 << PAD_PIN(gp), ®->reg_clr);
return 0;
}
int gpio_direction_output(int gp, int value)
{
uint32_t bank = PAD_BANK(gp);
uint32_t offset = PINCTRL_DOE(bank);
struct mx28_register *reg =
(struct mx28_register *)(MXS_PINCTRL_BASE + offset);
writel(1 << PAD_PIN(gp), ®->reg_set);
gpio_set_value(gp, value);
return 0;
}
int gpio_request(int gp, const char *label)
{
if (PAD_BANK(gp) > PINCTRL_BANKS)
return -EINVAL;
return 0;
}
void gpio_free(int gp)
{
}
void gpio_toggle_value(int gp)
{
gpio_set_value(gp, !gpio_get_value(gp));
}
|