blob: 49ad517e554421f3857834f63b1283c042a65849 [file] [log] [blame]
Sathish Ambley4149e842012-03-23 11:53:55 -07001/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13#include <linux/bitmap.h>
14#include <linux/bitops.h>
15#include <linux/gpio.h>
16#include <linux/init.h>
17#include <linux/io.h>
18#include <linux/irq.h>
19
20#include <mach/msm_iomap.h>
21#include <mach/gpiomux.h>
22#include "gpio-msm-common.h"
23
24/* Bits of interest in the GPIO_IN_OUT register.
25 */
26enum {
27 GPIO_IN_BIT = 0,
28 GPIO_OUT_BIT = 1
29};
30
31/* Bits of interest in the GPIO_INTR_STATUS register.
32 */
33enum {
34 INTR_STATUS_BIT = 0,
35};
36
37/* Bits of interest in the GPIO_CFG register.
38 */
39enum {
40 GPIO_OE_BIT = 9,
41};
42
43/* Bits of interest in the GPIO_INTR_CFG register.
44 */
45enum {
46 INTR_ENABLE_BIT = 0,
47 INTR_POL_CTL_BIT = 1,
48 INTR_DECT_CTL_BIT = 2,
49 INTR_RAW_STATUS_EN_BIT = 4,
50 INTR_TARGET_PROC_BIT = 5,
51 INTR_DIR_CONN_EN_BIT = 8,
52};
53
54/*
55 * There is no 'DC_POLARITY_LO' because the GIC is incapable
56 * of asserting on falling edge or level-low conditions. Even though
57 * the registers allow for low-polarity inputs, the case can never arise.
58 */
59enum {
60 DC_GPIO_SEL_BIT = 0,
61 DC_POLARITY_BIT = 8,
62};
63
64/*
65 * When a GPIO triggers, two separate decisions are made, controlled
66 * by two separate flags.
67 *
68 * - First, INTR_RAW_STATUS_EN controls whether or not the GPIO_INTR_STATUS
69 * register for that GPIO will be updated to reflect the triggering of that
70 * gpio. If this bit is 0, this register will not be updated.
71 * - Second, INTR_ENABLE controls whether an interrupt is triggered.
72 *
73 * If INTR_ENABLE is set and INTR_RAW_STATUS_EN is NOT set, an interrupt
74 * can be triggered but the status register will not reflect it.
75 */
76#define INTR_RAW_STATUS_EN BIT(INTR_RAW_STATUS_EN_BIT)
77#define INTR_ENABLE BIT(INTR_ENABLE_BIT)
78#define INTR_POL_CTL_HI BIT(INTR_POL_CTL_BIT)
79#define INTR_DIR_CONN_EN BIT(INTR_DIR_CONN_EN_BIT)
80#define DC_POLARITY_HI BIT(DC_POLARITY_BIT)
81
82#define INTR_TARGET_PROC_APPS (4 << INTR_TARGET_PROC_BIT)
83#define INTR_TARGET_PROC_NONE (7 << INTR_TARGET_PROC_BIT)
84
85#define INTR_DECT_CTL_LEVEL (0 << INTR_DECT_CTL_BIT)
86#define INTR_DECT_CTL_POS_EDGE (1 << INTR_DECT_CTL_BIT)
87#define INTR_DECT_CTL_NEG_EDGE (2 << INTR_DECT_CTL_BIT)
88#define INTR_DECT_CTL_DUAL_EDGE (3 << INTR_DECT_CTL_BIT)
89#define INTR_DECT_CTL_MASK (3 << INTR_DECT_CTL_BIT)
90
91#define GPIO_CONFIG(gpio) (MSM_TLMM_BASE + 0x1000 + (0x10 * (gpio)))
92#define GPIO_IN_OUT(gpio) (MSM_TLMM_BASE + 0x1004 + (0x10 * (gpio)))
93#define GPIO_INTR_CFG(gpio) (MSM_TLMM_BASE + 0x1008 + (0x10 * (gpio)))
94#define GPIO_INTR_STATUS(gpio) (MSM_TLMM_BASE + 0x100c + (0x10 * (gpio)))
95#define GPIO_DIR_CONN_INTR(intr) (MSM_TLMM_BASE + 0x2800 + (0x04 * (intr)))
96
97static inline void set_gpio_bits(unsigned n, void __iomem *reg)
98{
99 __raw_writel(__raw_readl(reg) | n, reg);
100}
101
102static inline void clr_gpio_bits(unsigned n, void __iomem *reg)
103{
104 __raw_writel(__raw_readl(reg) & ~n, reg);
105}
106
107unsigned __msm_gpio_get_inout(unsigned gpio)
108{
109 return __raw_readl(GPIO_IN_OUT(gpio)) & BIT(GPIO_IN_BIT);
110}
111
112void __msm_gpio_set_inout(unsigned gpio, unsigned val)
113{
114 __raw_writel(val ? BIT(GPIO_OUT_BIT) : 0, GPIO_IN_OUT(gpio));
115}
116
117void __msm_gpio_set_config_direction(unsigned gpio, int input, int val)
118{
119 if (input) {
120 clr_gpio_bits(BIT(GPIO_OE_BIT), GPIO_CONFIG(gpio));
121 } else {
122 __msm_gpio_set_inout(gpio, val);
123 set_gpio_bits(BIT(GPIO_OE_BIT), GPIO_CONFIG(gpio));
124 }
125}
126
127void __msm_gpio_set_polarity(unsigned gpio, unsigned val)
128{
129 if (val)
130 clr_gpio_bits(INTR_POL_CTL_HI, GPIO_INTR_CFG(gpio));
131 else
132 set_gpio_bits(INTR_POL_CTL_HI, GPIO_INTR_CFG(gpio));
133}
134
135unsigned __msm_gpio_get_intr_status(unsigned gpio)
136{
137 return __raw_readl(GPIO_INTR_STATUS(gpio)) &
138 BIT(INTR_STATUS_BIT);
139}
140
141void __msm_gpio_set_intr_status(unsigned gpio)
142{
143 __raw_writel(BIT(INTR_STATUS_BIT), GPIO_INTR_STATUS(gpio));
144}
145
146unsigned __msm_gpio_get_intr_config(unsigned gpio)
147{
148 return __raw_readl(GPIO_INTR_CFG(gpio));
149}
150
151void __msm_gpio_set_intr_cfg_enable(unsigned gpio, unsigned val)
152{
153 unsigned cfg;
154
155 cfg = __raw_readl(GPIO_INTR_CFG(gpio));
156 if (val) {
157 cfg &= ~(INTR_TARGET_PROC_NONE | INTR_DIR_CONN_EN);
158 cfg |= INTR_RAW_STATUS_EN | INTR_ENABLE | INTR_TARGET_PROC_APPS;
159 } else {
160 cfg &= ~(INTR_TARGET_PROC_APPS | INTR_RAW_STATUS_EN |
161 INTR_ENABLE);
162 cfg |= INTR_TARGET_PROC_NONE;
163 }
164 __raw_writel(cfg, GPIO_INTR_CFG(gpio));
165}
166
167void __msm_gpio_set_intr_cfg_type(unsigned gpio, unsigned type)
168{
169 unsigned cfg;
170
171 cfg = __raw_readl(GPIO_INTR_CFG(gpio));
172 cfg &= ~INTR_DECT_CTL_MASK;
173 if (type == IRQ_TYPE_EDGE_RISING)
174 cfg |= INTR_DECT_CTL_POS_EDGE;
175 else if (type == IRQ_TYPE_EDGE_FALLING)
176 cfg |= INTR_DECT_CTL_NEG_EDGE;
177 else if (type == IRQ_TYPE_EDGE_BOTH)
178 cfg |= INTR_DECT_CTL_DUAL_EDGE;
179 else
180 cfg |= INTR_DECT_CTL_LEVEL;
181
182 if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH))
183 cfg |= INTR_POL_CTL_HI;
184 else
185 cfg &= ~INTR_POL_CTL_HI;
186
187 __raw_writel(cfg, GPIO_INTR_CFG(gpio));
188}
189
190void __gpio_tlmm_config(unsigned config)
191{
192 unsigned flags;
193 unsigned gpio = GPIO_PIN(config);
194
195 flags = ((GPIO_DIR(config) << 9) & (0x1 << 9)) |
196 ((GPIO_DRVSTR(config) << 6) & (0x7 << 6)) |
197 ((GPIO_FUNC(config) << 2) & (0xf << 2)) |
198 ((GPIO_PULL(config) & 0x3));
199 __raw_writel(flags, GPIO_CONFIG(gpio));
200}
201
202void __msm_gpio_install_direct_irq(unsigned gpio, unsigned irq,
203 unsigned int input_polarity)
204{
205 unsigned cfg;
206
207 set_gpio_bits(BIT(GPIO_OE_BIT), GPIO_CONFIG(gpio));
208 cfg = __raw_readl(GPIO_INTR_CFG(gpio));
209 cfg &= ~(INTR_TARGET_PROC_NONE | INTR_RAW_STATUS_EN | INTR_ENABLE);
210 cfg |= INTR_TARGET_PROC_APPS | INTR_DIR_CONN_EN;
211 __raw_writel(cfg, GPIO_INTR_CFG(gpio));
212
213 cfg = gpio;
214 if (input_polarity)
215 cfg |= DC_POLARITY_HI;
216 __raw_writel(cfg, GPIO_DIR_CONN_INTR(irq));
217}