1 /* $NetBSD: gpiosim.c,v 1.6 2009/08/07 08:08:18 mbalmer Exp $ */
2 /* $OpenBSD: gpiosim.c,v 1.1 2008/11/23 18:46:49 mbalmer Exp $ */
5 * Copyright (c) 2007, 2008, 2009 Marc Balmer <marc@msys.ch>
8 * Permission to use, copy, modify, and distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
17 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
18 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 /* 32 bit wide GPIO simulator */
22 #include <sys/param.h>
23 #include <sys/systm.h>
24 #include <sys/device.h>
26 #include <sys/malloc.h>
27 #include <sys/sysctl.h>
28 #include <sys/ioccom.h>
30 #include <dev/gpio/gpiovar.h>
32 #define GPIOSIM_NPINS 32
34 struct gpiosim_softc
{
36 device_t sc_gdev
; /* gpio that attaches here */
38 struct gpio_chipset_tag sc_gpio_gc
;
39 gpio_pin_t sc_gpio_pins
[GPIOSIM_NPINS
];
41 struct sysctllog
*sc_log
;
44 int gpiosim_match(device_t
, cfdata_t
, void *);
45 void gpiosimattach(int);
46 void gpiosim_attach(device_t
, device_t
, void *);
47 int gpiosim_detach(device_t
, int);
48 int gpiosim_sysctl(SYSCTLFN_PROTO
);
50 int gpiosim_pin_read(void *, int);
51 void gpiosim_pin_write(void *, int, int);
52 void gpiosim_pin_ctl(void *, int, int);
54 CFATTACH_DECL_NEW(gpiosim
, sizeof(struct gpiosim_softc
), gpiosim_match
,
55 gpiosim_attach
, gpiosim_detach
, NULL
);
57 extern struct cfdriver gpiosim_cd
;
60 gpiosim_match(device_t parent
, cfdata_t match
, void *aux
)
66 gpiosimattach(int num
)
71 err
= config_cfattach_attach(gpiosim_cd
.cd_name
, &gpiosim_ca
);
73 printf("%s: unable to register cfattach\n", gpiosim_cd
.cd_name
);
75 for (n
= 0; n
< num
; n
++) {
76 cf
= malloc(sizeof(*cf
), M_DEVBUF
, M_WAITOK
);
77 cf
->cf_name
= "gpiosim";
78 cf
->cf_atname
= "gpiosim";
80 cf
->cf_fstate
= FSTATE_NOTFOUND
;
81 config_attach_pseudo(cf
);
86 gpiosim_attach(device_t parent
, device_t self
, void *aux
)
88 struct gpiosim_softc
*sc
= device_private(self
);
89 struct gpiobus_attach_args gba
;
90 const struct sysctlnode
*node
;
95 printf("%s", device_xname(sc
->sc_dev
));
97 /* initialize pin array */
98 for (i
= 0; i
< GPIOSIM_NPINS
; i
++) {
99 sc
->sc_gpio_pins
[i
].pin_num
= i
;
100 sc
->sc_gpio_pins
[i
].pin_caps
= GPIO_PIN_INPUT
|
101 GPIO_PIN_OUTPUT
| GPIO_PIN_OPENDRAIN
|
102 GPIO_PIN_PULLUP
| GPIO_PIN_PULLDOWN
|
103 GPIO_PIN_INVIN
| GPIO_PIN_INVOUT
;
105 /* read initial state */
106 sc
->sc_gpio_pins
[i
].pin_flags
= GPIO_PIN_INPUT
;
109 /* create controller tag */
110 sc
->sc_gpio_gc
.gp_cookie
= sc
;
111 sc
->sc_gpio_gc
.gp_pin_read
= gpiosim_pin_read
;
112 sc
->sc_gpio_gc
.gp_pin_write
= gpiosim_pin_write
;
113 sc
->sc_gpio_gc
.gp_pin_ctl
= gpiosim_pin_ctl
;
115 /* gba.gba_name = "gpio"; */
116 gba
.gba_gc
= &sc
->sc_gpio_gc
;
117 gba
.gba_pins
= sc
->sc_gpio_pins
;
118 gba
.gba_npins
= GPIOSIM_NPINS
;
121 pmf_device_register(self
, NULL
, NULL
);
123 sysctl_createv(NULL
, 0, NULL
, NULL
,
125 CTLTYPE_NODE
, "hw", NULL
,
128 sysctl_createv(&sc
->sc_log
, 0, NULL
, &node
,
130 CTLTYPE_NODE
, device_xname(sc
->sc_dev
),
131 SYSCTL_DESCR("GPIO simulator"),
133 CTL_HW
, CTL_CREATE
, CTL_EOL
);
136 printf(": can't create sysctl node\n");
140 sysctl_createv(&sc
->sc_log
, 0, &node
, NULL
,
142 CTLTYPE_INT
, "value",
143 SYSCTL_DESCR("Current GPIO simulator value"),
144 gpiosim_sysctl
, 0, sc
, 0,
145 CTL_CREATE
, CTL_EOL
);
147 printf(": simulating %d pins\n", GPIOSIM_NPINS
);
148 sc
->sc_gdev
= config_found_ia(self
, "gpiobus", &gba
, gpiobus_print
);
152 gpiosim_detach(device_t self
, int flags
)
154 struct gpiosim_softc
*sc
= device_private(self
);
156 /* Detach the gpio driver that attached here */
157 if (sc
->sc_gdev
!= NULL
)
158 config_detach(sc
->sc_gdev
, 0);
160 pmf_device_deregister(self
);
161 if (sc
->sc_log
!= NULL
) {
162 sysctl_teardown(&sc
->sc_log
);
169 gpiosim_sysctl(SYSCTLFN_ARGS
)
171 struct sysctlnode node
;
172 struct gpiosim_softc
*sc
;
176 sc
= node
.sysctl_data
;
178 node
.sysctl_data
= &val
;
181 error
= sysctl_lookup(SYSCTLFN_CALL(&node
));
182 if (error
|| newp
== NULL
)
190 gpiosim_pin_read(void *arg
, int pin
)
192 struct gpiosim_softc
*sc
= arg
;
194 if (sc
->sc_state
& (1 << pin
))
195 return GPIO_PIN_HIGH
;
201 gpiosim_pin_write(void *arg
, int pin
, int value
)
203 struct gpiosim_softc
*sc
= arg
;
206 sc
->sc_state
&= ~(1 << pin
);
208 sc
->sc_state
|= (1 << pin
);
212 gpiosim_pin_ctl(void *arg
, int pin
, int flags
)
214 struct gpiosim_softc
*sc
= arg
;
216 sc
->sc_gpio_pins
[pin
].pin_flags
= flags
;