1 /* $OpenBSD: sitara_cm.c,v 1.2 2013/11/06 19:03:07 syl Exp $ */
2 /* $NetBSD: sitara_cm.c,v 1.1 2013/04/17 14:31:02 bouyer Exp $ */
5 * Ben Gray <ben.r.gray@gmail.com>.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by Ben Gray.
19 * 4. The name of the company nor the name of the author may be used to
20 * endorse or promote products derived from this software without specific
21 * prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY BEN GRAY ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL BEN GRAY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
29 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
31 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
32 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 * SCM - System Control Module
38 * Hopefully in the end this module will contain a bunch of utility functions
39 * for configuring and querying the general system control registers, but for
40 * now it only does pin(pad) multiplexing.
42 * This is different from the GPIO module in that it is used to configure the
43 * pins between modules not just GPIO input/output.
45 * This file contains the generic top level driver, however it relies on chip
46 * specific settings and therefore expects an array of sitara_cm_padconf structs
47 * call ti_padconf_devmap to be located somewhere in the kernel.
50 #include <sys/types.h>
51 #include <sys/cdefs.h>
52 #include <sys/param.h>
53 #include <sys/systm.h>
54 #include <sys/kernel.h>
55 #include <sys/device.h>
58 #include <machine/bus.h>
60 #include <armv7/armv7/armv7var.h>
61 #include <armv7/omap/sitara_cm.h>
62 #include <armv7/omap/sitara_cmreg.h>
64 void sitara_cm_attach(struct device
*parent
, struct device
*self
, void *aux
);
66 struct sitara_cm_softc
{
68 bus_space_tag_t sc_iot
;
69 bus_space_handle_t sc_ioh
;
72 struct cfattach sitaracm_ca
= {
73 sizeof (struct sitara_cm_softc
), NULL
, sitara_cm_attach
76 struct cfdriver sitaracm_cd
= {
77 NULL
, "sitaracm", DV_DULL
80 static struct sitara_cm_softc
*sitara_cm_sc
= NULL
;
82 #define sitara_cm_read_2(sc, reg) \
83 bus_space_read_2((sc)->sc_iot, (sc)->sc_ioh, (reg))
84 #define sitara_cm_write_2(sc, reg, val) \
85 bus_space_write_2((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
86 #define sitara_cm_read_4(sc, reg) \
87 bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg))
88 #define sitara_cm_write_4(sc, reg, val) \
89 bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
93 * ti_padconf_devmap - Array of pins, should be defined one per SoC
95 * This array is typically defined in one of the targeted *_scm_pinumx.c
96 * files and is specific to the given SoC platform. Each entry in the array
97 * corresponds to an individual pin.
99 extern const struct sitara_cm_device sitara_cm_dev
;
103 * sitara_cm_padconf_from_name - searches the list of pads and returns entry
104 * with matching ball name.
105 * @ballname: the name of the ball
108 * A pointer to the matching padconf or NULL if the ball wasn't found.
110 static const struct sitara_cm_padconf
*
111 sitara_cm_padconf_from_name(const char *ballname
)
113 const struct sitara_cm_padconf
*padconf
;
115 padconf
= sitara_cm_dev
.padconf
;
116 while (padconf
->ballname
!= NULL
) {
117 if (strcmp(ballname
, padconf
->ballname
) == 0)
126 * sitara_cm_padconf_set_internal - sets the muxmode and state for a pad/pin
127 * @padconf: pointer to the pad structure
128 * @muxmode: the name of the mode to use for the pin, i.e. "uart1_rx"
129 * @state: the state to put the pad/pin in, i.e. PADCONF_PIN_???
133 * Internally locks it's own context.
137 * EINVAL if pin requested is outside valid range or already in use.
140 sitara_cm_padconf_set_internal(struct sitara_cm_softc
*sc
,
141 const struct sitara_cm_padconf
*padconf
,
142 const char *muxmode
, unsigned int state
)
147 /* populate the new value for the PADCONF register */
148 reg_val
= (uint16_t)(state
& sitara_cm_dev
.padconf_sate_mask
);
150 /* find the new mode requested */
151 for (mode
= 0; mode
< 8; mode
++) {
152 if ((padconf
->muxmodes
[mode
] != NULL
) &&
153 (strcmp(padconf
->muxmodes
[mode
], muxmode
) == 0)) {
158 /* couldn't find the mux mode */
160 printf("%s: Invalid mux mode \"%s\"\n", __func__
, muxmode
);
164 /* set the mux mode */
165 reg_val
|= (uint16_t)(mode
& sitara_cm_dev
.padconf_muxmode_mask
);
167 /* write the register value (16-bit writes) */
168 sitara_cm_write_2(sc
, padconf
->reg_off
, reg_val
);
174 * sitara_cm_padconf_set - sets the muxmode and state for a pad/pin
175 * @padname: the name of the pad, i.e. "c12"
176 * @muxmode: the name of the mode to use for the pin, i.e. "uart1_rx"
177 * @state: the state to put the pad/pin in, i.e. PADCONF_PIN_???
181 * Internally locks it's own context.
185 * EINVAL if pin requested is outside valid range or already in use.
188 sitara_cm_padconf_set(const char *padname
, const char *muxmode
, unsigned int state
)
190 const struct sitara_cm_padconf
*padconf
;
195 /* find the pin in the devmap */
196 padconf
= sitara_cm_padconf_from_name(padname
);
201 sitara_cm_padconf_set_internal(sitara_cm_sc
, padconf
, muxmode
, state
)
206 * sitara_cm_padconf_get - gets the muxmode and state for a pad/pin
207 * @padname: the name of the pad, i.e. "c12"
208 * @muxmode: upon return will contain the name of the muxmode of the pin
209 * @state: upon return will contain the state of the pad/pin
213 * Internally locks it's own context.
217 * EINVAL if pin requested is outside valid range or already in use.
220 sitara_cm_padconf_get(const char *padname
, const char **muxmode
,
223 const struct sitara_cm_padconf
*padconf
;
229 /* find the pin in the devmap */
230 padconf
= sitara_cm_padconf_from_name(padname
);
234 /* read the register value (16-bit reads) */
235 reg_val
= sitara_cm_read_2(sitara_cm_sc
, padconf
->reg_off
);
239 *state
= (reg_val
& sitara_cm_dev
.padconf_sate_mask
);
243 *muxmode
= padconf
->muxmodes
[
244 (reg_val
& sitara_cm_dev
.padconf_muxmode_mask
)
252 * sitara_cm_padconf_set_gpiomode - converts a pad to GPIO mode.
253 * @gpio: the GPIO pin number (0-195)
254 * @state: the state to put the pad/pin in, i.e. PADCONF_PIN_???
259 * Internally locks it's own context.
263 * EINVAL if pin requested is outside valid range or already in use.
266 sitara_cm_padconf_set_gpiomode(uint32_t gpio
, unsigned int state
)
268 const struct sitara_cm_padconf
*padconf
;
274 /* find the gpio pin in the padconf array */
275 padconf
= sitara_cm_dev
.padconf
;
276 while (padconf
->ballname
!= NULL
) {
277 if (padconf
->gpio_pin
== gpio
)
281 if (padconf
->ballname
== NULL
)
284 /* populate the new value for the PADCONF register */
285 reg_val
= (uint16_t)(state
& sitara_cm_dev
.padconf_sate_mask
);
287 /* set the mux mode */
289 (uint16_t)(padconf
->gpio_mode
& sitara_cm_dev
.padconf_muxmode_mask
);
291 /* write the register value (16-bit writes) */
292 sitara_cm_write_2(sitara_cm_sc
, padconf
->reg_off
, reg_val
);
298 * sitara_cm_padconf_get_gpiomode - gets the current GPIO mode of the pin
299 * @gpio: the GPIO pin number (0-195)
300 * @state: upon return will contain the state
305 * Internally locks it's own context.
309 * EINVAL if pin requested is outside valid range or not configured as GPIO.
312 sitara_cm_padconf_get_gpiomode(uint32_t gpio
, unsigned int *state
)
314 const struct sitara_cm_padconf
*padconf
;
320 /* find the gpio pin in the padconf array */
321 padconf
= sitara_cm_dev
.padconf
;
322 while (padconf
->ballname
!= NULL
) {
323 if (padconf
->gpio_pin
== gpio
)
327 if (padconf
->ballname
== NULL
)
330 /* read the current register settings */
331 reg_val
= sitara_cm_read_2(sitara_cm_sc
, padconf
->reg_off
);
334 * check to make sure the pins is configured as GPIO in the
337 if ((reg_val
& sitara_cm_dev
.padconf_muxmode_mask
) !=
342 * read and store the reset of the state,
343 * i.e. pull-up, pull-down, etc
346 *state
= (reg_val
& sitara_cm_dev
.padconf_sate_mask
);
353 sitara_cm_reg_read_4(uint32_t reg
, uint32_t *val
)
358 *val
= sitara_cm_read_4(sitara_cm_sc
, reg
);
363 sitara_cm_reg_write_4(uint32_t reg
, uint32_t val
)
368 sitara_cm_write_4(sitara_cm_sc
, reg
, val
);
373 sitara_cm_attach(struct device
*parent
, struct device
*self
, void *aux
)
375 struct sitara_cm_softc
*sc
= (struct sitara_cm_softc
*)self
;
376 struct armv7_attach_args
*aa
= aux
;
380 panic("sitara_cm_attach: already attached");
382 sc
->sc_iot
= aa
->aa_iot
;
384 if (bus_space_map(aa
->aa_iot
, aa
->aa_dev
->mem
[0].addr
,
385 aa
->aa_dev
->mem
[0].size
, 0, &sc
->sc_ioh
) != 0)
386 panic("%s: bus_space_map failed!\n", __func__
);
390 if (sitara_cm_reg_read_4(OMAP2SCM_REVISION
, &rev
) != 0)
391 panic("sitara_cm_attach: read revision");
392 printf(": control module, rev %d.%d\n",
393 SCM_REVISION_MAJOR(rev
), SCM_REVISION_MINOR(rev
));