1.1 --- a/pkg/landfall-examples/letux400_i2c/letux400_i2c.cc Sun Jan 03 17:53:36 2021 +0100
1.2 +++ b/pkg/landfall-examples/letux400_i2c/letux400_i2c.cc Wed Jan 06 00:46:11 2021 +0100
1.3 @@ -23,10 +23,27 @@
1.4 #include <l4/devices/i2c-jz4730.h>
1.5 #include <l4/devices/memory.h>
1.6
1.7 +#include <l4/re/c/util/cap_alloc.h>
1.8 +#include <l4/sys/factory.h>
1.9 +#include <l4/sys/icu.h>
1.10 +#include <l4/sys/irq.h>
1.11 +#include <l4/sys/rcv_endpoint.h>
1.12 +
1.13 #include <stdio.h>
1.14 +#include <unistd.h>
1.15
1.16
1.17
1.18 +/* Device and resource discovery. */
1.19 +
1.20 +static long item_in_range(long start, long end, long index)
1.21 +{
1.22 + if (start < end)
1.23 + return start + index;
1.24 + else
1.25 + return start - index;
1.26 +}
1.27 +
1.28 /* Scan the I2C bus by performing speculative reads from each device address. */
1.29
1.30 static void i2c_scan(void *i2c_channel)
1.31 @@ -87,6 +104,71 @@
1.32 void *cpm;
1.33 void *i2c, *i2c0;
1.34
1.35 + /* Interrupts. */
1.36 +
1.37 + l4_uint32_t i2c_irq_start = 0, i2c_irq_end = 0;
1.38 + l4_cap_idx_t icucap, irq0cap;
1.39 +
1.40 + /* Obtain resource details describing the interrupt for I2C channel 0. */
1.41 +
1.42 + printf("Access IRQ...\n");
1.43 +
1.44 + if (get_irq("jz4730-i2c", &i2c_irq_start, &i2c_irq_end) < 0)
1.45 + return 1;
1.46 +
1.47 + printf("IRQ range at %d...%d.\n", i2c_irq_start, i2c_irq_end);
1.48 +
1.49 + /* Obtain capabilities for the interrupt controller and an interrupt. */
1.50 +
1.51 + irq0cap = l4re_util_cap_alloc();
1.52 + icucap = l4re_env_get_cap("icu");
1.53 +
1.54 + if (l4_is_invalid_cap(icucap))
1.55 + {
1.56 + printf("No 'icu' capability available in the virtual bus.\n");
1.57 + return 1;
1.58 + }
1.59 +
1.60 + if (l4_is_invalid_cap(irq0cap))
1.61 + {
1.62 + printf("Capabilities not available for interrupts.\n");
1.63 + return 1;
1.64 + }
1.65 +
1.66 + /* Create interrupt objects. */
1.67 +
1.68 + long err;
1.69 +
1.70 + err = l4_error(l4_factory_create_irq(l4re_global_env->factory, irq0cap));
1.71 +
1.72 + if (err)
1.73 + {
1.74 + printf("Could not create IRQ object: %lx\n", err);
1.75 + return 1;
1.76 + }
1.77 +
1.78 + /* Bind interrupt objects to IRQ numbers. */
1.79 +
1.80 + err = l4_error(l4_icu_bind(icucap,
1.81 + item_in_range(i2c_irq_start, i2c_irq_end, 0),
1.82 + irq0cap));
1.83 +
1.84 + if (err)
1.85 + {
1.86 + printf("Could not bind IRQ to the ICU: %ld\n", err);
1.87 + return 1;
1.88 + }
1.89 +
1.90 + /* Attach ourselves to the interrupt handler. */
1.91 +
1.92 + err = l4_error(l4_rcv_ep_bind_thread(irq0cap, l4re_env()->main_thread, 0));
1.93 +
1.94 + if (err)
1.95 + {
1.96 + printf("Could not attach to IRQs: %ld\n", err);
1.97 + return 1;
1.98 + }
1.99 +
1.100 /* Peripheral memory. */
1.101
1.102 l4_addr_t cpm_base = 0, cpm_base_end = 0;
1.103 @@ -112,7 +194,7 @@
1.104
1.105 cpm = jz4730_cpm_init(cpm_base);
1.106 i2c = jz4730_i2c_init(i2c_base, i2c_base_end, cpm, 100000); /* 100 kHz */
1.107 - i2c0 = jz4730_i2c_get_channel(i2c, 0);
1.108 + i2c0 = jz4730_i2c_get_channel(i2c, 0, irq0cap);
1.109
1.110 /* Enable I2C. */
1.111
1.112 @@ -128,30 +210,43 @@
1.113
1.114 printf("Written: %d\n", nwritten);
1.115
1.116 - /* Issue selection of device register 0. */
1.117 + do
1.118 + {
1.119 + /* Issue selection of device register 0. */
1.120
1.121 - buf[0] = 0;
1.122 - nwritten = jz4730_i2c_write(i2c0, 0x51, buf, 1);
1.123 + buf[0] = 0;
1.124 + nwritten = jz4730_i2c_write(i2c0, 0x51, buf, 1);
1.125 +
1.126 + printf("Written: %d\n", nwritten);
1.127
1.128 - printf("Written: %d\n", nwritten);
1.129 + /* Read the contents of 16 registers. */
1.130 +
1.131 + unsigned int nread = jz4730_i2c_read(i2c0, 0x51, buf, 16);
1.132
1.133 - /* Read the contents of 16 registers. */
1.134 -
1.135 - unsigned int nread = jz4730_i2c_read(i2c0, 0x51, buf, 16);
1.136 + printf("Read: %d\n", nread);
1.137 + for (unsigned int i = 0; i < nread; i++)
1.138 + printf("%02x ", buf[i]);
1.139 + printf("\n");
1.140
1.141 - printf("Read: %d\n", nread);
1.142 - for (unsigned int i = 0; i < nread; i++)
1.143 - printf("%02x ", buf[i]);
1.144 - printf("\n");
1.145 + /* Show the interpreted date and time. */
1.146 +
1.147 + rtc_datetime(buf);
1.148
1.149 - /* Show the interpreted date and time. */
1.150 + /* Scan the bus. */
1.151 +
1.152 + printf("Scan I2C0...\n");
1.153 + i2c_scan(i2c0);
1.154
1.155 - rtc_datetime(buf);
1.156 + sleep(5);
1.157 + }
1.158 + while(1);
1.159
1.160 - /* Scan the bus. */
1.161 + /* Detach from the interrupt. */
1.162
1.163 - printf("Scan I2C0...\n");
1.164 - i2c_scan(i2c0);
1.165 + err = l4_error(l4_irq_detach(irq0cap));
1.166 +
1.167 + if (err)
1.168 + printf("Error detaching from IRQ objects: %ld\n", err);
1.169
1.170 return 0;
1.171 }