1 /* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
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.
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.
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
17 #include <linux/module.h>
18 #include <linux/spinlock.h>
20 #include "proc_comm.h"
22 static DEFINE_SPINLOCK(gpiomux_lock
);
24 static void __msm_gpiomux_write(unsigned gpio
, gpiomux_config_t val
)
26 unsigned tlmm_config
= (val
& ~GPIOMUX_CTL_MASK
) |
27 ((gpio
& 0x3ff) << 4);
28 unsigned tlmm_disable
= 0;
31 rc
= msm_proc_comm(PCOM_RPC_GPIO_TLMM_CONFIG_EX
,
32 &tlmm_config
, &tlmm_disable
);
34 pr_err("%s: unexpected proc_comm failure %d: %08x %08x\n",
35 __func__
, rc
, tlmm_config
, tlmm_disable
);
38 int msm_gpiomux_write(unsigned gpio
,
39 gpiomux_config_t active
,
40 gpiomux_config_t suspended
)
42 struct msm_gpiomux_config
*cfg
= msm_gpiomux_configs
+ gpio
;
43 unsigned long irq_flags
;
44 gpiomux_config_t setting
;
46 if (gpio
>= GPIOMUX_NGPIOS
)
49 spin_lock_irqsave(&gpiomux_lock
, irq_flags
);
51 if (active
& GPIOMUX_VALID
)
54 if (suspended
& GPIOMUX_VALID
)
55 cfg
->suspended
= suspended
;
57 setting
= cfg
->ref
? active
: suspended
;
58 if (setting
& GPIOMUX_VALID
)
59 __msm_gpiomux_write(gpio
, setting
);
61 spin_unlock_irqrestore(&gpiomux_lock
, irq_flags
);
64 EXPORT_SYMBOL(msm_gpiomux_write
);
66 int msm_gpiomux_get(unsigned gpio
)
68 struct msm_gpiomux_config
*cfg
= msm_gpiomux_configs
+ gpio
;
69 unsigned long irq_flags
;
71 if (gpio
>= GPIOMUX_NGPIOS
)
74 spin_lock_irqsave(&gpiomux_lock
, irq_flags
);
75 if (cfg
->ref
++ == 0 && cfg
->active
& GPIOMUX_VALID
)
76 __msm_gpiomux_write(gpio
, cfg
->active
);
77 spin_unlock_irqrestore(&gpiomux_lock
, irq_flags
);
80 EXPORT_SYMBOL(msm_gpiomux_get
);
82 int msm_gpiomux_put(unsigned gpio
)
84 struct msm_gpiomux_config
*cfg
= msm_gpiomux_configs
+ gpio
;
85 unsigned long irq_flags
;
87 if (gpio
>= GPIOMUX_NGPIOS
)
90 spin_lock_irqsave(&gpiomux_lock
, irq_flags
);
91 BUG_ON(cfg
->ref
== 0);
92 if (--cfg
->ref
== 0 && cfg
->suspended
& GPIOMUX_VALID
)
93 __msm_gpiomux_write(gpio
, cfg
->suspended
);
94 spin_unlock_irqrestore(&gpiomux_lock
, irq_flags
);
97 EXPORT_SYMBOL(msm_gpiomux_put
);
99 static int __init
gpiomux_init(void)
103 for (n
= 0; n
< GPIOMUX_NGPIOS
; ++n
) {
104 msm_gpiomux_configs
[n
].ref
= 0;
105 if (!(msm_gpiomux_configs
[n
].suspended
& GPIOMUX_VALID
))
107 __msm_gpiomux_write(n
, msm_gpiomux_configs
[n
].suspended
);
111 postcore_initcall(gpiomux_init
);