diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/gpio/gpio_if.m | 77 | ||||
-rw-r--r-- | sys/dev/gpio/gpioc.c | 47 | ||||
-rw-r--r-- | sys/sys/gpio.h | 21 |
3 files changed, 142 insertions, 3 deletions
diff --git a/sys/dev/gpio/gpio_if.m b/sys/dev/gpio/gpio_if.m index 6306f33..d25a0c7 100644 --- a/sys/dev/gpio/gpio_if.m +++ b/sys/dev/gpio/gpio_if.m @@ -56,6 +56,43 @@ CODE { return (0); } + + static int + gpio_default_pwm_getcaps(device_t dev __unused, int32_t pwm __unused, + uint32_t pini __unused, uint32_t *caps) + { + + *caps = 0; + + return (0); + } + + static int + gpio_default_pwm_max(device_t dev __unused, uint32_t *pwmmax) + { + + *pwmmax = 0; + + return (0); + } + + static int + gpio_default_pwm_get(device_t dev __unused, uint32_t pwm __unused, + uint32_t pin __unused, uint32_t reg __unused, + uint32_t *value __unused) + { + + return (EINVAL); + } + + static int + gpio_default_pwm_set(device_t dev __unused, uint32_t pwm __unused, + uint32_t pin __unused, uint32_t reg __unused, + uint32_t value __unused) + { + + return (EINVAL); + } }; HEADER { @@ -140,6 +177,46 @@ METHOD int pin_setflags { }; # +# Get maximum pwm number +# +METHOD int pwm_max { + device_t dev; + int *maxpwm; +} DEFAULT gpio_default_pwm_max; + +# +# Get pwm capabilities +# +METHOD int pwm_getcaps { + device_t dev; + int32_t pwm_num; + uint32_t pin_num; + uint32_t *caps; +} DEFAULT gpio_default_pwm_getcaps; + +# +# Get pwm settings of pin specifed by pin_num +# +METHOD int pwm_get { + device_t dev; + int32_t pwm_num; + uint32_t pin_num; + uint32_t pwm_reg; + uint32_t *pwm_value; +} DEFAULT gpio_default_pwm_get; + +# +# Set pwm settings of pin specifed by pin_num +# +METHOD int pwm_set { + device_t dev; + int32_t pwm_num; + uint32_t pin_num; + uint32_t pwm_reg; + uint32_t pwm_value; +} DEFAULT gpio_default_pwm_set; + +# # Allow the GPIO controller to map the gpio-specifier on its own. # METHOD int map_gpios { diff --git a/sys/dev/gpio/gpioc.c b/sys/dev/gpio/gpioc.c index a5a9d81..2a6895a 100644 --- a/sys/dev/gpio/gpioc.c +++ b/sys/dev/gpio/gpioc.c @@ -121,9 +121,10 @@ gpioc_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag, struct thread *td) { device_t bus; - int max_pin, res; + int max_pin, max_pwm, res; struct gpioc_softc *sc = cdev->si_drv1; struct gpio_pin pin; + struct gpio_pwm_req pwmreq; struct gpio_req req; uint32_t caps; @@ -142,9 +143,16 @@ gpioc_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag, res = GPIO_PIN_GETFLAGS(sc->sc_pdev, pin.gp_pin, &pin.gp_flags); /* Fail early */ - if (res) + if (res != 0) + break; + res = GPIO_PIN_GETCAPS(sc->sc_pdev, pin.gp_pin, + &pin.gp_caps); + if (res != 0) + break; + res = GPIO_PWM_GETCAPS(sc->sc_pdev, -1, pin.gp_pin, + &pin.gp_pwm_caps); + if (res != 0) break; - GPIO_PIN_GETCAPS(sc->sc_pdev, pin.gp_pin, &pin.gp_caps); GPIOBUS_PIN_GETNAME(bus, pin.gp_pin, pin.gp_name); bcopy(&pin, arg, sizeof(pin)); break; @@ -185,6 +193,39 @@ gpioc_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag, res = GPIOBUS_PIN_SETNAME(bus, pin.gp_pin, pin.gp_name); break; + case GPIOMAXPWM: + max_pwm = -1; + res = GPIO_PWM_MAX(sc->sc_pdev, &max_pwm); + bcopy(&max_pwm, arg, sizeof(max_pwm)); + break; + case GPIOPWMGETCONFIG: + bcopy(arg, &pwmreq, sizeof(pwmreq)); + res = GPIO_PWM_GETCAPS(sc->sc_pdev, pwmreq.gp_pwm, + pwmreq.gp_pwm_pin, &pwmreq.gp_pwm_caps); + dprintf("pwm getcaps pwm %d pin %d -> caps %#x\n", + pwmreq.gp_pwm, pwmreq.gp_pwm_pin, + pwmreq.gp_pwm_caps); + bcopy(&pwmreq, arg, sizeof(pwmreq)); + break; + case GPIOPWMGET: + bcopy(arg, &pwmreq, sizeof(pwmreq)); + res = GPIO_PWM_GET(sc->sc_pdev, pwmreq.gp_pwm, + pwmreq.gp_pwm_pin, pwmreq.gp_pwm_reg, + &pwmreq.gp_pwm_value); + dprintf("pwm get pwm %d pin %d -> reg %#x %d\n", + pwmreq.gp_pwm, pwmreq.gp_pwm_pin, pwmreq.gp_pwm_reg, + pwmreq.gp_pwm_value); + bcopy(&pwmreq, arg, sizeof(pwmreq)); + break; + case GPIOPWMSET: + bcopy(arg, &pwmreq, sizeof(pwmreq)); + res = GPIO_PWM_SET(sc->sc_pdev, pwmreq.gp_pwm, + pwmreq.gp_pwm_pin, pwmreq.gp_pwm_reg, + pwmreq.gp_pwm_value); + dprintf("pwm set pwm %d pin %d -> reg %#x %d\n", + pwmreq.gp_pwm, pwmreq.gp_pwm_pin, pwmreq.gp_pwm_reg, + pwmreq.gp_pwm_value); + break; default: return (ENOTTY); break; diff --git a/sys/sys/gpio.h b/sys/sys/gpio.h index 9b0a1b5..4b63baa 100644 --- a/sys/sys/gpio.h +++ b/sys/sys/gpio.h @@ -56,6 +56,11 @@ #define GPIO_PIN_LOW 0x00 /* low level (logical 0) */ #define GPIO_PIN_HIGH 0x01 /* high level (logical 1) */ +/* GPIO PWM settings */ +#define GPIO_PWM_DUTY 0x01 /* PWM duty cycle */ +#define GPIO_PWM_FREQ 0x02 /* PWM frequency */ +#define GPIO_PWM_PERIOD 0x04 /* PWM period */ + /* Max name length of a pin */ #define GPIOMAXNAME 64 @@ -70,6 +75,8 @@ #define GPIO_PIN_INVIN 0x00000080 /* invert input */ #define GPIO_PIN_INVOUT 0x00000100 /* invert output */ #define GPIO_PIN_PULSATE 0x00000200 /* pulsate in hardware */ +#define GPIO_PIN_PWM 0x00000400 /* pwm output */ +#define GPIO_PIN_MUX 0x00000800 /* pin mux */ /* GPIO interrupt capabilities */ #define GPIO_INTR_NONE 0x00000000 /* no interrupt support */ #define GPIO_INTR_LEVEL_LOW 0x00010000 /* level trigger, low */ @@ -86,6 +93,7 @@ struct gpio_pin { char gp_name[GPIOMAXNAME]; /* human-readable name */ uint32_t gp_caps; /* capabilities */ uint32_t gp_flags; /* current flags */ + uint32_t gp_pwm_caps; /* pwm capabilities */ }; /* GPIO pin request (read/write/toggle) */ @@ -94,6 +102,15 @@ struct gpio_req { uint32_t gp_value; /* value */ }; +/* GPIO pwm request (read/write) */ +struct gpio_pwm_req { + int32_t gp_pwm; /* pwm number */ + uint32_t gp_pwm_pin; /* pin number */ + uint32_t gp_pwm_reg; /* register */ + uint32_t gp_pwm_value; /* value */ + uint32_t gp_pwm_caps; /* pwm capabilities */ +}; + /* * ioctls */ @@ -104,5 +121,9 @@ struct gpio_req { #define GPIOSET _IOW('G', 4, struct gpio_req) #define GPIOTOGGLE _IOWR('G', 5, struct gpio_req) #define GPIOSETNAME _IOW('G', 6, struct gpio_pin) +#define GPIOMAXPWM _IOR('G', 7, int) +#define GPIOPWMGETCONFIG _IOWR('G', 8, struct gpio_pwm_req) +#define GPIOPWMGET _IOWR('G', 9, struct gpio_pwm_req) +#define GPIOPWMSET _IOW('G', 10, struct gpio_pwm_req) #endif /* __GPIO_H__ */ |