blob: 8c42bd61872b53d61f5948b07f70bde9bb1d111c [file] [log] [blame]
Duy Truong790f06d2013-02-13 16:38:12 -08001/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
Gregory Bean0cc2fc12010-11-24 11:53:51 -08002 *
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 *
Gregory Bean0cc2fc12010-11-24 11:53:51 -080012 */
Gregory Bean70cc2c02010-11-24 11:53:52 -080013#include <linux/bitmap.h>
14#include <linux/bitops.h>
Rohit Vaswanie50680c2012-06-13 18:26:18 +053015#include <linux/delay.h>
Gregory Bean0cc2fc12010-11-24 11:53:51 -080016#include <linux/gpio.h>
Gregory Bean70cc2c02010-11-24 11:53:52 -080017#include <linux/init.h>
Steve Mucklef132c6c2012-06-06 18:30:57 -070018#include <linux/io.h>
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -070019#include <linux/irq.h>
Will Deacon03dd7652011-02-21 14:54:57 +000020
Gregory Bean0cc2fc12010-11-24 11:53:51 -080021#include <mach/msm_iomap.h>
Steve Mucklef132c6c2012-06-06 18:30:57 -070022#include <mach/gpiomux.h>
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -070023#include "gpio-msm-common.h"
Gregory Bean0cc2fc12010-11-24 11:53:51 -080024
25/* Bits of interest in the GPIO_IN_OUT register.
26 */
27enum {
Steve Mucklef132c6c2012-06-06 18:30:57 -070028 GPIO_IN_BIT = 0,
29 GPIO_OUT_BIT = 1
Gregory Bean70cc2c02010-11-24 11:53:52 -080030};
31
32/* Bits of interest in the GPIO_INTR_STATUS register.
33 */
34enum {
Steve Mucklef132c6c2012-06-06 18:30:57 -070035 INTR_STATUS_BIT = 0,
Gregory Bean0cc2fc12010-11-24 11:53:51 -080036};
37
38/* Bits of interest in the GPIO_CFG register.
39 */
40enum {
Steve Mucklef132c6c2012-06-06 18:30:57 -070041 GPIO_OE_BIT = 9,
Gregory Bean0cc2fc12010-11-24 11:53:51 -080042};
43
Gregory Bean70cc2c02010-11-24 11:53:52 -080044/* Bits of interest in the GPIO_INTR_CFG register.
Steve Mucklef132c6c2012-06-06 18:30:57 -070045 */
46enum {
47 INTR_ENABLE_BIT = 0,
48 INTR_POL_CTL_BIT = 1,
49 INTR_DECT_CTL_BIT = 2,
50 INTR_RAW_STATUS_EN_BIT = 3,
51};
52
53/* Codes of interest in GPIO_INTR_CFG_SU.
54 */
55enum {
56 TARGET_PROC_SCORPION = 4,
57 TARGET_PROC_NONE = 7,
58};
59
60/*
61 * There is no 'DC_POLARITY_LO' because the GIC is incapable
62 * of asserting on falling edge or level-low conditions. Even though
63 * the registers allow for low-polarity inputs, the case can never arise.
64 */
65enum {
66 DC_POLARITY_HI = BIT(11),
67 DC_IRQ_ENABLE = BIT(3),
68};
69
Steve Mucklef132c6c2012-06-06 18:30:57 -070070/*
Gregory Bean70cc2c02010-11-24 11:53:52 -080071 * When a GPIO triggers, two separate decisions are made, controlled
72 * by two separate flags.
73 *
74 * - First, INTR_RAW_STATUS_EN controls whether or not the GPIO_INTR_STATUS
75 * register for that GPIO will be updated to reflect the triggering of that
76 * gpio. If this bit is 0, this register will not be updated.
77 * - Second, INTR_ENABLE controls whether an interrupt is triggered.
78 *
79 * If INTR_ENABLE is set and INTR_RAW_STATUS_EN is NOT set, an interrupt
80 * can be triggered but the status register will not reflect it.
81 */
Steve Mucklef132c6c2012-06-06 18:30:57 -070082#define INTR_RAW_STATUS_EN BIT(INTR_RAW_STATUS_EN_BIT)
83#define INTR_ENABLE BIT(INTR_ENABLE_BIT)
84#define INTR_DECT_CTL_EDGE BIT(INTR_DECT_CTL_BIT)
85#define INTR_POL_CTL_HI BIT(INTR_POL_CTL_BIT)
Gregory Bean70cc2c02010-11-24 11:53:52 -080086
87#define GPIO_INTR_CFG_SU(gpio) (MSM_TLMM_BASE + 0x0400 + (0x04 * (gpio)))
Steve Mucklef132c6c2012-06-06 18:30:57 -070088#define DIR_CONN_INTR_CFG_SU(irq) (MSM_TLMM_BASE + 0x0700 + (0x04 * (irq)))
Gregory Bean0cc2fc12010-11-24 11:53:51 -080089#define GPIO_CONFIG(gpio) (MSM_TLMM_BASE + 0x1000 + (0x10 * (gpio)))
90#define GPIO_IN_OUT(gpio) (MSM_TLMM_BASE + 0x1004 + (0x10 * (gpio)))
Gregory Bean70cc2c02010-11-24 11:53:52 -080091#define GPIO_INTR_CFG(gpio) (MSM_TLMM_BASE + 0x1008 + (0x10 * (gpio)))
92#define GPIO_INTR_STATUS(gpio) (MSM_TLMM_BASE + 0x100c + (0x10 * (gpio)))
93
Gregory Bean70cc2c02010-11-24 11:53:52 -080094static inline void set_gpio_bits(unsigned n, void __iomem *reg)
95{
Steve Mucklef132c6c2012-06-06 18:30:57 -070096 __raw_writel(__raw_readl(reg) | n, reg);
Gregory Bean70cc2c02010-11-24 11:53:52 -080097}
98
Steve Mucklef132c6c2012-06-06 18:30:57 -070099static inline void clr_gpio_bits(unsigned n, void __iomem *reg)
Gregory Bean70cc2c02010-11-24 11:53:52 -0800100{
Steve Mucklef132c6c2012-06-06 18:30:57 -0700101 __raw_writel(__raw_readl(reg) & ~n, reg);
Gregory Bean70cc2c02010-11-24 11:53:52 -0800102}
103
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700104unsigned __msm_gpio_get_inout(unsigned gpio)
Gregory Bean0cc2fc12010-11-24 11:53:51 -0800105{
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700106 return __raw_readl(GPIO_IN_OUT(gpio)) & BIT(GPIO_IN_BIT);
Gregory Bean0cc2fc12010-11-24 11:53:51 -0800107}
108
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700109void __msm_gpio_set_inout(unsigned gpio, unsigned val)
Gregory Bean0cc2fc12010-11-24 11:53:51 -0800110{
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700111 __raw_writel(val ? BIT(GPIO_OUT_BIT) : 0, GPIO_IN_OUT(gpio));
Gregory Bean0cc2fc12010-11-24 11:53:51 -0800112}
113
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700114void __msm_gpio_set_config_direction(unsigned gpio, int input, int val)
Gregory Bean0cc2fc12010-11-24 11:53:51 -0800115{
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700116 if (input)
117 clr_gpio_bits(BIT(GPIO_OE_BIT), GPIO_CONFIG(gpio));
118 else {
119 __msm_gpio_set_inout(gpio, val);
120 set_gpio_bits(BIT(GPIO_OE_BIT), GPIO_CONFIG(gpio));
121 }
Gregory Bean0cc2fc12010-11-24 11:53:51 -0800122}
123
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700124void __msm_gpio_set_polarity(unsigned gpio, unsigned val)
Gregory Bean0cc2fc12010-11-24 11:53:51 -0800125{
Steve Mucklef132c6c2012-06-06 18:30:57 -0700126 if (val)
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700127 clr_gpio_bits(INTR_POL_CTL_HI, GPIO_INTR_CFG(gpio));
Steve Mucklef132c6c2012-06-06 18:30:57 -0700128 else
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700129 set_gpio_bits(INTR_POL_CTL_HI, GPIO_INTR_CFG(gpio));
Steve Mucklef132c6c2012-06-06 18:30:57 -0700130}
131
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700132unsigned __msm_gpio_get_intr_status(unsigned gpio)
Gregory Bean70cc2c02010-11-24 11:53:52 -0800133{
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700134 return __raw_readl(GPIO_INTR_STATUS(gpio)) &
Steve Mucklef132c6c2012-06-06 18:30:57 -0700135 BIT(INTR_STATUS_BIT);
Gregory Bean70cc2c02010-11-24 11:53:52 -0800136}
137
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700138void __msm_gpio_set_intr_status(unsigned gpio)
Gregory Bean70cc2c02010-11-24 11:53:52 -0800139{
Steve Mucklef132c6c2012-06-06 18:30:57 -0700140 __raw_writel(BIT(INTR_STATUS_BIT), GPIO_INTR_STATUS(gpio));
Steve Mucklef132c6c2012-06-06 18:30:57 -0700141}
142
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700143unsigned __msm_gpio_get_intr_config(unsigned gpio)
Steve Mucklef132c6c2012-06-06 18:30:57 -0700144{
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700145 return __raw_readl(GPIO_INTR_CFG(gpio));
Gregory Bean70cc2c02010-11-24 11:53:52 -0800146}
147
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700148void __msm_gpio_set_intr_cfg_enable(unsigned gpio, unsigned val)
Gregory Bean70cc2c02010-11-24 11:53:52 -0800149{
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700150 if (val) {
Rohit Vaswanie50680c2012-06-13 18:26:18 +0530151 set_gpio_bits(INTR_ENABLE, GPIO_INTR_CFG(gpio));
Gregory Bean70cc2c02010-11-24 11:53:52 -0800152
Gregory Bean70cc2c02010-11-24 11:53:52 -0800153 } else {
Rohit Vaswanie50680c2012-06-13 18:26:18 +0530154 clr_gpio_bits(INTR_ENABLE, GPIO_INTR_CFG(gpio));
Gregory Bean70cc2c02010-11-24 11:53:52 -0800155 }
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700156}
Gregory Bean70cc2c02010-11-24 11:53:52 -0800157
Rohit Vaswanif4f36582012-08-28 11:49:11 -0700158unsigned __msm_gpio_get_intr_cfg_enable(unsigned gpio)
159{
160 return __msm_gpio_get_intr_config(gpio) & INTR_ENABLE;
161}
162
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700163void __msm_gpio_set_intr_cfg_type(unsigned gpio, unsigned type)
164{
165 unsigned cfg;
166
Rohit Vaswaniea45a492012-08-03 11:47:42 -0700167 /* RAW_STATUS_EN is left on for all gpio irqs. Due to the
168 * internal circuitry of TLMM, toggling the RAW_STATUS
169 * could cause the INTR_STATUS to be set for EDGE interrupts.
170 */
171 cfg = __msm_gpio_get_intr_config(gpio);
172 cfg |= INTR_RAW_STATUS_EN;
173 __raw_writel(cfg, GPIO_INTR_CFG(gpio));
174 __raw_writel(TARGET_PROC_SCORPION, GPIO_INTR_CFG_SU(gpio));
175
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700176 cfg = __msm_gpio_get_intr_config(gpio);
177 if (type & IRQ_TYPE_EDGE_BOTH)
178 cfg |= INTR_DECT_CTL_EDGE;
Gregory Bean70cc2c02010-11-24 11:53:52 -0800179 else
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700180 cfg &= ~INTR_DECT_CTL_EDGE;
Gregory Bean70cc2c02010-11-24 11:53:52 -0800181
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700182 if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH))
183 cfg |= INTR_POL_CTL_HI;
184 else
185 cfg &= ~INTR_POL_CTL_HI;
Gregory Bean70cc2c02010-11-24 11:53:52 -0800186
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700187 __raw_writel(cfg, GPIO_INTR_CFG(gpio));
Rohit Vaswanie50680c2012-06-13 18:26:18 +0530188 /* Sometimes it might take a little while to update
189 * the interrupt status after the RAW_STATUS is enabled
Rohit Vaswaniea45a492012-08-03 11:47:42 -0700190 * We clear the interrupt status before enabling the
191 * interrupt in the unmask call-back.
Rohit Vaswanie50680c2012-06-13 18:26:18 +0530192 */
193 udelay(5);
Gregory Bean70cc2c02010-11-24 11:53:52 -0800194}
195
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700196void __gpio_tlmm_config(unsigned config)
Steve Mucklef132c6c2012-06-06 18:30:57 -0700197{
198 uint32_t flags;
199 unsigned gpio = GPIO_PIN(config);
200
Steve Mucklef132c6c2012-06-06 18:30:57 -0700201 flags = ((GPIO_DIR(config) << 9) & (0x1 << 9)) |
202 ((GPIO_DRVSTR(config) << 6) & (0x7 << 6)) |
203 ((GPIO_FUNC(config) << 2) & (0xf << 2)) |
204 ((GPIO_PULL(config) & 0x3));
205 __raw_writel(flags, GPIO_CONFIG(gpio));
Steve Mucklef132c6c2012-06-06 18:30:57 -0700206}
Steve Mucklef132c6c2012-06-06 18:30:57 -0700207
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700208void __msm_gpio_install_direct_irq(unsigned gpio, unsigned irq,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700209 unsigned int input_polarity)
210{
Steve Mucklef132c6c2012-06-06 18:30:57 -0700211 uint32_t bits;
212
Steve Mucklef132c6c2012-06-06 18:30:57 -0700213 __raw_writel(__raw_readl(GPIO_CONFIG(gpio)) | BIT(GPIO_OE_BIT),
214 GPIO_CONFIG(gpio));
215 __raw_writel(__raw_readl(GPIO_INTR_CFG(gpio)) &
216 ~(INTR_RAW_STATUS_EN | INTR_ENABLE),
217 GPIO_INTR_CFG(gpio));
218 __raw_writel(DC_IRQ_ENABLE | TARGET_PROC_NONE,
219 GPIO_INTR_CFG_SU(gpio));
220
221 bits = TARGET_PROC_SCORPION | (gpio << 3);
222 if (input_polarity)
223 bits |= DC_POLARITY_HI;
224 __raw_writel(bits, DIR_CONN_INTR_CFG_SU(irq));
Steve Mucklef132c6c2012-06-06 18:30:57 -0700225}