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