Date: Thu, 21 Jul 2011 01:04:09 GMT From: Jakub Wojciech Klama <jceel@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 196472 for review Message-ID: <201107210104.p6L149i2023665@skunkworks.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@196472?ac=10 Change 196472 by jceel@jceel_cyclone on 2011/07/21 01:03:33 Add initial version of GPIO driver. Affected files ... .. //depot/projects/soc2011/jceel_lpc/sys/arm/conf/EA3250#6 edit .. //depot/projects/soc2011/jceel_lpc/sys/arm/lpc/files.lpc#5 edit .. //depot/projects/soc2011/jceel_lpc/sys/arm/lpc/lpc_gpio.c#2 edit .. //depot/projects/soc2011/jceel_lpc/sys/arm/lpc/lpcreg.h#4 edit .. //depot/projects/soc2011/jceel_lpc/sys/boot/fdt/dts/ea3250.dts#6 edit Differences ... ==== //depot/projects/soc2011/jceel_lpc/sys/arm/conf/EA3250#6 (text+ko) ==== @@ -86,6 +86,12 @@ device mmcsd device lpcmmc +device gpio +device gpioled +device lpcgpio + +#device lpcfb + # Flattened Device Tree options FDT options FDT_DTB_STATIC ==== //depot/projects/soc2011/jceel_lpc/sys/arm/lpc/files.lpc#5 (text+ko) ==== @@ -12,5 +12,7 @@ arm/lpc/if_lpe.c optional lpe arm/lpc/lpc_ohci.c optional ohci arm/lpc/lpc_mmc.c optional lpcmmc +#arm/lpc/lpc_fb.c optional lpcfb +arm/lpc/lpc_gpio.c optional lpcgpio dev/uart/uart_dev_ns8250.c optional uart kern/kern_clocksource.c standard ==== //depot/projects/soc2011/jceel_lpc/sys/arm/lpc/lpc_gpio.c#2 (text+ko) ==== @@ -26,3 +26,272 @@ */ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bio.h> +#include <sys/bus.h> +#include <sys/conf.h> +#include <sys/endian.h> +#include <sys/kernel.h> +#include <sys/kthread.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/module.h> +#include <sys/mutex.h> +#include <sys/queue.h> +#include <sys/resource.h> +#include <sys/rman.h> +#include <sys/time.h> +#include <sys/timetc.h> +#include <sys/watchdog.h> +#include <sys/gpio.h> + +#include <machine/bus.h> +#include <machine/cpu.h> +#include <machine/cpufunc.h> +#include <machine/resource.h> +#include <machine/frame.h> +#include <machine/intr.h> + +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +#include <arm/lpc/lpcreg.h> +#include <arm/lpc/lpcvar.h> + +#include "gpio_if.h" + +struct lpc_gpio_softc +{ + device_t lg_dev; + struct resource * lg_res; + bus_space_tag_t lg_bst; + bus_space_handle_t lg_bsh; +}; + +#define LPC_GPIO_NPINS (32 * 2) + +static int lpc_gpio_probe(device_t); +static int lpc_gpio_attach(device_t); +static int lpc_gpio_detach(device_t); + +static int lpc_gpio_pin_max(device_t, int *); +static int lpc_gpio_pin_getcaps(device_t, uint32_t, uint32_t *); +static int lpc_gpio_pin_getflags(device_t, uint32_t, uint32_t *); +static int lpc_gpio_pin_setflags(device_t, uint32_t, uint32_t); +static int lpc_gpio_pin_getname(device_t, uint32_t, char *); +static int lpc_gpio_pin_get(device_t, uint32_t, uint32_t *); +static int lpc_gpio_pin_set(device_t, uint32_t, uint32_t); +static int lpc_gpio_pin_toggle(device_t, uint32_t); + +#define lpc_gpio_read_4(_sc, _reg) \ + bus_space_read_4(_sc->lg_bst, _sc->lg_bsh, _reg) +#define lpc_gpio_write_4(_sc, _reg, _val) \ + bus_space_write_4(_sc->lg_bst, _sc->lg_bsh, _reg, _val) + +static int +lpc_gpio_probe(device_t dev) +{ + if (!ofw_bus_is_compatible(dev, "lpc,gpio")) + return (ENXIO); + + return (BUS_PROBE_DEFAULT); +} + +static int +lpc_gpio_attach(device_t dev) +{ + struct lpc_gpio_softc *sc = device_get_softc(dev); + int rid; + + sc->lg_dev = dev; + + rid = 0; + sc->lg_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, + RF_ACTIVE); + if (!sc->lg_res) { + device_printf(dev, "cannot allocate memory window\n"); + return (ENXIO); + } + + sc->lg_bst = rman_get_bustag(sc->lg_res); + sc->lg_bsh = rman_get_bushandle(sc->lg_res); + + device_add_child(dev, "gpioc", device_get_unit(dev)); + device_add_child(dev, "gpiobus", device_get_unit(dev)); + + return (bus_generic_attach(dev)); +} + +static int +lpc_gpio_detach(device_t dev) +{ + /* XXX */ + return (0); +} + +static int +lpc_gpio_pin_max(device_t dev, int *npins) +{ + /* Currently supports only P0 and P1 */ + *npins = LPC_GPIO_NPINS; + return (0); +} + +static int +lpc_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps) +{ + if (pin > LPC_GPIO_NPINS) + return (ENODEV); + + *caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT; + return (0); +} + +static int +lpc_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags) +{ + struct lpc_gpio_softc *sc = device_get_softc(dev); + uint32_t direction; + + if (pin >= 32) { + pin -= 32; + direction = lpc_gpio_read_4(sc, LPC_GPIO_P1_DIR_STATE); + } else { + direction = lpc_gpio_read_4(sc, LPC_GPIO_P1_DIR_STATE); + } + + if (direction & (1 << pin)) + *flags = GPIO_PIN_OUTPUT; + else + *flags = GPIO_PIN_INPUT; + + return (0); +} + +static int +lpc_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags) +{ + struct lpc_gpio_softc *sc = device_get_softc(dev); + uint32_t direction, state; + + if (flags & GPIO_PIN_INPUT) + direction = 0; + + if (flags & GPIO_PIN_OUTPUT) + direction = 1; + + if (pin >= 32) { + pin -= 32; + state = lpc_gpio_read_4(sc, LPC_GPIO_P1_DIR_STATE); + lpc_gpio_write_4(sc, LPC_GPIO_P1_DIR_SET, state | (direction << pin)); + } else { + state = lpc_gpio_read_4(sc, LPC_GPIO_P1_DIR_STATE); + lpc_gpio_write_4(sc, LPC_GPIO_P1_DIR_SET, state | (direction << pin)); + + } + + return (0); +} + +static int +lpc_gpio_pin_getname(device_t dev, uint32_t pin, char *name) +{ + snprintf(name, GPIOMAXNAME - 1, "pin%d", pin); + return (0); +} + +static int +lpc_gpio_pin_get(device_t dev, uint32_t pin, uint32_t *value) +{ + struct lpc_gpio_softc *sc = device_get_softc(dev); + uint32_t state; + + if (pin >= 32) { + pin -= 32; + state = lpc_gpio_read_4(sc, LPC_GPIO_P1_INP_STATE); + *value = (state & (1 << pin)); + } else { + state = lpc_gpio_read_4(sc, LPC_GPIO_P0_INP_STATE); + *value = (state & (1 << pin)); + } + + return (0); +} + +static int +lpc_gpio_pin_set(device_t dev, uint32_t pin, uint32_t value) +{ + struct lpc_gpio_softc *sc = device_get_softc(dev); + uint32_t state; + + if (pin >= 32) { + pin -= 32; + state = lpc_gpio_read_4(sc, LPC_GPIO_P1_OUTP_STATE); + state = value ? state | (1 << pin) : state & ~(1 << pin); + lpc_gpio_write_4(sc, LPC_GPIO_P1_OUTP_SET, state); + } else { + state = lpc_gpio_read_4(sc, LPC_GPIO_P0_OUTP_STATE); + state = value ? state | (1 << pin) : state & ~(1 << pin); + lpc_gpio_write_4(sc, LPC_GPIO_P0_OUTP_SET, state | (1 << pin)); + } + + return (0); +} + +static int +lpc_gpio_pin_toggle(device_t dev, uint32_t pin) +{ + struct lpc_gpio_softc *sc = device_get_softc(dev); + uint32_t state; + + if (pin >= 32) { + pin -= 32; + state = lpc_gpio_read_4(sc, LPC_GPIO_P1_OUTP_STATE); + state = (state & (1 << pin)) ? state & ~(1 << pin) : state | (1 << pin); + lpc_gpio_write_4(sc, LPC_GPIO_P1_OUTP_SET, state); + } else { + state = lpc_gpio_read_4(sc, LPC_GPIO_P0_OUTP_STATE); + state = (state & (1 << pin)) ? state & ~(1 << pin) : state | (1 << pin); + lpc_gpio_write_4(sc, LPC_GPIO_P0_OUTP_SET, state | (1 << pin)); + } + + return (0); + +} + +static device_method_t lpc_gpio_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, lpc_gpio_probe), + DEVMETHOD(device_attach, lpc_gpio_attach), + DEVMETHOD(device_detach, lpc_gpio_detach), + + /* GPIO interface */ + DEVMETHOD(gpio_pin_max, lpc_gpio_pin_max), + DEVMETHOD(gpio_pin_getcaps, lpc_gpio_pin_getcaps), + DEVMETHOD(gpio_pin_getflags, lpc_gpio_pin_getflags), + DEVMETHOD(gpio_pin_setflags, lpc_gpio_pin_setflags), + DEVMETHOD(gpio_pin_getname, lpc_gpio_pin_getname), + DEVMETHOD(gpio_pin_set, lpc_gpio_pin_set), + DEVMETHOD(gpio_pin_get, lpc_gpio_pin_get), + DEVMETHOD(gpio_pin_toggle, lpc_gpio_pin_toggle), + + { 0, 0 } +}; + +static devclass_t lpc_gpio_devclass; + +static driver_t lpc_gpio_driver = { + "lpcgpio", + lpc_gpio_methods, + sizeof(struct lpc_gpio_softc), +}; + +extern devclass_t gpiobus_devclass, gpioc_devclass; +extern driver_t gpiobus_driver, gpioc_driver; + +DRIVER_MODULE(lpcgpio, simplebus, lpc_gpio_driver, lpc_gpio_devclass, 0, 0); +DRIVER_MODULE(gpiobus, lpcgpio, gpiobus_driver, gpiobus_devclass, 0, 0); +DRIVER_MODULE(gpioc, lpcgpio, gpioc_driver, gpioc_devclass, 0, 0); +MODULE_VERSION(lpcgpio, 1); ==== //depot/projects/soc2011/jceel_lpc/sys/arm/lpc/lpcreg.h#4 (text+ko) ==== @@ -341,5 +341,61 @@ #define LPC_ISP3101_OTG_INTR_RISING 0x0e #define LPC_ISP3101_REG_CLEAR_ADDR 0x01 +/* + * LCD Controller (from UM10326: LPC32x0 User manual, page 229) + */ +#define LPC_LCD_TIMH 0x00 +#define LPC_LCD_TIMV 0x04 +#define LPC_LCD_POL 0x08 +#define LPC_LCD_LE 0x0c +#define LPC_LCD_UPBASE 0x10 +#define LPC_LCD_LPBASE 0x14 +#define LPC_LCD_CTRL 0x18 +#define LPC_LCD_INTMSK 0x1c +#define LPC_LCD_INTRAW 0x20 +#define LPC_LCD_INTSTAT 0x24 +#define LPC_LCD_INTCLR 0x28 +#define LPC_LCD_UPCURR 0x2c +#define LPC_LCD_LPCURR 0x30 +#define LPC_LCD_PAL 0x200 +#define LPC_LCD_CRSR_IMG 0x800 +#define LPC_LCD_CRSR_CTRL 0xc00 +#define LPC_LCD_CRSR_CFG 0xc04 +#define LPC_LCD_CRSR_PAL0 0xc08 +#define LPC_LCD_CRSR_PAL1 0xc0c +#define LPC_LCD_CRSR_XY 0xc10 +#define LPC_LCD_CRSR_CLIP 0xc14 +#define LPC_LCD_CRSR_INTMSK 0xc20 +#define LPC_LCD_CRSR_INTCLR 0xc24 +#define LPC_LCD_CRSR_INTRAW 0xc28 +#define LPC_LCD_CRSR_INTSTAT 0xc2c + +/* + * GPIO (from UM10326: LPC32x0 User manual, page 606) + */ +#define LPC_GPIO_P0_INP_STATE 0x40 +#define LPC_GPIO_P0_OUTP_SET 0x44 +#define LPC_GPIO_P0_OUTP_CLR 0x48 +#define LPC_GPIO_P0_OUTP_STATE 0x4c +#define LPC_GPIO_P0_DIR_SET 0x50 +#define LPC_GPIO_P0_DIR_CLR 0x54 +#define LPC_GPIO_P0_DIR_STATE 0x58 +#define LPC_GPIO_P1_INP_STATE 0x60 +#define LPC_GPIO_P1_OUTP_SET 0x64 +#define LPC_GPIO_P1_OUTP_CLR 0x68 +#define LPC_GPIO_P1_OUTP_STATE 0x6c +#define LPC_GPIO_P1_DIR_SET 0x70 +#define LPC_GPIO_P1_DIR_CLR 0x74 +#define LPC_GPIO_P1_DIR_STATE 0x78 +#define LPC_GPIO_P2_INP_STATE 0x1c +#define LPC_GPIO_P2_OUTP_SET 0x20 +#define LPC_GPIO_P2_OUTP_CLR 0x24 +#define LPC_GPIO_P2_DIR_SET 0x10 +#define LPC_GPIO_P2_DIR_CLR 0x14 +#define LPC_GPIO_P2_DIR_STATE 0x14 +#define LPC_GPIO_P3_INP_STATE 0x00 +#define LPC_GPIO_P3_OUTP_SET 0x04 +#define LPC_GPIO_P3_OUTP_CLR 0x08 +#define LPC_GPIO_P3_OUTP_STATE 0x0c #endif /* _ARM_LPC_LPCREG_H */ ==== //depot/projects/soc2011/jceel_lpc/sys/boot/fdt/dts/ea3250.dts#6 (text+ko) ==== @@ -166,6 +166,11 @@ interrupts = <24>; interrupt-parent = <&PIC>; }; + + gpio@28000 { + compatible = "lpc,gpio"; + reg = <0x28000 0x4000>; + }; }; ahb6@30000000 { @@ -180,6 +185,13 @@ interrupts = <59>; interrupt-parent = <&PIC>; }; + + lpcfb@1040000 { + compatible = "lpc,fb"; + reg = <0x1040000 0x20000>; + interrupts = <14>; + interrupt-parent = <&PIC>; + }; lpe@1060000 { compatible = "lpc,ethernet"; @@ -209,7 +221,7 @@ lpcmmc@98000 { compatible = "lpc,mmc"; reg = <0x98000 0x4000>; - interrupts = <15>; + interrupts = <15 13>; interrupt-parent = <&PIC>; }; };
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201107210104.p6L149i2023665>