xref: /openbmc/u-boot/drivers/gpio/db8500_gpio.c (revision 84dee301)
1*84dee301SMathieu J. Poirier /*
2*84dee301SMathieu J. Poirier  * Code ported from Nomadik GPIO driver in ST-Ericsson Linux kernel code.
3*84dee301SMathieu J. Poirier  * The purpose is that GPIO config found in kernel should work by simply
4*84dee301SMathieu J. Poirier  * copy-paste it to U-boot.
5*84dee301SMathieu J. Poirier  *
6*84dee301SMathieu J. Poirier  * Original Linux authors:
7*84dee301SMathieu J. Poirier  * Copyright (C) 2008,2009 STMicroelectronics
8*84dee301SMathieu J. Poirier  * Copyright (C) 2009 Alessandro Rubini <rubini@unipv.it>
9*84dee301SMathieu J. Poirier  *   Rewritten based on work by Prafulla WADASKAR <prafulla.wadaskar@st.com>
10*84dee301SMathieu J. Poirier  *
11*84dee301SMathieu J. Poirier  * Ported to U-boot by:
12*84dee301SMathieu J. Poirier  * Copyright (C) 2010 Joakim Axelsson <joakim.axelsson AT stericsson.com>
13*84dee301SMathieu J. Poirier  *
14*84dee301SMathieu J. Poirier  * This program is free software; you can redistribute it and/or modify
15*84dee301SMathieu J. Poirier  * it under the terms of the GNU General Public License version 2 as
16*84dee301SMathieu J. Poirier  * published by the Free Software Foundation.
17*84dee301SMathieu J. Poirier  */
18*84dee301SMathieu J. Poirier 
19*84dee301SMathieu J. Poirier #include <common.h>
20*84dee301SMathieu J. Poirier #include <asm/io.h>
21*84dee301SMathieu J. Poirier 
22*84dee301SMathieu J. Poirier #include <asm/arch/db8500_gpio.h>
23*84dee301SMathieu J. Poirier #include <asm/arch/db8500_pincfg.h>
24*84dee301SMathieu J. Poirier #include <linux/compiler.h>
25*84dee301SMathieu J. Poirier 
26*84dee301SMathieu J. Poirier #define IO_ADDR(x) (void *) (x)
27*84dee301SMathieu J. Poirier 
28*84dee301SMathieu J. Poirier /*
29*84dee301SMathieu J. Poirier  * The GPIO module in the db8500 Systems-on-Chip is an
30*84dee301SMathieu J. Poirier  * AMBA device, managing 32 pins and alternate functions. The logic block
31*84dee301SMathieu J. Poirier  * is currently only used in the db8500.
32*84dee301SMathieu J. Poirier  */
33*84dee301SMathieu J. Poirier 
34*84dee301SMathieu J. Poirier #define GPIO_TOTAL_PINS		268
35*84dee301SMathieu J. Poirier #define GPIO_PINS_PER_BLOCK	32
36*84dee301SMathieu J. Poirier #define GPIO_BLOCKS_COUNT	(GPIO_TOTAL_PINS/GPIO_PINS_PER_BLOCK + 1)
37*84dee301SMathieu J. Poirier #define GPIO_BLOCK(pin)		(((pin + GPIO_PINS_PER_BLOCK) >> 5) - 1)
38*84dee301SMathieu J. Poirier #define GPIO_PIN_WITHIN_BLOCK(pin)	((pin)%(GPIO_PINS_PER_BLOCK))
39*84dee301SMathieu J. Poirier 
40*84dee301SMathieu J. Poirier /* Register in the logic block */
41*84dee301SMathieu J. Poirier #define DB8500_GPIO_DAT		0x00
42*84dee301SMathieu J. Poirier #define DB8500_GPIO_DATS	0x04
43*84dee301SMathieu J. Poirier #define DB8500_GPIO_DATC	0x08
44*84dee301SMathieu J. Poirier #define DB8500_GPIO_PDIS	0x0c
45*84dee301SMathieu J. Poirier #define DB8500_GPIO_DIR		0x10
46*84dee301SMathieu J. Poirier #define DB8500_GPIO_DIRS	0x14
47*84dee301SMathieu J. Poirier #define DB8500_GPIO_DIRC	0x18
48*84dee301SMathieu J. Poirier #define DB8500_GPIO_SLPC	0x1c
49*84dee301SMathieu J. Poirier #define DB8500_GPIO_AFSLA	0x20
50*84dee301SMathieu J. Poirier #define DB8500_GPIO_AFSLB	0x24
51*84dee301SMathieu J. Poirier 
52*84dee301SMathieu J. Poirier #define DB8500_GPIO_RIMSC	0x40
53*84dee301SMathieu J. Poirier #define DB8500_GPIO_FIMSC	0x44
54*84dee301SMathieu J. Poirier #define DB8500_GPIO_IS		0x48
55*84dee301SMathieu J. Poirier #define DB8500_GPIO_IC		0x4c
56*84dee301SMathieu J. Poirier #define DB8500_GPIO_RWIMSC	0x50
57*84dee301SMathieu J. Poirier #define DB8500_GPIO_FWIMSC	0x54
58*84dee301SMathieu J. Poirier #define DB8500_GPIO_WKS		0x58
59*84dee301SMathieu J. Poirier 
60*84dee301SMathieu J. Poirier static void __iomem *get_gpio_addr(unsigned gpio)
61*84dee301SMathieu J. Poirier {
62*84dee301SMathieu J. Poirier 	/* Our list of GPIO chips */
63*84dee301SMathieu J. Poirier 	static void __iomem *gpio_addrs[GPIO_BLOCKS_COUNT] = {
64*84dee301SMathieu J. Poirier 		IO_ADDR(CFG_GPIO_0_BASE),
65*84dee301SMathieu J. Poirier 		IO_ADDR(CFG_GPIO_1_BASE),
66*84dee301SMathieu J. Poirier 		IO_ADDR(CFG_GPIO_2_BASE),
67*84dee301SMathieu J. Poirier 		IO_ADDR(CFG_GPIO_3_BASE),
68*84dee301SMathieu J. Poirier 		IO_ADDR(CFG_GPIO_4_BASE),
69*84dee301SMathieu J. Poirier 		IO_ADDR(CFG_GPIO_5_BASE),
70*84dee301SMathieu J. Poirier 		IO_ADDR(CFG_GPIO_6_BASE),
71*84dee301SMathieu J. Poirier 		IO_ADDR(CFG_GPIO_7_BASE),
72*84dee301SMathieu J. Poirier 		IO_ADDR(CFG_GPIO_8_BASE)
73*84dee301SMathieu J. Poirier 	};
74*84dee301SMathieu J. Poirier 
75*84dee301SMathieu J. Poirier 	return gpio_addrs[GPIO_BLOCK(gpio)];
76*84dee301SMathieu J. Poirier }
77*84dee301SMathieu J. Poirier 
78*84dee301SMathieu J. Poirier static unsigned get_gpio_offset(unsigned gpio)
79*84dee301SMathieu J. Poirier {
80*84dee301SMathieu J. Poirier 	return GPIO_PIN_WITHIN_BLOCK(gpio);
81*84dee301SMathieu J. Poirier }
82*84dee301SMathieu J. Poirier 
83*84dee301SMathieu J. Poirier /* Can only be called from config_pin. Don't configure alt-mode directly */
84*84dee301SMathieu J. Poirier static void gpio_set_mode(unsigned gpio, enum db8500_gpio_alt mode)
85*84dee301SMathieu J. Poirier {
86*84dee301SMathieu J. Poirier 	void __iomem *addr = get_gpio_addr(gpio);
87*84dee301SMathieu J. Poirier 	unsigned offset = get_gpio_offset(gpio);
88*84dee301SMathieu J. Poirier 	u32 bit = 1 << offset;
89*84dee301SMathieu J. Poirier 	u32 afunc, bfunc;
90*84dee301SMathieu J. Poirier 
91*84dee301SMathieu J. Poirier 	afunc = readl(addr + DB8500_GPIO_AFSLA) & ~bit;
92*84dee301SMathieu J. Poirier 	bfunc = readl(addr + DB8500_GPIO_AFSLB) & ~bit;
93*84dee301SMathieu J. Poirier 	if (mode & DB8500_GPIO_ALT_A)
94*84dee301SMathieu J. Poirier 		afunc |= bit;
95*84dee301SMathieu J. Poirier 	if (mode & DB8500_GPIO_ALT_B)
96*84dee301SMathieu J. Poirier 		bfunc |= bit;
97*84dee301SMathieu J. Poirier 	writel(afunc, addr + DB8500_GPIO_AFSLA);
98*84dee301SMathieu J. Poirier 	writel(bfunc, addr + DB8500_GPIO_AFSLB);
99*84dee301SMathieu J. Poirier }
100*84dee301SMathieu J. Poirier 
101*84dee301SMathieu J. Poirier /**
102*84dee301SMathieu J. Poirier  * db8500_gpio_set_pull() - enable/disable pull up/down on a gpio
103*84dee301SMathieu J. Poirier  * @gpio: pin number
104*84dee301SMathieu J. Poirier  * @pull: one of DB8500_GPIO_PULL_DOWN, DB8500_GPIO_PULL_UP,
105*84dee301SMathieu J. Poirier  *  and DB8500_GPIO_PULL_NONE
106*84dee301SMathieu J. Poirier  *
107*84dee301SMathieu J. Poirier  * Enables/disables pull up/down on a specified pin.  This only takes effect if
108*84dee301SMathieu J. Poirier  * the pin is configured as an input (either explicitly or by the alternate
109*84dee301SMathieu J. Poirier  * function).
110*84dee301SMathieu J. Poirier  *
111*84dee301SMathieu J. Poirier  * NOTE: If enabling the pull up/down, the caller must ensure that the GPIO is
112*84dee301SMathieu J. Poirier  * configured as an input.  Otherwise, due to the way the controller registers
113*84dee301SMathieu J. Poirier  * work, this function will change the value output on the pin.
114*84dee301SMathieu J. Poirier  */
115*84dee301SMathieu J. Poirier void db8500_gpio_set_pull(unsigned gpio, enum db8500_gpio_pull pull)
116*84dee301SMathieu J. Poirier {
117*84dee301SMathieu J. Poirier 	void __iomem *addr = get_gpio_addr(gpio);
118*84dee301SMathieu J. Poirier 	unsigned offset = get_gpio_offset(gpio);
119*84dee301SMathieu J. Poirier 	u32 bit = 1 << offset;
120*84dee301SMathieu J. Poirier 	u32 pdis;
121*84dee301SMathieu J. Poirier 
122*84dee301SMathieu J. Poirier 	pdis = readl(addr + DB8500_GPIO_PDIS);
123*84dee301SMathieu J. Poirier 	if (pull == DB8500_GPIO_PULL_NONE)
124*84dee301SMathieu J. Poirier 		pdis |= bit;
125*84dee301SMathieu J. Poirier 	else
126*84dee301SMathieu J. Poirier 		pdis &= ~bit;
127*84dee301SMathieu J. Poirier 	writel(pdis, addr + DB8500_GPIO_PDIS);
128*84dee301SMathieu J. Poirier 
129*84dee301SMathieu J. Poirier 	if (pull == DB8500_GPIO_PULL_UP)
130*84dee301SMathieu J. Poirier 		writel(bit, addr + DB8500_GPIO_DATS);
131*84dee301SMathieu J. Poirier 	else if (pull == DB8500_GPIO_PULL_DOWN)
132*84dee301SMathieu J. Poirier 		writel(bit, addr + DB8500_GPIO_DATC);
133*84dee301SMathieu J. Poirier }
134*84dee301SMathieu J. Poirier 
135*84dee301SMathieu J. Poirier void db8500_gpio_make_input(unsigned gpio)
136*84dee301SMathieu J. Poirier {
137*84dee301SMathieu J. Poirier 	void __iomem *addr = get_gpio_addr(gpio);
138*84dee301SMathieu J. Poirier 	unsigned offset = get_gpio_offset(gpio);
139*84dee301SMathieu J. Poirier 
140*84dee301SMathieu J. Poirier 	writel(1 << offset, addr + DB8500_GPIO_DIRC);
141*84dee301SMathieu J. Poirier }
142*84dee301SMathieu J. Poirier 
143*84dee301SMathieu J. Poirier int db8500_gpio_get_input(unsigned gpio)
144*84dee301SMathieu J. Poirier {
145*84dee301SMathieu J. Poirier 	void __iomem *addr = get_gpio_addr(gpio);
146*84dee301SMathieu J. Poirier 	unsigned offset = get_gpio_offset(gpio);
147*84dee301SMathieu J. Poirier 	u32 bit = 1 << offset;
148*84dee301SMathieu J. Poirier 
149*84dee301SMathieu J. Poirier 	printf("db8500_gpio_get_input gpio=%u addr=%p offset=%u bit=%#x\n",
150*84dee301SMathieu J. Poirier 		gpio, addr, offset, bit);
151*84dee301SMathieu J. Poirier 
152*84dee301SMathieu J. Poirier 	return (readl(addr + DB8500_GPIO_DAT) & bit) != 0;
153*84dee301SMathieu J. Poirier }
154*84dee301SMathieu J. Poirier 
155*84dee301SMathieu J. Poirier void db8500_gpio_make_output(unsigned gpio, int val)
156*84dee301SMathieu J. Poirier {
157*84dee301SMathieu J. Poirier 	void __iomem *addr = get_gpio_addr(gpio);
158*84dee301SMathieu J. Poirier 	unsigned offset = get_gpio_offset(gpio);
159*84dee301SMathieu J. Poirier 
160*84dee301SMathieu J. Poirier 	writel(1 << offset, addr + DB8500_GPIO_DIRS);
161*84dee301SMathieu J. Poirier 	db8500_gpio_set_output(gpio, val);
162*84dee301SMathieu J. Poirier }
163*84dee301SMathieu J. Poirier 
164*84dee301SMathieu J. Poirier void db8500_gpio_set_output(unsigned gpio, int val)
165*84dee301SMathieu J. Poirier {
166*84dee301SMathieu J. Poirier 	void __iomem *addr = get_gpio_addr(gpio);
167*84dee301SMathieu J. Poirier 	unsigned offset = get_gpio_offset(gpio);
168*84dee301SMathieu J. Poirier 
169*84dee301SMathieu J. Poirier 	if (val)
170*84dee301SMathieu J. Poirier 		writel(1 << offset, addr + DB8500_GPIO_DATS);
171*84dee301SMathieu J. Poirier 	else
172*84dee301SMathieu J. Poirier 		writel(1 << offset, addr + DB8500_GPIO_DATC);
173*84dee301SMathieu J. Poirier }
174*84dee301SMathieu J. Poirier 
175*84dee301SMathieu J. Poirier /**
176*84dee301SMathieu J. Poirier  * config_pin - configure a pin's mux attributes
177*84dee301SMathieu J. Poirier  * @cfg: pin confguration
178*84dee301SMathieu J. Poirier  *
179*84dee301SMathieu J. Poirier  * Configures a pin's mode (alternate function or GPIO), its pull up status,
180*84dee301SMathieu J. Poirier  * and its sleep mode based on the specified configuration.  The @cfg is
181*84dee301SMathieu J. Poirier  * usually one of the SoC specific macros defined in mach/<soc>-pins.h.  These
182*84dee301SMathieu J. Poirier  * are constructed using, and can be further enhanced with, the macros in
183*84dee301SMathieu J. Poirier  * plat/pincfg.h.
184*84dee301SMathieu J. Poirier  *
185*84dee301SMathieu J. Poirier  * If a pin's mode is set to GPIO, it is configured as an input to avoid
186*84dee301SMathieu J. Poirier  * side-effects.  The gpio can be manipulated later using standard GPIO API
187*84dee301SMathieu J. Poirier  * calls.
188*84dee301SMathieu J. Poirier  */
189*84dee301SMathieu J. Poirier static void config_pin(unsigned long cfg)
190*84dee301SMathieu J. Poirier {
191*84dee301SMathieu J. Poirier 	int pin = PIN_NUM(cfg);
192*84dee301SMathieu J. Poirier 	int pull = PIN_PULL(cfg);
193*84dee301SMathieu J. Poirier 	int af = PIN_ALT(cfg);
194*84dee301SMathieu J. Poirier 	int output = PIN_DIR(cfg);
195*84dee301SMathieu J. Poirier 	int val = PIN_VAL(cfg);
196*84dee301SMathieu J. Poirier 
197*84dee301SMathieu J. Poirier 	if (output)
198*84dee301SMathieu J. Poirier 		db8500_gpio_make_output(pin, val);
199*84dee301SMathieu J. Poirier 	else {
200*84dee301SMathieu J. Poirier 		db8500_gpio_make_input(pin);
201*84dee301SMathieu J. Poirier 		db8500_gpio_set_pull(pin, pull);
202*84dee301SMathieu J. Poirier 	}
203*84dee301SMathieu J. Poirier 
204*84dee301SMathieu J. Poirier 	gpio_set_mode(pin, af);
205*84dee301SMathieu J. Poirier }
206*84dee301SMathieu J. Poirier 
207*84dee301SMathieu J. Poirier /**
208*84dee301SMathieu J. Poirier  * db8500_config_pins - configure several pins at once
209*84dee301SMathieu J. Poirier  * @cfgs: array of pin configurations
210*84dee301SMathieu J. Poirier  * @num: number of elments in the array
211*84dee301SMathieu J. Poirier  *
212*84dee301SMathieu J. Poirier  * Configures several pins using config_pin(). Refer to that function for
213*84dee301SMathieu J. Poirier  * further information.
214*84dee301SMathieu J. Poirier  */
215*84dee301SMathieu J. Poirier void db8500_gpio_config_pins(unsigned long *cfgs, size_t num)
216*84dee301SMathieu J. Poirier {
217*84dee301SMathieu J. Poirier 	size_t i;
218*84dee301SMathieu J. Poirier 
219*84dee301SMathieu J. Poirier 	for (i = 0; i < num; i++)
220*84dee301SMathieu J. Poirier 		config_pin(cfgs[i]);
221*84dee301SMathieu J. Poirier }
222