Landfall

pkg/landfall-examples/ci20_leds/ci20_leds.c

142:a9f3e40e79ee
17 months ago Paul Boddie Incorporated API changes made to the L4Re distribution since Subversion r83. l4re-git-distribution
     1 /*     2  * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>     3  *     economic rights: Technische Universit??t Dresden (Germany)     4  * Copyright (C) 2017, 2018, 2023 Paul Boddie <paul@boddie.org.uk>     5  *     6  * This file is part of TUD:OS and distributed under the terms of the     7  * GNU General Public License 2.     8  * Please see the COPYING-GPL-2 file for details.     9  */    10 /*    11  * Access the LED and other GPIOs on the MIPS Creator CI20 board.    12  * This example shows how to use the following GPIOs:    13  *    14  * PD17 - SW1 button    15  * PF15 - blue/red LED (high -> red, low -> blue)    16  */    17     18 #include <l4/devices/gpio-jz4780.h>    19 #include <l4/io/io.h>    20 #include <l4/re/env.h>    21 #include <l4/re/c/util/cap_alloc.h>    22 #include <l4/sys/factory.h>    23 #include <l4/sys/icu.h>    24 #include <l4/sys/ipc.h>    25 #include <l4/sys/irq.h>    26 #include <l4/sys/rcv_endpoint.h>    27 #include <l4/vbus/vbus.h>    28 #include <stdio.h>    29 #include <unistd.h>    30 #include <stdint.h>    31     32 enum {    33   LED = 15, // via PORTF    34   SW1 = 17, // via PORTD    35 };    36     37     38     39 /* Device and resource discovery. */    40     41 static char const *resource_type(enum l4io_resource_types_t type)    42 {    43   switch (type)    44   {    45     case L4VBUS_RESOURCE_INVALID:    46     return "INVALID";    47     48     case L4VBUS_RESOURCE_IRQ:    49     return "IRQ";    50     51     case L4VBUS_RESOURCE_MEM:    52     return "MEMORY";    53     54     default:    55     return "OTHER";    56   }    57 }    58     59 static int gpio_get_device(char const *hid, l4io_device_handle_t *dh, l4io_resource_handle_t *rh)    60 {    61   int result = l4io_lookup_device(hid, dh, 0, rh);    62     63   if (result < 0)    64     printf("Could not access '%s': %s\n", hid, result == -L4_ENOENT ? "no such device" : "no device");    65     66   return result;    67 }    68     69 static int gpio_get_resource(l4io_device_handle_t dh, l4io_resource_t *res,    70                              enum l4io_resource_types_t type)    71 {    72   int current = 0, result = 0;    73   l4_cap_idx_t vbus = l4re_env_get_cap("vbus");    74     75   do    76   {    77     result = l4vbus_get_resource(vbus, dh, current, res);    78     79     if (result)    80       printf("Could not access resource of type %s.\n", resource_type(type));    81     else    82       printf("Resource %d: type %s, start=%lx, end=%lx\n", res->id,    83         resource_type(res->type), res->start, res->end);    84     85     current++;    86   }    87   while ((!result) && (res->type != type));    88     89   return result;    90 }    91     92 static int gpio_get_irq(char const *hid, l4_uint32_t *start, l4_uint32_t *end)    93 {    94   l4io_device_handle_t dh;    95   l4io_resource_handle_t rh;    96   l4io_resource_t res;    97   int result;    98     99   result = gpio_get_device(hid, &dh, &rh);   100    101   if (result < 0)   102     return result;   103    104   result = gpio_get_resource(dh, &res, L4IO_RESOURCE_IRQ);   105    106   if (result)   107     return result;   108    109   *start = res.start;   110   *end = res.end;   111    112   return result;   113 }   114    115 static int gpio_get_memory(char const *hid, l4_addr_t *start, l4_addr_t *end)   116 {   117   l4io_device_handle_t dh;   118   l4io_resource_handle_t rh;   119   l4io_resource_t res;   120   int result;   121    122   result = gpio_get_device(hid, &dh, &rh);   123    124   if (result < 0)   125     return result;   126    127   result = gpio_get_resource(dh, &res, L4IO_RESOURCE_MEM);   128    129   if (result)   130     return result;   131    132   if ((result = l4io_request_iomem(res.start, res.end - res.start + 1,   133                                   L4IO_MEM_NONCACHED, start)))   134   {   135     printf("Could not get address for '%s'.\n", hid);   136     return result;   137   }   138    139   printf("Resource at 0x%lx...0x%lx.\n", res.start, res.end);   140    141   *end = *start + (res.end - res.start + 1);   142    143   return 0;   144 }   145    146 static long item_in_range(long start, long end, long index)   147 {   148   if (start < end)   149     return start + index;   150   else   151     return start - index;   152 }   153    154 int main(void)   155 {   156   l4_addr_t gpio_base = 0, gpio_base_end = 0, port_d, port_d_end, port_f, port_f_end;   157   l4_uint32_t gpio_irq_start = 0, gpio_irq_end = 0, gpio_irq;   158   l4_cap_idx_t irqcap, icucap;   159   l4_msgtag_t tag;   160   long err;   161   void *gpio_port_d, *gpio_port_f, *gpio_irq_pin;   162   int result = 0;   163   int led = 0;   164    165   /* Obtain capabilities for the interrupt controller and an interrupt. */   166    167   irqcap = l4re_util_cap_alloc();   168   icucap = l4re_env_get_cap("icu");   169    170   if (l4_is_invalid_cap(icucap))   171   {   172     printf("No 'icu' capability available in the virtual bus.\n");   173     return 1;   174   }   175    176   if (l4_is_invalid_cap(irqcap))   177   {   178     printf("No capability available for the interrupt.\n");   179     return 1;   180   }   181    182   /* Obtain resource details describing the interrupt and I/O memory. */   183    184   printf("Access IRQ...\n");   185    186   if ((result = gpio_get_irq("jz4780-gpio", &gpio_irq_start, &gpio_irq_end)) < 0)   187     return 1;   188    189   gpio_irq = item_in_range(gpio_irq_start, gpio_irq_end, 3);   190   printf("IRQ range at %d...%d.\n", gpio_irq_start, gpio_irq_end);   191   printf("PORTD IRQ at %d.\n", gpio_irq);   192    193   printf("Access GPIO...\n");   194    195   if ((result = gpio_get_memory("jz4780-gpio", &gpio_base, &gpio_base_end)) < 0)   196     return 1;   197    198   port_d = gpio_base + 0x300;   199   port_d_end = port_d + 0x100;   200   port_f = gpio_base + 0x500;   201   port_f_end = port_f + 0x100;   202    203   printf("GPIO at 0x%lx...0x%lx.\n", gpio_base, gpio_base_end);   204   printf("PORTD at 0x%lx...0x%lx.\n", port_d, port_d_end);   205   printf("PORTF at 0x%lx...0x%lx.\n", port_f, port_f_end);   206    207   gpio_port_d = jz4780_gpio_init(port_d, port_d_end, 32, 0xffff4fff, 0x0000b000);   208   gpio_port_f = jz4780_gpio_init(port_f, port_f_end, 32, 0xffa7f00f, 0x00580ff0);   209    210   /* Create an interrupt object. */   211    212   if ((err = l4_error(tag = l4_factory_create_irq(l4re_global_env->factory, irqcap))))   213   {   214     printf("Could not create IRQ object: %lx\n", err);   215     return 1;   216   }   217    218   /* Bind the interrupt object to the IRQ number. */   219    220   if ((err = l4_error(l4_icu_bind(icucap, gpio_irq, irqcap))))   221   {   222     printf("Could not bind IRQ %d to the ICU: %ld\n", gpio_irq, err);   223     return 1;   224   }   225    226   /* Attach ourselves to the interrupt handler. */   227    228   tag = l4_rcv_ep_bind_thread(irqcap, l4re_env()->main_thread, 0xDEAD);   229    230   if ((err = l4_error(tag)))   231   {   232     printf("Could not attach to IRQ %d: %ld\n", gpio_irq, err);   233     return 1;   234   }   235    236   /* Set the GPIO pins up. */   237    238   printf("Set up GPIO pins...\n");   239    240   jz4780_gpio_setup(gpio_port_d, SW1, L4VBUS_GPIO_SETUP_IRQ, 1);   241   jz4780_gpio_setup(gpio_port_f, LED, L4VBUS_GPIO_SETUP_OUTPUT, 0);   242    243   gpio_irq_pin = jz4780_gpio_get_irq(gpio_port_d, SW1);   244   jz4780_gpio_irq_set_mode(gpio_irq_pin, L4_IRQ_F_LEVEL_HIGH);   245    246   printf("Press SW1 to invert LED.\n");   247    248   while (1)   249   {   250     tag = l4_irq_receive(irqcap, L4_IPC_NEVER);   251    252     if ((err = l4_ipc_error(tag, l4_utcb())))   253     {   254       printf("Error on IRQ receive: %ld\n", err);   255       continue;   256     }   257    258     printf("SW1: %x\n", jz4780_gpio_get(gpio_port_d, SW1));   259    260     if (jz4780_gpio_get(gpio_port_d, SW1))   261     {   262       printf("Invert LED\n");   263       jz4780_gpio_set(gpio_port_f, LED, led);   264       led = 1 - led;   265     }   266   }   267    268   /* Detach from the interrupt. */   269    270   tag = l4_irq_detach(irqcap);   271    272   if ((err = l4_error(tag)))   273     printf("Error detaching from IRQ: %ld\n", err);   274    275   return 0;   276 }