1140308Scognet/* $NetBSD: iq31244_7seg.c,v 1.2 2003/07/15 00:25:01 lukem Exp $ */ 2140308Scognet 3140308Scognet/*- 4140308Scognet * Copyright (c) 2001, 2002, 2003 Wasabi Systems, Inc. 5140308Scognet * All rights reserved. 6140308Scognet * 7140308Scognet * Written by Jason R. Thorpe for Wasabi Systems, Inc. 8140308Scognet * 9140308Scognet * Redistribution and use in source and binary forms, with or without 10140308Scognet * modification, are permitted provided that the following conditions 11140308Scognet * are met: 12140308Scognet * 1. Redistributions of source code must retain the above copyright 13140308Scognet * notice, this list of conditions and the following disclaimer. 14140308Scognet * 2. Redistributions in binary form must reproduce the above copyright 15140308Scognet * notice, this list of conditions and the following disclaimer in the 16140308Scognet * documentation and/or other materials provided with the distribution. 17140308Scognet * 3. All advertising materials mentioning features or use of this software 18140308Scognet * must display the following acknowledgement: 19140308Scognet * This product includes software developed for the NetBSD Project by 20140308Scognet * Wasabi Systems, Inc. 21140308Scognet * 4. The name of Wasabi Systems, Inc. may not be used to endorse 22140308Scognet * or promote products derived from this software without specific prior 23140308Scognet * written permission. 24140308Scognet * 25140308Scognet * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 26140308Scognet * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27140308Scognet * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28140308Scognet * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 29140308Scognet * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30140308Scognet * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31140308Scognet * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32140308Scognet * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33140308Scognet * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34140308Scognet * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35140308Scognet * POSSIBILITY OF SUCH DAMAGE. 36140308Scognet */ 37140308Scognet 38140308Scognet/* 39140308Scognet * Support for the 7-segment display on the Intel IQ31244. 40140308Scognet */ 41140308Scognet 42140308Scognet#include <sys/cdefs.h> 43140308Scognet__FBSDID("$FreeBSD$"); 44140308Scognet 45140308Scognet#include <sys/param.h> 46140308Scognet#include <sys/systm.h> 47140308Scognet#include <sys/kernel.h> 48140308Scognet#include <sys/module.h> 49140308Scognet#include <sys/bus.h> 50140350Scognet#include <sys/sysctl.h> 51140308Scognet 52140308Scognet#include <machine/bus.h> 53140308Scognet 54140308Scognet#include <arm/xscale/i80321/iq80321reg.h> 55140308Scognet#include <arm/xscale/i80321/iq80321var.h> 56140308Scognet 57140308Scognet#define WRITE(x, v) *((__volatile uint8_t *) (x)) = (v) 58140308Scognet 59140308Scognetstatic int snakestate; 60140308Scognet 61140308Scognet/* 62140308Scognet * The 7-segment display looks like so: 63140308Scognet * 64140308Scognet * A 65140308Scognet * +-----+ 66140308Scognet * | | 67140308Scognet * F | | B 68140308Scognet * | G | 69140308Scognet * +-----+ 70140308Scognet * | | 71140308Scognet * E | | C 72140308Scognet * | D | 73140308Scognet * +-----+ o DP 74140308Scognet * 75140308Scognet * Setting a bit clears the corresponding segment on the 76140308Scognet * display. 77140308Scognet */ 78140308Scognet#define SEG_A (1 << 0) 79140308Scognet#define SEG_B (1 << 1) 80140308Scognet#define SEG_C (1 << 2) 81140308Scognet#define SEG_D (1 << 3) 82140308Scognet#define SEG_E (1 << 4) 83140308Scognet#define SEG_F (1 << 5) 84140308Scognet#define SEG_G (1 << 6) 85140308Scognet#define SEG_DP (1 << 7) 86140308Scognet 87140308Scognetstatic const uint8_t digitmap[] = { 88140308Scognet/* +#####+ 89140308Scognet * # # 90140308Scognet * # # 91140308Scognet * # # 92140308Scognet * +-----+ 93140308Scognet * # # 94140308Scognet * # # 95140308Scognet * # # 96140308Scognet * +#####+ 97140308Scognet */ 98140308Scognet SEG_G, 99140308Scognet 100140308Scognet/* +-----+ 101140308Scognet * | # 102140308Scognet * | # 103140308Scognet * | # 104140308Scognet * +-----+ 105140308Scognet * | # 106140308Scognet * | # 107140308Scognet * | # 108140308Scognet * +-----+ 109140308Scognet */ 110140308Scognet SEG_A|SEG_D|SEG_E|SEG_F|SEG_G, 111140308Scognet 112140308Scognet/* +#####+ 113140308Scognet * | # 114140308Scognet * | # 115140308Scognet * | # 116140308Scognet * +#####+ 117140308Scognet * # | 118140308Scognet * # | 119140308Scognet * # | 120140308Scognet * +#####+ 121140308Scognet */ 122140308Scognet SEG_C|SEG_F, 123140308Scognet 124140308Scognet/* +#####+ 125140308Scognet * | # 126140308Scognet * | # 127140308Scognet * | # 128140308Scognet * +#####+ 129140308Scognet * | # 130140308Scognet * | # 131140308Scognet * | # 132140308Scognet * +#####+ 133140308Scognet */ 134140308Scognet SEG_E|SEG_F, 135140308Scognet 136140308Scognet/* +-----+ 137140308Scognet * # # 138140308Scognet * # # 139140308Scognet * # # 140140308Scognet * +#####+ 141140308Scognet * | # 142140308Scognet * | # 143140308Scognet * | # 144140308Scognet * +-----+ 145140308Scognet */ 146140308Scognet SEG_A|SEG_D|SEG_E, 147140308Scognet 148140308Scognet/* +#####+ 149140308Scognet * # | 150140308Scognet * # | 151140308Scognet * # | 152140308Scognet * +#####+ 153140308Scognet * | # 154140308Scognet * | # 155140308Scognet * | # 156140308Scognet * +#####+ 157140308Scognet */ 158140308Scognet SEG_B|SEG_E, 159140308Scognet 160140308Scognet/* +#####+ 161140308Scognet * # | 162140308Scognet * # | 163140308Scognet * # | 164140308Scognet * +#####+ 165140308Scognet * # # 166140308Scognet * # # 167140308Scognet * # # 168140308Scognet * +#####+ 169140308Scognet */ 170140308Scognet SEG_B, 171140308Scognet 172140308Scognet/* +#####+ 173140308Scognet * | # 174140308Scognet * | # 175140308Scognet * | # 176140308Scognet * +-----+ 177140308Scognet * | # 178140308Scognet * | # 179140308Scognet * | # 180140308Scognet * +-----+ 181140308Scognet */ 182140308Scognet SEG_D|SEG_E|SEG_F, 183140308Scognet 184140308Scognet/* +#####+ 185140308Scognet * # # 186140308Scognet * # # 187140308Scognet * # # 188140308Scognet * +#####+ 189140308Scognet * # # 190140308Scognet * # # 191140308Scognet * # # 192140308Scognet * +#####+ 193140308Scognet */ 194140308Scognet 0, 195140308Scognet 196140308Scognet/* +#####+ 197140308Scognet * # # 198140308Scognet * # # 199140308Scognet * # # 200140308Scognet * +#####+ 201140308Scognet * | # 202140308Scognet * | # 203140308Scognet * | # 204140308Scognet * +-----+ 205140308Scognet */ 206140308Scognet SEG_D|SEG_E, 207140308Scognet}; 208140308Scognet 209236987Simpstatic uint8_t 210140308Scognetiq80321_7seg_xlate(char c) 211140308Scognet{ 212140308Scognet uint8_t rv; 213140308Scognet 214140308Scognet if (c >= '0' && c <= '9') 215140308Scognet rv = digitmap[c - '0']; 216140308Scognet else if (c == '.') 217140308Scognet rv = (uint8_t) ~SEG_DP; 218140308Scognet else 219140308Scognet rv = 0xff; 220140308Scognet 221140308Scognet return (rv); 222140308Scognet} 223140308Scognet 224140308Scognetvoid 225140308Scognetiq80321_7seg(char a, char b) 226140308Scognet{ 227140308Scognet uint8_t msb, lsb; 228140308Scognet 229140308Scognet msb = iq80321_7seg_xlate(a); 230140308Scognet lsb = iq80321_7seg_xlate(b); 231140308Scognet 232140308Scognet snakestate = 0; 233140308Scognet 234140308Scognet WRITE(IQ80321_7SEG_MSB, msb); 235140308Scognet WRITE(IQ80321_7SEG_LSB, lsb); 236140308Scognet} 237140308Scognet 238140308Scognetstatic const uint8_t snakemap[][2] = { 239140308Scognet 240140308Scognet/* +#####+ +#####+ 241140308Scognet * | | | | 242140308Scognet * | | | | 243140308Scognet * | | | | 244140308Scognet * +-----+ +-----+ 245140308Scognet * | | | | 246140308Scognet * | | | | 247140308Scognet * | | | | 248140308Scognet * +-----+ +-----+ 249140308Scognet */ 250140308Scognet { ~SEG_A, ~SEG_A }, 251140308Scognet 252140308Scognet/* +-----+ +-----+ 253140308Scognet * # | | # 254140308Scognet * # | | # 255140308Scognet * # | | # 256140308Scognet * +-----+ +-----+ 257140308Scognet * | | | | 258140308Scognet * | | | | 259140308Scognet * | | | | 260140308Scognet * +-----+ +-----+ 261140308Scognet */ 262140308Scognet { ~SEG_F, ~SEG_B }, 263140308Scognet 264140308Scognet/* +-----+ +-----+ 265140308Scognet * | | | | 266140308Scognet * | | | | 267140308Scognet * | | | | 268140308Scognet * +#####+ +#####+ 269140308Scognet * | | | | 270140308Scognet * | | | | 271140308Scognet * | | | | 272140308Scognet * +-----+ +-----+ 273140308Scognet */ 274140308Scognet { ~SEG_G, ~SEG_G }, 275140308Scognet 276140308Scognet/* +-----+ +-----+ 277140308Scognet * | | | | 278140308Scognet * | | | | 279140308Scognet * | | | | 280140308Scognet * +-----+ +-----+ 281140308Scognet * | # # | 282140308Scognet * | # # | 283140308Scognet * | # # | 284140308Scognet * +-----+ +-----+ 285140308Scognet */ 286140308Scognet { ~SEG_C, ~SEG_E }, 287140308Scognet 288140308Scognet/* +-----+ +-----+ 289140308Scognet * | | | | 290140308Scognet * | | | | 291140308Scognet * | | | | 292140308Scognet * +-----+ +-----+ 293140308Scognet * | | | | 294140308Scognet * | | | | 295140308Scognet * | | | | 296140308Scognet * +#####+ +#####+ 297140308Scognet */ 298140308Scognet { ~SEG_D, ~SEG_D }, 299140308Scognet 300140308Scognet/* +-----+ +-----+ 301140308Scognet * | | | | 302140308Scognet * | | | | 303140308Scognet * | | | | 304140308Scognet * +-----+ +-----+ 305140308Scognet * # | | # 306140308Scognet * # | | # 307140308Scognet * # | | # 308140308Scognet * +-----+ +-----+ 309140308Scognet */ 310140308Scognet { ~SEG_E, ~SEG_C }, 311140308Scognet 312140308Scognet/* +-----+ +-----+ 313140308Scognet * | | | | 314140308Scognet * | | | | 315140308Scognet * | | | | 316140308Scognet * +#####+ +#####+ 317140308Scognet * | | | | 318140308Scognet * | | | | 319140308Scognet * | | | | 320140308Scognet * +-----+ +-----+ 321140308Scognet */ 322140308Scognet { ~SEG_G, ~SEG_G }, 323140308Scognet 324140308Scognet/* +-----+ +-----+ 325140308Scognet * | # # | 326140308Scognet * | # # | 327140308Scognet * | # # | 328140308Scognet * +-----+ +-----+ 329140308Scognet * | | | | 330140308Scognet * | | | | 331140308Scognet * | | | | 332140308Scognet * +-----+ +-----+ 333140308Scognet */ 334140308Scognet { ~SEG_B, ~SEG_F }, 335140308Scognet}; 336140308Scognet 337227309Sedstatic SYSCTL_NODE(_hw, OID_AUTO, sevenseg, CTLFLAG_RD, 0, "7 seg"); 338146618Scognetstatic int freq = 20; 339236987SimpSYSCTL_INT(_hw_sevenseg, OID_AUTO, freq, CTLFLAG_RW, &freq, 0, 340140350Scognet "7 Seg update frequency"); 341140308Scognetstatic void 342140308Scognetiq31244_7seg_snake(void) 343140308Scognet{ 344140308Scognet static int snakefreq; 345140308Scognet int cur = snakestate; 346140308Scognet 347140308Scognet snakefreq++; 348140350Scognet if ((snakefreq % freq)) 349140308Scognet return; 350140308Scognet WRITE(IQ80321_7SEG_MSB, snakemap[cur][0]); 351140308Scognet WRITE(IQ80321_7SEG_LSB, snakemap[cur][1]); 352140308Scognet 353140308Scognet snakestate = (cur + 1) & 7; 354140308Scognet} 355140308Scognet 356140308Scognetstruct iq31244_7seg_softc { 357140308Scognet device_t dev; 358140308Scognet}; 359140308Scognet 360140308Scognetstatic int 361140308Scognetiq31244_7seg_probe(device_t dev) 362140308Scognet{ 363140308Scognet 364140308Scognet device_set_desc(dev, "IQ31244 7seg"); 365140308Scognet return (0); 366140308Scognet} 367140308Scognet 368140308Scognetextern void (*i80321_hardclock_hook)(void); 369140308Scognetstatic int 370140308Scognetiq31244_7seg_attach(device_t dev) 371140308Scognet{ 372140308Scognet 373140308Scognet i80321_hardclock_hook = iq31244_7seg_snake; 374140308Scognet return (0); 375140308Scognet} 376140308Scognet 377140308Scognetstatic device_method_t iq31244_7seg_methods[] = { 378140308Scognet DEVMETHOD(device_probe, iq31244_7seg_probe), 379140308Scognet DEVMETHOD(device_attach, iq31244_7seg_attach), 380140308Scognet {0, 0}, 381140308Scognet}; 382140308Scognet 383140308Scognetstatic driver_t iq31244_7seg_driver = { 384140308Scognet "iqseg", 385140308Scognet iq31244_7seg_methods, 386140308Scognet sizeof(struct iq31244_7seg_softc), 387140308Scognet}; 388140308Scognetstatic devclass_t iq31244_7seg_devclass; 389140308Scognet 390140308ScognetDRIVER_MODULE(iqseg, iq, iq31244_7seg_driver, iq31244_7seg_devclass, 0, 0); 391