xref: /netbsd-src/sys/arch/evbarm/netwalker/netwalker_spi.c (revision a10897af822efa378460c88423597e3608385784)
1*a10897afSskrll /*	$NetBSD: netwalker_spi.c,v 1.4 2020/01/15 10:25:47 skrll Exp $	*/
2459f2ce0Shkenken 
3459f2ce0Shkenken /*-
4459f2ce0Shkenken  * Copyright (c) 2009  Genetec Corporation.  All rights reserved.
5459f2ce0Shkenken  * Written by Hashimoto Kenichi for Genetec Corporation.
6459f2ce0Shkenken  *
7459f2ce0Shkenken  * Redistribution and use in source and binary forms, with or without
8459f2ce0Shkenken  * modification, are permitted provided that the following conditions
9459f2ce0Shkenken  * are met:
10459f2ce0Shkenken  * 1. Redistributions of source code must retain the above copyright
11459f2ce0Shkenken  *    notice, this list of conditions and the following disclaimer.
12459f2ce0Shkenken  * 2. Redistributions in binary form must reproduce the above copyright
13459f2ce0Shkenken  *    notice, this list of conditions and the following disclaimer in the
14459f2ce0Shkenken  *    documentation and/or other materials provided with the distribution.
15459f2ce0Shkenken  *
16459f2ce0Shkenken  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
17459f2ce0Shkenken  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18459f2ce0Shkenken  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19459f2ce0Shkenken  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
20459f2ce0Shkenken  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21459f2ce0Shkenken  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22459f2ce0Shkenken  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23459f2ce0Shkenken  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24459f2ce0Shkenken  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25459f2ce0Shkenken  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26459f2ce0Shkenken  * SUCH DAMAGE.
27459f2ce0Shkenken  */
28459f2ce0Shkenken 
29459f2ce0Shkenken #include <sys/cdefs.h>
30*a10897afSskrll __KERNEL_RCSID(0, "$NetBSD: netwalker_spi.c,v 1.4 2020/01/15 10:25:47 skrll Exp $");
31459f2ce0Shkenken 
32459f2ce0Shkenken #include "opt_imxspi.h"
33459f2ce0Shkenken 
34001dea06Shkenken #define	_INTR_PRIVATE
35001dea06Shkenken 
36459f2ce0Shkenken #include <sys/param.h>
37459f2ce0Shkenken #include <sys/bus.h>
38459f2ce0Shkenken #include <sys/device.h>
39001dea06Shkenken #include <sys/gpio.h>
40459f2ce0Shkenken 
41459f2ce0Shkenken #include <arm/imx/imx51reg.h>
42459f2ce0Shkenken #include <arm/imx/imx51var.h>
43459f2ce0Shkenken #include <arm/imx/imx51_ccmvar.h>
44459f2ce0Shkenken #include <arm/imx/imx51_ccmreg.h>
45459f2ce0Shkenken #include <arm/imx/imx51_iomuxreg.h>
46459f2ce0Shkenken #include <arm/imx/imxgpiovar.h>
47459f2ce0Shkenken #include <arm/imx/imxspivar.h>
48b68d413bShkenken #include <arm/imx/imxspireg.h>
49459f2ce0Shkenken 
50459f2ce0Shkenken struct imx51spi_softc {
51b68d413bShkenken 	struct imxspi_softc	sc_spi; /* Must be first */
52b68d413bShkenken 
53459f2ce0Shkenken 	struct spi_chipset_tag	sc_tag;
54459f2ce0Shkenken };
55459f2ce0Shkenken 
56459f2ce0Shkenken CFATTACH_DECL_NEW(spi_netwalker, sizeof(struct imx51spi_softc),
57459f2ce0Shkenken     imxspi_match, imxspi_attach, NULL, NULL);
58459f2ce0Shkenken 
59459f2ce0Shkenken static int
imxspi_cs_enable(void * arg,int slave)60459f2ce0Shkenken imxspi_cs_enable(void *arg, int slave)
61459f2ce0Shkenken {
62459f2ce0Shkenken 	switch (slave) {
63459f2ce0Shkenken 	case 0:
64*a10897afSskrll 		imxgpio_data_write(GPIO_NO(4, 24), GPIO_PIN_LOW);
65*a10897afSskrll 		imxgpio_set_direction(GPIO_NO(4, 24), GPIO_PIN_OUTPUT);
66459f2ce0Shkenken 		break;
67459f2ce0Shkenken 	case 1:
68*a10897afSskrll 		imxgpio_data_write(GPIO_NO(4, 25), GPIO_PIN_LOW);
69*a10897afSskrll 		imxgpio_set_direction(GPIO_NO(4, 25), GPIO_PIN_OUTPUT);
70459f2ce0Shkenken 		break;
71459f2ce0Shkenken 	case 2:
72*a10897afSskrll 		imxgpio_data_write(GPIO_NO(3, 0), GPIO_PIN_LOW);
73*a10897afSskrll 		imxgpio_set_direction(GPIO_NO(3, 0), GPIO_PIN_OUTPUT);
74459f2ce0Shkenken 		break;
75459f2ce0Shkenken 	}
76459f2ce0Shkenken 
77459f2ce0Shkenken 	return 0;
78459f2ce0Shkenken }
79459f2ce0Shkenken 
80459f2ce0Shkenken static int
imxspi_cs_disable(void * arg,int slave)81459f2ce0Shkenken imxspi_cs_disable(void *arg, int slave)
82459f2ce0Shkenken {
83459f2ce0Shkenken 	switch (slave) {
84459f2ce0Shkenken 	case 0:
85*a10897afSskrll 		imxgpio_data_write(GPIO_NO(4, 24), GPIO_PIN_HIGH);
86*a10897afSskrll 		imxgpio_set_direction(GPIO_NO(4, 24), GPIO_PIN_INPUT);
87459f2ce0Shkenken 		break;
88459f2ce0Shkenken 	case 1:
89*a10897afSskrll 		imxgpio_data_write(GPIO_NO(4, 25), GPIO_PIN_HIGH);
90*a10897afSskrll 		imxgpio_set_direction(GPIO_NO(4, 25), GPIO_PIN_INPUT);
91459f2ce0Shkenken 		break;
92459f2ce0Shkenken 	case 2:
93*a10897afSskrll 		imxgpio_data_write(GPIO_NO(3, 0), GPIO_PIN_HIGH);
94*a10897afSskrll 		imxgpio_set_direction(GPIO_NO(3, 0), GPIO_PIN_INPUT);
95459f2ce0Shkenken 		break;
96459f2ce0Shkenken 	}
97459f2ce0Shkenken 
98459f2ce0Shkenken 	return 0;
99459f2ce0Shkenken }
100459f2ce0Shkenken 
101459f2ce0Shkenken int
imxspi_match(device_t parent,cfdata_t cf,void * aux)102459f2ce0Shkenken imxspi_match(device_t parent, cfdata_t cf, void *aux)
103459f2ce0Shkenken {
104459f2ce0Shkenken 	if (strcmp(cf->cf_name, "imxspi") == 0)
105459f2ce0Shkenken 		return 1;
106459f2ce0Shkenken 	if (cf->cf_unit != 0)
107459f2ce0Shkenken 		return 1;
108459f2ce0Shkenken 
109459f2ce0Shkenken 	return 0;
110459f2ce0Shkenken }
111459f2ce0Shkenken 
112459f2ce0Shkenken void
imxspi_attach(device_t parent,device_t self,void * aux)113459f2ce0Shkenken imxspi_attach(device_t parent, device_t self, void *aux)
114459f2ce0Shkenken {
115b68d413bShkenken 	struct imx51spi_softc *isc = device_private(self);
116b68d413bShkenken 	struct imxspi_softc *sc = &isc->sc_spi;
117459f2ce0Shkenken 	struct axi_attach_args *aa = aux;
118459f2ce0Shkenken 	int cf_flags = device_cfdata(self)->cf_flags;
119b68d413bShkenken 	bus_addr_t addr;
120b68d413bShkenken 	bus_size_t size;
121459f2ce0Shkenken 
122b68d413bShkenken 	addr = aa->aa_addr;
123b68d413bShkenken 	size = aa->aa_size;
124b68d413bShkenken 	if (size <= 0)
125b68d413bShkenken 		size = SPI_SIZE;
126459f2ce0Shkenken 
127b68d413bShkenken 	isc->sc_tag.cookie = sc;
128b68d413bShkenken 
129b68d413bShkenken 	switch (device_unit(self)) {
130b68d413bShkenken 	case 0:
131459f2ce0Shkenken 		/* CS 0 GPIO setting */
132*a10897afSskrll 		imxgpio_data_write(GPIO_NO(4, 24), GPIO_PIN_HIGH);
133*a10897afSskrll 		imxgpio_set_direction(GPIO_NO(4, 24), GPIO_PIN_INPUT);
134459f2ce0Shkenken 
135459f2ce0Shkenken 		/* CS 1 GPIO setting */
136*a10897afSskrll 		imxgpio_data_write(GPIO_NO(4, 25), GPIO_PIN_HIGH);
137*a10897afSskrll 		imxgpio_set_direction(GPIO_NO(4, 25), GPIO_PIN_INPUT);
138459f2ce0Shkenken 
139459f2ce0Shkenken 		/* CS 2 */
140459f2ce0Shkenken 		/* OJ6SH-T25 Shutdown */
141*a10897afSskrll 		imxgpio_data_write(GPIO_NO(3, 14), GPIO_PIN_LOW);
142*a10897afSskrll 		imxgpio_set_direction(GPIO_NO(3, 14), GPIO_PIN_OUTPUT);
143459f2ce0Shkenken 
144459f2ce0Shkenken 		/* CS 2 GPIO setting */
145*a10897afSskrll 		imxgpio_data_write(GPIO_NO(3, 0), GPIO_PIN_HIGH);
146*a10897afSskrll 		imxgpio_set_direction(GPIO_NO(3, 0), GPIO_PIN_INPUT);
147459f2ce0Shkenken 
148b68d413bShkenken 		isc->sc_tag.spi_cs_enable = imxspi_cs_enable;
149b68d413bShkenken 		isc->sc_tag.spi_cs_disable = imxspi_cs_disable;
150b68d413bShkenken 		break;
151459f2ce0Shkenken 	}
152459f2ce0Shkenken 
153b68d413bShkenken 	sc->sc_iot = aa->aa_iot;
154b68d413bShkenken 	sc->sc_enhanced = cf_flags;
155459f2ce0Shkenken 
156b68d413bShkenken 	sc->sc_nslaves = IMXSPINSLAVES;
157b68d413bShkenken 	sc->sc_freq = imx51_get_clock(IMX51CLK_CSPI_CLK_ROOT);
158b68d413bShkenken 	sc->sc_tag = &isc->sc_tag;
159459f2ce0Shkenken 
160b68d413bShkenken 	if (bus_space_map(sc->sc_iot, addr, size, 0, &sc->sc_ioh)) {
161b68d413bShkenken 		aprint_error_dev(sc->sc_dev, "couldn't map registers\n");
162b68d413bShkenken 		return;
163b68d413bShkenken 	}
164459f2ce0Shkenken 
165b68d413bShkenken 	/* enable device interrupts */
166b68d413bShkenken 	sc->sc_ih = intr_establish(aa->aa_irq, IPL_BIO, IST_LEVEL,
167b68d413bShkenken 	    imxspi_intr, sc);
168b68d413bShkenken 
169b68d413bShkenken 	imxspi_attach_common(self);
170459f2ce0Shkenken }
171