Home | History | Annotate | Line # | Download | only in dev
wzero3_ssp.c revision 1.2
      1 /*	$NetBSD: wzero3_ssp.c,v 1.2 2010/05/13 21:01:59 nonaka Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2010 NONAKA Kimihiro <nonaka (at) netbsd.org>
      5  * All rights reserved.
      6  *
      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  *
     16  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 
     29 #include <sys/cdefs.h>
     30 __KERNEL_RCSID(0, "$NetBSD: wzero3_ssp.c,v 1.2 2010/05/13 21:01:59 nonaka Exp $");
     31 
     32 #include <sys/param.h>
     33 #include <sys/systm.h>
     34 #include <sys/device.h>
     35 #include <sys/mutex.h>
     36 #include <sys/pmf.h>
     37 #include <sys/bus.h>
     38 
     39 #include <machine/bootinfo.h>
     40 #include <machine/platid.h>
     41 #include <machine/platid_mask.h>
     42 
     43 #include <arm/xscale/pxa2x0reg.h>
     44 #include <arm/xscale/pxa2x0var.h>
     45 #include <arm/xscale/pxa2x0_gpio.h>
     46 
     47 #include <hpcarm/dev/wzero3_reg.h>
     48 #include <hpcarm/dev/wzero3_sspvar.h>
     49 
     50 #define WS003SH_SSCR0_MAX1233	0x0000048f	/* 16bit/SPI/div by 5 */
     51 #define WS007SH_SSCR0_ADS7846	0x000006ab	/* 12bit/Microwire/div by 7 */
     52 #define WS011SH_SSCR0_TP	0x0010068f	/* 32bit/SPI/div by 7 */
     53 #define WS011SH_SSCR0_TENKEY	0x0000068f	/* 16bit/SPI/div by 7 */
     54 
     55 struct wzero3ssp_model;
     56 struct wzero3ssp_softc {
     57 	device_t sc_dev;
     58 	bus_space_tag_t sc_iot;
     59 	bus_space_handle_t sc_ioh;
     60 	kmutex_t sc_mtx;
     61 	const struct wzero3ssp_model *sc_model;
     62 };
     63 
     64 static int	wzero3ssp_match(device_t, cfdata_t, void *);
     65 static void	wzero3ssp_attach(device_t, device_t, void *);
     66 
     67 CFATTACH_DECL_NEW(wzero3ssp, sizeof(struct wzero3ssp_softc),
     68 	wzero3ssp_match, wzero3ssp_attach, NULL, NULL);
     69 
     70 static void	wzero3ssp_init(struct wzero3ssp_softc *);
     71 static bool	wzero3ssp_resume(device_t dv, const pmf_qual_t *);
     72 static uint32_t	wzero3ssp_read_ads7846(struct wzero3ssp_softc *, uint32_t);
     73 static uint32_t	wzero3ssp_read_max1233(struct wzero3ssp_softc *, uint32_t,
     74 		    uint32_t);
     75 
     76 static struct wzero3ssp_softc *wzero3ssp_sc;
     77 
     78 static const struct wzero3ssp_model {
     79 	platid_mask_t *platid;
     80 	u_long sspaddr;
     81 } wzero3ssp_table[] = {
     82 	/* WS003SH */
     83 	{
     84 		&platid_mask_MACH_SHARP_WZERO3_WS003SH,
     85 		PXA2X0_SSP2_BASE,
     86 	},
     87 	/* WS004SH */
     88 	{
     89 		&platid_mask_MACH_SHARP_WZERO3_WS004SH,
     90 		PXA2X0_SSP2_BASE,
     91 	},
     92 	/* WS007SH */
     93 	{
     94 		&platid_mask_MACH_SHARP_WZERO3_WS007SH,
     95 		PXA2X0_SSP1_BASE,
     96 	},
     97 	/* WS011SH */
     98 	{
     99 		&platid_mask_MACH_SHARP_WZERO3_WS011SH,
    100 		PXA2X0_SSP1_BASE,
    101 	},
    102 #if 0
    103 	/* WS0020H */
    104 	{
    105 		&platid_mask_MACH_SHARP_WZERO3_WS020SH,
    106 		PXA2X0_SSP1_BASE,
    107 	},
    108 #endif
    109 	{
    110 		NULL, 0,
    111 	},
    112 };
    113 
    114 static const struct wzero3ssp_model *
    115 wzero3ssp_lookup(void)
    116 {
    117 	const struct wzero3ssp_model *model;
    118 
    119 	for (model = wzero3ssp_table; model->platid != NULL; model++) {
    120 		if (platid_match(&platid, model->platid)) {
    121 			return model;
    122 		}
    123 	}
    124 	return NULL;
    125 }
    126 
    127 static int
    128 wzero3ssp_match(device_t parent, cfdata_t cf, void *aux)
    129 {
    130 
    131 	if (strcmp(cf->cf_name, "wzero3ssp") != 0)
    132 		return 0;
    133 	if (wzero3ssp_lookup() == NULL)
    134 		return 0;
    135 	if (wzero3ssp_sc != NULL)
    136 		return 0;
    137 	return 1;
    138 }
    139 
    140 static void
    141 wzero3ssp_attach(device_t parent, device_t self, void *aux)
    142 {
    143 	struct wzero3ssp_softc *sc = device_private(self);
    144 
    145 	sc->sc_dev = self;
    146 	wzero3ssp_sc = sc;
    147 
    148 	aprint_normal("\n");
    149 	aprint_naive("\n");
    150 
    151 	sc->sc_model = wzero3ssp_lookup();
    152 	if (sc->sc_model == NULL) {
    153 		aprint_error_dev(self, "unknown model\n");
    154 		return;
    155 	}
    156 
    157 	mutex_init(&sc->sc_mtx, MUTEX_DEFAULT, IPL_TTY);
    158 
    159 	sc->sc_iot = &pxa2x0_bs_tag;
    160 	if (bus_space_map(sc->sc_iot, sc->sc_model->sspaddr, PXA2X0_SSP_SIZE, 0,
    161 	     &sc->sc_ioh)) {
    162 		aprint_error_dev(sc->sc_dev, "can't map bus space\n");
    163 		return;
    164 	}
    165 
    166 	if (!pmf_device_register(sc->sc_dev, NULL, wzero3ssp_resume))
    167 		aprint_error_dev(sc->sc_dev,
    168 		    "couldn't establish power handler\n");
    169 
    170 	wzero3ssp_init(sc);
    171 }
    172 
    173 /*
    174  * Initialize the dedicated SSP unit and disable all chip selects.
    175  * This function is called with interrupts disabled.
    176  */
    177 static void
    178 wzero3ssp_init(struct wzero3ssp_softc *sc)
    179 {
    180 
    181 	if (sc->sc_model->sspaddr == PXA2X0_SSP1_BASE)
    182 		pxa2x0_clkman_config(CKEN_SSP2, 1);
    183 	else if (sc->sc_model->sspaddr == PXA2X0_SSP2_BASE)
    184 		pxa2x0_clkman_config(CKEN_SSP3, 1);
    185 
    186 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0, 0);
    187 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR1, 0);
    188 
    189 	/* XXX */
    190 	if (platid_match(&platid, &platid_mask_MACH_SHARP_WZERO3_WS003SH)
    191 	 || platid_match(&platid, &platid_mask_MACH_SHARP_WZERO3_WS004SH)) {
    192 		pxa2x0_gpio_set_function(39/*GPIO_WS003SH_XXX*/,
    193 		    GPIO_OUT|GPIO_SET);
    194 		pxa2x0_gpio_set_function(GPIO_WS003SH_MAX1233_CS,
    195 		    GPIO_OUT|GPIO_SET);
    196 	}
    197 	if (platid_match(&platid, &platid_mask_MACH_SHARP_WZERO3_WS007SH)) {
    198 		pxa2x0_gpio_set_function(GPIO_WS007SH_ADS7846_CS,
    199 		    GPIO_OUT|GPIO_SET);
    200 	}
    201 }
    202 
    203 static bool
    204 wzero3ssp_resume(device_t dv, const pmf_qual_t *qual)
    205 {
    206 	struct wzero3ssp_softc *sc = device_private(dv);
    207 
    208 	mutex_enter(&sc->sc_mtx);
    209 	wzero3ssp_init(sc);
    210 	mutex_exit(&sc->sc_mtx);
    211 
    212 	return true;
    213 }
    214 
    215 /*
    216  * Transmit a single data word to one of the ICs, keep the chip selected
    217  * afterwards, and don't wait for data to be returned in SSDR.  Interrupts
    218  * must be held off until wzero3ssp_ic_stop() gets called.
    219  */
    220 void
    221 wzero3ssp_ic_start(int ic, uint32_t cmd)
    222 {
    223 	struct wzero3ssp_softc *sc;
    224 
    225 	KASSERT(wzero3ssp_sc != NULL);
    226 	sc = wzero3ssp_sc;
    227 
    228 	mutex_enter(&sc->sc_mtx);
    229 
    230 	/* disable other ICs */
    231 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0, 0);
    232 	if (ic != WZERO3_SSP_IC_ADS7846)
    233 		pxa2x0_gpio_set_bit(GPIO_WS007SH_ADS7846_CS);
    234 
    235 	/* activate the chosen one */
    236 	switch (ic) {
    237 	case WZERO3_SSP_IC_ADS7846:
    238 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0, 0);
    239 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0,
    240 		    WS007SH_SSCR0_ADS7846);
    241 		pxa2x0_gpio_clear_bit(GPIO_WS007SH_ADS7846_CS);
    242 		bus_space_write_1(sc->sc_iot, sc->sc_ioh, SSP_SSDR, cmd);
    243 		while ((bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR)
    244 		    & SSSR_TNF) != SSSR_TNF)
    245 			continue;	/* poll */
    246 		break;
    247 	case WZERO3_SSP_IC_MAX1233:
    248 	case WZERO3_SSP_IC_NUM:
    249 	default:
    250 		break;
    251 	}
    252 }
    253 
    254 /*
    255  * Read the last value from SSDR and deactivate all chip-selects.
    256  */
    257 uint32_t
    258 wzero3ssp_ic_stop(int ic)
    259 {
    260 	struct wzero3ssp_softc *sc;
    261 	uint32_t rv;
    262 
    263 	KASSERT(wzero3ssp_sc != NULL);
    264 	sc = wzero3ssp_sc;
    265 
    266 	switch (ic) {
    267 	case WZERO3_SSP_IC_ADS7846:
    268 		/* read result of last command */
    269 		while ((bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR)
    270 		    & SSSR_RNE) != SSSR_RNE)
    271 			continue;	/* poll */
    272 		rv = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR);
    273 		pxa2x0_gpio_set_bit(GPIO_WS007SH_ADS7846_CS);
    274 		break;
    275 	case WZERO3_SSP_IC_MAX1233:
    276 	case WZERO3_SSP_IC_NUM:
    277 	default:
    278 		rv = 0;
    279 		break;
    280 	}
    281 
    282 	mutex_exit(&sc->sc_mtx);
    283 
    284 	return rv;
    285 }
    286 
    287 /*
    288  * Activate one of the chip-select lines, transmit one word value in
    289  * each direction, and deactivate the chip-select again.
    290  */
    291 uint32_t
    292 wzero3ssp_ic_send(int ic, uint32_t data, uint32_t data2)
    293 {
    294 	struct wzero3ssp_softc *sc;
    295 
    296 	if (wzero3ssp_sc == NULL) {
    297 		aprint_error("%s: not configured\n", __func__);
    298 		return 0;
    299 	}
    300 	sc = wzero3ssp_sc;
    301 
    302 	switch (ic) {
    303 	case WZERO3_SSP_IC_ADS7846:
    304 		return wzero3ssp_read_ads7846(sc, data);
    305 	case WZERO3_SSP_IC_MAX1233:
    306 		return wzero3ssp_read_max1233(sc, data, data2);
    307 	case WZERO3_SSP_IC_NUM:
    308 	default:
    309 		aprint_error("%s: invalid IC %d\n", __func__, ic);
    310 		return 0;
    311 	}
    312 }
    313 
    314 static uint32_t
    315 wzero3ssp_read_ads7846(struct wzero3ssp_softc *sc, uint32_t cmd)
    316 {
    317 	uint32_t rv;
    318 
    319 	mutex_enter(&sc->sc_mtx);
    320 
    321 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0, 0);
    322 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0,
    323 	    WS007SH_SSCR0_ADS7846);
    324 
    325 	pxa2x0_gpio_clear_bit(GPIO_WS007SH_ADS7846_CS);
    326 
    327 	/* send cmd */
    328 	while (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR) & SSSR_TNF))
    329 		continue;	/* poll */
    330 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR, cmd);
    331 	while (bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR) & SSSR_BUSY)
    332 		continue;	/* poll */
    333 
    334 	while (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR) & SSSR_RNE))
    335 		continue;	/* poll */
    336 	rv = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR);
    337 
    338 	pxa2x0_gpio_set_bit(GPIO_WS007SH_ADS7846_CS);
    339 
    340 	mutex_exit(&sc->sc_mtx);
    341 
    342 	return rv;
    343 }
    344 
    345 static uint32_t
    346 wzero3ssp_read_max1233(struct wzero3ssp_softc *sc, uint32_t cmd, uint32_t data)
    347 {
    348 	uint32_t rv;
    349 
    350 	mutex_enter(&sc->sc_mtx);
    351 
    352 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0, 0);
    353 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0,
    354 	    WS003SH_SSCR0_MAX1233);
    355 
    356 	pxa2x0_gpio_set_bit(39/*GPIO_WS003SH_XXX*/);
    357 	pxa2x0_gpio_clear_bit(GPIO_WS003SH_MAX1233_CS);
    358 
    359 	/* send cmd */
    360 	while (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR) & SSSR_TNF))
    361 		continue;	/* poll */
    362 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR, cmd);
    363 	while (bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR) & SSSR_BUSY)
    364 		continue;	/* poll */
    365 	while (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR) & SSSR_RNE))
    366 		continue;	/* poll */
    367 	(void)bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR);
    368 
    369 	while (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR) & SSSR_TNF))
    370 		continue;	/* poll */
    371 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR, data);
    372 	while (bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR) & SSSR_BUSY)
    373 		continue;	/* poll */
    374 	while (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR) & SSSR_RNE))
    375 		continue;	/* poll */
    376 	rv = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR);
    377 
    378 	pxa2x0_gpio_set_bit(GPIO_WS003SH_MAX1233_CS);
    379 
    380 	mutex_exit(&sc->sc_mtx);
    381 
    382 	return rv;
    383 }
    384