2 * linux/arch/arm/mach-sc8800s/mfp-sprd.c
4 * Spreadtrum SoC multi-function pin configuration support
6 * The GPIOs on SoC can be configured as one of many alternate
9 * Author: Yingchun Li(yingchun.li@spreadtrum.com)
10 * Created: March 10, 2010
11 * Copyright: Spreadtrum Inc.
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation.
19 //#include <linux/module.h>
20 //#include <linux/kernel.h>
22 //#include <mach/mfp.h>
23 //#include <mach/regs_cpc.h>
24 #include <asm/arch/mfp.h>
25 #include <asm/arch/sc8800g_reg_base.h>
26 #include <asm/arch/sc8800g_cpc.h>
28 #include <asm/arch/adi_hal_internal.h>
31 NOTE: pin to gpio's map, you should check it from your chip's spec
33 in the map table, pin as the index, for mostly we use
34 MFP_PIN_TO_GPIO to get the gpio from the pin
36 const static unsigned long pin_gpio_map[MFP_PIN_MAX] = {
37 [MFP_PIN_MAX - 1] = 0xffff
43 we cann't find a easy way to map pin to gpio, so drop it.
45 unsigned long mfp_to_gpio(int pin)
50 static int __mfp_validate(unsigned long c)
55 static unsigned long __mfp_get_pin_reg(int c)
58 if (!(c& A_DIE_PIN)) {
59 pin_offset = MFP_CFG_TO_REG_OFFS(c);
60 return (unsigned long)PIN_CTL_BASE + pin_offset;
63 pin_offset = MFP_CFG_TO_REG_OFFS(c);
64 return (unsigned long)ANA_PIN_CTL_BASE + pin_offset;
68 #define pin_is_a_die(c) (c & A_DIE_PIN)
70 #define MFP_DBG(fmt...) pr_debug(fmt)
71 static unsigned long __mfp_get_physical(int c)
74 if (!(c & A_DIE_PIN)) {
75 pin_offset = MFP_CFG_TO_REG_OFFS(c);
76 return (unsigned long)SPRD_CPC_PHYS + pin_offset;
79 pin_offset = MFP_CFG_TO_REG_OFFS(c);
80 return (unsigned long)SPRD_MISC_PHYS + 0x180 + pin_offset;
84 #define MFP_DBG(fmt...)
87 static int __mfp_config_pin(unsigned long c)
90 unsigned long pin_reg;
91 unsigned long pin_cfg;
94 pin_reg = __mfp_get_pin_reg(c);
95 pin_area = pin_is_a_die(c);
97 MFP_DBG("register is :0x%x, old config is %x\r\n",
98 __mfp_get_physical(c),
99 pin_area == A_DIE_PIN ? ANA_REG_GET(pin_reg) :
100 __raw_readl(pin_reg));
102 local_irq_save(flags);
103 if (pin_area == A_DIE_PIN)
104 pin_cfg = ANA_REG_GET(pin_reg);
106 pin_cfg =__raw_readl(pin_reg);
107 if (c & MFP_IO_SET) {
108 pin_cfg = (pin_cfg & ~MFP_IO_MASK) | (c & MFP_IO_MASK);
111 if (c & MFP_S_PULL_SET) {
112 pin_cfg = (pin_cfg & ~MFP_S_PULL_MASK) | (c & MFP_S_PULL_MASK);
115 if (c & MFP_AF_SET) {
116 pin_cfg = (pin_cfg & ~MFP_AF_MASK) | (c & MFP_AF_MASK);
119 if (c & MFP_F_PULL_SET) {
120 pin_cfg = (pin_cfg & ~MFP_F_PULL_MASK) | (c & MFP_F_PULL_MASK);
123 if (c & MFP_DS_SET) {
124 pin_cfg = (pin_cfg & ~MFP_DS_MASK) | (c & MFP_DS_MASK);
127 if (pin_area == A_DIE_PIN)
128 ANA_REG_SET(pin_reg, pin_cfg);
130 __raw_writel(pin_cfg, pin_reg);
131 local_irq_restore(flags);
133 MFP_DBG("new config is :%x\r\n", (int)pin_cfg);
138 void sprd_mfp_config(unsigned long *mfp_cfgs, int num)
145 for (i = 0, c = mfp_cfgs; i < num; i++, c++) {
147 res = __mfp_validate((*c));
151 local_irq_save(flags);
153 __mfp_config_pin(*c);
155 local_irq_restore(flags);
158 //EXPORT_SYMBOL_GPL(sprd_mfp_config);