Landfall

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

229:810ca800993b
11 months ago Paul Boddie Employ a picture representation compatible with 16-bit SPI transfers over DMA. cpm-library-improvements
paul@218 1
/*
paul@218 2
 * Access various peripherals on the MIPS Creator CI20 board.
paul@218 3
 *
paul@218 4
 * Copyright (C) 2023 Paul Boddie <paul@boddie.org.uk>
paul@218 5
 *
paul@218 6
 * This program is free software; you can redistribute it and/or
paul@218 7
 * modify it under the terms of the GNU General Public License as
paul@218 8
 * published by the Free Software Foundation; either version 2 of
paul@218 9
 * the License, or (at your option) any later version.
paul@218 10
 *
paul@218 11
 * This program is distributed in the hope that it will be useful,
paul@218 12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
paul@218 13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
paul@218 14
 * GNU General Public License for more details.
paul@218 15
 *
paul@218 16
 * You should have received a copy of the GNU General Public License
paul@218 17
 * along with this program; if not, write to the Free Software
paul@218 18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
paul@218 19
 * Boston, MA  02110-1301, USA
paul@218 20
 */
paul@218 21
paul@218 22
#include "common.h"
paul@218 23
#include "defs.h"
paul@218 24
paul@218 25
#include <l4/devices/dma.h>
paul@218 26
#include <l4/devices/memory.h>
paul@218 27
paul@218 28
#include <l4/io/io.h>
paul@218 29
#include <l4/re/env.h>
paul@218 30
#include <l4/re/c/util/cap_alloc.h>
paul@218 31
#include <l4/sys/cache.h>
paul@218 32
#include <l4/sys/factory.h>
paul@218 33
#include <l4/sys/icu.h>
paul@218 34
#include <l4/sys/ipc.h>
paul@218 35
#include <l4/sys/irq.h>
paul@218 36
#include <l4/sys/rcv_endpoint.h>
paul@218 37
#include <l4/vbus/vbus.h>
paul@218 38
paul@218 39
#include <stdio.h>
paul@218 40
#include <unistd.h>
paul@218 41
#include <stdint.h>
paul@218 42
#include <stdlib.h>
paul@218 43
#include <string.h>
paul@218 44
paul@218 45
paul@218 46
paul@218 47
/* Common configuration. */
paul@218 48
paul@218 49
static l4_cap_idx_t icucap;
paul@218 50
paul@218 51
paul@218 52
paul@218 53
/* Device and resource discovery. */
paul@218 54
paul@218 55
static long item_in_range(long start, long end, long index)
paul@218 56
{
paul@218 57
  if (start < end)
paul@218 58
    return start + index;
paul@218 59
  else if (start > end)
paul@218 60
    return start - index;
paul@218 61
  else
paul@218 62
    return start;
paul@218 63
}
paul@218 64
paul@218 65
paul@218 66
paul@218 67
/* Common functions. */
paul@218 68
paul@218 69
static int init_irq(int num, l4_cap_idx_t irq, l4_uint32_t start, l4_uint32_t end)
paul@218 70
{
paul@218 71
  /* Create interrupt object. */
paul@218 72
paul@218 73
  long err = l4_error(l4_factory_create_irq(l4re_global_env->factory, irq));
paul@218 74
paul@218 75
  if (err)
paul@218 76
  {
paul@218 77
    printf("Could not create IRQ object: %ld\n", err);
paul@218 78
    return 1;
paul@218 79
  }
paul@218 80
paul@218 81
  /* Bind interrupt objects to IRQ numbers. */
paul@218 82
paul@218 83
  err = l4_error(l4_icu_bind(icucap,
paul@218 84
                             item_in_range(start, end, num),
paul@218 85
                             irq));
paul@218 86
paul@218 87
  if (err)
paul@218 88
  {
paul@218 89
    printf("Could not bind IRQ to the ICU: %ld\n", err);
paul@218 90
    return 1;
paul@218 91
  }
paul@218 92
paul@218 93
  /* Attach ourselves to the interrupt handler. */
paul@218 94
paul@218 95
  err = l4_error(l4_rcv_ep_bind_thread(irq, l4re_env()->main_thread, num));
paul@218 96
paul@218 97
  if (err)
paul@218 98
  {
paul@218 99
    printf("Could not attach to IRQs: %ld\n", err);
paul@218 100
    return 1;
paul@218 101
  }
paul@218 102
paul@218 103
  return 0;
paul@218 104
}
paul@218 105
paul@218 106
static const char *delimiters = " \n";
paul@218 107
paul@218 108
static char *read_token(const char *message)
paul@218 109
{
paul@218 110
  char *token;
paul@218 111
paul@218 112
  if ((token = strtok(NULL, delimiters)) == NULL)
paul@218 113
  {
paul@218 114
    if (message != NULL)
paul@218 115
      printf("%s?\n", message);
paul@218 116
  }
paul@218 117
paul@218 118
  return token;
paul@218 119
}
paul@218 120
paul@218 121
static int read_increment(const char *message, int *increment)
paul@218 122
{
paul@218 123
  char *token = read_token(message);
paul@218 124
paul@218 125
  if (token == NULL)
paul@218 126
    return 0;
paul@218 127
paul@218 128
  *increment = !strncmp(token, "i", 1);
paul@218 129
  return 1;
paul@218 130
}
paul@218 131
paul@218 132
static int read_encoded_number(const char *message, const char *format, unsigned int *num)
paul@218 133
{
paul@218 134
  char *token = read_token(message);
paul@218 135
paul@218 136
  if (token == NULL)
paul@218 137
    return 0;
paul@218 138
paul@218 139
  sscanf(token, format, num);
paul@218 140
  return 1;
paul@218 141
}
paul@218 142
paul@218 143
static int read_number(const char *message, unsigned int *num)
paul@218 144
{
paul@218 145
  char *token = read_token(message);
paul@218 146
paul@218 147
  if (token == NULL)
paul@218 148
    return 0;
paul@218 149
paul@218 150
  if (!strncmp(token, "0x", 2) || !strncmp(token, "0X", 2))
paul@218 151
    sscanf(token, "%x", num);
paul@218 152
  else
paul@218 153
    *num = atoi(token);
paul@218 154
paul@218 155
  return 1;
paul@218 156
}
paul@218 157
paul@218 158
static int get_resource_number(const char *type, unsigned int available)
paul@218 159
{
paul@218 160
  unsigned int num;
paul@218 161
paul@218 162
  if (!read_number(type, &num))
paul@218 163
    return -1;
paul@218 164
paul@218 165
  if (num >= available)
paul@218 166
  {
paul@218 167
    printf("%s number out of range.\n", type);
paul@218 168
    return -1;
paul@218 169
  }
paul@218 170
paul@218 171
  return num;
paul@218 172
}
paul@218 173
paul@218 174
static int get_channel_number(unsigned int available)
paul@218 175
{
paul@218 176
  return get_resource_number("Channel", available);
paul@218 177
}
paul@218 178
paul@218 179
static int get_region_number(unsigned int available)
paul@218 180
{
paul@218 181
  return get_resource_number("Region", available);
paul@218 182
}
paul@218 183
paul@218 184
static void *get_channel(int num_channels, void *channels[], int *num)
paul@218 185
{
paul@218 186
  int n = get_channel_number(num_channels);
paul@218 187
  void *channel;
paul@218 188
paul@218 189
  if (n < 0)
paul@218 190
    return NULL;
paul@218 191
paul@218 192
  channel = channels[n];
paul@218 193
paul@218 194
  if (channel == NULL)
paul@218 195
    printf("Channel needs creating.\n");
paul@218 196
paul@218 197
  if (num != NULL)
paul@218 198
    *num = n;
paul@218 199
paul@218 200
  return channel;
paul@218 201
}
paul@218 202
paul@218 203
static void list_channels(int num_channels, void *channels[])
paul@218 204
{
paul@218 205
  int num;
paul@218 206
  void *channel;
paul@218 207
paul@218 208
  for (num = 0; num < num_channels; num++)
paul@218 209
  {
paul@218 210
    printf("Channel %d: ", num);
paul@218 211
paul@218 212
    channel = channels[num];
paul@218 213
paul@218 214
    if (channel == NULL)
paul@218 215
      printf("(inactive)\n");
paul@218 216
    else
paul@218 217
      printf("active\n");
paul@218 218
  }
paul@218 219
}
paul@218 220
paul@221 221
static struct dma_region *_get_dma_region(void)
paul@221 222
{
paul@221 223
  int num = get_region_number(num_dma_regions);
paul@221 224
paul@221 225
  if (num < 0)
paul@221 226
    return NULL;
paul@221 227
paul@221 228
  return &dma_regions[num];
paul@221 229
}
paul@218 230
paul@218 231
paul@218 232
paul@218 233
/* AIC/I2S operations. */
paul@218 234
paul@218 235
static void new_aic_channel(void *aic)
paul@218 236
{
paul@218 237
  int num = get_channel_number(num_aic_channels);
paul@218 238
  void *channel;
paul@218 239
paul@218 240
  if (num < 0)
paul@218 241
    return;
paul@218 242
paul@218 243
  channel = get_channel(num_dma_channels, dma_channels, NULL);
paul@218 244
paul@218 245
  if (channel == NULL)
paul@218 246
    return;
paul@218 247
paul@218 248
  aic_channels[num] = aic_get_channel(aic, num, channel);
paul@218 249
}
paul@218 250
paul@218 251
static void aic_transfer_data(void)
paul@218 252
{
paul@218 253
  void *channel = get_channel(num_aic_channels, aic_channels, NULL);
paul@221 254
  struct dma_region *region;
paul@221 255
  uint32_t count, rate, resolution, transferred;
paul@218 256
paul@218 257
  if (channel == NULL)
paul@218 258
    return;
paul@218 259
paul@221 260
  region = _get_dma_region();
paul@221 261
paul@221 262
  if (region == NULL)
paul@221 263
    return;
paul@221 264
paul@218 265
  if (!read_number("Sample size", &count))
paul@218 266
    return;
paul@218 267
paul@218 268
  if (!read_number("Sample rate", &rate))
paul@218 269
    return;
paul@218 270
paul@218 271
  if (!read_number("Sample resolution", &resolution))
paul@218 272
    return;
paul@218 273
paul@221 274
  transferred = aic_transfer(channel, region->paddr, count, rate, resolution);
paul@218 275
paul@218 276
  printf("Transferred: %d\n", transferred);
paul@218 277
}
paul@218 278
paul@218 279
paul@218 280
paul@218 281
/* CPM operations. */
paul@218 282
paul@218 283
static const char *clock_id(enum Clock_identifiers clock)
paul@218 284
{
paul@218 285
  for (int i = 0; clocks[i].id != NULL; i++)
paul@218 286
    if (clock == clocks[i].clock)
paul@218 287
      return clocks[i].id;
paul@218 288
paul@218 289
  return NULL;
paul@218 290
}
paul@218 291
paul@218 292
static enum Clock_identifiers get_clock(char *id)
paul@218 293
{
paul@218 294
  if (id != NULL)
paul@218 295
  {
paul@218 296
    for (int i = 0; clocks[i].id != NULL; i++)
paul@218 297
      if (!strcmp(id, clocks[i].id))
paul@218 298
        return clocks[i].clock;
paul@218 299
  }
paul@218 300
paul@218 301
  return Clock_undefined;
paul@218 302
}
paul@218 303
paul@218 304
static const char list_clocks_separator[] = "--------------------------------";
paul@218 305
paul@218 306
#define sep(x) (list_clocks_separator + sizeof(list_clocks_separator) - 1 - x)
paul@218 307
paul@218 308
static void list_clocks(void *cpm)
paul@218 309
{
paul@218 310
  /* Read information from the clock and power management unit. */
paul@218 311
paul@218 312
  printf("%-5s  %-10s  %-7s  %-6s  %-12s  %-12s  %-24s  %-12s  %-3s\n"
paul@218 313
         "%-5s  %-10s  %-7s  %-6s  %-12s  %-12s  %-24s  %-12s  %-3s\n",
paul@218 314
         "Id", "Clock", "Type", "Source", "Source Clock", "Source Freq.",
paul@218 315
         "Parameters", "Frequency", "On",
paul@218 316
         sep(5), sep(10), sep(7), sep(6), sep(12), sep(12),
paul@218 317
         sep(24), sep(12), sep(3));
paul@218 318
paul@218 319
  for (int i = 0; clocks[i].id != NULL; i++)
paul@218 320
  {
paul@218 321
    uint32_t parameters[4];
paul@218 322
    char parameter_str[25] = {0};
paul@218 323
    const char *source_id = clock_id(cpm_get_source_clock(cpm, clocks[i].clock));
paul@218 324
    int num_parameters = cpm_get_parameters(cpm, clocks[i].clock, parameters);
paul@218 325
paul@218 326
    for (int p = 0, pos = 0; p < num_parameters; p++)
paul@218 327
    {
paul@218 328
      int result = sprintf(parameter_str + pos, "%-7d ", parameters[p]);
paul@218 329
      if (result < 0)
paul@218 330
        break;
paul@218 331
      pos += result;
paul@218 332
    }
paul@218 333
paul@218 334
    printf("%-5s  %-10s  %-7s  %-6d  %-12s  %-12lld  %-24s  %-12lld  %-3s\n",
paul@218 335
      clocks[i].id,
paul@218 336
      clocks[i].name,
paul@218 337
      cpm_clock_type(cpm, clocks[i].clock),
paul@218 338
      cpm_get_source(cpm, clocks[i].clock),
paul@218 339
      source_id != NULL ? source_id : "...",
paul@218 340
      cpm_get_source_frequency(cpm, clocks[i].clock),
paul@218 341
      parameter_str,
paul@218 342
      cpm_get_frequency(cpm, clocks[i].clock),
paul@218 343
      cpm_have_clock(cpm, clocks[i].clock) ? "on" : "off");
paul@218 344
  }
paul@218 345
}
paul@218 346
paul@218 347
static enum Clock_identifiers get_clock_by_name(void)
paul@218 348
{
paul@218 349
  char *token;
paul@218 350
  enum Clock_identifiers clock;
paul@218 351
paul@218 352
  if ((token = read_token("Clock")) == NULL)
paul@218 353
    return Clock_undefined;
paul@218 354
paul@218 355
  clock = get_clock(token);
paul@218 356
paul@218 357
  if (clock == Clock_undefined)
paul@218 358
  {
paul@218 359
    printf("Unrecognised clock: %s\n", token);
paul@218 360
    return Clock_undefined;
paul@218 361
  }
paul@218 362
paul@218 363
  return clock;
paul@218 364
}
paul@218 365
paul@218 366
static void set_frequency(void *cpm)
paul@218 367
{
paul@218 368
  enum Clock_identifiers clock;
paul@218 369
  unsigned int frequency;
paul@218 370
paul@218 371
  clock = get_clock_by_name();
paul@218 372
paul@218 373
  if (clock == Clock_undefined)
paul@218 374
    return;
paul@218 375
paul@218 376
  if (!read_number("Frequency", &frequency))
paul@218 377
    return;
paul@218 378
paul@218 379
  if (!cpm_set_frequency(cpm, clock, frequency))
paul@218 380
    printf("Frequency not set.\n");
paul@218 381
}
paul@218 382
paul@218 383
static void set_parameters(void *cpm)
paul@218 384
{
paul@218 385
  char *token;
paul@218 386
  enum Clock_identifiers clock;
paul@218 387
  uint32_t parameters[4];
paul@218 388
  int num_parameters;
paul@218 389
paul@218 390
  clock = get_clock_by_name();
paul@218 391
paul@218 392
  if (clock == Clock_undefined)
paul@218 393
    return;
paul@218 394
paul@218 395
  for (num_parameters = 0; num_parameters < 4; num_parameters++)
paul@218 396
  {
paul@218 397
    if ((token = read_token(NULL)) == NULL)
paul@218 398
      break;
paul@218 399
paul@218 400
    parameters[num_parameters] = atoi(token);
paul@218 401
  }
paul@218 402
paul@218 403
  if (!num_parameters)
paul@218 404
  {
paul@218 405
    printf("Parameters?\n");
paul@218 406
    return;
paul@218 407
  }
paul@218 408
paul@218 409
  if (!cpm_set_parameters(cpm, clock, num_parameters, parameters))
paul@218 410
    printf("Too few or invalid parameters.\n");
paul@218 411
}
paul@218 412
paul@218 413
static void set_source(void *cpm)
paul@218 414
{
paul@218 415
  enum Clock_identifiers clock;
paul@218 416
  unsigned int source;
paul@218 417
paul@218 418
  clock = get_clock_by_name();
paul@218 419
paul@218 420
  if (clock == Clock_undefined)
paul@218 421
    return;
paul@218 422
paul@218 423
  if (!read_number("Source", &source))
paul@218 424
    return;
paul@218 425
paul@218 426
  cpm_set_source(cpm, clock, source);
paul@218 427
}
paul@218 428
paul@218 429
static void start_clock(void *cpm)
paul@218 430
{
paul@218 431
  enum Clock_identifiers clock;
paul@218 432
paul@218 433
  clock = get_clock_by_name();
paul@218 434
paul@218 435
  if (clock == Clock_undefined)
paul@218 436
    return;
paul@218 437
paul@218 438
  cpm_start_clock(cpm, clock);
paul@218 439
}
paul@218 440
paul@218 441
static void stop_clock(void *cpm)
paul@218 442
{
paul@218 443
  enum Clock_identifiers clock;
paul@218 444
paul@218 445
  clock = get_clock_by_name();
paul@218 446
paul@218 447
  if (clock == Clock_undefined)
paul@218 448
    return;
paul@218 449
paul@218 450
  cpm_stop_clock(cpm, clock);
paul@218 451
}
paul@218 452
paul@218 453
paul@218 454
paul@218 455
/* DMA configuration. */
paul@218 456
paul@218 457
static l4_uint32_t dma_irq_start = 0, dma_irq_end = 0;
paul@218 458
paul@218 459
/* DMA operations. */
paul@218 460
paul@218 461
static int init_dma(void)
paul@218 462
{
paul@218 463
  unsigned int i;
paul@218 464
paul@218 465
  for (i = 0; i < num_dma_regions; i++)
paul@218 466
    dma_regions[i].mem = L4_INVALID_CAP;
paul@218 467
paul@218 468
  /* Here, only one IRQ is used. */
paul@218 469
paul@218 470
  dma_irq = l4re_util_cap_alloc();
paul@218 471
  return init_irq(0, dma_irq, dma_irq_start, dma_irq_end);
paul@218 472
}
paul@218 473
paul@218 474
static void list_dma_regions(void)
paul@218 475
{
paul@218 476
  unsigned int num;
paul@218 477
  struct dma_region *region;
paul@218 478
  unsigned int i;
paul@218 479
paul@218 480
  for (num = 0; num < num_dma_regions; num++)
paul@218 481
  {
paul@218 482
    printf("Region %d: ", num);
paul@218 483
paul@218 484
    region = &dma_regions[num];
paul@218 485
paul@218 486
    if (l4_is_invalid_cap(region->mem))
paul@218 487
      printf("(inactive)\n");
paul@218 488
    else
paul@218 489
    {
paul@218 490
      printf("size = %d; align = %d; virtual = 0x%lx; physical = 0x%llx\ndata =",
paul@218 491
             region->size, region->align, region->vaddr, region->paddr);
paul@218 492
paul@218 493
      for (i = 0; (i < region->size) && (i < 16); i++)
paul@218 494
        printf(" %02x", *((uint8_t *) region->vaddr + i));
paul@218 495
paul@218 496
      printf("\n");
paul@218 497
    }
paul@218 498
  }
paul@218 499
}
paul@218 500
paul@218 501
static void new_dma_channel(void *dma)
paul@218 502
{
paul@218 503
  int num = get_channel_number(num_dma_channels);
paul@218 504
paul@218 505
  if (num < 0)
paul@218 506
    return;
paul@218 507
paul@218 508
  if (dma_channels[num] != NULL)
paul@218 509
  {
paul@218 510
    printf("Channel already defined.\n");
paul@218 511
    return;
paul@218 512
  }
paul@218 513
paul@218 514
  dma_channels[num] = dma_get_channel(dma, num, dma_irq);
paul@218 515
}
paul@218 516
paul@218 517
static void new_dma_region(void)
paul@218 518
{
paul@218 519
  struct dma_region *region = _get_dma_region();
paul@218 520
paul@218 521
  if (region == NULL)
paul@218 522
  {
paul@218 523
    list_dma_regions();
paul@218 524
    return;
paul@218 525
  }
paul@218 526
paul@218 527
  if (l4_is_valid_cap(region->mem))
paul@218 528
  {
paul@218 529
    printf("Region already defined.\n");
paul@218 530
    return;
paul@218 531
  }
paul@218 532
paul@218 533
  if (!read_number("Size", &region->size))
paul@218 534
    return;
paul@218 535
paul@218 536
  if (!read_number("Alignment", &region->align))
paul@218 537
    return;
paul@218 538
paul@218 539
  if (get_dma_region(region->size, region->align, &region->vaddr, &region->paddr, &region->mem))
paul@218 540
    printf("Could not allocate region.\n");
paul@218 541
}
paul@218 542
paul@218 543
static void set_dma_region(void)
paul@218 544
{
paul@218 545
  char *token;
paul@218 546
  struct dma_region *region = _get_dma_region();
paul@218 547
  FILE *fp;
paul@218 548
paul@218 549
  if (region == NULL)
paul@218 550
  {
paul@218 551
    list_dma_regions();
paul@218 552
    return;
paul@218 553
  }
paul@218 554
paul@218 555
  if (l4_is_invalid_cap(region->mem))
paul@218 556
  {
paul@218 557
    printf("Region needs creating.\n");
paul@218 558
    return;
paul@218 559
  }
paul@218 560
paul@218 561
  memset((void *) region->vaddr, 0, region->size);
paul@218 562
paul@218 563
  if ((token = read_token("Filename")) == NULL)
paul@218 564
    return;
paul@218 565
paul@218 566
  /* Populate the region from the file. */
paul@218 567
paul@218 568
  fp = fopen(token, "r");
paul@218 569
paul@218 570
  if (fp == NULL)
paul@218 571
  {
paul@218 572
    printf("File not readable.\n");
paul@218 573
    return;
paul@218 574
  }
paul@218 575
paul@218 576
  fread((char *) region->vaddr, sizeof(char), region->size, fp);
paul@218 577
  fclose(fp);
paul@218 578
paul@218 579
  l4_cache_flush_data(region->vaddr, region->vaddr + region->size);
paul@218 580
}
paul@218 581
paul@218 582
static void dma_transfer_data(void)
paul@218 583
{
paul@221 584
  uint32_t count, to_transfer, transferred;
paul@218 585
  unsigned int source_address, destination_address, source_width, destination_width,
paul@218 586
               transfer_unit_size, request_type;
paul@218 587
  int source_increment, destination_increment;
paul@218 588
  void *channel = get_channel(num_dma_channels, dma_channels, NULL);
paul@218 589
  unsigned int i;
paul@218 590
paul@218 591
  if (channel == NULL)
paul@218 592
    return;
paul@218 593
paul@218 594
  if (!read_number("Source address", &source_address))
paul@218 595
    return;
paul@218 596
paul@218 597
  if (!read_number("Destination address", &destination_address))
paul@218 598
    return;
paul@218 599
paul@218 600
  if (!read_number("Transfer size", &count))
paul@218 601
    return;
paul@218 602
paul@218 603
  if (!read_increment("Source increment", &source_increment))
paul@218 604
    return;
paul@218 605
paul@218 606
  if (!read_increment("Destination increment", &destination_increment))
paul@218 607
    return;
paul@218 608
paul@218 609
  if (!read_number("Source width", &source_width))
paul@218 610
    return;
paul@218 611
paul@218 612
  if (!read_number("Destination width", &destination_width))
paul@218 613
    return;
paul@218 614
paul@218 615
  if (!read_number("Transfer unit size", &transfer_unit_size))
paul@218 616
    return;
paul@218 617
paul@218 618
  if (!read_number("Request type", &request_type))
paul@218 619
    return;
paul@218 620
paul@218 621
  /* Invalidate DMA region contents in case of transfers between regions. */
paul@218 622
paul@218 623
  for (i = 0; i < num_dma_regions; i++)
paul@218 624
    l4_cache_inv_data(dma_regions[i].vaddr, dma_regions[i].vaddr + dma_regions[i].size);
paul@218 625
paul@218 626
  to_transfer = dma_transfer(channel, source_address, destination_address,
paul@221 627
                             count,
paul@221 628
                             source_increment, destination_increment,
paul@221 629
                             source_width, destination_width,
paul@221 630
                             transfer_unit_size,
paul@221 631
                             request_type);
paul@218 632
paul@218 633
  transferred = to_transfer ? count - dma_wait(channel) : 0;
paul@218 634
paul@218 635
  printf("Transferred: %d\n", transferred);
paul@218 636
}
paul@218 637
paul@218 638
paul@218 639
paul@218 640
/* GPIO operations. */
paul@218 641
paul@218 642
static char get_gpio_dir_label(unsigned int value, unsigned int level)
paul@218 643
{
paul@218 644
  return value == Fix_input ? (level ? 'I' : 'i') : (level ? 'O' : 'o');
paul@218 645
}
paul@218 646
paul@218 647
static char get_gpio_irq_label(unsigned int value)
paul@218 648
{
paul@218 649
  switch (value)
paul@218 650
  {
paul@218 651
    case L4_IRQ_F_NEG_EDGE: return 'f';
paul@218 652
    case L4_IRQ_F_POS_EDGE: return 'r';
paul@218 653
    case L4_IRQ_F_LEVEL_LOW: return 'l';
paul@218 654
    case L4_IRQ_F_LEVEL_HIGH: return 'h';
paul@218 655
    default: return '?';
paul@218 656
  }
paul@218 657
}
paul@218 658
paul@218 659
static void list_gpios(void *gpio[])
paul@218 660
{
paul@218 661
  unsigned int port, pin;
paul@218 662
  unsigned int func, value, level;
paul@218 663
paul@218 664
  printf("gpio: I = input high; i = input low; O = output high; o = output low\n"
paul@218 665
         "irq:  h = high level; l = low level; r = rising edge; f = falling edge\n"
paul@218 666
         "alt: function number\n\n");
paul@218 667
paul@218 668
  /* Show pin numbering. */
paul@218 669
paul@218 670
  printf("Port/Pin ");
paul@218 671
paul@218 672
  for (pin = 0; pin < 32; pin++)
paul@218 673
  {
paul@218 674
    if (!(pin % 10))
paul@218 675
      printf(" %d", pin);
paul@218 676
    else
paul@218 677
      printf(" %d", pin % 10);
paul@218 678
  }
paul@218 679
paul@218 680
  printf("\n");
paul@218 681
paul@218 682
  for (port = 0; port < num_gpio_ports; port++)
paul@218 683
  {
paul@218 684
    /* Show port and pin configuration. */
paul@218 685
paul@218 686
    printf("%c        ", gpio_port_labels[port]);
paul@218 687
paul@218 688
    for (pin = 0; pin < 32; pin++)
paul@218 689
    {
paul@218 690
      /* Pad below the first pin digit for multiples of ten other than zero. */
paul@218 691
paul@218 692
      if (pin && !(pin % 10))
paul@218 693
        printf(" ");
paul@218 694
paul@218 695
      gpio_config_pad_get(gpio[port], pin, &func, &value);
paul@218 696
paul@218 697
      switch (func)
paul@218 698
      {
paul@218 699
        case Function_alt: printf(" %d", value); break;
paul@218 700
        case Function_irq: printf(" %c", get_gpio_irq_label(value)); break;
paul@218 701
        case Function_gpio:
paul@218 702
        {
paul@218 703
          level = gpio_get(gpio[port], pin);
paul@218 704
          printf(" %c", get_gpio_dir_label(value, level));
paul@218 705
          break;
paul@218 706
        }
paul@218 707
        default: printf(" ?"); break;
paul@218 708
      }
paul@218 709
    }
paul@218 710
paul@218 711
    printf("\n");
paul@218 712
  }
paul@218 713
}
paul@218 714
paul@218 715
static int get_port_and_pin(unsigned int *port, unsigned int *pin)
paul@218 716
{
paul@218 717
  char *token;
paul@218 718
paul@218 719
  if ((token = read_token("Port")) == NULL)
paul@218 720
    return 0;
paul@218 721
paul@218 722
  if ((token[0] < 'A') || ((unsigned int) token[0] - (unsigned int) 'A' >= num_gpio_ports))
paul@218 723
  {
paul@218 724
    printf("Bad port: %c\n", token[0]);
paul@218 725
    return 0;
paul@218 726
  }
paul@218 727
paul@218 728
  *port = (unsigned int) token[0] - (unsigned int) 'A';
paul@218 729
paul@218 730
  if (!read_number("Pin", pin))
paul@218 731
    return 0;
paul@218 732
paul@218 733
  return 1;
paul@218 734
}
paul@218 735
paul@218 736
static void set_gpio_alt_func(void *gpio[])
paul@218 737
{
paul@218 738
  unsigned int port, pin, value;
paul@218 739
paul@218 740
  if (!get_port_and_pin(&port, &pin))
paul@218 741
    return;
paul@218 742
paul@218 743
  if (!read_number("Function", &value))
paul@218 744
    return;
paul@218 745
paul@218 746
  gpio_config_pad(gpio[port], pin, Function_alt, value);
paul@218 747
}
paul@218 748
paul@218 749
static void set_gpio_pad(void *gpio[])
paul@218 750
{
paul@218 751
  char *token;
paul@218 752
  unsigned int port, pin, mode, value = 0;
paul@218 753
paul@218 754
  if (!get_port_and_pin(&port, &pin))
paul@218 755
    return;
paul@218 756
paul@218 757
  if ((token = read_token("Mode")) == NULL)
paul@218 758
    return;
paul@218 759
paul@218 760
  if (!strcmp(token, "in"))
paul@218 761
    mode = Fix_input;
paul@218 762
  else if (!strcmp(token, "irq"))
paul@218 763
    mode = Fix_irq;
paul@218 764
  else if (!strcmp(token, "out"))
paul@218 765
  {
paul@218 766
    mode = Fix_output;
paul@218 767
paul@218 768
    if ((token = read_token(NULL)) != NULL)
paul@218 769
      value = atoi(token);
paul@218 770
  }
paul@218 771
  else
paul@218 772
  {
paul@218 773
    printf("Mode not recognised.\n");
paul@218 774
    return;
paul@218 775
  }
paul@218 776
paul@218 777
  gpio_setup(gpio[port], pin, mode, value);
paul@218 778
}
paul@218 779
paul@218 780
static void set_gpio_pull(void *gpio[])
paul@218 781
{
paul@218 782
  char *token;
paul@218 783
  unsigned int port, pin, mode;
paul@218 784
paul@218 785
  if (!get_port_and_pin(&port, &pin))
paul@218 786
    return;
paul@218 787
paul@218 788
  if ((token = read_token("Mode")) == NULL)
paul@218 789
    return;
paul@218 790
paul@218 791
  if (!strcmp(token, "down"))
paul@218 792
    mode = Pull_down;
paul@218 793
  else if (!strcmp(token, "none"))
paul@218 794
    mode = Pull_none;
paul@218 795
  else if (!strcmp(token, "up"))
paul@218 796
    mode = Pull_up;
paul@218 797
  else
paul@218 798
  {
paul@218 799
    printf("Mode not recognised.\n");
paul@218 800
    return;
paul@218 801
  }
paul@218 802
paul@218 803
  gpio_config_pull(gpio[port], pin, mode);
paul@218 804
}
paul@218 805
paul@218 806
paul@218 807
paul@218 808
/* I2C configuration. */
paul@218 809
paul@218 810
static l4_uint32_t i2c_irq_start = 0, i2c_irq_end = 0;
paul@218 811
paul@218 812
/* I2C operations. */
paul@218 813
paul@218 814
static int _i2c_read(void *channel, uint8_t *buf, unsigned length,
paul@218 815
                     int stop, l4_cap_idx_t irqcap, unsigned timeout)
