Landfall

Annotated pkg/landfall-examples/ci20_cpm/ci20_cpm.c

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