blob: fb43562d1600514617a4a59a5a7812f4e32985e2 [file] [log] [blame]
Steve Mucklef132c6c2012-06-06 18:30:57 -07001/* Copyright (c) 2010-2012, Code Aurora Forum. 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>
Gregory Bean0cc2fc12010-11-24 11:53:51 -080015#include <linux/gpio.h>
Gregory Bean70cc2c02010-11-24 11:53:52 -080016#include <linux/init.h>
Steve Mucklef132c6c2012-06-06 18:30:57 -070017#include <linux/io.h>
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -070018#include <linux/irq.h>
Will Deacon03dd7652011-02-21 14:54:57 +000019
Gregory Bean0cc2fc12010-11-24 11:53:51 -080020#include <mach/msm_iomap.h>
Steve Mucklef132c6c2012-06-06 18:30:57 -070021#include <mach/gpiomux.h>
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -070022#include "gpio-msm-common.h"
Gregory Bean0cc2fc12010-11-24 11:53:51 -080023
24/* Bits of interest in the GPIO_IN_OUT register.
25 */
26enum {
Steve Mucklef132c6c2012-06-06 18:30:57 -070027 GPIO_IN_BIT = 0,
28 GPIO_OUT_BIT = 1
Gregory Bean70cc2c02010-11-24 11:53:52 -080029};
30
31/* Bits of interest in the GPIO_INTR_STATUS register.
32 */
33enum {
Steve Mucklef132c6c2012-06-06 18:30:57 -070034 INTR_STATUS_BIT = 0,
Gregory Bean0cc2fc12010-11-24 11:53:51 -080035};
36
37/* Bits of interest in the GPIO_CFG register.
38 */
39enum {
Steve Mucklef132c6c2012-06-06 18:30:57 -070040 GPIO_OE_BIT = 9,
Gregory Bean0cc2fc12010-11-24 11:53:51 -080041};
42
Gregory Bean70cc2c02010-11-24 11:53:52 -080043/* Bits of interest in the GPIO_INTR_CFG register.
Steve Mucklef132c6c2012-06-06 18:30:57 -070044 */
45enum {
46 INTR_ENABLE_BIT = 0,
47 INTR_POL_CTL_BIT = 1,
48 INTR_DECT_CTL_BIT = 2,
49 INTR_RAW_STATUS_EN_BIT = 3,
50};
51
52/* Codes of interest in GPIO_INTR_CFG_SU.
53 */
54enum {
55 TARGET_PROC_SCORPION = 4,
56 TARGET_PROC_NONE = 7,
57};
58
59/*
60 * There is no 'DC_POLARITY_LO' because the GIC is incapable
61 * of asserting on falling edge or level-low conditions. Even though
62 * the registers allow for low-polarity inputs, the case can never arise.
63 */
64enum {
65 DC_POLARITY_HI = BIT(11),
66 DC_IRQ_ENABLE = BIT(3),
67};
68
Steve Mucklef132c6c2012-06-06 18:30:57 -070069/*
Gregory Bean70cc2c02010-11-24 11:53:52 -080070 * When a GPIO triggers, two separate decisions are made, controlled
71 * by two separate flags.
72 *
73 * - First, INTR_RAW_STATUS_EN controls whether or not the GPIO_INTR_STATUS
74 * register for that GPIO will be updated to reflect the triggering of that
75 * gpio. If this bit is 0, this register will not be updated.
76 * - Second, INTR_ENABLE controls whether an interrupt is triggered.
77 *
78 * If INTR_ENABLE is set and INTR_RAW_STATUS_EN is NOT set, an interrupt
79 * can be triggered but the status register will not reflect it.
80 */
Steve Mucklef132c6c2012-06-06 18:30:57 -070081#define INTR_RAW_STATUS_EN BIT(INTR_RAW_STATUS_EN_BIT)
82#define INTR_ENABLE BIT(INTR_ENABLE_BIT)
83#define INTR_DECT_CTL_EDGE BIT(INTR_DECT_CTL_BIT)
84#define INTR_POL_CTL_HI BIT(INTR_POL_CTL_BIT)
Gregory Bean70cc2c02010-11-24 11:53:52 -080085
86#define GPIO_INTR_CFG_SU(gpio) (MSM_TLMM_BASE + 0x0400 + (0x04 * (gpio)))
Steve Mucklef132c6c2012-06-06 18:30:57 -070087#define DIR_CONN_INTR_CFG_SU(irq) (MSM_TLMM_BASE + 0x0700 + (0x04 * (irq)))
Gregory Bean0cc2fc12010-11-24 11:53:51 -080088#define GPIO_CONFIG(gpio) (MSM_TLMM_BASE + 0x1000 + (0x10 * (gpio)))
89#define GPIO_IN_OUT(gpio) (MSM_TLMM_BASE + 0x1004 + (0x10 * (gpio)))
Gregory Bean70cc2c02010-11-24 11:53:52 -080090#define GPIO_INTR_CFG(gpio) (MSM_TLMM_BASE + 0x1008 + (0x10 * (gpio)))
91#define GPIO_INTR_STATUS(gpio) (MSM_TLMM_BASE + 0x100c + (0x10 * (gpio)))
92
Gregory Bean70cc2c02010-11-24 11:53:52 -080093static inline void set_gpio_bits(unsigned n, void __iomem *reg)
94{
Steve Mucklef132c6c2012-06-06 18:30:57 -070095 __raw_writel(__raw_readl(reg) | n, reg);
Gregory Bean70cc2c02010-11-24 11:53:52 -080096}
97
Steve Mucklef132c6c2012-06-06 18:30:57 -070098static inline void clr_gpio_bits(unsigned n, void __iomem *reg)
Gregory Bean70cc2c02010-11-24 11:53:52 -080099{
Steve Mucklef132c6c2012-06-06 18:30:57 -0700100 __raw_writel(__raw_readl(reg) & ~n, reg);
Gregory Bean70cc2c02010-11-24 11:53:52 -0800101}
102
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700103unsigned __msm_gpio_get_inout(unsigned gpio)
Gregory Bean0cc2fc12010-11-24 11:53:51 -0800104{
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700105 return __raw_readl(GPIO_IN_OUT(gpio)) & BIT(GPIO_IN_BIT);
Gregory Bean0cc2fc12010-11-24 11:53:51 -0800106}
107
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700108void __msm_gpio_set_inout(unsigned gpio, unsigned val)
Gregory Bean0cc2fc12010-11-24 11:53:51 -0800109{
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700110 __raw_writel(val ? BIT(GPIO_OUT_BIT) : 0, GPIO_IN_OUT(gpio));
Gregory Bean0cc2fc12010-11-24 11:53:51 -0800111}
112
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700113void __msm_gpio_set_config_direction(unsigned gpio, int input, int val)
Gregory Bean0cc2fc12010-11-24 11:53:51 -0800114{
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700115 if (input)
116 clr_gpio_bits(BIT(GPIO_OE_BIT), GPIO_CONFIG(gpio));
117 else {
118 __msm_gpio_set_inout(gpio, val);
119 set_gpio_bits(BIT(GPIO_OE_BIT), GPIO_CONFIG(gpio));
120 }
Gregory Bean0cc2fc12010-11-24 11:53:51 -0800121}
122
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700123void __msm_gpio_set_polarity(unsigned gpio, unsigned val)
Gregory Bean0cc2fc12010-11-24 11:53:51 -0800124{
Steve Mucklef132c6c2012-06-06 18:30:57 -0700125 if (val)
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700126 clr_gpio_bits(INTR_POL_CTL_HI, GPIO_INTR_CFG(gpio));
Steve Mucklef132c6c2012-06-06 18:30:57 -0700127 else
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700128 set_gpio_bits(INTR_POL_CTL_HI, GPIO_INTR_CFG(gpio));
Steve Mucklef132c6c2012-06-06 18:30:57 -0700129}
130
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700131unsigned __msm_gpio_get_intr_status(unsigned gpio)
Gregory Bean70cc2c02010-11-24 11:53:52 -0800132{
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700133 return __raw_readl(GPIO_INTR_STATUS(gpio)) &
Steve Mucklef132c6c2012-06-06 18:30:57 -0700134 BIT(INTR_STATUS_BIT);
Gregory Bean70cc2c02010-11-24 11:53:52 -0800135}
136
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700137void __msm_gpio_set_intr_status(unsigned gpio)
Gregory Bean70cc2c02010-11-24 11:53:52 -0800138{
Steve Mucklef132c6c2012-06-06 18:30:57 -0700139 __raw_writel(BIT(INTR_STATUS_BIT), GPIO_INTR_STATUS(gpio));
Steve Mucklef132c6c2012-06-06 18:30:57 -0700140}
141
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700142unsigned __msm_gpio_get_intr_config(unsigned gpio)
Steve Mucklef132c6c2012-06-06 18:30:57 -0700143{
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700144 return __raw_readl(GPIO_INTR_CFG(gpio));
Gregory Bean70cc2c02010-11-24 11:53:52 -0800145}
146
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700147void __msm_gpio_set_intr_cfg_enable(unsigned gpio, unsigned val)
Gregory Bean70cc2c02010-11-24 11:53:52 -0800148{
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700149 if (val) {
150 set_gpio_bits(INTR_RAW_STATUS_EN | INTR_ENABLE,
151 GPIO_INTR_CFG(gpio));
152 __raw_writel(TARGET_PROC_SCORPION, GPIO_INTR_CFG_SU(gpio));
Gregory Bean70cc2c02010-11-24 11:53:52 -0800153
Gregory Bean70cc2c02010-11-24 11:53:52 -0800154 } else {
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700155 __raw_writel(TARGET_PROC_NONE, GPIO_INTR_CFG_SU(gpio));
156 clr_gpio_bits(INTR_RAW_STATUS_EN | INTR_ENABLE,
157 GPIO_INTR_CFG(gpio));
Gregory Bean70cc2c02010-11-24 11:53:52 -0800158 }
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700159}
Gregory Bean70cc2c02010-11-24 11:53:52 -0800160
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700161void __msm_gpio_set_intr_cfg_type(unsigned gpio, unsigned type)
162{
163 unsigned cfg;
164
165 cfg = __msm_gpio_get_intr_config(gpio);
166 if (type & IRQ_TYPE_EDGE_BOTH)
167 cfg |= INTR_DECT_CTL_EDGE;
Gregory Bean70cc2c02010-11-24 11:53:52 -0800168 else
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700169 cfg &= ~INTR_DECT_CTL_EDGE;
Gregory Bean70cc2c02010-11-24 11:53:52 -0800170
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700171 if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH))
172 cfg |= INTR_POL_CTL_HI;
173 else
174 cfg &= ~INTR_POL_CTL_HI;
Gregory Bean70cc2c02010-11-24 11:53:52 -0800175
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700176 __raw_writel(cfg, GPIO_INTR_CFG(gpio));
Gregory Bean70cc2c02010-11-24 11:53:52 -0800177}
178
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700179void __gpio_tlmm_config(unsigned config)
Steve Mucklef132c6c2012-06-06 18:30:57 -0700180{
181 uint32_t flags;
182 unsigned gpio = GPIO_PIN(config);
183
Steve Mucklef132c6c2012-06-06 18:30:57 -0700184 flags = ((GPIO_DIR(config) << 9) & (0x1 << 9)) |
185 ((GPIO_DRVSTR(config) << 6) & (0x7 << 6)) |
186 ((GPIO_FUNC(config) << 2) & (0xf << 2)) |
187 ((GPIO_PULL(config) & 0x3));
188 __raw_writel(flags, GPIO_CONFIG(gpio));
Steve Mucklef132c6c2012-06-06 18:30:57 -0700189}
Steve Mucklef132c6c2012-06-06 18:30:57 -0700190
Sathish Ambleyd2ad0fa2012-03-23 11:23:47 -0700191void __msm_gpio_install_direct_irq(unsigned gpio, unsigned irq,
Steve Mucklef132c6c2012-06-06 18:30:57 -0700192 unsigned int input_polarity)
193{
Steve Mucklef132c6c2012-06-06 18:30:57 -0700194 uint32_t bits;
195
Steve Mucklef132c6c2012-06-06 18:30:57 -0700196 __raw_writel(__raw_readl(GPIO_CONFIG(gpio)) | BIT(GPIO_OE_BIT),
197 GPIO_CONFIG(gpio));
198 __raw_writel(__raw_readl(GPIO_INTR_CFG(gpio)) &
199 ~(INTR_RAW_STATUS_EN | INTR_ENABLE),
200 GPIO_INTR_CFG(gpio));
201 __raw_writel(DC_IRQ_ENABLE | TARGET_PROC_NONE,
202 GPIO_INTR_CFG_SU(gpio));
203
204 bits = TARGET_PROC_SCORPION | (gpio << 3);
205 if (input_polarity)
206 bits |= DC_POLARITY_HI;
207 __raw_writel(bits, DIR_CONN_INTR_CFG_SU(irq));
Steve Mucklef132c6c2012-06-06 18:30:57 -0700208}