1 /*
2  * arch/arm/plat-spear/include/plat/padmux.c
3  *
4  * SPEAr platform specific gpio pads muxing source file
5  *
6  * Copyright (C) 2009 ST Microelectronics
7  * Viresh Kumar<viresh.kumar@st.com>
8  *
9  * This file is licensed under the terms of the GNU General Public
10  * License version 2. This program is licensed "as is" without any
11  * warranty of any kind, whether express or implied.
12  */
13 
14 #include <linux/err.h>
15 #include <linux/io.h>
16 #include <linux/slab.h>
17 #include <plat/padmux.h>
18 
19 /*
20  * struct pmx: pmx definition structure
21  *
22  * base: base address of configuration registers
23  * mode_reg: mode configurations
24  * mux_reg: muxing configurations
25  * active_mode: pointer to current active mode
26  */
27 struct pmx {
28 	u32 base;
29 	struct pmx_reg mode_reg;
30 	struct pmx_reg mux_reg;
31 	struct pmx_mode *active_mode;
32 };
33 
34 static struct pmx *pmx;
35 
36 /**
37  * pmx_mode_set - Enables an multiplexing mode
38  * @mode - pointer to pmx mode
39  *
40  * It will set mode of operation in hardware.
41  * Returns -ve on Err otherwise 0
42  */
pmx_mode_set(struct pmx_mode * mode)43 static int pmx_mode_set(struct pmx_mode *mode)
44 {
45 	u32 val;
46 
47 	if (!mode->name)
48 		return -EFAULT;
49 
50 	pmx->active_mode = mode;
51 
52 	val = readl(pmx->base + pmx->mode_reg.offset);
53 	val &= ~pmx->mode_reg.mask;
54 	val |= mode->mask & pmx->mode_reg.mask;
55 	writel(val, pmx->base + pmx->mode_reg.offset);
56 
57 	return 0;
58 }
59 
60 /**
61  * pmx_devs_enable - Enables list of devices
62  * @devs - pointer to pmx device array
63  * @count - number of devices to enable
64  *
65  * It will enable pads for all required peripherals once and only once.
66  * If peripheral is not supported by current mode then request is rejected.
67  * Conflicts between peripherals are not handled and peripherals will be
68  * enabled in the order they are present in pmx_dev array.
69  * In case of conflicts last peripheral enabled will be present.
70  * Returns -ve on Err otherwise 0
71  */
pmx_devs_enable(struct pmx_dev ** devs,u8 count)72 static int pmx_devs_enable(struct pmx_dev **devs, u8 count)
73 {
74 	u32 val, i, mask;
75 
76 	if (!count)
77 		return -EINVAL;
78 
79 	val = readl(pmx->base + pmx->mux_reg.offset);
80 	for (i = 0; i < count; i++) {
81 		u8 j = 0;
82 
83 		if (!devs[i]->name || !devs[i]->modes) {
84 			printk(KERN_ERR "padmux: dev name or modes is null\n");
85 			continue;
86 		}
87 		/* check if peripheral exists in active mode */
88 		if (pmx->active_mode) {
89 			bool found = false;
90 			for (j = 0; j < devs[i]->mode_count; j++) {
91 				if (devs[i]->modes[j].ids &
92 						pmx->active_mode->id) {
93 					found = true;
94 					break;
95 				}
96 			}
97 			if (found == false) {
98 				printk(KERN_ERR "%s device not available in %s"\
99 						"mode\n", devs[i]->name,
100 						pmx->active_mode->name);
101 				continue;
102 			}
103 		}
104 
105 		/* enable peripheral */
106 		mask = devs[i]->modes[j].mask & pmx->mux_reg.mask;
107 		if (devs[i]->enb_on_reset)
108 			val &= ~mask;
109 		else
110 			val |= mask;
111 
112 		devs[i]->is_active = true;
113 	}
114 	writel(val, pmx->base + pmx->mux_reg.offset);
115 	kfree(pmx);
116 
117 	/* this will ensure that multiplexing can't be changed now */
118 	pmx = (struct pmx *)-1;
119 
120 	return 0;
121 }
122 
123 /**
124  * pmx_register - registers a platform requesting pad mux feature
125  * @driver - pointer to driver structure containing driver specific parameters
126  *
127  * Also this must be called only once. This will allocate memory for pmx
128  * structure, will call pmx_mode_set, will call pmx_devs_enable.
129  * Returns -ve on Err otherwise 0
130  */
pmx_register(struct pmx_driver * driver)131 int pmx_register(struct pmx_driver *driver)
132 {
133 	int ret = 0;
134 
135 	if (pmx)
136 		return -EPERM;
137 	if (!driver->base || !driver->devs)
138 		return -EFAULT;
139 
140 	pmx = kzalloc(sizeof(*pmx), GFP_KERNEL);
141 	if (!pmx)
142 		return -ENOMEM;
143 
144 	pmx->base = (u32)driver->base;
145 	pmx->mode_reg.offset = driver->mode_reg.offset;
146 	pmx->mode_reg.mask = driver->mode_reg.mask;
147 	pmx->mux_reg.offset = driver->mux_reg.offset;
148 	pmx->mux_reg.mask = driver->mux_reg.mask;
149 
150 	/* choose mode to enable */
151 	if (driver->mode) {
152 		ret = pmx_mode_set(driver->mode);
153 		if (ret)
154 			goto pmx_fail;
155 	}
156 	ret = pmx_devs_enable(driver->devs, driver->devs_count);
157 	if (ret)
158 		goto pmx_fail;
159 
160 	return 0;
161 
162 pmx_fail:
163 	return ret;
164 }
165