Landfall

pkg/landfall-examples/ci20_cpm/ci20_cpm.c

289:3c7cc99ed90f
6 months ago Paul Boddie Widened various address and size values to avoid overflow/truncation issues. Fixed high-capacity card support by changing the initialisation procedure. cpm-library-improvements
     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, 2021, 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 clock and power management unit on the MIPS Creator CI20 board.    12  */    13     14 #include <l4/devices/cpm-jz4780.h>    15 #include <l4/io/io.h>    16 #include <l4/re/env.h>    17 #include <l4/re/c/util/cap_alloc.h>    18 #include <l4/sys/factory.h>    19 #include <l4/sys/icu.h>    20 #include <l4/sys/ipc.h>    21 #include <l4/sys/irq.h>    22 #include <l4/vbus/vbus.h>    23 #include <stdio.h>    24 #include <unistd.h>    25 #include <stdint.h>    26     27     28     29 /* Device and resource discovery. */    30     31 static char const *resource_type(enum l4io_resource_types_t type)    32 {    33   switch (type)    34   {    35     case L4VBUS_RESOURCE_INVALID:    36     return "INVALID";    37     38     case L4VBUS_RESOURCE_IRQ:    39     return "IRQ";    40     41     case L4VBUS_RESOURCE_MEM:    42     return "MEMORY";    43     44     default:    45     return "OTHER";    46   }    47 }    48     49 static int cpm_get_device(char const *hid, l4io_device_handle_t *dh, l4io_resource_handle_t *rh)    50 {    51   int result = l4io_lookup_device(hid, dh, 0, rh);    52     53   if (result < 0)    54     printf("Could not access '%s': %s\n", hid, result == -L4_ENOENT ? "no such device" : "no device");    55     56   return result;    57 }    58     59 static int cpm_get_resource(l4io_device_handle_t dh, l4io_resource_t *res,    60                             enum l4io_resource_types_t type)    61 {    62   int current = 0, result = 0;    63   l4_cap_idx_t vbus = l4re_env_get_cap("vbus");    64     65   do    66   {    67     result = l4vbus_get_resource(vbus, dh, current, res);    68     69     if (result)    70       printf("Could not access resource of type %s.\n", resource_type(type));    71     else    72       printf("Resource %d: type %s, start=%lx, end=%lx\n", res->id,    73         resource_type(res->type), res->start, res->end);    74     75     current++;    76   }    77   while ((!result) && (res->type != type));    78     79   return result;    80 }    81     82 static int cpm_get_memory(char const *hid, l4_addr_t *start, l4_addr_t *end)    83 {    84   l4io_device_handle_t dh;    85   l4io_resource_handle_t rh;    86   l4io_resource_t res;    87   int result;    88     89   result = cpm_get_device(hid, &dh, &rh);    90     91   if (result < 0)    92     return result;    93     94   result = cpm_get_resource(dh, &res, L4IO_RESOURCE_MEM);    95     96   if (result)    97     return result;    98     99   if ((result = l4io_request_iomem(res.start, res.end - res.start + 1,   100                                   L4IO_MEM_NONCACHED, start)))   101   {   102     printf("Could not get address for '%s'.\n", hid);   103     return result;   104   }   105    106   printf("Resource at 0x%lx...0x%lx.\n", res.start, res.end);   107    108   *end = *start + (res.end - res.start + 1);   109    110   return 0;   111 }   112    113 int main(void)   114 {   115   l4_addr_t cpm_base = 0, cpm_base_end = 0;   116   void *cpm;   117   int result = 0;   118    119   /* Obtain resource details describing I/O memory. */   120    121   printf("Access CPM...\n");   122    123   if ((result = cpm_get_memory("jz4780-cpm", &cpm_base, &cpm_base_end)) < 0)   124     return 1;   125    126   printf("CPM at 0x%lx...0x%lx.\n", cpm_base, cpm_base_end);   127    128   cpm = jz4780_cpm_init(cpm_base);   129    130   /* Read information from the clock and power management unit. */   131    132   printf("Main source: %d\n", jz4780_cpm_get_source(cpm, Clock_main));   133   printf("  Main frequency: %lld\n", jz4780_cpm_get_frequency(cpm, Clock_main));   134   printf("APLL frequency: %lld\n", jz4780_cpm_get_frequency(cpm, Clock_pll_A));   135   printf("EPLL frequency: %lld\n", jz4780_cpm_get_frequency(cpm, Clock_pll_E));   136   printf("MPLL frequency: %lld\n", jz4780_cpm_get_frequency(cpm, Clock_pll_M));   137   printf("VPLL frequency: %lld\n", jz4780_cpm_get_frequency(cpm, Clock_pll_V));   138   printf("CPU frequency: %lld\n", jz4780_cpm_get_frequency(cpm, Clock_cpu));   139   printf("Memory source: %d\n", jz4780_cpm_get_source(cpm, Clock_ddr));   140   printf("  Memory source frequency: %lld\n", jz4780_cpm_get_source_frequency(cpm, Clock_ddr));   141   printf("  Memory frequency: %lld\n", jz4780_cpm_get_frequency(cpm, Clock_ddr));   142   printf("APB source: %d\n", jz4780_cpm_get_source(cpm, Clock_pclock));   143   printf("  APB source frequency: %lld\n", jz4780_cpm_get_source_frequency(cpm, Clock_pclock));   144   printf("  Slow peripheral (APB) frequency: %lld\n", jz4780_cpm_get_frequency(cpm, Clock_pclock));   145   printf("AHB0 source: %d\n", jz4780_cpm_get_source(cpm, Clock_hclock0));   146   printf("  AHB0 source frequency: %lld\n", jz4780_cpm_get_source_frequency(cpm, Clock_hclock0));   147   printf("  Fast peripheral (AHB0) frequency: %lld\n", jz4780_cpm_get_frequency(cpm, Clock_hclock0));   148   printf("AHB2 source: %d\n", jz4780_cpm_get_source(cpm, Clock_hclock2));   149   printf("  AHB2 source frequency: %lld\n", jz4780_cpm_get_source_frequency(cpm, Clock_hclock2));   150   printf("  Fast peripheral (AHB2) frequency: %lld\n", jz4780_cpm_get_frequency(cpm, Clock_hclock2));   151   printf("LCD source: %d\n", jz4780_cpm_get_source(cpm, Clock_lcd));   152   printf("  LCD source frequency: %lld\n", jz4780_cpm_get_source_frequency(cpm, Clock_lcd));   153   printf("  LCD frequency: %lld\n", jz4780_cpm_get_frequency(cpm, Clock_lcd));   154   printf("  LCD pixel clock frequency: %lld\n", jz4780_cpm_get_frequency(cpm, Clock_lcd_pixel0));   155    156   /* Attempt to set the pixel clock frequency. */   157    158   jz4780_cpm_set_frequency(cpm, Clock_lcd_pixel0, 108000000);   159    160   printf("LCD source: %d\n", jz4780_cpm_get_source(cpm, Clock_lcd));   161   printf("  LCD source frequency: %lld\n", jz4780_cpm_get_source_frequency(cpm, Clock_lcd));   162   printf("  LCD frequency: %lld\n", jz4780_cpm_get_frequency(cpm, Clock_lcd));   163   printf("  LCD pixel clock frequency: %lld\n", jz4780_cpm_get_frequency(cpm, Clock_lcd_pixel0));   164    165   /* Change the pixel clock source. */   166    167   jz4780_cpm_set_source_clock(cpm, Clock_lcd_pixel0, Clock_pll_V);   168    169   printf("LCD source: %d\n", jz4780_cpm_get_source(cpm, Clock_lcd));   170   printf("  LCD source frequency: %lld\n", jz4780_cpm_get_source_frequency(cpm, Clock_lcd));   171   printf("  LCD frequency: %lld\n", jz4780_cpm_get_frequency(cpm, Clock_lcd));   172   printf("  LCD pixel clock frequency: %lld\n", jz4780_cpm_get_frequency(cpm, Clock_lcd_pixel0));   173    174   /* Attempt to set the VPLL output to EXCLK divided by 4. */   175    176   jz4780_cpm_set_parameters(cpm, Clock_pll_V, 3, (uint32_t []) {1, 4, 1});   177    178   printf("VPLL source: %d\n", jz4780_cpm_get_source(cpm, Clock_pll_V));   179   printf("  VPLL source frequency: %lld\n", jz4780_cpm_get_source_frequency(cpm, Clock_pll_V));   180   printf("  VPLL frequency: %lld\n", jz4780_cpm_get_frequency(cpm, Clock_pll_V));   181    182   return 0;   183 }