1 /* $NetBSD: s3c2410_spi.c,v 1.4 2005/12/11 12:16:51 christos Exp $ */
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
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
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>
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>
59 bus_space_handle_t ioh
;
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
*,
69 static int ssspi_print(void *, const char *);
71 /* attach structures */
72 CFATTACH_DECL(ssspi
, sizeof(struct ssspi_softc
), ssspi_match
, ssspi_attach
,
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
);
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
) {
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
115 if (bus_space_map(iot
, S3C2410_SPI0_BASE
,
116 2 * S3C24X0_SPI_SIZE
,
118 aprint_error(": can't map registers\n");
125 sc
->index
= sa
->sa_index
;
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
,
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
);
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
;
169 uint32_t pgcon
, pecon
;
170 bus_space_handle_t gpioh
= s3c2xx0_softc
->sc_gpio_ioh
;
171 bus_space_tag_t iot
= sc
->iot
;
174 prescaler
= pclk
/ 2 / bps
- 1;
176 if (prescaler
<= 0 || 0xff < prescaler
)
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
);
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
);
198 pgcon
= bus_space_read_4(iot
, gpioh
, GPIO_PGCON
);
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
);