Mike Frysinger | 07f8227 | 2008-10-12 21:55:45 -0400 | [diff] [blame] | 1 | /* |
| 2 | * Control GPIO pins on the fly |
| 3 | * |
| 4 | * Copyright (c) 2008 Analog Devices Inc. |
| 5 | * |
| 6 | * Licensed under the GPL-2 or later. |
| 7 | */ |
| 8 | |
| 9 | #include <common.h> |
| 10 | #include <command.h> |
| 11 | |
| 12 | #include <asm/blackfin.h> |
| 13 | |
| 14 | int do_gpio(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) |
| 15 | { |
| 16 | if (argc != 3) { |
| 17 | show_usage: |
| 18 | printf("Usage:\n%s\n", cmdtp->usage); |
| 19 | return 1; |
| 20 | } |
| 21 | |
| 22 | /* parse the behavior */ |
| 23 | ulong port_cmd = 0; |
| 24 | switch (argv[1][0]) { |
| 25 | case 'i': break; |
| 26 | case 's': port_cmd = (PORTFIO_SET - PORTFIO); break; |
| 27 | case 'c': port_cmd = (PORTFIO_CLEAR - PORTFIO); break; |
| 28 | case 't': port_cmd = (PORTFIO_TOGGLE - PORTFIO); break; |
| 29 | default: goto show_usage; |
| 30 | } |
| 31 | |
| 32 | /* parse the pin with format: [p]<fgh><#> */ |
| 33 | const char *str_pin = argv[2]; |
| 34 | |
| 35 | /* grab the [p]<fgh> portion */ |
| 36 | ulong port_base; |
| 37 | if (*str_pin == 'p') ++str_pin; |
| 38 | switch (*str_pin) { |
| 39 | case 'f': port_base = PORTFIO; break; |
| 40 | case 'g': port_base = PORTGIO; break; |
| 41 | case 'h': port_base = PORTHIO; break; |
| 42 | default: goto show_usage; |
| 43 | } |
| 44 | |
| 45 | /* grab the <#> portion */ |
| 46 | ulong pin = simple_strtoul(str_pin+1, NULL, 10); |
| 47 | ulong pin_mask = (1 << pin); |
| 48 | if (pin > 15) |
| 49 | goto show_usage; |
| 50 | |
| 51 | /* finally, let's do it: set direction and exec command */ |
| 52 | switch (*str_pin) { |
| 53 | case 'f': bfin_write_PORTF_FER(bfin_read_PORTF_FER() & ~pin_mask); break; |
| 54 | case 'g': bfin_write_PORTG_FER(bfin_read_PORTG_FER() & ~pin_mask); break; |
| 55 | case 'h': bfin_write_PORTH_FER(bfin_read_PORTH_FER() & ~pin_mask); break; |
| 56 | } |
| 57 | |
| 58 | ulong port_dir = port_base + (PORTFIO_DIR - PORTFIO); |
| 59 | if (argv[1][0] == 'i') |
| 60 | bfin_write16(port_dir, bfin_read16(port_dir) & ~pin_mask); |
| 61 | else { |
| 62 | bfin_write16(port_dir, bfin_read16(port_dir) | pin_mask); |
| 63 | bfin_write16(port_base + port_cmd, pin_mask); |
| 64 | } |
| 65 | |
| 66 | printf("gpio: pin %li on port %c has been %c\n", pin, *str_pin, argv[1][0]); |
| 67 | |
| 68 | return 0; |
| 69 | } |
| 70 | |
| 71 | U_BOOT_CMD(gpio, 3, 0, do_gpio, |
| 72 | "gpio - set/clear/toggle gpio output pins\n", |
| 73 | "<s|c|t> <port><pin>\n" |
| 74 | " - set/clear/toggle the specified pin\n"); |