paul@218 816
{
paul@218 817
  l4_msgtag_t tag;
paul@218 818
paul@218 819
  i2c_start_read(channel, buf, length, stop);
paul@218 820
paul@218 821
  while (!i2c_read_done(channel))
paul@218 822
  {
paul@218 823
    tag = l4_irq_receive(irqcap, l4_timeout(L4_IPC_TIMEOUT_NEVER, l4_timeout_from_us(timeout)));
paul@218 824
paul@218 825
    // NOTE: Error not returned.
paul@218 826
paul@218 827
    if (l4_ipc_error(tag, l4_utcb()))
paul@218 828
      break;
paul@218 829
paul@218 830
    if (i2c_failed(channel))
paul@218 831
      break;
paul@218 832
paul@218 833
    i2c_read(channel);
paul@218 834
  }
paul@218 835
paul@218 836
  if (stop)
paul@218 837
    i2c_stop(channel);
paul@218 838
paul@218 839
  return i2c_have_read(channel);
paul@218 840
}
paul@218 841
paul@218 842
static int _i2c_write(void *channel, uint8_t *buf, unsigned length,
paul@218 843
                      int stop, l4_cap_idx_t irqcap, unsigned timeout)
paul@218 844
{
paul@218 845
  l4_msgtag_t tag;
paul@218 846
paul@218 847
  i2c_start_write(channel, buf, length, stop);
paul@218 848
paul@218 849
  while (!i2c_write_done(channel))
paul@218 850
  {
paul@218 851
    tag = l4_irq_receive(irqcap, l4_timeout(L4_IPC_TIMEOUT_NEVER, l4_timeout_from_us(timeout)));
paul@218 852
paul@218 853
    // NOTE: Error not returned.
paul@218 854
paul@218 855
    if (l4_ipc_error(tag, l4_utcb()))
paul@218 856
      break;
paul@218 857
paul@218 858
    if (i2c_failed(channel))
paul@218 859
      break;
paul@218 860
paul@218 861
    i2c_write(channel);
paul@218 862
  }
paul@218 863
paul@218 864
  if (stop)
paul@218 865
    i2c_stop(channel);
paul@218 866
paul@218 867
  return i2c_have_written(channel);
paul@218 868
}
paul@218 869
paul@218 870
static void list_i2c_channels(void)
paul@218 871
{
paul@218 872
  unsigned int num;
paul@218 873
  void *channel;
paul@218 874
paul@218 875
  printf("i2c: channel\n\n");
paul@218 876
paul@218 877
  for (num = 0; num < num_i2c_channels; num++)
paul@218 878
  {
paul@218 879
    printf("Channel %d: ", num);
paul@218 880
paul@218 881
    channel = i2c_channels[num];
paul@218 882
paul@218 883
    if (channel == NULL)
paul@218 884
      printf("(inactive)\n");
paul@218 885
    else
paul@218 886
      printf("%d Hz\n", i2c_get_frequency(channel));
paul@218 887
  }
paul@218 888
}
paul@218 889
paul@218 890
static void new_i2c_channel(void *i2c)
paul@218 891
{
paul@218 892
  l4_cap_idx_t irqcap;
paul@218 893
  int num = get_channel_number(num_i2c_channels);
paul@218 894
paul@218 895
  if (num < 0)
paul@218 896
    return;
paul@218 897
paul@218 898
  irqcap = l4re_util_cap_alloc();
paul@218 899
paul@218 900
  if (init_irq(num, irqcap, i2c_irq_start, i2c_irq_end))
paul@218 901
    return;
paul@218 902
paul@218 903
  i2c_channels[num] = i2c_get_channel(i2c, num);
paul@218 904
  i2c_irqs[num] = irqcap;
paul@218 905
}
paul@218 906
paul@218 907
static void i2c_get(void)
paul@218 908
{
paul@218 909
  void *channel;
paul@218 910
  int num;
paul@218 911
  uint8_t buffer[32];
paul@218 912
  unsigned int address, reg, count;
paul@218 913
  int i, transferred;
paul@218 914
paul@218 915
  channel = get_channel(num_i2c_channels, i2c_channels, &num);
paul@218 916
paul@218 917
  if (channel == NULL)
paul@218 918
    return;
paul@218 919
paul@218 920
  if (!read_encoded_number("Address", "%2x", &address))
paul@218 921
    return;
paul@218 922
paul@218 923
  if (address >= 0x80)
paul@218 924
  {
paul@218 925
    printf("Address must be less than 80.\n");
paul@218 926
    return;
paul@218 927
  }
paul@218 928
paul@218 929
  if (!read_encoded_number("Register", "%2x", &reg))
paul@218 930
    return;
paul@218 931
paul@218 932
  if (!read_number(NULL, &count))
paul@218 933
    count = 1;
paul@218 934
paul@218 935
  buffer[0] = (uint8_t) (reg & 0xff);
paul@218 936
paul@218 937
  i2c_set_target(channel, address);
paul@218 938
paul@218 939
  if (!_i2c_write(channel, buffer, 1, 0, i2c_irqs[num], 1000000))
paul@218 940
  {
paul@218 941
    printf("Register request failed.\n");
paul@218 942
    return;
paul@218 943
  }
paul@218 944
paul@218 945
  transferred = _i2c_read(channel, buffer, count, 1, i2c_irqs[num], 1000000);
paul@218 946
paul@218 947
  if (!transferred)
paul@218 948
  {
paul@218 949
    printf("Register read failed.\n");
paul@218 950
    return;
paul@218 951
  }
paul@218 952
paul@218 953
  for (i = 0; i < transferred; i++)
paul@218 954
    printf("%02x ", buffer[i]);
paul@218 955
  printf("\n");
paul@218 956
}
paul@218 957
paul@218 958
static void i2c_scan(void)
paul@218 959
{
paul@218 960
  void *channel;
paul@218 961
  unsigned int address;
paul@218 962
  uint8_t buffer[1];
paul@218 963
  int num;
paul@218 964
paul@218 965
  channel = get_channel(num_i2c_channels, i2c_channels, &num);
paul@218 966
paul@218 967
  if (channel == NULL)
paul@218 968
    return;
paul@218 969
paul@218 970
  for (address = 0; address < 0x20; address++)
paul@218 971
    printf("%02x ", address);
paul@218 972
  printf("\n");
paul@218 973
paul@218 974
  for (address = 0; address < 0x20; address++)
paul@218 975
    printf("-- ");
paul@218 976
paul@218 977
  for (address = 0; address < 0x80; address++)
paul@218 978
  {
paul@218 979
    if ((address % 32) == 0)
paul@218 980
      printf("\n");
paul@218 981
paul@218 982
    i2c_set_target(channel, address);
paul@218 983
paul@218 984
    if (_i2c_read(channel, buffer, 1, 1, i2c_irqs[num], 1000))
paul@218 985
      printf("%02x ", address);
paul@218 986
    else
paul@218 987
      printf("-- ");
paul@218 988
  }
paul@218 989
paul@218 990
  printf("\n");
paul@218 991
  for (address = 0; address < 0x20; address++)
paul@218 992
    printf("-- ");
paul@218 993
  printf("\n\n");
paul@218 994
}
paul@218 995
paul@218 996
paul@218 997
paul@218 998
/* SPI operations. */
paul@218 999
paul@222 1000
static void new_spi_channel(void *spi, void *gpio[])
paul@221 1001
{
paul@222 1002
  unsigned int control_port, control_pin, control_alt_func_input;
paul@222 1003
  int control_alt_func;
paul@222 1004
  void *control_chip;
paul@221 1005
  int num = get_channel_number(num_spi_channels);
paul@221 1006
  void *channel;
paul@221 1007
  uint32_t frequency;
paul@221 1008
paul@221 1009
  if (num < 0)
paul@221 1010
    return;
paul@221 1011
paul@221 1012
  channel = get_channel(num_dma_channels, dma_channels, NULL);
paul@221 1013
paul@221 1014
  if (channel == NULL)
paul@221 1015
    return;
paul@221 1016
paul@221 1017
  if (!read_number("Frequency", &frequency))
paul@221 1018
    return;
paul@221 1019
paul@222 1020
  if (!get_port_and_pin(&control_port, &control_pin))
paul@222 1021
    control_chip = NULL;
paul@222 1022
  else
paul@222 1023
    control_chip = gpio[control_port];
paul@222 1024
paul@222 1025
  if (!read_number("Function", &control_alt_func_input))
paul@222 1026
    control_alt_func = -1;
paul@222 1027
  else
paul@222 1028
    control_alt_func = control_alt_func_input;
paul@222 1029
paul@222 1030
  spi_channels[num] = spi_get_channel(spi, num, channel, frequency,
paul@222 1031
                                      control_chip, control_pin,
paul@222 1032
                                      control_alt_func);
paul@221 1033
}
paul@221 1034
paul@221 1035
static void new_spi_channel_gpio(void *gpio[])
paul@218 1036
{
paul@222 1037
  unsigned int clock_port, clock_pin, data_port, data_pin, enable_port,
paul@222 1038
               enable_pin, control_port, control_pin;
paul@222 1039
  void *control_chip;
paul@218 1040
  int num = get_channel_number(num_spi_channels);
paul@218 1041
  uint32_t frequency;
paul@218 1042
paul@218 1043
  if (num < 0)
paul@218 1044
    return;
paul@218 1045
paul@222 1046
  if (!read_number("Frequency", &frequency))
paul@222 1047
    return;
paul@222 1048
paul@218 1049
  if (!get_port_and_pin(&clock_port, &clock_pin))
paul@218 1050
    return;
paul@218 1051
paul@218 1052
  if (!get_port_and_pin(&data_port, &data_pin))
paul@218 1053
    return;
paul@218 1054
paul@218 1055
  if (!get_port_and_pin(&enable_port, &enable_pin))
paul@218 1056
    return;
paul@218 1057
paul@222 1058
  if (!get_port_and_pin(&control_port, &control_pin))
paul@222 1059
    control_chip = NULL;
paul@222 1060
  else
paul@222 1061
    control_chip = gpio[control_port];
paul@218 1062
paul@222 1063
  spi_channels[num] = spi_get_channel_gpio(frequency,
paul@222 1064
                                           gpio[clock_port], clock_pin,
paul@221 1065
                                           gpio[data_port], data_pin,
paul@221 1066
                                           gpio[enable_port], enable_pin,
paul@222 1067
                                           control_chip, control_pin);
paul@222 1068
}
paul@222 1069
paul@222 1070
static void spi_control(int acquire)
paul@222 1071
{
paul@222 1072
  unsigned int level;
paul@222 1073
  void *channel = get_channel(num_spi_channels, spi_channels, NULL);
paul@222 1074
paul@222 1075
  if (acquire)
paul@222 1076
  {
paul@222 1077
    if (!read_number("Level", &level))
paul@222 1078
      return;
paul@222 1079
paul@222 1080
    spi_acquire_control(channel, level);
paul@222 1081
  }
paul@222 1082
  else
paul@222 1083
    spi_release_control(channel);
paul@218 1084
}
paul@218 1085
paul@221 1086
static void spi_send_data_gpio(void)
paul@218 1087
{
paul@218 1088
  void *channel = get_channel(num_spi_channels, spi_channels, NULL);
paul@218 1089
  int bytes;
paul@218 1090
  unsigned int byte;
paul@218 1091
  uint8_t buffer[256];
paul@218 1092
paul@218 1093
  bytes = 0;
paul@218 1094
paul@218 1095
  while (read_encoded_number(NULL, "%2x", &byte))
paul@218 1096
  {
paul@218 1097
    buffer[bytes] = (uint8_t) (byte & 0xff);
paul@218 1098
    bytes++;
paul@218 1099
  }
paul@218 1100
paul@221 1101
  spi_send_gpio(channel, bytes, buffer);
paul@221 1102
}
paul@221 1103
paul@221 1104
static void spi_send_data_units(void)
paul@221 1105
{
paul@221 1106
  void *channel = get_channel(num_spi_channels, spi_channels, NULL);
paul@221 1107
  unsigned int char_size, unit_size, value;
paul@221 1108
  uint8_t buffer[256];
paul@221 1109
  int byte = 0;
paul@221 1110
paul@221 1111
  if (!read_number("Unit size", &unit_size))
paul@221 1112
    return;
paul@221 1113
paul@221 1114
  if (!read_number("Character size", &char_size))
paul@221 1115
    return;
paul@221 1116
paul@221 1117
  /* Read hex digits for bytes. Multiple bytes make up each unit and are read
paul@221 1118
     from most to least significant. Where the unit size exceeds the character
paul@221 1119
     size, the last bit before the character indicates the GPC bit. */
paul@221 1120
paul@221 1121
  while ((byte < 256) && read_encoded_number(NULL, "%2x", &value))
paul@221 1122
    buffer[byte++] = value;
paul@221 1123
paul@222 1124
  spi_send_units(channel, byte, (uint8_t *) buffer, unit_size, char_size);
paul@221 1125
}
paul@221 1126
paul@221 1127
static void spi_transfer_data(void)
paul@221 1128
{
paul@221 1129
  void *channel = get_channel(num_spi_channels, spi_channels, NULL);
paul@223 1130
  struct dma_region *region, *desc_region;
paul@221 1131
  unsigned int char_size, unit_size;
paul@221 1132
  uint32_t count, transferred;
paul@221 1133
paul@221 1134
  if (channel == NULL)
paul@221 1135
    return;
paul@221 1136
paul@221 1137
  region = _get_dma_region();
paul@221 1138
paul@221 1139
  if (region == NULL)
paul@221 1140
    return;
paul@221 1141
paul@221 1142
  if (!read_number("Transfer size", &count))
paul@221 1143
    return;
paul@221 1144
paul@221 1145
  if (!read_number("Unit size", &unit_size))
paul@221 1146
    return;
paul@221 1147
paul@221 1148
  if (!read_number("Character size", &char_size))
paul@221 1149
    return;
paul@221 1150
paul@223 1151
  desc_region = _get_dma_region();
paul@223 1152
paul@223 1153
  transferred = spi_transfer(channel, region->paddr, count, unit_size, char_size,
paul@223 1154
                             desc_region != NULL ? desc_region->vaddr : 0,
paul@223 1155
                             desc_region != NULL ? desc_region->paddr : 0);
paul@221 1156
paul@221 1157
  printf("Transferred: %d\n", transferred);
paul@218 1158
}
paul@218 1159
paul@218 1160
paul@218 1161
paul@218 1162
/* Command processing. */
paul@218 1163
paul@218 1164
static void handle_aic(void *aic)
paul@218 1165
{
paul@218 1166
  char *token;
paul@218 1167
paul@218 1168
  if ((token = read_token(NULL)) != NULL)
paul@218 1169
  {
paul@218 1170
    if (!strcmp(token, "l") || !strcmp(token, "list"))
paul@218 1171
      list_channels(num_aic_channels, aic_channels);
paul@218 1172
    else if (!strcmp(token, "c") || !strcmp(token, "channel"))
paul@218 1173
      new_aic_channel(aic);
paul@218 1174
    else if (!strcmp(token, "t") || !strcmp(token, "transfer"))
paul@218 1175
      aic_transfer_data();
paul@218 1176
    else
paul@218 1177
      printf("aic channel | list | set | transfer\n");
paul@218 1178
  }
paul@218 1179
  else
paul@218 1180
    list_channels(num_aic_channels, aic_channels);
paul@218 1181
}
paul@218 1182
paul@218 1183
static void handle_cpm(void *cpm)
paul@218 1184
{
paul@218 1185
  char *token;
paul@218 1186
paul@218 1187
  if ((token = read_token(NULL)) != NULL)
paul@218 1188
  {
paul@218 1189
    if (!strcmp(token, "l") || !strcmp(token, "list"))
paul@218 1190
      list_clocks(cpm);
paul@218 1191
    else if (!strcmp(token, "f") || !strcmp(token, "frequency"))
paul@218 1192
      set_frequency(cpm);
paul@218 1193
    else if (!strcmp(token, "p") || !strcmp(token, "parameters"))
paul@218 1194
      set_parameters(cpm);
paul@218 1195
    else if (!strcmp(token, "s") || !strcmp(token, "source"))
paul@218 1196
      set_source(cpm);
paul@218 1197
    else if (!strcmp(token, "start"))
paul@218 1198
      start_clock(cpm);
paul@218 1199
    else if (!strcmp(token, "stop"))
paul@218 1200
      stop_clock(cpm);
paul@218 1201
    else
paul@218 1202
      printf("cpm list | frequency | parameters | source | start | stop\n");
paul@218 1203
  }
paul@218 1204
  else
paul@218 1205
    list_clocks(cpm);
paul@218 1206
}
paul@218 1207
paul@218 1208
static void handle_dma(void *dma)
paul@218 1209
{
paul@218 1210
  char *token;
paul@218 1211
paul@218 1212
  if ((token = read_token(NULL)) != NULL)
paul@218 1213
  {
paul@218 1214
    if (!strcmp(token, "l") || !strcmp(token, "list"))
paul@218 1215
      list_channels(num_dma_channels, dma_channels);
paul@218 1216
    else if (!strcmp(token, "c") || !strcmp(token, "channel"))
paul@218 1217
      new_dma_channel(dma);
paul@218 1218
    else if (!strcmp(token, "r") || !strcmp(token, "region"))
paul@218 1219
      new_dma_region();
paul@218 1220
    else if (!strcmp(token, "s") || !strcmp(token, "set"))
paul@218 1221
      set_dma_region();
paul@218 1222
    else if (!strcmp(token, "t") || !strcmp(token, "transfer"))
paul@218 1223
      dma_transfer_data();
paul@218 1224
    else
paul@218 1225
      printf("dma channel | list | region | set | transfer\n");
paul@218 1226
  }
paul@218 1227
  else
paul@218 1228
    list_channels(num_dma_channels, dma_channels);
paul@218 1229
}
paul@218 1230
paul@218 1231
static void handle_gpio(void *gpio[])
paul@218 1232
{
paul@218 1233
  char *token;
paul@218 1234
paul@218 1235
  if ((token = read_token(NULL)) != NULL)
paul@218 1236
  {
paul@218 1237
    if (!strcmp(token, "l") || !strcmp(token, "list"))
paul@218 1238
      list_gpios(gpio);
paul@218 1239
    else if (!strcmp(token, "a") || !strcmp(token, "alt"))
paul@218 1240
      set_gpio_alt_func(gpio);
paul@218 1241
    else if (!strcmp(token, "i") || !strcmp(token, "io"))
paul@218 1242
      set_gpio_pad(gpio);
paul@218 1243
    else if (!strcmp(token, "p") || !strcmp(token, "pull"))
paul@218 1244
      set_gpio_pull(gpio);
paul@218 1245
    else
paul@218 1246
      printf("gpio list | alt | io | pull\n");
paul@218 1247
  }
paul@218 1248
  else
paul@218 1249
    list_gpios(gpio);
paul@218 1250
}
paul@218 1251
paul@218 1252
static void handle_i2c(void *i2c)
paul@218 1253
{
paul@218 1254
  char *token;
paul@218 1255
paul@218 1256
  if ((token = read_token(NULL)) != NULL)
paul@218 1257
  {
paul@218 1258
    if (!strcmp(token, "l") || !strcmp(token, "list"))
paul@218 1259
      list_i2c_channels();
paul@218 1260
    else if (!strcmp(token, "c") || !strcmp(token, "channel"))
paul@218 1261
      new_i2c_channel(i2c);
paul@218 1262
    else if (!strcmp(token, "g") || !strcmp(token, "get"))
paul@218 1263
      i2c_get();
paul@218 1264
    else if (!strcmp(token, "s") || !strcmp(token, "scan"))
paul@218 1265
      i2c_scan();
paul@218 1266
    else
paul@218 1267
      printf("i2c channel | get | list | scan\n");
paul@218 1268
  }
paul@218 1269
  else
paul@218 1270
    list_i2c_channels();
paul@218 1271
}
paul@218 1272
paul@221 1273
static void handle_spi(void *spi, void *gpio[])
paul@218 1274
{
paul@218 1275
  char *token;
paul@218 1276
paul@218 1277
  if ((token = read_token(NULL)) != NULL)
paul@218 1278
  {
paul@218 1279
    if (!strcmp(token, "l") || !strcmp(token, "list"))
paul@218 1280
      list_channels(num_spi_channels, spi_channels);
paul@222 1281
    else if (!strcmp(token, "a") || !strcmp(token, "control-acquire"))
paul@222 1282
      spi_control(1);
paul@222 1283
    else if (!strcmp(token, "r") || !strcmp(token, "control-release"))
paul@222 1284
      spi_control(0);
paul@218 1285
    else if (!strcmp(token, "c") || !strcmp(token, "channel"))
paul@222 1286
      new_spi_channel(spi, gpio);
paul@221 1287
    else if (!strcmp(token, "g") || !strcmp(token, "gpio") || !strcmp(token, "gpio-channel"))
paul@221 1288
      new_spi_channel_gpio(gpio);
paul@218 1289
    else if (!strcmp(token, "s") || !strcmp(token, "send"))
paul@221 1290
      spi_send_data_gpio();
paul@221 1291
    else if (!strcmp(token, "S") || !strcmp(token, "send-units"))
paul@221 1292
      spi_send_data_units();
paul@221 1293
    else if (!strcmp(token, "t") || !strcmp(token, "transfer"))
paul@221 1294
      spi_transfer_data();
paul@218 1295
    else
paul@222 1296
      printf("spi channel | control-acquire | control-release | gpio-channel | list | send | send-units | transfer\n");
paul@218 1297
  }
paul@218 1298
  else
paul@218 1299
    list_channels(num_spi_channels, spi_channels);
paul@218 1300
}
paul@218 1301
paul@218 1302
paul@218 1303
paul@218 1304
int main(void)
paul@218 1305
{
paul@218 1306
  l4_addr_t aic_base = 0, aic_base_end = 0;
paul@218 1307
  l4_addr_t aic_phys_base = 0, aic_phys_base_end = 0;
paul@218 1308
  l4_addr_t cpm_base = 0, cpm_base_end = 0;
paul@218 1309
  l4_addr_t dma_base = 0, dma_base_end = 0;
paul@218 1310
  l4_addr_t gpio_base = 0, gpio_base_end = 0;
paul@218 1311
  l4_addr_t i2c_base = 0, i2c_base_end = 0;
paul@221 1312
  l4_addr_t ssi_base = 0, ssi_base_end = 0;
paul@221 1313
  l4_addr_t ssi_phys_base = 0, ssi_phys_base_end = 0;
paul@221 1314
  void *aic, *cpm, *dma, *gpio[num_gpio_ports], *i2c, *spi;
paul@218 1315
  int result = 0;
paul@218 1316
  unsigned int port;
paul@218 1317
paul@218 1318
  icucap = l4re_env_get_cap("icu");
paul@218 1319
paul@218 1320
  /* Obtain resource details describing I/O memory. */
paul@218 1321
paul@218 1322
  printf("Access CPM...\n");
paul@218 1323
paul@218 1324
  if ((result = get_memory(memory_regions[CPM], &cpm_base, &cpm_base_end)) < 0)
paul@218 1325
    return 1;
paul@218 1326
paul@218 1327
  printf("CPM at 0x%lx...0x%lx.\n", cpm_base, cpm_base_end);
paul@218 1328
paul@218 1329
  cpm = cpm_init(cpm_base);
paul@218 1330
paul@218 1331
  printf("Access DMA...\n");
paul@218 1332
paul@218 1333
  if ((result = get_memory(memory_regions[DMA], &dma_base, &dma_base_end)) < 0)
paul@218 1334
    return 1;
paul@218 1335
paul@218 1336
  printf("DMA at 0x%lx...0x%lx.\n", dma_base, dma_base_end);
paul@218 1337
paul@218 1338
  dma = dma_init(dma_base, dma_base_end, cpm);
paul@218 1339
paul@218 1340
  if (get_irq(memory_regions[DMA], &dma_irq_start, &dma_irq_end) < 0)
paul@218 1341
    return 1;
paul@218 1342
paul@218 1343
  printf("IRQ range at %d...%d.\n", dma_irq_start, dma_irq_end);
paul@218 1344
paul@218 1345
  if (init_dma())
paul@218 1346
    return 1;
paul@218 1347
paul@218 1348
  dma_enable(dma);
paul@218 1349
paul@218 1350
  printf("Access GPIO...\n");
paul@218 1351
paul@218 1352
  if ((result = get_memory(memory_regions[GPIO], &gpio_base, &gpio_base_end)) < 0)
paul@218 1353
    return 1;
paul@218 1354
paul@218 1355
  printf("GPIO at 0x%lx...0x%lx.\n", gpio_base, gpio_base_end);
paul@218 1356
paul@218 1357
  for (port = 0; port < num_gpio_ports; port++)
paul@218 1358
    gpio[port] = gpio_init(gpio_base + port * 0x100, gpio_base + (port + 1) * 0x100,
paul@218 1359
                           32, gpio_ports[port].pull_ups, gpio_ports[port].pull_downs);
paul@218 1360
paul@218 1361
  printf("Access I2C...\n");
paul@218 1362
paul@218 1363
  if ((result = get_memory(memory_regions[I2C], &i2c_base, &i2c_base_end)) < 0)
paul@218 1364
    return 1;
paul@218 1365
paul@218 1366
  printf("I2C at 0x%lx...0x%lx.\n", i2c_base, i2c_base_end);
paul@218 1367
paul@218 1368
  i2c = i2c_init(i2c_base, i2c_base_end, cpm, 100000);
paul@218 1369
paul@218 1370
  if (get_irq(memory_regions[I2C], &i2c_irq_start, &i2c_irq_end) < 0)
paul@218 1371
    return 1;
paul@218 1372
paul@218 1373
  printf("IRQ range at %d...%d.\n", i2c_irq_start, i2c_irq_end);
paul@218 1374
paul@218 1375
  printf("Access AIC...\n");
paul@218 1376
paul@218 1377
  if ((result = get_memory_complete(memory_regions[AIC], &aic_base, &aic_base_end,
paul@218 1378
                                    &aic_phys_base, &aic_phys_base_end)) < 0)
paul@218 1379
    return 1;
paul@218 1380
paul@218 1381
  printf("AIC at 0x%lx...0x%lx.\n", aic_base, aic_base_end);
paul@218 1382
paul@218 1383
  aic = aic_init(aic_phys_base, aic_base, aic_base_end, cpm);
paul@218 1384
paul@221 1385
  printf("Access SSI...\n");
paul@221 1386
paul@221 1387
  if ((result = get_memory_complete(memory_regions[SSI], &ssi_base, &ssi_base_end,
paul@221 1388
                                    &ssi_phys_base, &ssi_phys_base_end)) < 0)
paul@218 1389
    return 1;
paul@218 1390
paul@221 1391
  printf("SSI at 0x%lx...0x%lx.\n", ssi_base, ssi_base_end);
paul@221 1392
paul@221 1393
  spi = spi_init(ssi_phys_base, ssi_base, ssi_base_end, cpm);
paul@218 1394
paul@218 1395
  /* Start the interactive session. */
paul@218 1396
paul@218 1397
  printf("aic, cpm, dma, gpio, i2c, spi\n");
paul@218 1398
paul@218 1399
  while (1)
paul@218 1400
  {
paul@218 1401
    char cmdline[256], *token;
paul@218 1402
paul@218 1403
    printf("> ");
paul@218 1404
paul@221 1405
    token = fgets(cmdline, 256, stdin);
paul@218 1406
paul@218 1407
    if (token == NULL)
paul@218 1408
      break;
paul@218 1409
paul@218 1410
    if ((token = strtok(cmdline, delimiters)) == NULL)
paul@218 1411
      continue;
paul@218 1412
paul@218 1413
    /* AIC/I2S commands. */
paul@218 1414
paul@218 1415
    if (!strcmp(token, "a") || !strcmp(token, "aic") || !strcmp(token, "i2s"))
paul@218 1416
      handle_aic(aic);
paul@218 1417
paul@218 1418
    /* CPM commands. */
paul@218 1419
paul@218 1420
    else if (!strcmp(token, "c") || !strcmp(token, "cpm"))
paul@218 1421
      handle_cpm(cpm);
paul@218 1422
paul@218 1423
    /* DMA commands. */
paul@218 1424
paul@218 1425
    else if (!strcmp(token, "d") || !strcmp(token, "dma"))
paul@218 1426
      handle_dma(dma);
paul@218 1427
paul@218 1428
    /* GPIO commands. */
paul@218 1429
paul@218 1430
    else if (!strcmp(token, "g") || !strcmp(token, "gpio"))
paul@218 1431
      handle_gpio(gpio);
paul@218 1432
paul@218 1433
    /* I2C commands. */
paul@218 1434
paul@218 1435
    else if (!strcmp(token, "i") || !strcmp(token, "i2c"))
paul@218 1436
      handle_i2c(i2c);
paul@218 1437
paul@218 1438
    /* SPI commands. */
paul@218 1439
paul@218 1440
    else if (!strcmp(token, "s") || !strcmp(token, "spi"))
paul@221 1441
      handle_spi(spi, gpio);
paul@218 1442
paul@221 1443
    /* Comments and blank lines. */
paul@221 1444
paul@221 1445
    else if (strncmp(token, "#", 1) && strlen(token))
paul@218 1446
      printf("Command?\n");
paul@218 1447
  }
paul@218 1448
paul@218 1449
  printf("End of session.\n");
paul@218 1450
  return 0;
paul@218 1451
}