0
votes

Is there anyway we can find the physical address of the BBB's LEDs? I am new to this, but I am trying to write a device driver that access hardware directly. Thank you :).

1

1 Answers

1
votes

Yes, you can consult the BBB schematics to find the pins connecting LEDs here. Let me help you with that. enter image description here

And here are the actual chipset pins.

enter image description here

So, you need to access and control the pins GPIO1_21, GPIO1_22, GPIO1_23 and GPIO1_24. For this, you need to make sure no other driver is configuring/using these pins. Most probably these pins are already being controlled by the existing "gpio-leds" driver. See the device tree node for gpio-led driver below (source)

leds {
        pinctrl-names = "default";
        pinctrl-0 = <&user_leds_s0>;

        compatible = "gpio-leds";

        led@2 {
            label = "beaglebone:green:heartbeat";
            gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>;
            linux,default-trigger = "heartbeat";
            default-state = "off";
        };

        led@3 {
            label = "beaglebone:green:mmc0";
            gpios = <&gpio1 22 GPIO_ACTIVE_HIGH>;
            linux,default-trigger = "mmc0";
            default-state = "off";
        };

        led@4 {
            label = "beaglebone:green:usr2";
            gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>;
            linux,default-trigger = "cpu0";
            default-state = "off";
        };

        led@5 {
            label = "beaglebone:green:usr3";
            gpios = <&gpio1 24 GPIO_ACTIVE_HIGH>;
            linux,default-trigger = "mmc1";
            default-state = "off";
        };
    };

You need to either disable or override the above node to use your own driver. Also make sure to select the correct pinmux setting for your driver so these pins are in gpio mode. You can reuse the default "user_leds_s0" pin group shown below.

&am33xx_pinmux {
    pinctrl-names = "default";
    pinctrl-0 = <&clkout2_pin>;

    user_leds_s0: user_leds_s0 {
        pinctrl-single,pins = <
            0x54 (PIN_OUTPUT_PULLDOWN | MUX_MODE7)  /* gpmc_a5.gpio1_21 */
            0x58 (PIN_OUTPUT_PULLUP | MUX_MODE7)    /* gpmc_a6.gpio1_22 */
            0x5c (PIN_OUTPUT_PULLDOWN | MUX_MODE7)  /* gpmc_a7.gpio1_23 */
            0x60 (PIN_OUTPUT_PULLUP | MUX_MODE7)    /* gpmc_a8.gpio1_24 */
        >;
    };

Finally, instead of using the physical address of the GPIO pin directly, you should use Linux's GPIO interface as it has already taken control of the GPIO registers. Your final devicetree node for your custom driver could look something like this:

leds {
        pinctrl-names = "default";
        pinctrl-0 = <&user_leds_s0>;

        compatible = "my-gpio-led-driver";

        userled-gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>, /* USR0 */
                <&gpio1 22 GPIO_ACTIVE_HIGH>, /* USR1 */
                <&gpio1 23 GPIO_ACTIVE_HIGH>; /* USR2 */
                <&gpio1 24 GPIO_ACTIVE_HIGH>; /* USR3 */


}

In the driver code, you can refer to these GPIO pins as below

    struct gpio_desc *usr_led0, *usr_led1, *usr_led2, *usr_led3;

    usr_led0 = gpiod_get_index(dev, "userled", 0, GPIOD_OUT_HIGH);
    usr_led1 = gpiod_get_index(dev, "userled", 1, GPIOD_OUT_HIGH);
    usr_led2 = gpiod_get_index(dev, "userled", 2, GPIOD_OUT_HIGH);
    usr_led3 = gpiod_get_index(dev, "userled", 3, GPIOD_OUT_HIGH);

Then you can use linux gpio consumer interface (gpiod_* API) to control the leds.

Follow these links for more details:

  1. Requesting the GPIO pins required in the device tree.
  2. Getting and controlling the GPIO pins from kernel driver.