Landfall

pkg/landfall-examples/ci20_leds/ci20_leds.c

139:74eafd298a88
2022-01-14 Paul Boddie Removed superfluous flag, fixed comment.
     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 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/vbus/vbus.h>    27 #include <stdio.h>    28 #include <unistd.h>    29 #include <stdint.h>    30     31 enum {    32   LED = 15, // via PORTF    33   SW1 = 17, // via PORTD    34 };    35     36     37     38 /* Device and resource discovery. */    39     40 static char const *resource_type(enum l4io_resource_types_t type)    41 {    42   switch (type)    43   {    44     case L4VBUS_RESOURCE_INVALID:    45     return "INVALID";    46     47     case L4VBUS_RESOURCE_IRQ:    48     return "IRQ";    49     50     case L4VBUS_RESOURCE_MEM:    51     return "MEMORY";    52     53     default:    54     return "OTHER";    55   }    56 }    57     58 static int gpio_get_device(char const *hid, l4io_device_handle_t *dh, l4io_resource_handle_t *rh)    59 {    60   int result = l4io_lookup_device(hid, dh, 0, rh);    61     62   if (result < 0)    63     printf("Could not access '%s': %s\n", hid, result == -L4_ENOENT ? "no such device" : "no device");    64     65   return result;    66 }    67     68 static int gpio_get_resource(l4io_device_handle_t dh, l4io_resource_t *res,    69                              enum l4io_resource_types_t type)    70 {    71   int current = 0, result = 0;    72   l4_cap_idx_t vbus = l4re_env_get_cap("vbus");    73     74   do    75   {    76     result = l4vbus_get_resource(vbus, dh, current, res);    77     78     if (result)    79       printf("Could not access resource of type %s.\n", resource_type(type));    80     else    81       printf("Resource %d: type %s, start=%lx, end=%lx\n", res->id,    82         resource_type(res->type), res->start, res->end);    83     84     current++;    85   }    86   while ((!result) && (res->type != type));    87     88   return result;    89 }    90     91 static int gpio_get_irq(char const *hid, l4_uint32_t *start, l4_uint32_t *end)    92 {    93   l4io_device_handle_t dh;    94   l4io_resource_handle_t rh;    95   l4io_resource_t res;    96   int result;    97     98   result = gpio_get_device(hid, &dh, &rh);    99    100   if (result < 0)   101     return result;   102    103   result = gpio_get_resource(dh, &res, L4IO_RESOURCE_IRQ);   104    105   if (result)   106     return result;   107    108   *start = res.start;   109   *end = res.end;   110    111   return result;   112 }   113    114 static int gpio_get_memory(char const *hid, l4_addr_t *start, l4_addr_t *end)   115 {   116   l4io_device_handle_t dh;   117   l4io_resource_handle_t rh;   118   l4io_resource_t res;   119   int result;   120    121   result = gpio_get_device(hid, &dh, &rh);   122    123   if (result < 0)   124     return result;   125    126   result = gpio_get_resource(dh, &res, L4IO_RESOURCE_MEM);   127    128   if (result)   129     return result;   130    131   if ((result = l4io_request_iomem(res.start, res.end - res.start + 1,   132                                   L4IO_MEM_NONCACHED, start)))   133   {   134     printf("Could not get address for '%s'.\n", hid);   135     return result;   136   }   137    138   printf("Resource at 0x%lx...0x%lx.\n", res.start, res.end);   139    140   *end = *start + (res.end - res.start + 1);   141    142   return 0;   143 }   144    145 static long item_in_range(long start, long end, long index)   146 {   147   if (start < end)   148     return start + index;   149   else   150     return start - index;   151 }   152    153 int main(void)   154 {   155   l4_addr_t gpio_base = 0, gpio_base_end = 0, port_d, port_d_end, port_f, port_f_end;   156   l4_uint32_t gpio_irq_start = 0, gpio_irq_end = 0, gpio_irq;   157   l4_cap_idx_t irqcap, icucap;   158   l4_msgtag_t tag;   159   long err;   160   void *gpio_port_d, *gpio_port_f, *gpio_irq_pin;   161   int result = 0;   162   int led = 0;   163    164   /* Obtain capabilities for the interrupt controller and an interrupt. */   165    166   irqcap = l4re_util_cap_alloc();   167   icucap = l4re_env_get_cap("icu");   168    169   if (l4_is_invalid_cap(icucap))   170   {   171     printf("No 'icu' capability available in the virtual bus.\n");   172     return 1;   173   }   174    175   if (l4_is_invalid_cap(irqcap))   176   {   177     printf("No capability available for the interrupt.\n");   178     return 1;   179   }   180    181   /* Obtain resource details describing the interrupt and I/O memory. */   182    183   printf("Access IRQ...\n");   184    185   if ((result = gpio_get_irq("jz4780-gpio", &gpio_irq_start, &gpio_irq_end)) < 0)   186     return 1;   187    188   gpio_irq = item_in_range(gpio_irq_start, gpio_irq_end, 3);   189   printf("IRQ range at %d...%d.\n", gpio_irq_start, gpio_irq_end);   190   printf("PORTD IRQ at %d.\n", gpio_irq);   191    192   printf("Access GPIO...\n");   193    194   if ((result = gpio_get_memory("jz4780-gpio", &gpio_base, &gpio_base_end)) < 0)   195     return 1;   196    197   port_d = gpio_base + 0x300;   198   port_d_end = port_d + 0x100;   199   port_f = gpio_base + 0x500;   200   port_f_end = port_f + 0x100;   201    202   printf("GPIO at 0x%lx...0x%lx.\n", gpio_base, gpio_base_end);   203   printf("PORTD at 0x%lx...0x%lx.\n", port_d, port_d_end);   204   printf("PORTF at 0x%lx...0x%lx.\n", port_f, port_f_end);   205    206   gpio_port_d = jz4780_gpio_init(port_d, port_d_end, 32, 0xffff4fff, 0x0000b000);   207   gpio_port_f = jz4780_gpio_init(port_f, port_f_end, 32, 0xffa7f00f, 0x00580ff0);   208    209   /* Create an interrupt object. */   210    211   if ((err = l4_error(tag = l4_factory_create_irq(l4re_global_env->factory, irqcap))))   212   {   213     printf("Could not create IRQ object: %lx\n", err);   214     return 1;   215   }   216    217   /* Bind the interrupt object to the IRQ number. */   218    219   if ((err = l4_error(l4_icu_bind(icucap, gpio_irq, irqcap))))   220   {   221     printf("Could not bind IRQ %d to the ICU: %ld\n", gpio_irq, err);   222     return 1;   223   }   224    225   /* Attach ourselves to the interrupt handler. */   226    227   tag = l4_irq_attach(irqcap, 0xDEAD, l4re_env()->main_thread);   228    229   if ((err = l4_error(tag)))   230   {   231     printf("Could not attach to IRQ %d: %ld\n", gpio_irq, err);   232     return 1;   233   }   234    235   /* Set the GPIO pins up. */   236    237   printf("Set up GPIO pins...\n");   238    239   jz4780_gpio_setup(gpio_port_d, SW1, L4VBUS_GPIO_SETUP_IRQ, 1);   240   jz4780_gpio_setup(gpio_port_f, LED, L4VBUS_GPIO_SETUP_OUTPUT, 0);   241    242   gpio_irq_pin = jz4780_gpio_get_irq(gpio_port_d, SW1);   243   jz4780_gpio_irq_set_mode(gpio_irq_pin, L4_IRQ_F_LEVEL_HIGH);   244    245   printf("Press SW1 to invert LED.\n");   246    247   while (1)   248   {   249     tag = l4_irq_receive(irqcap, L4_IPC_NEVER);   250    251     if ((err = l4_ipc_error(tag, l4_utcb())))   252     {   253       printf("Error on IRQ receive: %ld\n", err);   254       continue;   255     }   256    257     printf("SW1: %x\n", jz4780_gpio_get(gpio_port_d, SW1));   258    259     if (jz4780_gpio_get(gpio_port_d, SW1))   260     {   261       printf("Invert LED\n");   262       jz4780_gpio_set(gpio_port_f, LED, led);   263       led = 1 - led;   264     }   265   }   266    267   /* Detach from the interrupt. */   268    269   tag = l4_irq_detach(irqcap);   270    271   if ((err = l4_error(tag)))   272     printf("Error detaching from IRQ: %ld\n", err);   273    274   return 0;   275 }