Landfall

pkg/devices/keypad/src/qi_lb60/keypad-qi_lb60.cc

141:7aa21a758551
2022-09-27 Paul Boddie Fixed architecture-specific build directory detection.
     1 /*     2  * Export the keypad GPIOs on the Ben NanoNote as a data space accessible via     3  * the "keypad" capability.     4  *     5  * Copyright (C) 2018 Paul Boddie <paul@boddie.org.uk>     6  *     7  * This program is free software; you can redistribute it and/or     8  * modify it under the terms of the GNU General Public License as     9  * published by the Free Software Foundation; either version 2 of    10  * the License, or (at your option) any later version.    11  *    12  * This program is distributed in the hope that it will be useful,    13  * but WITHOUT ANY WARRANTY; without even the implied warranty of    14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    15  * GNU General Public License for more details.    16  *    17  * You should have received a copy of the GNU General Public License    18  * along with this program; if not, write to the Free Software    19  * Foundation, Inc., 51 Franklin Street, Fifth Floor,    20  * Boston, MA  02110-1301, USA    21  */    22     23 #include <l4/devices/gpio-jz4740.h>    24 #include <l4/devices/dataspace.h>    25 #include <l4/devices/memory.h>    26 #include "keypad-server.h"    27 #include "keypad-event-loop.h"    28     29 #include <l4/re/dataspace>    30 #include <l4/re/env>    31 #include <l4/re/util/object_registry>    32     33 #include <l4/sys/cache.h>    34     35 #include <stdint.h>    36     37 enum Jz4740_keypad_gpio    38 {    39   Jz4740_keypad_gpio_inputs_count = 8,    40   Jz4740_keypad_gpio_outputs_count = 8,    41 };    42     43 /* Port D input pins. */    44     45 const uint8_t Jz4740_keypad_inputs[Jz4740_keypad_gpio_inputs_count] = {    46   18, 19, 20, 21, 22, 23, 24, 26    47 };    48     49 const Pin_slice Jz4740_keypad_inputs_mask = {0x05fc0000, 0};    50     51 /* Port C output pins. */    52     53 const uint8_t Jz4740_keypad_outputs[Jz4740_keypad_gpio_outputs_count] = {    54   10, 11, 12, 13, 14, 15, 16, 17    55 };    56     57 const Pin_slice Jz4740_keypad_outputs_mask = {0x0003fc00, 0};    58     59 /* Peripheral memory regions. */    60     61 static l4_addr_t gpio_virt_base = 0, gpio_virt_base_end = 0;    62     63 /* GPIO abstractions. */    64     65 static void *gpio_port_c, *gpio_port_d;    66     67 /* Keypad status: an array of keypad column values. */    68     69 uint32_t *keypad = 0;    70     71 /* Imported keypad memory referenced by the array. */    72     73 void *keymem = 0;    74     75     76     77 /* Set up access to memory. */    78     79 static int setup_memory()    80 {    81   if (get_memory("jz4740-gpio", &gpio_virt_base, &gpio_virt_base_end) < 0)    82     return 1;    83     84   gpio_port_c = jz4740_gpio_init(gpio_virt_base + 0x200, gpio_virt_base + 0x300, 32);    85   gpio_port_d = jz4740_gpio_init(gpio_virt_base + 0x300, gpio_virt_base + 0x400, 32);    86     87   return 0;    88 }    89     90     91     92 /* Initialise the pins for scanning the keypad. */    93     94 static void init_keyscan()    95 {    96   jz4740_gpio_multi_setup(gpio_port_d, &Jz4740_keypad_inputs_mask, Hw::Gpio_chip::Input, 0);    97   jz4740_gpio_multi_config_pull(gpio_port_d, &Jz4740_keypad_inputs_mask, Hw::Gpio_chip::Pull_up);    98   jz4740_gpio_multi_setup(gpio_port_c, &Jz4740_keypad_outputs_mask, Hw::Gpio_chip::Input, 0);    99 }   100    101 /*   102 Scan the keypad by enabling each output column and inspecting each input row.   103 Store each column bitmap in the keypad array.   104 */   105    106 static void scan_keypad()   107 {   108   uint8_t column, row, value;   109    110   for (column = 0; column < Jz4740_keypad_gpio_outputs_count; column++)   111   {   112     jz4740_gpio_setup(gpio_port_c, Jz4740_keypad_outputs[column], Hw::Gpio_chip::Output, 0);   113     l4_sleep(1);   114    115     value = 0;   116    117     for (row = 0; row < Jz4740_keypad_gpio_inputs_count; row++)   118       value = (value << 1) | (jz4740_gpio_get(gpio_port_d, Jz4740_keypad_inputs[row]) ? 0 : 1);   119    120     keypad[column] = value;   121    122     jz4740_gpio_setup(gpio_port_c, Jz4740_keypad_outputs[column], Hw::Gpio_chip::Input, 0);   123   }   124    125   l4_cache_clean_data((unsigned long) keypad,   126                       (unsigned long) keypad + Jz4740_keypad_gpio_outputs_count);   127 }   128    129    130    131 static L4Re::Util::Registry_server<> server;   132    133    134    135 /* Main program. */   136    137 int main(void)   138 {   139   /* Memory allocation capability for the keypad data. */   140    141   L4::Cap<L4Re::Dataspace> mem;   142   l4_size_t mem_size = Jz4740_keypad_gpio_outputs_count * sizeof(uint32_t);   143    144   if (setup_memory()) return 1;   145    146   mem = allocate_data(mem_size, &keymem);   147    148   if (!mem.is_valid()) return 1;   149    150   keypad = (uint32_t *) keymem;   151    152   /* Set up keypad access and start scanning. */   153    154   init_keyscan();   155    156   /* Set up a thread to scan the keypad concurrently with the server loop. */   157    158   Keypad_event_loop loop;   159   loop.attach(scan_keypad);   160   loop.start();   161    162   /* Initialise and register a server object. */   163    164   Keypad_server server_obj(mem);   165   server.registry()->register_obj(&server_obj, "keypad");   166    167   /* Enter the IPC server loop. */   168    169   server.loop();   170   return 0;   171 }