xref: /openbmc/u-boot/drivers/gpio/mxs_gpio.c (revision 70b95ded03bc13715e595c3a87ec323d9d1dfc62)
1  /*
2   * Freescale i.MX28 GPIO control code
3   *
4   * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
5   * on behalf of DENX Software Engineering GmbH
6   *
7   * SPDX-License-Identifier:	GPL-2.0+
8   */
9  
10  #include <common.h>
11  #include <linux/errno.h>
12  #include <asm/io.h>
13  #include <asm/arch/iomux.h>
14  #include <asm/arch/imx-regs.h>
15  
16  #if	defined(CONFIG_MX23)
17  #define	PINCTRL_BANKS		3
18  #define	PINCTRL_DOUT(n)		(0x0500 + ((n) * 0x10))
19  #define	PINCTRL_DIN(n)		(0x0600 + ((n) * 0x10))
20  #define	PINCTRL_DOE(n)		(0x0700 + ((n) * 0x10))
21  #define	PINCTRL_PIN2IRQ(n)	(0x0800 + ((n) * 0x10))
22  #define	PINCTRL_IRQEN(n)	(0x0900 + ((n) * 0x10))
23  #define	PINCTRL_IRQSTAT(n)	(0x0c00 + ((n) * 0x10))
24  #elif	defined(CONFIG_MX28)
25  #define	PINCTRL_BANKS		5
26  #define	PINCTRL_DOUT(n)		(0x0700 + ((n) * 0x10))
27  #define	PINCTRL_DIN(n)		(0x0900 + ((n) * 0x10))
28  #define	PINCTRL_DOE(n)		(0x0b00 + ((n) * 0x10))
29  #define	PINCTRL_PIN2IRQ(n)	(0x1000 + ((n) * 0x10))
30  #define	PINCTRL_IRQEN(n)	(0x1100 + ((n) * 0x10))
31  #define	PINCTRL_IRQSTAT(n)	(0x1400 + ((n) * 0x10))
32  #else
33  #error "Please select CONFIG_MX23 or CONFIG_MX28"
34  #endif
35  
36  #define GPIO_INT_FALL_EDGE	0x0
37  #define GPIO_INT_LOW_LEV	0x1
38  #define GPIO_INT_RISE_EDGE	0x2
39  #define GPIO_INT_HIGH_LEV	0x3
40  #define GPIO_INT_LEV_MASK	(1 << 0)
41  #define GPIO_INT_POL_MASK	(1 << 1)
42  
43  void mxs_gpio_init(void)
44  {
45  	int i;
46  
47  	for (i = 0; i < PINCTRL_BANKS; i++) {
48  		writel(0, MXS_PINCTRL_BASE + PINCTRL_PIN2IRQ(i));
49  		writel(0, MXS_PINCTRL_BASE + PINCTRL_IRQEN(i));
50  		/* Use SCT address here to clear the IRQSTAT bits */
51  		writel(0xffffffff, MXS_PINCTRL_BASE + PINCTRL_IRQSTAT(i) + 8);
52  	}
53  }
54  
55  int gpio_get_value(unsigned gpio)
56  {
57  	uint32_t bank = PAD_BANK(gpio);
58  	uint32_t offset = PINCTRL_DIN(bank);
59  	struct mxs_register_32 *reg =
60  		(struct mxs_register_32 *)(MXS_PINCTRL_BASE + offset);
61  
62  	return (readl(&reg->reg) >> PAD_PIN(gpio)) & 1;
63  }
64  
65  void gpio_set_value(unsigned gpio, int value)
66  {
67  	uint32_t bank = PAD_BANK(gpio);
68  	uint32_t offset = PINCTRL_DOUT(bank);
69  	struct mxs_register_32 *reg =
70  		(struct mxs_register_32 *)(MXS_PINCTRL_BASE + offset);
71  
72  	if (value)
73  		writel(1 << PAD_PIN(gpio), &reg->reg_set);
74  	else
75  		writel(1 << PAD_PIN(gpio), &reg->reg_clr);
76  }
77  
78  int gpio_direction_input(unsigned gpio)
79  {
80  	uint32_t bank = PAD_BANK(gpio);
81  	uint32_t offset = PINCTRL_DOE(bank);
82  	struct mxs_register_32 *reg =
83  		(struct mxs_register_32 *)(MXS_PINCTRL_BASE + offset);
84  
85  	writel(1 << PAD_PIN(gpio), &reg->reg_clr);
86  
87  	return 0;
88  }
89  
90  int gpio_direction_output(unsigned gpio, int value)
91  {
92  	uint32_t bank = PAD_BANK(gpio);
93  	uint32_t offset = PINCTRL_DOE(bank);
94  	struct mxs_register_32 *reg =
95  		(struct mxs_register_32 *)(MXS_PINCTRL_BASE + offset);
96  
97  	gpio_set_value(gpio, value);
98  
99  	writel(1 << PAD_PIN(gpio), &reg->reg_set);
100  
101  	return 0;
102  }
103  
104  int gpio_request(unsigned gpio, const char *label)
105  {
106  	if (PAD_BANK(gpio) >= PINCTRL_BANKS)
107  		return -1;
108  
109  	return 0;
110  }
111  
112  int gpio_free(unsigned gpio)
113  {
114  	return 0;
115  }
116  
117  int name_to_gpio(const char *name)
118  {
119  	unsigned bank, pin;
120  	char *end;
121  
122  	bank = simple_strtoul(name, &end, 10);
123  
124  	if (!*end || *end != ':')
125  		return bank;
126  
127  	pin = simple_strtoul(end + 1, NULL, 10);
128  
129  	return (bank << MXS_PAD_BANK_SHIFT) | (pin << MXS_PAD_PIN_SHIFT);
130  }
131