xref: /netbsd-src/sys/arch/evbarm/mpcsa/mpcsa_spi.c (revision cbab9cadce21ae72fac13910001079fff214cc29)
1*cbab9cadSchs /*	$Id: mpcsa_spi.c,v 1.3 2012/10/27 17:17:48 chs Exp $	*/
2*cbab9cadSchs /*	$NetBSD: mpcsa_spi.c,v 1.3 2012/10/27 17:17:48 chs Exp $	*/
3c62a0ac4Smatt 
4c62a0ac4Smatt /*
5c62a0ac4Smatt  * Copyright (c) 2007 Embedtronics Oy. All rights reserved.
6c62a0ac4Smatt  *
7c62a0ac4Smatt  * Redistribution and use in source and binary forms, with or without
8c62a0ac4Smatt  * modification, are permitted provided that the following conditions
9c62a0ac4Smatt  * are met:
10c62a0ac4Smatt  * 1. Redistributions of source code must retain the above copyright
11c62a0ac4Smatt  *    notice, this list of conditions and the following disclaimer.
12c62a0ac4Smatt  * 2. Redistributions in binary form must reproduce the above copyright
13c62a0ac4Smatt  *    notice, this list of conditions and the following disclaimer in the
14c62a0ac4Smatt  *    documentation and/or other materials provided with the distribution.
15c62a0ac4Smatt  *
16c62a0ac4Smatt  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17c62a0ac4Smatt  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18c62a0ac4Smatt  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19c62a0ac4Smatt  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20c62a0ac4Smatt  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21c62a0ac4Smatt  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22c62a0ac4Smatt  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23c62a0ac4Smatt  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24c62a0ac4Smatt  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25c62a0ac4Smatt  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26c62a0ac4Smatt  * SUCH DAMAGE.
27c62a0ac4Smatt  */
28c62a0ac4Smatt 
29c62a0ac4Smatt #include <sys/cdefs.h>
30*cbab9cadSchs __KERNEL_RCSID(0, "$NetBSD: mpcsa_spi.c,v 1.3 2012/10/27 17:17:48 chs Exp $");
31c62a0ac4Smatt 
32c62a0ac4Smatt #include <sys/param.h>
33c62a0ac4Smatt #include <sys/systm.h>
34c62a0ac4Smatt #include <sys/kernel.h>
35c62a0ac4Smatt #include <sys/device.h>
36c62a0ac4Smatt #include <sys/lock.h>
37c62a0ac4Smatt #include <arm/at91/at91reg.h>
38c62a0ac4Smatt #include <arm/at91/at91var.h>
39c62a0ac4Smatt #include <arm/at91/at91spivar.h>
40c62a0ac4Smatt #include <arm/at91/at91piovar.h>
41c62a0ac4Smatt 
42c62a0ac4Smatt #ifdef MPCSA_SPI_DEBUG
43c62a0ac4Smatt int mpcsa_spi_debug = MPCSA_SPI_DEBUG;
44c62a0ac4Smatt #define DPRINTFN(n,x)	if (mpcsa_spi_debug>(n)) printf x;
45c62a0ac4Smatt #else
46c62a0ac4Smatt #define DPRINTFN(n,x)
47c62a0ac4Smatt #endif
48c62a0ac4Smatt 
49c62a0ac4Smatt struct at91pio_softc;
50c62a0ac4Smatt 
51c62a0ac4Smatt struct mpcsa_spi_softc {
52*cbab9cadSchs 	struct at91spi_softc	sc_at91spi;
53c62a0ac4Smatt 	struct at91pio_softc	*sc_pioa, *sc_piod;
54c62a0ac4Smatt };
55c62a0ac4Smatt 
56*cbab9cadSchs static int mpcsa_spi_match(device_t, cfdata_t, void *);
57*cbab9cadSchs static void mpcsa_spi_attach(device_t, device_t, void *);
58c62a0ac4Smatt 
59*cbab9cadSchs CFATTACH_DECL_NEW(mpcsa_spi, sizeof(struct mpcsa_spi_softc),
60c62a0ac4Smatt 	      mpcsa_spi_match, mpcsa_spi_attach, NULL, NULL);
61c62a0ac4Smatt 
62c62a0ac4Smatt static int mpcsa_spi_select(void *self, int sel);
63c62a0ac4Smatt 
64c62a0ac4Smatt struct at91spi_machdep mpcsa_spi_tag = {
65c62a0ac4Smatt 	mpcsa_spi_select
66c62a0ac4Smatt };
67c62a0ac4Smatt 
68c62a0ac4Smatt static int
mpcsa_spi_match(device_t parent,cfdata_t match,void * aux)69*cbab9cadSchs mpcsa_spi_match(device_t parent, cfdata_t match, void *aux)
70c62a0ac4Smatt {
71c62a0ac4Smatt 	if (strcmp(match->cf_name, "at91spi") == 0 && strcmp(match->cf_atname, "mpcsa_spi") == 0)
72c62a0ac4Smatt 		return 2;
73c62a0ac4Smatt 	return 0;
74c62a0ac4Smatt }
75c62a0ac4Smatt 
76c62a0ac4Smatt #define	GPIO_SPICS0(func)	(func)(sc->sc_pioa, 3)
77c62a0ac4Smatt #define	GPIO_SPICS1(func)	(func)(sc->sc_pioa, 4)
78c62a0ac4Smatt #define	GPIO_SPICS2(func)	(func)(sc->sc_piod, 19)
79c62a0ac4Smatt 
80c62a0ac4Smatt 
81c62a0ac4Smatt static void
mpcsa_spi_attach(device_t parent,device_t self,void * aux)82*cbab9cadSchs mpcsa_spi_attach(device_t parent, device_t self, void *aux)
83c62a0ac4Smatt {
84*cbab9cadSchs 	struct mpcsa_spi_softc *sc = device_private(self);
85c62a0ac4Smatt 
86c62a0ac4Smatt 	// do some checks
87c62a0ac4Smatt 	if ((sc->sc_pioa = at91pio_sc(AT91_PIOA)) == NULL) {
88c62a0ac4Smatt 		printf("no PIOA!\n");
89c62a0ac4Smatt 		return;
90c62a0ac4Smatt 	}
91c62a0ac4Smatt 	if ((sc->sc_piod = at91pio_sc(AT91_PIOD)) == NULL) {
92c62a0ac4Smatt 		printf("no PIOD!\n");
93c62a0ac4Smatt 		return;
94c62a0ac4Smatt 	}
95c62a0ac4Smatt 
96c62a0ac4Smatt 	// initialize softc
97*cbab9cadSchs 	sc->sc_at91spi.sc_spi.sct_nslaves = 3;	// number of slaves
98c62a0ac4Smatt 
99c62a0ac4Smatt 	// configure GPIO
100c62a0ac4Smatt 	GPIO_SPICS0(at91pio_out); GPIO_SPICS0(at91pio_set);
101c62a0ac4Smatt 	GPIO_SPICS1(at91pio_out); GPIO_SPICS1(at91pio_set);
102c62a0ac4Smatt 	GPIO_SPICS2(at91pio_out); GPIO_SPICS2(at91pio_set);
103c62a0ac4Smatt 
104c62a0ac4Smatt 	// and call common routine
105c62a0ac4Smatt 	at91spi_attach_common(parent, self, aux, &mpcsa_spi_tag);
106c62a0ac4Smatt }
107c62a0ac4Smatt 
mpcsa_spi_select(void * self,int sel)108c62a0ac4Smatt static int mpcsa_spi_select(void *self, int sel)
109c62a0ac4Smatt {
110*cbab9cadSchs 	struct mpcsa_spi_softc *sc = device_private(self);
111c62a0ac4Smatt 
112c62a0ac4Smatt 	/* first deselect everything */
113c62a0ac4Smatt 	GPIO_SPICS0(at91pio_set);
114c62a0ac4Smatt 	GPIO_SPICS1(at91pio_set);
115c62a0ac4Smatt 	GPIO_SPICS2(at91pio_set);
116c62a0ac4Smatt 
117c62a0ac4Smatt 	/* then select wanted target */
118c62a0ac4Smatt 	switch (sel) {
119c62a0ac4Smatt 	case -1:
120c62a0ac4Smatt 	  break;
121c62a0ac4Smatt 	case 0:
122c62a0ac4Smatt 	  GPIO_SPICS0(at91pio_clear);
123c62a0ac4Smatt 	  break;
124c62a0ac4Smatt 	case 1:
125c62a0ac4Smatt 	  GPIO_SPICS2(at91pio_clear);
126c62a0ac4Smatt 	  break;
127c62a0ac4Smatt 	case 2:
128c62a0ac4Smatt 	  GPIO_SPICS2(at91pio_clear);
129c62a0ac4Smatt 	  break;
130c62a0ac4Smatt 	default:
131c62a0ac4Smatt 	  return EINVAL;
132c62a0ac4Smatt 	}
133c62a0ac4Smatt 
134c62a0ac4Smatt 	return 0;
135c62a0ac4Smatt }
136