1/*	$NetBSD: imx51_iomux.c,v 1.3 2012/04/15 09:51:31 bsh Exp $	*/
2
3/*
4 * Copyright (c) 2009, 2010  Genetec Corporation.  All rights reserved.
5 * Written by Hashimoto Kenichi for Genetec Corporation.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL GENETEC CORPORATION
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28#include <sys/cdefs.h>
29__KERNEL_RCSID(0, "$NetBSD: imx51_iomux.c,v 1.3 2012/04/15 09:51:31 bsh Exp $");
30
31#define	_INTR_PRIVATE
32
33#include "locators.h"
34
35#include <sys/param.h>
36#include <sys/evcnt.h>
37#include <sys/atomic.h>
38#include <sys/device.h>
39
40#include <uvm/uvm_extern.h>
41
42#include <machine/intr.h>
43
44#include <arm/cpu.h>
45#include <arm/armreg.h>
46#include <arm/cpufunc.h>
47
48#include <sys/bus.h>
49
50#include <arm/imx/imx51reg.h>
51#include <arm/imx/imx51var.h>
52
53struct iomux_softc {
54	bus_space_tag_t iomux_memt;
55	bus_space_handle_t iomux_memh;
56};
57
58#define	IOMUX_READ(iomux, reg) \
59	bus_space_read_4((iomux)->iomux_memt, (iomux)->iomux_memh, (reg))
60#define	IOMUX_WRITE(iomux, reg, val) \
61	bus_space_write_4((iomux)->iomux_memt, (iomux)->iomux_memh, (reg), (val))
62
63static int iomux_match(device_t, cfdata_t, void *);
64static void iomux_attach(device_t, device_t, void *);
65
66static struct iomux_softc *iomuxsc = NULL;
67
68CFATTACH_DECL_NEW(imxiomux, sizeof(struct iomux_softc),
69    iomux_match, iomux_attach, NULL, NULL);
70
71int
72iomux_match(device_t parent, cfdata_t cfdata, void *aux)
73{
74	struct axi_attach_args *axia = aux;
75
76	if (axia->aa_addr != IOMUXC_BASE)
77		return 0;
78
79	return 1;
80}
81
82void
83iomux_attach(device_t parent, device_t self, void *aux)
84{
85	struct axi_attach_args * const axia = aux;
86	struct iomux_softc * const iomux = device_private(self);
87	int error;
88
89	if (axia->aa_size == AXICF_SIZE_DEFAULT)
90		axia->aa_size = IOMUXC_SIZE;
91
92	iomux->iomux_memt = axia->aa_iot;
93	error = bus_space_map(axia->aa_iot, axia->aa_addr, axia->aa_size,
94			      0, &iomux->iomux_memh);
95
96	if (error) {
97		aprint_error(": failed to map register %#lx@%#lx: %d\n",
98		    axia->aa_size, axia->aa_addr, error);
99		return;
100	}
101
102	aprint_normal("\n");
103
104	iomuxsc = iomux;
105}
106
107static void
108iomux_set_function_sub(struct iomux_softc *sc, uint32_t pin, uint32_t fn)
109{
110	bus_size_t mux_ctl_reg = IOMUX_PIN_TO_MUX_ADDRESS(pin);
111
112	if (mux_ctl_reg != IOMUX_MUX_NONE)
113		bus_space_write_4(sc->iomux_memt, sc->iomux_memh,
114		    mux_ctl_reg, fn);
115}
116
117void
118iomux_set_function(unsigned int pin, unsigned int fn)
119{
120	iomux_set_function_sub(iomuxsc, pin, fn);
121}
122
123
124static void
125iomux_set_pad_sub(struct iomux_softc *sc, uint32_t pin, uint32_t config)
126{
127	bus_size_t pad_ctl_reg = IOMUX_PIN_TO_PAD_ADDRESS(pin);
128
129	if (pad_ctl_reg != IOMUX_PAD_NONE)
130		bus_space_write_4(sc->iomux_memt, sc->iomux_memh,
131		    pad_ctl_reg, config);
132}
133
134void
135iomux_set_pad(unsigned int pin, unsigned int config)
136{
137	iomux_set_pad_sub(iomuxsc, pin, config);
138}
139
140#if 0
141void
142iomux_set_input(unsigned int input, unsigned int config)
143{
144	bus_size_t input_ctl_reg = input;
145
146	bus_space_write_4(iomuxsc->iomux_memt, iomuxsc->iomux_memh,
147	    input_ctl_reg, config);
148}
149#endif
150
151void
152iomux_mux_config(const struct iomux_conf *conflist)
153{
154	int i;
155
156	for (i = 0; conflist[i].pin != IOMUX_CONF_EOT; i++) {
157		iomux_set_pad_sub(iomuxsc, conflist[i].pin, conflist[i].pad);
158		iomux_set_function_sub(iomuxsc, conflist[i].pin,
159		    conflist[i].mux);
160	}
161}
162
163#if 0
164void
165iomux_input_config(const struct iomux_input_conf *conflist)
166{
167	int i;
168
169	for (i = 0; conflist[i].inout != -1; i++) {
170		iomux_set_inout(iomuxsc, conflist[i].inout,
171		    conflist[i].inout_mode);
172	}
173}
174#endif
175
176