paul@114 | 1 | /* |
paul@114 | 2 | * Access peripherals on the I2C bus. |
paul@114 | 3 | * |
paul@114 | 4 | * Copyright (C) 2018, 2020 Paul Boddie <paul@boddie.org.uk> |
paul@114 | 5 | * |
paul@114 | 6 | * This program is free software; you can redistribute it and/or |
paul@114 | 7 | * modify it under the terms of the GNU General Public License as |
paul@114 | 8 | * published by the Free Software Foundation; either version 2 of |
paul@114 | 9 | * the License, or (at your option) any later version. |
paul@114 | 10 | * |
paul@114 | 11 | * This program is distributed in the hope that it will be useful, |
paul@114 | 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
paul@114 | 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
paul@114 | 14 | * GNU General Public License for more details. |
paul@114 | 15 | * |
paul@114 | 16 | * You should have received a copy of the GNU General Public License |
paul@114 | 17 | * along with this program; if not, write to the Free Software |
paul@114 | 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, |
paul@114 | 19 | * Boston, MA 02110-1301, USA |
paul@114 | 20 | */ |
paul@114 | 21 | |
paul@114 | 22 | #include <l4/devices/cpm-jz4730.h> |
paul@114 | 23 | #include <l4/devices/i2c-jz4730.h> |
paul@114 | 24 | #include <l4/devices/memory.h> |
paul@114 | 25 | |
paul@114 | 26 | #include <stdio.h> |
paul@114 | 27 | |
paul@114 | 28 | |
paul@114 | 29 | |
paul@114 | 30 | /* Scan the I2C bus by performing speculative reads from each device address. */ |
paul@114 | 31 | |
paul@114 | 32 | static void i2c_scan(void *i2c_channel) |
paul@114 | 33 | { |
paul@114 | 34 | uint8_t buf[1]; |
paul@114 | 35 | unsigned int address; |
paul@114 | 36 | |
paul@114 | 37 | for (address = 0; address < 0x20; address++) |
paul@114 | 38 | printf("%02x ", address); |
paul@114 | 39 | printf("\n"); |
paul@114 | 40 | |
paul@114 | 41 | for (address = 0; address < 0x20; address++) |
paul@114 | 42 | printf("-- "); |
paul@114 | 43 | |
paul@114 | 44 | for (address = 0; address < 0x80; address++) |
paul@114 | 45 | { |
paul@114 | 46 | if ((address % 32) == 0) |
paul@114 | 47 | printf("\n"); |
paul@114 | 48 | |
paul@114 | 49 | if (jz4730_i2c_read(i2c_channel, address, buf, 1)) |
paul@114 | 50 | printf("%02x ", address); |
paul@114 | 51 | else |
paul@114 | 52 | printf("?? "); |
paul@114 | 53 | } |
paul@114 | 54 | |
paul@114 | 55 | printf("\n"); |
paul@114 | 56 | for (address = 0; address < 0x20; address++) |
paul@114 | 57 | printf("-- "); |
paul@114 | 58 | printf("\n\n"); |
paul@114 | 59 | } |
paul@114 | 60 | |
paul@114 | 61 | /* Interpret RTC registers. */ |
paul@114 | 62 | |
paul@114 | 63 | static void rtc_datetime(uint8_t *rtcregs) |
paul@114 | 64 | { |
paul@114 | 65 | const char *weekdays[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; |
paul@114 | 66 | |
paul@114 | 67 | printf("%s %d%d-%d%d-%d%d %d%d:%d%d:%d%d\n", |
paul@114 | 68 | weekdays[rtcregs[0x06] & 0x07], |
paul@114 | 69 | (rtcregs[0x08] & 0xf0) >> 4, |
paul@114 | 70 | rtcregs[0x08] & 0x0f, |
paul@114 | 71 | (rtcregs[0x07] & 0x10) >> 4, |
paul@114 | 72 | rtcregs[0x07] & 0x0f, |
paul@114 | 73 | (rtcregs[0x05] & 0x30) >> 4, |
paul@114 | 74 | rtcregs[0x05] & 0x0f, |
paul@114 | 75 | (rtcregs[0x04] & 0x30) >> 4, |
paul@114 | 76 | rtcregs[0x04] & 0x0f, |
paul@114 | 77 | (rtcregs[0x03] & 0x70) >> 4, |
paul@114 | 78 | rtcregs[0x03] & 0x0f, |
paul@114 | 79 | (rtcregs[0x02] & 0x70) >> 4, |
paul@114 | 80 | rtcregs[0x02] & 0x0f); |
paul@114 | 81 | } |
paul@114 | 82 | |
paul@114 | 83 | |
paul@114 | 84 | |
paul@114 | 85 | int main(void) |
paul@114 | 86 | { |
paul@114 | 87 | void *cpm; |
paul@114 | 88 | void *i2c, *i2c0; |
paul@114 | 89 | |
paul@114 | 90 | /* Peripheral memory. */ |
paul@114 | 91 | |
paul@114 | 92 | l4_addr_t cpm_base = 0, cpm_base_end = 0; |
paul@114 | 93 | l4_addr_t i2c_base = 0, i2c_base_end = 0; |
paul@114 | 94 | |
paul@114 | 95 | /* Obtain resource details describing I/O memory. */ |
paul@114 | 96 | |
paul@114 | 97 | printf("Access CPM...\n"); |
paul@114 | 98 | |
paul@114 | 99 | if (get_memory("jz4730-cpm", &cpm_base, &cpm_base_end) < 0) |
paul@114 | 100 | return 1; |
paul@114 | 101 | |
paul@114 | 102 | printf("CPM at 0x%lx...0x%lx.\n", cpm_base, cpm_base_end); |
paul@114 | 103 | |
paul@114 | 104 | printf("Access I2C...\n"); |
paul@114 | 105 | |
paul@114 | 106 | if (get_memory("jz4730-i2c", &i2c_base, &i2c_base_end) < 0) |
paul@114 | 107 | return 1; |
paul@114 | 108 | |
paul@114 | 109 | printf("I2C at 0x%lx...0x%lx.\n", i2c_base, i2c_base_end); |
paul@114 | 110 | |
paul@114 | 111 | /* Obtain CPM and I2C references. */ |
paul@114 | 112 | |
paul@114 | 113 | cpm = jz4730_cpm_init(cpm_base); |
paul@114 | 114 | i2c = jz4730_i2c_init(i2c_base, i2c_base_end, cpm, 100000); /* 100 kHz */ |
paul@114 | 115 | i2c0 = jz4730_i2c_get_channel(i2c, 0); |
paul@114 | 116 | |
paul@114 | 117 | /* Enable I2C. */ |
paul@114 | 118 | |
paul@114 | 119 | jz4730_i2c_enable(i2c0); |
paul@114 | 120 | |
paul@114 | 121 | uint8_t buf[32]; |
paul@114 | 122 | unsigned int nwritten; |
paul@114 | 123 | |
paul@114 | 124 | /* Set the clock: 12:34:56 on Saturday 2nd January 2021. */ |
paul@114 | 125 | |
paul@114 | 126 | buf[0] = 2; buf[1] = 0x56; buf[2] = 0x34; buf[3] = 0x12; buf[4] = 0x02; buf[5] = 0x06; buf[6] = 0x01; buf[7] = 0x21; |
paul@114 | 127 | nwritten = jz4730_i2c_write(i2c0, 0x51, buf, 8); |
paul@114 | 128 | |
paul@114 | 129 | printf("Written: %d\n", nwritten); |
paul@114 | 130 | |
paul@114 | 131 | /* Issue selection of device register 0. */ |
paul@114 | 132 | |
paul@114 | 133 | buf[0] = 0; |
paul@114 | 134 | nwritten = jz4730_i2c_write(i2c0, 0x51, buf, 1); |
paul@114 | 135 | |
paul@114 | 136 | printf("Written: %d\n", nwritten); |
paul@114 | 137 | |
paul@114 | 138 | /* Read the contents of 16 registers. */ |
paul@114 | 139 | |
paul@114 | 140 | unsigned int nread = jz4730_i2c_read(i2c0, 0x51, buf, 16); |
paul@114 | 141 | |
paul@114 | 142 | printf("Read: %d\n", nread); |
paul@114 | 143 | for (unsigned int i = 0; i < nread; i++) |
paul@114 | 144 | printf("%02x ", buf[i]); |
paul@114 | 145 | printf("\n"); |
paul@114 | 146 | |
paul@114 | 147 | /* Show the interpreted date and time. */ |
paul@114 | 148 | |
paul@114 | 149 | rtc_datetime(buf); |
paul@114 | 150 | |
paul@114 | 151 | /* Scan the bus. */ |
paul@114 | 152 | |
paul@114 | 153 | printf("Scan I2C0...\n"); |
paul@114 | 154 | i2c_scan(i2c0); |
paul@114 | 155 | |
paul@114 | 156 | return 0; |
paul@114 | 157 | } |