1/*
2 * Copyright (c) 2010
3 *	Ben Gray <ben.r.gray@gmail.com>.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 *    must display the following acknowledgement:
16 *	This product includes software developed by Ben Gray.
17 * 4. The name of the company nor the name of the author may be used to
18 *    endorse or promote products derived from this software without specific
19 *    prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY BEN GRAY ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL BEN GRAY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
30 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33/**
34 * Exposes pinmux module to pinctrl-compatible interface
35 */
36
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/kernel.h>
40#include <sys/module.h>
41#include <sys/bus.h>
42#include <sys/resource.h>
43#include <sys/rman.h>
44#include <sys/lock.h>
45#include <sys/mutex.h>
46
47#include <machine/bus.h>
48#include <machine/resource.h>
49
50#include <dev/ofw/openfirm.h>
51#include <dev/ofw/ofw_bus.h>
52#include <dev/ofw/ofw_bus_subr.h>
53#include <dev/fdt/fdt_pinctrl.h>
54
55#include <arm/ti/omap4/omap4_scm_padconf.h>
56#include <arm/ti/am335x/am335x_scm_padconf.h>
57#include <arm/ti/ti_cpuid.h>
58#include "ti_pinmux.h"
59
60struct pincfg {
61	uint32_t reg;
62	uint32_t conf;
63};
64
65static struct resource_spec ti_pinmux_res_spec[] = {
66	{ SYS_RES_MEMORY,	0,	RF_ACTIVE },	/* Control memory window */
67	{ -1, 0 }
68};
69
70static struct ti_pinmux_softc *ti_pinmux_sc;
71
72#define	ti_pinmux_read_2(sc, reg)		\
73    bus_space_read_2((sc)->sc_bst, (sc)->sc_bsh, (reg))
74#define	ti_pinmux_write_2(sc, reg, val)		\
75    bus_space_write_2((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
76#define	ti_pinmux_read_4(sc, reg)		\
77    bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
78#define	ti_pinmux_write_4(sc, reg, val)		\
79    bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
80
81/**
82 *	ti_padconf_devmap - Array of pins, should be defined one per SoC
83 *
84 *	This array is typically defined in one of the targeted *_scm_pinumx.c
85 *	files and is specific to the given SoC platform. Each entry in the array
86 *	corresponds to an individual pin.
87 */
88static const struct ti_pinmux_device *ti_pinmux_dev;
89
90/**
91 *	ti_pinmux_padconf_from_name - searches the list of pads and returns entry
92 *	                             with matching ball name.
93 *	@ballname: the name of the ball
94 *
95 *	RETURNS:
96 *	A pointer to the matching padconf or NULL if the ball wasn't found.
97 */
98static const struct ti_pinmux_padconf*
99ti_pinmux_padconf_from_name(const char *ballname)
100{
101	const struct ti_pinmux_padconf *padconf;
102
103	padconf = ti_pinmux_dev->padconf;
104	while (padconf->ballname != NULL) {
105		if (strcmp(ballname, padconf->ballname) == 0)
106			return(padconf);
107		padconf++;
108	}
109
110	return (NULL);
111}
112
113/**
114 *	ti_pinmux_padconf_set_internal - sets the muxmode and state for a pad/pin
115 *	@padconf: pointer to the pad structure
116 *	@muxmode: the name of the mode to use for the pin, i.e. "uart1_rx"
117 *	@state: the state to put the pad/pin in, i.e. PADCONF_PIN_???
118 *
119 *
120 *	LOCKING:
121 *	Internally locks it's own context.
122 *
123 *	RETURNS:
124 *	0 on success.
125 *	EINVAL if pin requested is outside valid range or already in use.
126 */
127static int
128ti_pinmux_padconf_set_internal(struct ti_pinmux_softc *sc,
129    const struct ti_pinmux_padconf *padconf,
130    const char *muxmode, unsigned int state)
131{
132	unsigned int mode;
133	uint16_t reg_val;
134
135	/* populate the new value for the PADCONF register */
136	reg_val = (uint16_t)(state & ti_pinmux_dev->padconf_sate_mask);
137
138	/* find the new mode requested */
139	for (mode = 0; mode < 8; mode++) {
140		if ((padconf->muxmodes[mode] != NULL) &&
141		    (strcmp(padconf->muxmodes[mode], muxmode) == 0)) {
142			break;
143		}
144	}
145
146	/* couldn't find the mux mode */
147	if (mode >= 8) {
148		printf("Invalid mode \"%s\"\n", muxmode);
149		return (EINVAL);
150	}
151
152	/* set the mux mode */
153	reg_val |= (uint16_t)(mode & ti_pinmux_dev->padconf_muxmode_mask);
154
155	if (bootverbose)
156		device_printf(sc->sc_dev, "setting internal %x for %s\n",
157		    reg_val, muxmode);
158	/* write the register value (16-bit writes) */
159	ti_pinmux_write_2(sc, padconf->reg_off, reg_val);
160
161	return (0);
162}
163
164/**
165 *	ti_pinmux_padconf_set - sets the muxmode and state for a pad/pin
166 *	@padname: the name of the pad, i.e. "c12"
167 *	@muxmode: the name of the mode to use for the pin, i.e. "uart1_rx"
168 *	@state: the state to put the pad/pin in, i.e. PADCONF_PIN_???
169 *
170 *
171 *	LOCKING:
172 *	Internally locks it's own context.
173 *
174 *	RETURNS:
175 *	0 on success.
176 *	EINVAL if pin requested is outside valid range or already in use.
177 */
178int
179ti_pinmux_padconf_set(const char *padname, const char *muxmode, unsigned int state)
180{
181	const struct ti_pinmux_padconf *padconf;
182
183	if (!ti_pinmux_sc)
184		return (ENXIO);
185
186	/* find the pin in the devmap */
187	padconf = ti_pinmux_padconf_from_name(padname);
188	if (padconf == NULL)
189		return (EINVAL);
190
191	return (ti_pinmux_padconf_set_internal(ti_pinmux_sc, padconf, muxmode, state));
192}
193
194/**
195 *	ti_pinmux_padconf_get - gets the muxmode and state for a pad/pin
196 *	@padname: the name of the pad, i.e. "c12"
197 *	@muxmode: upon return will contain the name of the muxmode of the pin
198 *	@state: upon return will contain the state of the pad/pin
199 *
200 *
201 *	LOCKING:
202 *	Internally locks it's own context.
203 *
204 *	RETURNS:
205 *	0 on success.
206 *	EINVAL if pin requested is outside valid range or already in use.
207 */
208int
209ti_pinmux_padconf_get(const char *padname, const char **muxmode,
210    unsigned int *state)
211{
212	const struct ti_pinmux_padconf *padconf;
213	uint16_t reg_val;
214
215	if (!ti_pinmux_sc)
216		return (ENXIO);
217
218	/* find the pin in the devmap */
219	padconf = ti_pinmux_padconf_from_name(padname);
220	if (padconf == NULL)
221		return (EINVAL);
222
223	/* read the register value (16-bit reads) */
224	reg_val = ti_pinmux_read_2(ti_pinmux_sc, padconf->reg_off);
225
226	/* save the state */
227	if (state)
228		*state = (reg_val & ti_pinmux_dev->padconf_sate_mask);
229
230	/* save the mode */
231	if (muxmode)
232		*muxmode = padconf->muxmodes[(reg_val & ti_pinmux_dev->padconf_muxmode_mask)];
233
234	return (0);
235}
236
237/**
238 *	ti_pinmux_padconf_set_gpiomode - converts a pad to GPIO mode.
239 *	@gpio: the GPIO pin number (0-195)
240 *	@state: the state to put the pad/pin in, i.e. PADCONF_PIN_???
241 *
242 *
243 *
244 *	LOCKING:
245 *	Internally locks it's own context.
246 *
247 *	RETURNS:
248 *	0 on success.
249 *	EINVAL if pin requested is outside valid range or already in use.
250 */
251int
252ti_pinmux_padconf_set_gpiomode(uint32_t gpio, unsigned int state)
253{
254	const struct ti_pinmux_padconf *padconf;
255	uint16_t reg_val;
256
257	if (!ti_pinmux_sc)
258		return (ENXIO);
259
260	/* find the gpio pin in the padconf array */
261	padconf = ti_pinmux_dev->padconf;
262	while (padconf->ballname != NULL) {
263		if (padconf->gpio_pin == gpio)
264			break;
265		padconf++;
266	}
267	if (padconf->ballname == NULL)
268		return (EINVAL);
269
270	/* populate the new value for the PADCONF register */
271	reg_val = (uint16_t)(state & ti_pinmux_dev->padconf_sate_mask);
272
273	/* set the mux mode */
274	reg_val |= (uint16_t)(padconf->gpio_mode & ti_pinmux_dev->padconf_muxmode_mask);
275
276	/* write the register value (16-bit writes) */
277	ti_pinmux_write_2(ti_pinmux_sc, padconf->reg_off, reg_val);
278
279	return (0);
280}
281
282/**
283 *	ti_pinmux_padconf_get_gpiomode - gets the current GPIO mode of the pin
284 *	@gpio: the GPIO pin number (0-195)
285 *	@state: upon return will contain the state
286 *
287 *
288 *
289 *	LOCKING:
290 *	Internally locks it's own context.
291 *
292 *	RETURNS:
293 *	0 on success.
294 *	EINVAL if pin requested is outside valid range or not configured as GPIO.
295 */
296int
297ti_pinmux_padconf_get_gpiomode(uint32_t gpio, unsigned int *state)
298{
299	const struct ti_pinmux_padconf *padconf;
300	uint16_t reg_val;
301
302	if (!ti_pinmux_sc)
303		return (ENXIO);
304
305	/* find the gpio pin in the padconf array */
306	padconf = ti_pinmux_dev->padconf;
307	while (padconf->ballname != NULL) {
308		if (padconf->gpio_pin == gpio)
309			break;
310		padconf++;
311	}
312	if (padconf->ballname == NULL)
313		return (EINVAL);
314
315	/* read the current register settings */
316	reg_val = ti_pinmux_read_2(ti_pinmux_sc, padconf->reg_off);
317
318	/* check to make sure the pins is configured as GPIO in the first state */
319	if ((reg_val & ti_pinmux_dev->padconf_muxmode_mask) != padconf->gpio_mode)
320		return (EINVAL);
321
322	/* read and store the reset of the state, i.e. pull-up, pull-down, etc */
323	if (state)
324		*state = (reg_val & ti_pinmux_dev->padconf_sate_mask);
325
326	return (0);
327}
328
329static int
330ti_pinmux_configure_pins(device_t dev, phandle_t cfgxref)
331{
332	struct pincfg *cfgtuples, *cfg;
333	phandle_t cfgnode;
334	int i, ntuples;
335	static struct ti_pinmux_softc *sc;
336
337	sc = device_get_softc(dev);
338	cfgnode = OF_node_from_xref(cfgxref);
339	ntuples = OF_getencprop_alloc_multi(cfgnode, "pinctrl-single,pins",
340	    sizeof(*cfgtuples), (void **)&cfgtuples);
341
342	if (ntuples < 0)
343		return (ENOENT);
344
345	if (ntuples == 0)
346		return (0); /* Empty property is not an error. */
347
348	for (i = 0, cfg = cfgtuples; i < ntuples; i++, cfg++) {
349		if (bootverbose) {
350			char name[32];
351			OF_getprop(cfgnode, "name", &name, sizeof(name));
352			printf("%16s: muxreg 0x%04x muxval 0x%02x\n",
353			    name, cfg->reg, cfg->conf);
354		}
355
356		/* write the register value (16-bit writes) */
357		ti_pinmux_write_2(sc, cfg->reg, cfg->conf);
358	}
359
360	OF_prop_free(cfgtuples);
361
362	return (0);
363}
364
365/*
366 * Device part of OMAP SCM driver
367 */
368
369static int
370ti_pinmux_probe(device_t dev)
371{
372	if (!ofw_bus_status_okay(dev))
373		return (ENXIO);
374
375	if (!ofw_bus_is_compatible(dev, "pinctrl-single"))
376		return (ENXIO);
377
378	if (ti_pinmux_sc) {
379		printf("%s: multiple pinctrl modules in device tree data, ignoring\n",
380		    __func__);
381		return (EEXIST);
382	}
383	switch (ti_chip()) {
384#ifdef SOC_OMAP4
385	case CHIP_OMAP_4:
386		ti_pinmux_dev = &omap4_pinmux_dev;
387		break;
388#endif
389#ifdef SOC_TI_AM335X
390	case CHIP_AM335X:
391		ti_pinmux_dev = &ti_am335x_pinmux_dev;
392		break;
393#endif
394	default:
395		printf("Unknown CPU in pinmux\n");
396		return (ENXIO);
397	}
398
399	device_set_desc(dev, "TI Pinmux Module");
400	return (BUS_PROBE_DEFAULT);
401}
402
403/**
404 *	ti_pinmux_attach - attaches the pinmux to the simplebus
405 *	@dev: new device
406 *
407 *	RETURNS
408 *	Zero on success or ENXIO if an error occuried.
409 */
410static int
411ti_pinmux_attach(device_t dev)
412{
413	struct ti_pinmux_softc *sc = device_get_softc(dev);
414
415#if 0
416	if (ti_pinmux_sc)
417		return (ENXIO);
418#endif
419
420	sc->sc_dev = dev;
421
422	if (bus_alloc_resources(dev, ti_pinmux_res_spec, sc->sc_res)) {
423		device_printf(dev, "could not allocate resources\n");
424		return (ENXIO);
425	}
426
427	sc->sc_bst = rman_get_bustag(sc->sc_res[0]);
428	sc->sc_bsh = rman_get_bushandle(sc->sc_res[0]);
429
430	if (ti_pinmux_sc == NULL)
431		ti_pinmux_sc = sc;
432
433	fdt_pinctrl_register(dev, "pinctrl-single,pins");
434	fdt_pinctrl_configure_tree(dev);
435
436	return (0);
437}
438
439static device_method_t ti_pinmux_methods[] = {
440	DEVMETHOD(device_probe,		ti_pinmux_probe),
441	DEVMETHOD(device_attach,	ti_pinmux_attach),
442
443        /* fdt_pinctrl interface */
444	DEVMETHOD(fdt_pinctrl_configure, ti_pinmux_configure_pins),
445	{ 0, 0 }
446};
447
448static driver_t ti_pinmux_driver = {
449	"ti_pinmux",
450	ti_pinmux_methods,
451	sizeof(struct ti_pinmux_softc),
452};
453
454DRIVER_MODULE(ti_pinmux, simplebus, ti_pinmux_driver, 0, 0);
455MODULE_VERSION(ti_pinmux, 1);
456MODULE_DEPEND(ti_pinmux, ti_scm, 1, 1, 1);
457