No empty .Rs/.Re
[netbsd-mini2440.git] / sys / arch / arm / s3c2xx0 / s3c2410_spi.c
blob77eaa23fab9c7454d258e3a227021cc150d7333d
1 /* $NetBSD: s3c2410_spi.c,v 1.4 2005/12/11 12:16:51 christos Exp $ */
3 /*
4 * Copyright (c) 2004 Genetec Corporation. All rights reserved.
5 * Written by Hiroyuki Bessho for Genetec Corporation.
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 * 3. The name of Genetec Corporation may not be used to endorse or
16 * promote products derived from this software without specific prior
17 * written permission.
19 * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORPORATION
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 * Support S3C2410's SPI dirver.
34 * Real works are done by drivers attached to SPI ports.
37 #include <sys/cdefs.h>
38 __KERNEL_RCSID(0, "$NetBSD: s3c2410_spi.c,v 1.4 2005/12/11 12:16:51 christos Exp $");
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/conf.h>
44 #include <machine/bus.h>
45 #include <machine/cpu.h>
47 #include <arm/s3c2xx0/s3c24x0var.h>
48 #include <arm/s3c2xx0/s3c24x0reg.h>
49 #include <arm/s3c2xx0/s3c2410reg.h>
51 #include <arm/s3c2xx0/s3c24x0_spi.h>
53 #include "locators.h"
55 struct ssspi_softc {
56 struct device dev;
58 bus_space_tag_t iot;
59 bus_space_handle_t ioh;
60 short index;
64 /* prototypes */
65 static int ssspi_match(struct device *, struct cfdata *, void *);
66 static void ssspi_attach(struct device *, struct device *, void *);
67 static int ssspi_search(struct device *, struct cfdata *,
68 const int *, void *);
69 static int ssspi_print(void *, const char *);
71 /* attach structures */
72 CFATTACH_DECL(ssspi, sizeof(struct ssspi_softc), ssspi_match, ssspi_attach,
73 NULL, NULL);
76 static int
77 ssspi_print(void *aux, const char *name)
79 struct ssspi_attach_args *spia = aux;
81 if (spia->spia_aux_intr != SSSPICF_INTR_DEFAULT)
82 printf(" intr %d", spia->spia_aux_intr);
83 return (UNCONF);
86 int
87 ssspi_match(struct device *parent, struct cfdata *match, void *aux)
89 struct s3c2xx0_attach_args *sa = aux;
91 /* S3C2410 have only two SPIs */
92 switch (sa->sa_index) {
93 case 0:
94 case 1:
95 break;
96 default:
97 return 0;
100 return 1;
103 void
104 ssspi_attach(struct device *parent, struct device *self, void *aux)
106 struct ssspi_softc *sc = (struct ssspi_softc*)self;
107 struct s3c2xx0_attach_args *sa = (struct s3c2xx0_attach_args *)aux;
108 bus_space_tag_t iot = sa->sa_iot;
110 static bus_space_handle_t spi_ioh = 0;
112 /* we map all registers for SPI0 and SPI1 at once, then
113 use subregions */
114 if (spi_ioh == 0) {
115 if (bus_space_map(iot, S3C2410_SPI0_BASE,
116 2 * S3C24X0_SPI_SIZE,
117 0, &spi_ioh)) {
118 aprint_error(": can't map registers\n");
119 return;
123 aprint_normal("\n");
125 sc->index = sa->sa_index;
126 sc->iot = iot;
128 bus_space_subregion(iot, spi_ioh, sc->index == 0 ? 0 : S3C24X0_SPI_SIZE,
129 S3C24X0_SPI_SIZE, &sc->ioh);
132 * Attach child devices
134 config_search_ia(ssspi_search, self, "ssspi", NULL);
138 ssspi_search(struct device *parent, struct cfdata *cf, const int *ldesc, void *aux)
140 struct ssspi_softc *sc = (struct ssspi_softc *)parent;
141 struct ssspi_attach_args spia;
142 static const unsigned char intr[] = { S3C24X0_INT_SPI0,
143 S3C2410_INT_SPI1 };
145 KASSERT(sc->index == 0 || sc->index == 1);
147 spia.spia_iot = sc->iot;
148 spia.spia_ioh = sc->ioh;
149 spia.spia_gpioh = s3c2xx0_softc->sc_gpio_ioh;
150 spia.spia_index = sc->index;
151 spia.spia_intr = intr[sc->index];
152 spia.spia_aux_intr = cf->cf_loc[SSSPICF_INTR];
153 spia.spia_dmat = s3c2xx0_softc->sc_dmat;
155 if (config_match(parent, cf, &spia))
156 config_attach(parent, cf, &spia, ssspi_print);
158 return 0;
162 * Intiialze SPI port. called by child devices.
165 s3c24x0_spi_setup(struct ssspi_softc *sc, uint32_t mode, int bps, int use_ss)
167 int pclk = s3c2xx0_softc->sc_pclk;
168 int prescaler;
169 uint32_t pgcon, pecon;
170 bus_space_handle_t gpioh = s3c2xx0_softc->sc_gpio_ioh;
171 bus_space_tag_t iot = sc->iot;
173 if (bps > 1) {
174 prescaler = pclk / 2 / bps - 1;
176 if (prescaler <= 0 || 0xff < prescaler)
177 return -1;
178 bus_space_write_1(sc->iot, sc->ioh, SPI_SPPRE, prescaler);
182 if (sc->index == 0) {
183 pecon = bus_space_read_4(iot, gpioh, GPIO_PECON);
185 if (use_ss) {
186 pgcon = bus_space_read_4(iot, gpioh, GPIO_PGCON);
187 pgcon = GPIO_SET_FUNC(pgcon, 2, PCON_ALTFUN2);
188 bus_space_write_4(iot, gpioh, GPIO_PGCON, pgcon);
191 pecon = GPIO_SET_FUNC(pecon, 11, PCON_ALTFUN2); /* SPIMISO0 */
192 pecon = GPIO_SET_FUNC(pecon, 12, PCON_ALTFUN2); /* SPIMOSI0 */
193 pecon = GPIO_SET_FUNC(pecon, 13, PCON_ALTFUN2); /* SPICL0 */
195 bus_space_write_4(iot, gpioh, GPIO_PECON, pecon);
197 else {
198 pgcon = bus_space_read_4(iot, gpioh, GPIO_PGCON);
200 if (use_ss)
201 pgcon = GPIO_SET_FUNC(pgcon, 3, PCON_ALTFUN2);
203 pgcon = GPIO_SET_FUNC(pgcon, 5, PCON_ALTFUN2); /* SPIMISO1 */
204 pgcon = GPIO_SET_FUNC(pgcon, 6, PCON_ALTFUN2); /* SPIMOSI1 */
205 pgcon = GPIO_SET_FUNC(pgcon, 7, PCON_ALTFUN2); /* SPICLK1 */
207 bus_space_write_4(iot, gpioh, GPIO_PGCON, pgcon);
210 bus_space_write_4(iot, sc->ioh, SPI_SPCON, mode);
212 return 0;