void bcm2835gpio_pin_write(u_int pin, u_int val) { const bus_space_tag_t iot = &bcm2835_bs_tag; const bus_space_handle_t ioh = BCM2835_IOPHYSTOVIRT(BCM2835_GPIO_BASE); bus_size_t reg; if (val) { reg = BCM2835_GPIO_GPSET(pin / BCM2835_GPIO_GPSET_PINS_PER_REGISTER); } else { reg = BCM2835_GPIO_GPCLR(pin / BCM2835_GPIO_GPCLR_PINS_PER_REGISTER); } bus_space_write_4(iot, ioh, reg, 1 << (pin % BCM2835_GPIO_GPSET_PINS_PER_REGISTER)); } On Thu, 23 Apr 2015, Jared McNeill wrote:
Set the value of a GPIO pin. Something like this (not compile tested): void bcm2835gpio_function_write(u_int pin, u_int val) { const bus_space_tag_t iot = &bcm2835_bs_tag;const bus_space_handle_t ioh = BCM2835_IOPHYSTOVIRT(BCM2835_GPIO_BASE);const u_int mask = (1 << BCM2835_GPIO_GPFSEL_BITS_PER_PIN) - 1; const u_int regid = (pin / BCM2835_GPIO_GPFSEL_PINS_PER_REGISTER); const u_int shift = (pin % BCM2835_GPIO_GPFSEL_PINS_PER_REGISTER) * BCM2835_GPIO_GPFSEL_BITS_PER_PIN; uint32_t v; v = bus_space_read_4(iot, ioh, BCM2835_GPIO_GPFSEL(regid)); v &= ~(mask << shift); v |= (val << shift); bus_space_write_4(iot, ioh, BCM2835_GPIO_GPFSEL(regid), v); } On Thu, 23 Apr 2015, Stephan wrote:One thing is unclear to me: What is bcm2835gpio_function_write supposed to do?2015-04-21 23:24 GMT+02:00 Jared McNeill <jmcneill%invisible.ca@localhost>:I would do this: - Add bcm2835gpio_function_write to bcm2835_gpio_subr.[ch] - Pass the gpio pin from rpi_device_register to the mmc driver as a device property. - In the MMC driver, if the pin property is set, use it to toggle the LED state. You've selected the right place to do it. Since this is all MD code (and we don't have a MI KPI for gpio access, unfortunately) this approach should be fine. On Tue, 21 Apr 2015, Stephan wrote:Okay, LED_ON() and LED_OFF() is pseudo-code and should have indicated the place to put the control functions in. The next question would be how to control the LED - for example by utilizing the GPIO framework or driver, which might be too much overhead. Another way could be writing directly to the corresponding register. I guess the given code snipped runs in process context and waits on a CV which gets signalled from the interrupt context?! Either way, it might be good to know how it is impleneted in Linux but I couldn?t find the appropriate place yet. The ultra-fragmented nature of Linux isn?t very helpful with finding things. 2015-04-21 14:24 GMT+02:00 Greg Troxel <gdt%ir.bbn.com@localhost>:Stephan <stephanwib%googlemail.com@localhost> writes:bcm_dmac_transfer(sc->sc_dmac); LED_ON(); while (sc->sc_state == EMMC_DMA_STATE_BUSY) { error = cv_timedwait(&sc->sc_cv, &sc->sc_lock, hz * 10); if (error == EWOULDBLOCK) { device_printf(sc->sc.sc_dev, "transfer timeout!\n"); bcm_dmac_halt(sc->sc_dmac); sc->sc_state = EMMC_DMA_STATE_IDLE; error = ETIMEDOUT; break; } } LED_OFF(); mutex_exit(&sc->sc_lock); This also needs to be put in an #ifdef to be only included in a Pi build. Comments / hints / better ideas?I wonder if it makes sense to generalize this, to have a bunch of naemd (#define?) notification types, and macros to on/off, so that they get defined to empty on systems where it doesn't make sense, and to something sensible on various systems that have indicators. Surely the RPI B isn't the only device where this makes sense, and there's probably a lot different. There was a comment about calling these "during the transfer" which was too vague to be really helpful, but you might want to check the locking/sleeping rules - generally one cannot call things that might sleep from interrupts, etc. But given that the code is already calling cv_timedwait, sleeping isn't really an issue (and I don't know what's behind LED_ON()). (A tangent: More generally, one of the harder things to figure out in NetBSD (or anything) is what the locking/etc. rules are, and I think it would help to have more explicit comments in each procedure about assumptions.)