/arch/arm/mach-fsm/tlmm-msm8660.c
C | 124 lines | 89 code | 19 blank | 16 comment | 3 complexity | a821ab567de4ac530a795893765bf76b MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
1/* Copyright (c) 2010, 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 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17#include <linux/io.h>
18#include <linux/module.h>
19#include <linux/spinlock.h>
20#include <mach/tlmm.h>
21#include <mach/msm_iomap.h>
22#include <mach/gpio.h>
23#include "tlmm-msm8660.h"
24
25enum msm_tlmm_register {
26 SDC4_HDRV_PULL_CTL = 0x20a0,
27 SDC3_HDRV_PULL_CTL = 0x20a4,
28};
29
30struct tlmm_field_cfg {
31 enum msm_tlmm_register reg;
32 u8 off;
33};
34
35static struct tlmm_field_cfg tlmm_hdrv_cfgs[] = {
36 {SDC4_HDRV_PULL_CTL, 6}, /* TLMM_HDRV_SDC4_CLK */
37 {SDC4_HDRV_PULL_CTL, 3}, /* TLMM_HDRV_SDC4_CMD */
38 {SDC4_HDRV_PULL_CTL, 0}, /* TLMM_HDRV_SDC4_DATA */
39 {SDC3_HDRV_PULL_CTL, 6}, /* TLMM_HDRV_SDC3_CLK */
40 {SDC3_HDRV_PULL_CTL, 3}, /* TLMM_HDRV_SDC3_CMD */
41 {SDC3_HDRV_PULL_CTL, 0}, /* TLMM_HDRV_SDC3_DATA */
42};
43
44static struct tlmm_field_cfg tlmm_pull_cfgs[] = {
45 {SDC4_HDRV_PULL_CTL, 11}, /* TLMM_PULL_SDC4_CMD */
46 {SDC4_HDRV_PULL_CTL, 9}, /* TLMM_PULL_SDC4_DATA */
47 {SDC3_HDRV_PULL_CTL, 11}, /* TLMM_PULL_SDC3_CMD */
48 {SDC3_HDRV_PULL_CTL, 9}, /* TLMM_PULL_SDC3_DATA */
49};
50
51static DEFINE_SPINLOCK(tlmm_lock);
52
53static void msm_tlmm_set_field(struct tlmm_field_cfg *configs,
54 unsigned id,
55 unsigned width,
56 unsigned val)
57{
58 unsigned long irqflags;
59 u32 mask = (1 << width) - 1;
60 u32 __iomem *reg = MSM_TLMM_BASE + configs[id].reg;
61 u32 reg_val;
62
63 spin_lock_irqsave(&tlmm_lock, irqflags);
64 reg_val = readl(reg);
65 reg_val &= ~(mask << configs[id].off);
66 reg_val |= (val & mask) << configs[id].off;
67 writel(reg_val, reg);
68 spin_unlock_irqrestore(&tlmm_lock, irqflags);
69}
70
71void msm_tlmm_set_hdrive(enum msm_tlmm_hdrive_tgt tgt, int drv_str)
72{
73 msm_tlmm_set_field(tlmm_hdrv_cfgs, tgt, 3, drv_str);
74}
75EXPORT_SYMBOL(msm_tlmm_set_hdrive);
76
77void msm_tlmm_set_pull(enum msm_tlmm_pull_tgt tgt, int pull)
78{
79 msm_tlmm_set_field(tlmm_pull_cfgs, tgt, 2, pull);
80}
81EXPORT_SYMBOL(msm_tlmm_set_pull);
82
83int gpio_tlmm_config(unsigned config, unsigned disable)
84{
85 uint32_t flags;
86 unsigned gpio = GPIO_PIN(config);
87
88 if (gpio > NR_MSM_GPIOS)
89 return -EINVAL;
90
91 flags = ((GPIO_DIR(config) << 9) & (0x1 << 9)) |
92 ((GPIO_DRVSTR(config) << 6) & (0x7 << 6)) |
93 ((GPIO_FUNC(config) << 2) & (0xf << 2)) |
94 ((GPIO_PULL(config) & 0x3));
95 writel(flags, GPIO_CONFIG(gpio));
96
97 return 0;
98}
99EXPORT_SYMBOL(gpio_tlmm_config);
100
101int msm_gpio_install_direct_irq(unsigned gpio, unsigned irq)
102{
103 unsigned long irq_flags;
104
105 if (gpio >= NR_MSM_GPIOS || irq >= NR_TLMM_SCSS_DIR_CONN_IRQ)
106 return -EINVAL;
107
108 spin_lock_irqsave(&tlmm_lock, irq_flags);
109
110 writel(readl(GPIO_CONFIG(gpio)) | BIT(GPIO_OE_BIT),
111 GPIO_CONFIG(gpio));
112 writel(readl(GPIO_INTR_CFG(gpio)) &
113 ~(INTR_RAW_STATUS_EN | INTR_ENABLE),
114 GPIO_INTR_CFG(gpio));
115 writel(DC_IRQ_ENABLE | TARGET_PROC_NONE,
116 GPIO_INTR_CFG_SU(gpio));
117 writel(DC_POLARITY_HI | TARGET_PROC_SCORPION | (gpio << 3),
118 DIR_CONN_INTR_CFG_SU(irq));
119
120 spin_unlock_irqrestore(&tlmm_lock, irq_flags);
121
122 return 0;
123}
124EXPORT_SYMBOL(msm_gpio_install_direct_irq);