From c85f89e2b8514ed2352e6c5ba6a90b6a3c949262 Mon Sep 17 00:00:00 2001 From: Jens Maus Date: Tue, 9 Mar 2021 20:46:43 +0100 Subject: [PATCH 01/22] added eq3_char_loop package (eQ-3 char loopback kernel module) --- .../package/eq3_char_loop/Config.in | 2 + .../package/eq3_char_loop/Makefile | 1 + .../package/eq3_char_loop/eq3_char_loop.c | 996 ++++++++++++++++++ .../package/eq3_char_loop/eq3_char_loop.mk | 19 + 4 files changed, 1018 insertions(+) create mode 100644 buildroot-external/package/eq3_char_loop/Config.in create mode 100644 buildroot-external/package/eq3_char_loop/Makefile create mode 100644 buildroot-external/package/eq3_char_loop/eq3_char_loop.c create mode 100644 buildroot-external/package/eq3_char_loop/eq3_char_loop.mk diff --git a/buildroot-external/package/eq3_char_loop/Config.in b/buildroot-external/package/eq3_char_loop/Config.in new file mode 100644 index 00000000000..810133231be --- /dev/null +++ b/buildroot-external/package/eq3_char_loop/Config.in @@ -0,0 +1,2 @@ +config BR2_PACKAGE_EQ3_CHAR_LOOP + bool "Support for eq3 char loop kernel module" diff --git a/buildroot-external/package/eq3_char_loop/Makefile b/buildroot-external/package/eq3_char_loop/Makefile new file mode 100644 index 00000000000..60251373355 --- /dev/null +++ b/buildroot-external/package/eq3_char_loop/Makefile @@ -0,0 +1 @@ +obj-m += eq3_char_loop.o diff --git a/buildroot-external/package/eq3_char_loop/eq3_char_loop.c b/buildroot-external/package/eq3_char_loop/eq3_char_loop.c new file mode 100644 index 00000000000..08f562946ce --- /dev/null +++ b/buildroot-external/package/eq3_char_loop/eq3_char_loop.c @@ -0,0 +1,996 @@ +/* +* eQ-3 char loopback driver for HomeMatic / HomeMatic IP dual stack implementations +* +* Copyright (c) 2015 by eQ-3 Entwicklung GmbH +* Author: Lars Reemts, lars.reemts@finalbit.de +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +* +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define EQ3LOOP_NUMBER_OF_CHANNELS 4 +#define EQ3LOOP_DRIVER_NAME "eq3loop" + +/* Use 'L' as magic number */ +#define EQ3LOOP_IOC_MAGIC 'L' + +#define EQ3LOOP_IOCSCREATESLAVE _IOW(EQ3LOOP_IOC_MAGIC, 1, uint32_t) +#define EQ3LOOP_IOCGEVENTS _IOR(EQ3LOOP_IOC_MAGIC, 2, uint32_t) + +#define EVENT_BIT_SLAVE_OPENED 0 +#define EVENT_BIT_SLAVE_CLOSED 1 +#define STATE_BIT_SLAVE_OPENED 15 + +#define CONNECTION_TYPE_MASTER 0 +#define CONNECTION_TYPE_SLAVE 1 + +#define BUFSIZE 1024 //just use buffer size power of 2. otherwise the size and index calculation dosn't work + +#define DUMP_READWRITE 0 + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0)) + #define _access_ok(__type, __addr, __size) access_ok(__addr, __size) +#else + #define _access_ok(__type, __addr, __size) access_ok(__type, __addr, __size) +#endif + +struct eq3loop_channel_data +{ + struct circ_buf master2slave_buf; + struct circ_buf slave2master_buf; + unsigned char _master2slave_buf[BUFSIZE]; + unsigned char _slave2master_buf[BUFSIZE]; + + wait_queue_head_t master2slaveq; + wait_queue_head_t slave2masterq; + struct semaphore sem; //semaphore for accessing this struct. + volatile long unsigned int pending_events; + volatile long unsigned int slave_open_count; + volatile long unsigned int created; + dev_t devnode; + char name[32]; + struct termios termios; +}; + +struct eq3loop_control_data { + dev_t devnode; + struct cdev cdev; + struct class * class; + struct eq3loop_channel_data channels[EQ3LOOP_NUMBER_OF_CHANNELS]; + struct semaphore sem; //semaphore for accessing this struct. +}; + +struct eq3loop_connection_data +{ + int connection_type; + struct eq3loop_channel_data* channel; + ssize_t (*read) (struct eq3loop_channel_data *, struct file *, char __user *, size_t, loff_t *); + ssize_t (*write) (struct eq3loop_channel_data *, struct file *, const char __user *, size_t, loff_t *); + long (*ioctl) (struct eq3loop_channel_data *, struct file *, unsigned int cmd, unsigned long arg); + int (*close) (struct eq3loop_channel_data *, struct file *); + unsigned int (*poll) (struct eq3loop_channel_data *, struct file*, poll_table* wait); +}; + +static struct eq3loop_control_data* control_data; + +static ssize_t eq3loop_read_slave(struct eq3loop_channel_data* channel, struct file *filp, char *buf, size_t count, loff_t *offset) +{ + ssize_t ret = 0; + int count_to_end,tail; + if (down_interruptible(&channel->sem)){ + return -ERESTARTSYS; + } + + + if( !channel->created ) + { + ret = -ENODEV; + goto out; + } + while( channel->created && !CIRC_CNT( channel->master2slave_buf.head, channel->master2slave_buf.tail, BUFSIZE)) { /* nothing to read */ + up(&channel->sem); /* release the lock */ + if (filp->f_flags & O_NONBLOCK) { + return -EAGAIN; + } + if (wait_event_interruptible(channel->master2slaveq, (!channel->created) || CIRC_CNT( channel->master2slave_buf.head, channel->master2slave_buf.tail, BUFSIZE))){ + return -ERESTARTSYS; /* signal: tell the fs layer to handle it */ + } + /* otherwise loop, but first reacquire the lock */ + if (down_interruptible(&channel->sem)){ + return -ERESTARTSYS; + } + } + + if( !channel->created ) + { + ret = -ENODEV; + goto out; + } + tail = channel->master2slave_buf.tail; + /* ok, data is there, return something */ + count = min((int)count, CIRC_CNT( channel->master2slave_buf.head, tail, BUFSIZE)); + count_to_end = min((int)count,CIRC_CNT_TO_END(channel->master2slave_buf.head,tail,BUFSIZE)); + + #if DUMP_READWRITE + { + int i; + printk( KERN_INFO EQ3LOOP_DRIVER_NAME ": eq3loop_read_slave() %s:", channel->name ); + for( i=0; imaster2slave_buf.buf[(tail + i) & (BUFSIZE - 1)] ); + } + } + #endif + + + if (copy_to_user(buf, channel->master2slave_buf.buf + tail, count_to_end)) { + ret = -EFAULT; + goto out; + } + tail = (tail + count_to_end) & (BUFSIZE - 1); + + if (copy_to_user(buf + count_to_end, channel->master2slave_buf.buf + tail, count - count_to_end)) { + ret = -EFAULT; + goto out; + } + tail = (tail + (count - count_to_end)) & (BUFSIZE - 1); + smp_mb(); + channel->master2slave_buf.tail = tail; + ret = count; + +out: + up (&channel->sem); + + if( ret > 0 ) + { + wake_up_interruptible( &channel->master2slaveq ); + } + else + { + printk( KERN_ERR EQ3LOOP_DRIVER_NAME ": eq3loop_read_slave() %s: error while reading from slave", channel->name ); + } + return ret; +} + +static ssize_t eq3loop_read_master(struct eq3loop_channel_data* channel, struct file *filp, char *buf, size_t count, loff_t *offset) +{ + ssize_t ret = 0; + int count_to_end,tail; + if (down_interruptible(&channel->sem)) + return -ERESTARTSYS; + + while( channel->slave_open_count && (!CIRC_CNT( channel->slave2master_buf.head, channel->slave2master_buf.tail, BUFSIZE))) { /* slave open but nothing to read */ + up(&channel->sem); /* release the lock */ + if (filp->f_flags & O_NONBLOCK) + return -EAGAIN; + if (wait_event_interruptible(channel->slave2masterq, (!channel->slave_open_count) || CIRC_CNT( channel->slave2master_buf.head, channel->slave2master_buf.tail, BUFSIZE))) + return -ERESTARTSYS; /* signal: tell the fs layer to handle it */ + /* otherwise loop, but first reacquire the lock */ + if (down_interruptible(&channel->sem)) + return -ERESTARTSYS; + } + if( channel->slave_open_count ) + { + tail = channel->slave2master_buf.tail; + /* ok, data is there, return something */ + count = min((int)count, CIRC_CNT( channel->slave2master_buf.head, tail, BUFSIZE)); + count_to_end = min((int)count,CIRC_CNT_TO_END(channel->slave2master_buf.head, tail, BUFSIZE)); + + #if DUMP_READWRITE + { + int i; + printk( KERN_INFO EQ3LOOP_DRIVER_NAME ": eq3loop_read_master() %s:", channel->name ); + for( i=0; islave2master_buf.buf[(tail + i) & (BUFSIZE - 1)] ); + } + } + #endif + + + if (copy_to_user(buf, channel->slave2master_buf.buf + tail, count_to_end)) { + ret = -EFAULT; + goto out; + } + tail = (tail + count_to_end) & (BUFSIZE - 1); + if (copy_to_user(buf + count_to_end, channel->slave2master_buf.buf + tail, count - count_to_end)) { + ret = -EFAULT; + goto out; + } + tail = (tail + (count - count_to_end)) & (BUFSIZE - 1); + smp_mb(); + channel->slave2master_buf.tail = tail; + ret = count; + } + + +out: + up (&channel->sem); + + if( ret > 0 ) + { + wake_up_interruptible( &channel->slave2masterq ); + } + + return ret; +} + +static ssize_t eq3loop_read(struct file *filp, char *buf, size_t count, loff_t *offset) +{ + struct eq3loop_connection_data *conn = filp->private_data; + if( conn && conn->read ) + { + return conn->read( conn->channel, filp, buf, count, offset ); + } + return -EFAULT; +} + +static ssize_t eq3loop_write_slave(struct eq3loop_channel_data* channel, struct file *filp, const char *buf, size_t count, loff_t *offset) +{ + int head; + ssize_t ret=0; + ssize_t count_to_end; + if (down_interruptible(&channel->sem)) + return -ERESTARTSYS; + + while(!CIRC_SPACE( channel->slave2master_buf.head, channel->slave2master_buf.tail, BUFSIZE)) { /* no space to write */ + up(&channel->sem); /* release the lock */ + if (filp->f_flags & O_NONBLOCK) + return -EAGAIN; + if (wait_event_interruptible(channel->slave2masterq, (!channel->created) || CIRC_SPACE( channel->slave2master_buf.head, channel->slave2master_buf.tail, BUFSIZE))) + return -ERESTARTSYS; /* signal: tell the fs layer to handle it */ + /* otherwise loop, but first reacquire the lock */ + if (down_interruptible(&channel->sem)) + return -ERESTARTSYS; + } + + if( !channel->created ) + { + ret = -ENODEV; + goto out; + } + head = channel->slave2master_buf.head; + if(CIRC_SPACE( head, channel->slave2master_buf.tail, BUFSIZE) < count) + { + ret=-EFAULT; + goto out; + } + + /* ok, space is free, write something */ + count_to_end = min((int)count, CIRC_SPACE_TO_END( head, channel->slave2master_buf.tail, BUFSIZE)); + + if(copy_from_user(channel->slave2master_buf.buf + head, buf, count_to_end)){ + ret=-EFAULT; + goto out; + } + head = (head + count_to_end) & (BUFSIZE - 1); + + if(copy_from_user(channel->slave2master_buf.buf + head, buf+count_to_end, count - count_to_end)){ + ret=-EFAULT; + goto out; + } + head = (head + (count - count_to_end)) & (BUFSIZE - 1); + #if DUMP_READWRITE + { + int i; + if(head < channel->slave2master_buf.head) + { + printk( KERN_INFO EQ3LOOP_DRIVER_NAME ": eq3loop_write_slave() reach end of circular buffer" ); + } + printk( KERN_INFO EQ3LOOP_DRIVER_NAME ": eq3loop_write_slave() %s:", channel->name ); + for( i=0; islave2master_buf.buf[(channel->slave2master_buf.head + i)& (BUFSIZE - 1)] ); + } + } + #endif + + + smp_mb(); + channel->slave2master_buf.head = head; + + ret = count; + +out: + up (&channel->sem); + + if( ret > 0 ) + { + wake_up_interruptible( &channel->slave2masterq ); + } + + return ret; +} + +static ssize_t eq3loop_write_master(struct eq3loop_channel_data* channel, struct file *filp, const char *buf, size_t count, loff_t *offset) +{ + ssize_t ret=0; + int head; + ssize_t count_to_end; + if (down_interruptible(&channel->sem)) + return -ERESTARTSYS; + + while(!CIRC_SPACE( channel->master2slave_buf.head, channel->master2slave_buf.tail, BUFSIZE)) { /* no space to write */ + up(&channel->sem); /* release the lock */ + if (filp->f_flags & O_NONBLOCK) + return -EAGAIN; + if (wait_event_interruptible(channel->master2slaveq, (!channel->slave_open_count) || CIRC_SPACE( channel->master2slave_buf.head, channel->master2slave_buf.tail, BUFSIZE))) + return -ERESTARTSYS; /* signal: tell the fs layer to handle it */ + /* otherwise loop, but first reacquire the lock */ + if (down_interruptible(&channel->sem)) + return -ERESTARTSYS; + } + head = channel->master2slave_buf.head; + if(CIRC_SPACE( head, channel->master2slave_buf.tail, BUFSIZE) < count) + { + ret=-EFAULT; + count_to_end = CIRC_SPACE( head, channel->master2slave_buf.tail, BUFSIZE); + printk( KERN_ERR EQ3LOOP_DRIVER_NAME ": eq3loop_write_master() %s: not enough space in buffers. free space = %zu, required space = %zu", channel->name,count_to_end,count ); + goto out; + } + /* ok, space is free, write something */ + count_to_end = min((int)count, CIRC_SPACE_TO_END( head, channel->master2slave_buf.tail, BUFSIZE)); + + if(copy_from_user(channel->master2slave_buf.buf + head, buf, count_to_end)){ + ret=-EFAULT; + printk( KERN_ERR EQ3LOOP_DRIVER_NAME ": eq3loop_write_master() %s: unable to copy buffer",channel->name ); + goto out; + } + head = (head + count_to_end) & (BUFSIZE - 1); + if(copy_from_user(channel->master2slave_buf.buf + head, buf+count_to_end,count - count_to_end)){ + ret=-EFAULT; + printk( KERN_ERR EQ3LOOP_DRIVER_NAME ": eq3loop_write_master() %s: unable to copy buffer",channel->name ); + goto out; + } + head = (head + (count - count_to_end)) & (BUFSIZE - 1); + #if DUMP_READWRITE + { + int i; + printk( KERN_INFO EQ3LOOP_DRIVER_NAME ": eq3loop_write_master() %s:", channel->name ); + for( i=0; imaster2slave_buf.buf[(channel->master2slave_buf.head + i)&(BUFSIZE - 1)] ); + } + } + #endif + smp_mb(); + channel->master2slave_buf.head = head; + ret = count; + +out: + up (&channel->sem); + if(ret < 0) + { + printk( KERN_INFO EQ3LOOP_DRIVER_NAME ": eq3loop_write_master() return error: %d", ret); + } + if( ret > 0 || CIRC_CNT(channel->master2slave_buf.head,channel->master2slave_buf.tail,BUFSIZE) ) + { + //send a signal to reading procces if return is ok or data in the buffer + wake_up_interruptible( &channel->master2slaveq ); + } + + return ret; +} + +static ssize_t eq3loop_write(struct file *filp, const char *buf, size_t count, loff_t *offset) +{ + struct eq3loop_connection_data *conn = filp->private_data; + if( conn && conn->write ) + { + return conn->write( conn->channel, filp, buf, count, offset ); + } + return -EFAULT; +} + +static long eq3loop_create_slave_dev( struct file *filp, const char* name ); + +static long eq3loop_ioctl_ctrl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + char buffer[64]; + long ret = 0; + + /* + * extract the type and number bitfields, and don't decode + * wrong cmds: return ENOTTY (inappropriate ioctl) before access_ok() + */ + if (_IOC_TYPE(cmd) != EQ3LOOP_IOC_MAGIC) return -ENOTTY; + + + switch(cmd) { + + case EQ3LOOP_IOCSCREATESLAVE: + ret = strncpy_from_user( buffer, (char*)arg, sizeof(buffer) ); + if( ret <= 0 ) + { + return -EFAULT; + } + return eq3loop_create_slave_dev( filp, buffer ); + default: + return -ENOTTY; + } +} + +static long eq3loop_ioctl_master(struct eq3loop_channel_data* channel, struct file *filp, unsigned int cmd, unsigned long arg) +{ + long ret = 0; + unsigned long temp = 0; + + /* + * extract the type and number bitfields, and don't decode + * wrong cmds: return ENOTTY (inappropriate ioctl) before access_ok() + */ + if (_IOC_TYPE(cmd) != EQ3LOOP_IOC_MAGIC) return -ENOTTY; + + /* + * the direction is a bitmask, and VERIFY_WRITE catches R/W + * transfers. `Type' is user-oriented, while + * access_ok is kernel-oriented, so the concept of "read" and + * "write" is reversed + */ + if (_IOC_DIR(cmd) & _IOC_READ) + ret = !_access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd)); + else if (_IOC_DIR(cmd) & _IOC_WRITE) + ret = !_access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd)); + if (ret) return -EFAULT; + + switch(cmd) { + + case EQ3LOOP_IOCGEVENTS: + if( test_and_clear_bit( EVENT_BIT_SLAVE_OPENED, &channel->pending_events ) ) + { + temp |= (1<pending_events ) ) + { + temp |= (1<pending_events ) ) + { + temp |= (1<pending_events = temp; + smp_mb(); + } + break; + default: + return -ENOTTY; + } + return ret; +} + +static long eq3loop_ioctl_slave(struct eq3loop_channel_data* channel, struct file *filp, unsigned int cmd, unsigned long arg) +{ + long ret = 0; + int temp; + + if (down_interruptible(&channel->sem)) + return -ERESTARTSYS; + + switch(cmd) { + + case TCGETS: + if( _access_ok(VERIFY_READ, (void *)arg, sizeof(struct termios) ) ) + { + ret = copy_to_user( (void*)arg, &channel->termios, sizeof(struct termios) ); + } else { + ret = -EFAULT; + } + break; + case TCSETS: + if( _access_ok(VERIFY_WRITE, (void *)arg, sizeof(struct termios) ) ) + { + ret = copy_from_user( &channel->termios, (void*)arg, sizeof(struct termios) ); + } else { + ret = -EFAULT; + } + break; + case TIOCINQ: + temp = CIRC_CNT( channel->master2slave_buf.head, channel->master2slave_buf.tail, BUFSIZE); + ret = __put_user( temp, (int*)arg ); + break; + case TIOCOUTQ: + temp = CIRC_CNT( channel->slave2master_buf.head, channel->slave2master_buf.tail, BUFSIZE); + ret = __put_user( temp, (int*)arg ); + break; + case TIOCEXCL: + break; + case TCFLSH: + break; + case TIOCMGET: + temp = TIOCM_DSR | TIOCM_CD | TIOCM_CTS; + ret = __put_user( temp, (int*)arg ); + break; + case TIOCMSET: + break; + case TIOCSERGETLSR: + ret = -ENOIOCTLCMD; + break; + case TIOCGICOUNT: + ret = -ENOIOCTLCMD; + break; + default: + ret = -ENOTTY; + break; + } + up (&channel->sem ); + if( ret == -ENOTTY ) + { + printk( KERN_NOTICE EQ3LOOP_DRIVER_NAME ": eq3loop_ioctl_slave() %s: unhandled ioctl 0x%04X\n", channel->name, cmd ); + ret = -ENOIOCTLCMD; + } + return ret; +} + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11)) +static int eq3loop_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) +#else +static long eq3loop_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +#endif +{ + struct eq3loop_connection_data *conn = filp->private_data; + if( !conn ) + { + return eq3loop_ioctl_ctrl( filp, cmd, arg ); + } + if( conn->ioctl ) + { + return conn->ioctl( conn->channel, filp, cmd, arg ); + } + + return -EFAULT; +} + + +static int eq3loop_close_slave(struct eq3loop_channel_data* channel, struct file *filp) +{ + int ret = 0; + + printk( KERN_INFO EQ3LOOP_DRIVER_NAME ": eq3loop_close_slave() %s\n", channel->name ); + + if (down_interruptible(&channel->sem)) + return -ERESTARTSYS; + + if( channel->slave_open_count ) + { + channel->slave_open_count--; + } + + kfree( filp->private_data ); + + set_bit( EVENT_BIT_SLAVE_CLOSED, &channel->pending_events ); + clear_bit( STATE_BIT_SLAVE_OPENED, &channel->pending_events ); + + if( !channel->created ) + { + printk( KERN_INFO EQ3LOOP_DRIVER_NAME ": eq3loop_close_slave() %s destroy device\n", channel->name ); + device_destroy(control_data->class, channel->devnode); + } + + up( &channel->sem ); + smp_mb(); + wake_up_interruptible( &channel->slave2masterq ); + return ret; +} + +static int eq3loop_close_master(struct eq3loop_channel_data* channel, struct file *filp) +{ + int ret = 0; + + printk( KERN_INFO EQ3LOOP_DRIVER_NAME ": eq3loop_close_master() %s\n", channel->name ); + + if (down_interruptible(&channel->sem)) + return -ERESTARTSYS; + + if (down_interruptible(&control_data->sem)) + { + ret = -ERESTARTSYS; + goto out; + } + + channel->created = 0; + + up( &control_data->sem ); + + kfree( filp->private_data ); + + if( !channel->slave_open_count ) + { + printk( KERN_INFO EQ3LOOP_DRIVER_NAME ": eq3loop_close_master() %s destroy device\n", channel->name ); + device_destroy(control_data->class, channel->devnode); + } + +out: + up( &channel->sem ); + wake_up_interruptible( &channel->master2slaveq ); + return ret; +} + +static int eq3loop_close(struct inode *inode, struct file *filp) +{ + struct eq3loop_connection_data *conn = filp->private_data; + if( !conn ) + { + return 0; + } + if( conn->close ) + { + return conn->close( conn->channel, filp ); + } + + return -ENODEV; +} + +static unsigned int eq3loop_poll_master(struct eq3loop_channel_data* channel, struct file* filp, poll_table* wait) +{ + unsigned int mask=0; + unsigned long requested_events = poll_requested_events( wait ); + + //printk( KERN_INFO EQ3LOOP_DRIVER_NAME ": eq3loop_poll_master() %s requested=0x%lX\n", channel->name, requested_events ); + + if( requested_events & ( POLLIN | POLLPRI | POLLERR ) ) + { + poll_wait(filp, &channel->slave2masterq, wait); + } + if( requested_events & POLLOUT ) + { + poll_wait(filp, &channel->master2slaveq, wait); + } + + if (down_interruptible(&channel->sem)) + return -ERESTARTSYS; + + if( channel->slave_open_count ) + { + if( CIRC_SPACE( channel->master2slave_buf.head, channel->master2slave_buf.tail, BUFSIZE) ) + { + mask |= POLLOUT | POLLWRNORM; + } + + if( CIRC_CNT( channel->slave2master_buf.head, channel->slave2master_buf.tail, BUFSIZE) ) + { + mask |= POLLIN | POLLRDNORM; + } + } + + if( test_bit( EVENT_BIT_SLAVE_OPENED, &channel->pending_events ) || test_bit( EVENT_BIT_SLAVE_CLOSED, &channel->pending_events ) ) + { + mask |= POLLPRI; + } + + + + up( &channel->sem ); + + return mask; +} + +static unsigned int eq3loop_poll_slave(struct eq3loop_channel_data* channel, struct file* filp, poll_table* wait) +{ + unsigned int mask=0; + unsigned long requested_events = poll_requested_events( wait ); + + if( requested_events & POLLIN ) + { + poll_wait(filp, &channel->master2slaveq, wait); + } + if( requested_events & POLLOUT ) + { + poll_wait(filp, &channel->slave2masterq, wait); + } + + if (down_interruptible(&channel->sem)) + return -ERESTARTSYS; + + if( CIRC_CNT( channel->master2slave_buf.head, channel->master2slave_buf.tail, BUFSIZE) ) + { + mask |= POLLIN | POLLRDNORM; + } + + if( CIRC_SPACE( channel->slave2master_buf.head, channel->slave2master_buf.tail, BUFSIZE) ) + { + mask |= POLLOUT | POLLWRNORM; + } + + if( !channel->created ) + { + mask |= POLLERR; + } + + up( &channel->sem ); + + return mask; +} + +static unsigned int eq3loop_poll(struct file* filp, poll_table* wait) +{ + struct eq3loop_connection_data *conn = filp->private_data; + if( !conn ) + { + return -EINVAL; + } + if( conn->poll ) + { + return conn->poll( conn->channel, filp, wait ); + } + + return -EINVAL; +} + + +static long eq3loop_create_slave_dev( struct file *filp, const char* name ) +{ + int channel_index = 0; + long ret = 0; + struct eq3loop_channel_data* channel; + struct eq3loop_connection_data* conn; + + if (down_interruptible(&control_data->sem)) + return -ERESTARTSYS; + + while( (channel_index < EQ3LOOP_NUMBER_OF_CHANNELS) && (control_data->channels[channel_index].created) ) + { + channel_index++; + } + if( channel_index >= EQ3LOOP_NUMBER_OF_CHANNELS ) + { + ret = -EINVAL; + goto out; + } + + channel = control_data->channels + channel_index; + memset( channel, 0, sizeof( struct eq3loop_channel_data ) ); + channel->devnode = MKDEV(MAJOR(control_data->devnode), MINOR(control_data->devnode) + channel_index + 1); + strncpy( channel->name, name, sizeof(channel->name)-1 ); + + if( !device_create(control_data->class, NULL, channel->devnode, "%s", name) ) + { + ret = -EBUSY; + goto out; + } + + printk( KERN_INFO EQ3LOOP_DRIVER_NAME ": created slave %s\n", name ); + + conn = kzalloc( sizeof(struct eq3loop_connection_data), GFP_KERNEL ); + if( !conn ) + { + ret = -ENOMEM; + goto out; + } + + sema_init(&channel->sem, 1); + init_waitqueue_head(&channel->master2slaveq); + init_waitqueue_head(&channel->slave2masterq); + + + channel->master2slave_buf.buf = channel->_master2slave_buf; + channel->slave2master_buf.buf = channel->_slave2master_buf; + + smp_mb(); + + channel->created = 1; + + +out: + up(&control_data->sem); + + if( !ret ) + { + conn->connection_type = CONNECTION_TYPE_MASTER; + conn->channel = channel; + conn->read = eq3loop_read_master; + conn->write = eq3loop_write_master; + conn->ioctl = eq3loop_ioctl_master; + conn->close = eq3loop_close_master; + conn->poll = eq3loop_poll_master; + filp->private_data = conn; + } + return ret; +} + +static int eq3loop_open_ctrl(struct file *filp) +{ + return 0; +} + +static int eq3loop_open_slave(struct eq3loop_channel_data* channel, struct file *filp) +{ + int ret = 0; + struct eq3loop_connection_data* conn; + + printk( KERN_INFO EQ3LOOP_DRIVER_NAME ": eq3loop_open_slave() %s\n", channel->name ); + + if (down_interruptible(&channel->sem)) + return -ERESTARTSYS; + + if( !channel->created ) + { + ret = -ENODEV; + goto out; + } + + if( channel->slave_open_count ) + { + ret = -EBUSY; + goto out; + } + + conn = kzalloc( sizeof(struct eq3loop_connection_data), GFP_KERNEL ); + if( !conn ) + { + ret = -ENOMEM; + goto out; + } + + channel->slave_open_count++; + + set_bit( EVENT_BIT_SLAVE_OPENED, &channel->pending_events ); + set_bit( STATE_BIT_SLAVE_OPENED, &channel->pending_events ); + + channel->master2slave_buf.head = 0; + channel->master2slave_buf.tail = 0; + + smp_mb(); + +out: + up( &channel->sem ); + + if( !ret ) + { + conn->connection_type = CONNECTION_TYPE_SLAVE; + conn->channel = channel; + conn->read = eq3loop_read_slave; + conn->write = eq3loop_write_slave; + conn->ioctl = eq3loop_ioctl_slave; + conn->close = eq3loop_close_slave; + conn->poll = eq3loop_poll_slave; + filp->private_data = conn; + wake_up_interruptible( &channel->slave2masterq ); + } + return ret; +} + + +static int eq3loop_open(struct inode *inode, struct file *filp) +{ + if( !control_data ) + { + return -ENODEV; + } + + if( inode->i_rdev == MKDEV(MAJOR(control_data->devnode), MINOR(control_data->devnode)) ) + { + return eq3loop_open_ctrl( filp ); + }else{ + unsigned int channel_index = MINOR( inode->i_rdev ) - MINOR(control_data->devnode) - 1; + if( channel_index >= EQ3LOOP_NUMBER_OF_CHANNELS ) + { + return -ENODEV; + } + return eq3loop_open_slave( &control_data->channels[channel_index], filp ); + } + + return -ENODEV; +} + +static struct file_operations eq3loop_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .read = eq3loop_read, + .write = eq3loop_write, + .open = eq3loop_open, + .release = eq3loop_close, + .poll = eq3loop_poll, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11)) + .ioctl = eq3loop_ioctl, +#else + .unlocked_ioctl = eq3loop_ioctl, + .compat_ioctl = eq3loop_ioctl, +#endif +}; + +static int __init eq3loop_init(void) +{ + int ret = 0; + + control_data = kzalloc(sizeof(struct eq3loop_control_data), GFP_KERNEL); + if (!control_data) { + ret = -ENOMEM; + goto out; + } + + ret = alloc_chrdev_region(&control_data->devnode, 0, EQ3LOOP_NUMBER_OF_CHANNELS + 1, EQ3LOOP_DRIVER_NAME); + if( ret ) + { + printk(KERN_ERR EQ3LOOP_DRIVER_NAME ": Unable to get device number region\n"); + goto out_free; + } + + cdev_init(&control_data->cdev, &eq3loop_fops); + control_data->cdev.owner=THIS_MODULE; + control_data->cdev.ops=&eq3loop_fops; + ret=cdev_add(&control_data->cdev, control_data->devnode, EQ3LOOP_NUMBER_OF_CHANNELS + 1); + if(ret){ + printk(KERN_ERR EQ3LOOP_DRIVER_NAME ": Unable to add driver\n"); + goto out_unregister_chrdev_region; + } + control_data->class=class_create(THIS_MODULE, EQ3LOOP_DRIVER_NAME); + if(IS_ERR(control_data->class)){ + ret = -EIO; + printk(KERN_ERR EQ3LOOP_DRIVER_NAME ": Unable to register driver class\n"); + goto out_cdev_del; + } + + sema_init(&control_data->sem, 1); + + device_create(control_data->class, NULL, MKDEV(MAJOR(control_data->devnode), MINOR(control_data->devnode)), "%s", EQ3LOOP_DRIVER_NAME); + + goto out; + + out_cdev_del: + cdev_del(&control_data->cdev); + + out_unregister_chrdev_region: + unregister_chrdev_region(control_data->devnode, EQ3LOOP_NUMBER_OF_CHANNELS + 1); + + out_free: + kfree(control_data); +out: + return ret; +} + +static void __exit eq3loop_exit(void) +{ + + unregister_chrdev_region(control_data->devnode, EQ3LOOP_NUMBER_OF_CHANNELS + 1); + device_destroy(control_data->class, MKDEV(MAJOR(control_data->devnode), MINOR(control_data->devnode))); + class_destroy(control_data->class); + cdev_del(&control_data->cdev); + + kfree(control_data); + + control_data = NULL; + +} + +module_init(eq3loop_init); +module_exit(eq3loop_exit); +MODULE_DESCRIPTION("eQ-3 IPC loopback char driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION("1.1"); diff --git a/buildroot-external/package/eq3_char_loop/eq3_char_loop.mk b/buildroot-external/package/eq3_char_loop/eq3_char_loop.mk new file mode 100644 index 00000000000..c5c67f2a695 --- /dev/null +++ b/buildroot-external/package/eq3_char_loop/eq3_char_loop.mk @@ -0,0 +1,19 @@ +############################################################# +# +# eQ-3 char loopback kernel module for HomeMatic/homematicIP +# dual stack implementations for the RPI-RF-MOD/HM-MOD-RPI-PCB +# +# Copyright (c) 2015 by eQ-3 Entwicklung GmbH +# https://github.com/eq-3/occu/tree/master/KernelDrivers +# +############################################################# + +EQ3_CHAR_LOOP_VERSION = 1.1.0 +EQ3_CHAR_LOOP_SITE = $(BR2_EXTERNAL_HASSOS_PATH)/package/eq3_char_loop +EQ3_CHAR_LOOP_SITE_METHOD = local +EQ3_CHAR_LOOP_LICENSE = GPL2 +#EQ3_CHAR_LOOP_LICENSE_FILES = LICENSE +EQ3_CHAR_LOOP_MODULE_SUBDIRS = . + +$(eval $(kernel-module)) +$(eval $(generic-package)) From 7c74c7bb92a1bf2a2223dc9c0452bd0f88b5c3ab Mon Sep 17 00:00:00 2001 From: Jens Maus Date: Tue, 9 Mar 2021 20:48:08 +0100 Subject: [PATCH 02/22] added rpi-rf-mod package (device tree overlay support for RPI-RF-MOD/HM-MOD-RPI-PCB) --- .../package/rpi-rf-mod/Config.in | 3 + .../rpi-rf-mod/dts/rpi-rf-mod-tinker.dts | 104 ++++++++++++++++++ .../package/rpi-rf-mod/dts/rpi-rf-mod.dts | 74 +++++++++++++ .../package/rpi-rf-mod/rpi-rf-mod.mk | 39 +++++++ 4 files changed, 220 insertions(+) create mode 100644 buildroot-external/package/rpi-rf-mod/Config.in create mode 100644 buildroot-external/package/rpi-rf-mod/dts/rpi-rf-mod-tinker.dts create mode 100644 buildroot-external/package/rpi-rf-mod/dts/rpi-rf-mod.dts create mode 100644 buildroot-external/package/rpi-rf-mod/rpi-rf-mod.mk diff --git a/buildroot-external/package/rpi-rf-mod/Config.in b/buildroot-external/package/rpi-rf-mod/Config.in new file mode 100644 index 00000000000..e4a6356b847 --- /dev/null +++ b/buildroot-external/package/rpi-rf-mod/Config.in @@ -0,0 +1,3 @@ +config BR2_PACKAGE_RPI_RF_MOD + select BR2_PACKAGE_RX8130_RTC + bool "Support for RPI-RF-MOD/HM-MOD-RPI-PCB GPIO HAT" diff --git a/buildroot-external/package/rpi-rf-mod/dts/rpi-rf-mod-tinker.dts b/buildroot-external/package/rpi-rf-mod/dts/rpi-rf-mod-tinker.dts new file mode 100644 index 00000000000..ff7412c5afe --- /dev/null +++ b/buildroot-external/package/rpi-rf-mod/dts/rpi-rf-mod-tinker.dts @@ -0,0 +1,104 @@ +/dts-v1/; +/plugin/; + +/* +** Device Tree Overlay for eQ-3 RPI-RF-MOD and +** HM-MOD-RPI-PCB for ASUS Tinkerboard +** +** Copyright (c) 2019-2020 Jens Maus +** Licensed under Apache 2.0 +** +*/ + +/ { + compatible = "asus,rk3288-tinker", "rockchip,rk3288"; + + // fragment to ensure we have the correct gpio pin + // setup for the RPI-RF-MOD and HM-MOD-RPI-PCB + fragment@0 { + target = <&pinctrl>; + __overlay__ { + rpi_rf_mod { + rpi_rf_mod_pins: rpi-rf-mod-pins { + rockchip,pins = <6 1 0 &pcfg_pull_none>, // GPIO6A1: reset + <7 23 0 &pcfg_pull_up>, // GPIO7C7: button + <7 7 0 &pcfg_output_low>, // GPIO7A7: red LED + <6 3 0 &pcfg_output_low>, // GPIO6A3: green LED + <6 4 0 &pcfg_output_low>; // GPIO6A4: blue LED + }; + }; + hm_mod_rpi_pcb { + hm_mod_rpi_pcb_pins: hm-mod-rpi-pcb-pins { + rockchip,pins = <6 0 0 &pcfg_pull_none>; // GPIO6A0: reset + }; + }; + }; + }; + + // fragment to define dedicated led nodes for + // each separate led supported by the RPI-RF-MOD + fragment@1 { + target-path = "/gpio-leds"; + __overlay__ { + pinctrl-names = "default"; + pinctrl-0 = <&rpi_rf_mod_pins>, <&hm_mod_rpi_pcb_pins>; + rpi-rf-mod-red { + label = "rpi_rf_mod:red"; + gpios = <&gpio7 7 0>; + default-state = "keep"; + linux,default-trigger = "none"; + }; + rpi-rf-mod-green { + label = "rpi_rf_mod:green"; + gpios = <&gpio6 3 0>; + default-state = "keep"; + linux,default-trigger = "none"; + }; + rpi-rf-mod-blue { + label = "rpi_rf_mod:blue"; + gpios = <&gpio6 4 0>; + default-state = "keep"; + linux,default-trigger = "none"; + }; + }; + }; + + // fragment to define settings for the rx8130 RTC clock + // of the RPI-RF-MOD + fragment@2 { + target = <&i2c1>; + __overlay__ { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + rx8130@32 { + compatible = "epson,rx8130-legacy"; + reg = <0x32>; + status = "okay"; + enable-external-capacitor; + }; + }; + }; + + // we have to disable uart2,uart3,i2s on the Tinkerboard or + // otherwise the gpio-leds cannot use the pins for the RPI-RF-MOD + fragment@3 { + target = <&uart2>; + __overlay__ { + status = "disabled"; + }; + }; + fragment@4 { + target = <&uart3>; + __overlay__ { + status = "disabled"; + }; + }; + fragment@5 { + target = <&i2s>; + __overlay__ { + status = "disabled"; + }; + }; +}; diff --git a/buildroot-external/package/rpi-rf-mod/dts/rpi-rf-mod.dts b/buildroot-external/package/rpi-rf-mod/dts/rpi-rf-mod.dts new file mode 100644 index 00000000000..0f3324740c0 --- /dev/null +++ b/buildroot-external/package/rpi-rf-mod/dts/rpi-rf-mod.dts @@ -0,0 +1,74 @@ +/dts-v1/; +/plugin/; + +/* +** Device Tree Overlay for eQ-3 RPI-RF-MOD and +** HM-MOD-RPI-PCB for RaspberryPi +** +** Copyright (c) 2018-2019 Jens Maus +** Licensed under Apache 2.0 +** +*/ + +/ { + compatible = "brcm,bcm2708"; + + // fragment to ensure we have the correct gpio pin + // setup for the RPI-RF-MOD + fragment@0 { + target = <&gpio>; + __overlay__ { + rpi_rf_mod_pins: rpi_rf_mod_pins { + brcm,pins = <19 18 12 16 20 21>; // 19=reset, 18=reset (HM-MOD), 12=button, 16=red, 20=green, 21=blue + brcm,pull = <0 0 2 0 0 0>; // 19,18=no-pullup, 12=pullup, 16,20,21=no-pullup + brcm,function = <0 0 0 1 1 1>; // 19,18,12=input, 16,20,21=output + }; + }; + }; + + // fragment to define dedicated led nodes for + // each separate led supported by the RPI-RF-MOD + fragment@1 { + target = <&leds>; + __overlay__ { + pinctrl-names = "default"; + pinctrl-0 = <&rpi_rf_mod_pins>; + rpi_rf_mod_red: rpi_rf_mod_red { + label = "rpi_rf_mod:red"; + gpios = <&gpio 16 0>; + default-state = "keep"; + linux,default-trigger = "none"; + }; + rpi_rf_mod_green: rpi_rf_mod_green { + label = "rpi_rf_mod:green"; + gpios = <&gpio 20 0>; + default-state = "keep"; + linux,default-trigger = "none"; + }; + rpi_rf_mod_blue: rpi_rf_mod_blue { + label = "rpi_rf_mod:blue"; + gpios = <&gpio 21 0>; + default-state = "keep"; + linux,default-trigger = "none"; + }; + }; + }; + + // fragment to define settings for the rx8130 RTC clock + // of the RPI-RF-MOD + fragment@2 { + target = <&i2c1>; + __overlay__ { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + rx8130@32 { + compatible = "epson,rx8130-legacy"; + reg = <0x32>; + status = "okay"; + enable-external-capacitor; + }; + }; + }; +}; diff --git a/buildroot-external/package/rpi-rf-mod/rpi-rf-mod.mk b/buildroot-external/package/rpi-rf-mod/rpi-rf-mod.mk new file mode 100644 index 00000000000..f52e5e09188 --- /dev/null +++ b/buildroot-external/package/rpi-rf-mod/rpi-rf-mod.mk @@ -0,0 +1,39 @@ +############################################################# +# +# Device tree overlay support for RPI-RF-MOD/HM-MOD-RPI-PCB +# rf modules for HomeMatic/homematicIP connectivity. +# +# Copyright (c) 2018-2021 Jens Maus +# https://github.com/jens-maus/RaspberryMatic/tree/master/buildroot-external/package/rpi-rf-mod +# +############################################################# + +RPI_RF_MOD_VERSION = 1.4.0 +RPI_RF_MOD_SITE = $(BR2_EXTERNAL_HASSOS_PATH)/package/rpi-rf-mod +RPI_RF_MOD_SITE_METHOD = local +RPI_RF_MOD_LICENSE = Apache-2.0 +#RPI_RF_MOD_LICENSE_FILES = LICENSE + +# RaspberryPi DTS file +ifneq (,$(findstring raspberrypi,$(BR2_PACKAGE_HASSIO_MACHINE))) + RPI_RF_MOD_DTS_FILE = rpi-rf-mod +endif + +# Tinkerboard DTS file +ifneq (,$(findstring tinker,$(BR2_PACKAGE_HASSIO_MACHINE))) + RPI_RF_MOD_DTS_FILE = rpi-rf-mod-tinker +endif + +define RPI_RF_MOD_BUILD_CMDS + if [[ -n "$(RPI_RF_MOD_DTS_FILE)" ]]; then \ + $(HOST_DIR)/bin/dtc -@ -I dts -O dtb -W no-unit_address_vs_reg -o $(@D)/dts/$(RPI_RF_MOD_DTS_FILE).dtbo $(@D)/dts/$(RPI_RF_MOD_DTS_FILE).dts; \ + fi +endef + +define RPI_RF_MOD_INSTALL_TARGET_CMDS + if [[ -n "$(RPI_RF_MOD_DTS_FILE)" ]]; then \ + $(INSTALL) -D -m 0644 $(@D)/dts/$(RPI_RF_MOD_DTS_FILE).dtbo $(BINARIES_DIR)/; \ + fi +endef + +$(eval $(generic-package)) From dab79237c246a5d5ca7cf635d0b66a450fae469a Mon Sep 17 00:00:00 2001 From: Jens Maus Date: Tue, 9 Mar 2021 20:49:40 +0100 Subject: [PATCH 03/22] added rx8130-rtc package (kernel module for RX-8130 RTC of RPI-RF-MOD) --- .../package/rx8130-rtc/Config.in | 2 + .../kernel-modules/rtc_rx8130ce/Makefile | 7 + .../kernel-modules/rtc_rx8130ce/rtc-rx8130.c | 856 ++++++++++++++++++ .../package/rx8130-rtc/rx8130-rtc.mk | 18 + 4 files changed, 883 insertions(+) create mode 100644 buildroot-external/package/rx8130-rtc/Config.in create mode 100755 buildroot-external/package/rx8130-rtc/kernel-modules/rtc_rx8130ce/Makefile create mode 100644 buildroot-external/package/rx8130-rtc/kernel-modules/rtc_rx8130ce/rtc-rx8130.c create mode 100644 buildroot-external/package/rx8130-rtc/rx8130-rtc.mk diff --git a/buildroot-external/package/rx8130-rtc/Config.in b/buildroot-external/package/rx8130-rtc/Config.in new file mode 100644 index 00000000000..bc6430bd47c --- /dev/null +++ b/buildroot-external/package/rx8130-rtc/Config.in @@ -0,0 +1,2 @@ +config BR2_PACKAGE_RX8130_RTC + bool "Support for Epson RX8130CE real time clock" diff --git a/buildroot-external/package/rx8130-rtc/kernel-modules/rtc_rx8130ce/Makefile b/buildroot-external/package/rx8130-rtc/kernel-modules/rtc_rx8130ce/Makefile new file mode 100755 index 00000000000..0a5cd567d1f --- /dev/null +++ b/buildroot-external/package/rx8130-rtc/kernel-modules/rtc_rx8130ce/Makefile @@ -0,0 +1,7 @@ +obj-m += rtc-rx8130.o + +all: + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules + +clean: + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean diff --git a/buildroot-external/package/rx8130-rtc/kernel-modules/rtc_rx8130ce/rtc-rx8130.c b/buildroot-external/package/rx8130-rtc/kernel-modules/rtc_rx8130ce/rtc-rx8130.c new file mode 100644 index 00000000000..bdb8796f0c6 --- /dev/null +++ b/buildroot-external/package/rx8130-rtc/kernel-modules/rtc_rx8130ce/rtc-rx8130.c @@ -0,0 +1,856 @@ +//====================================================================== +// Driver for the Epson RTC module RX-8130 CE +// +// Copyright(C) SEIKO EPSON CORPORATION 2014. All rights reserved. +// +// Derived from RX-8025 driver: +// Copyright (C) 2009 Wolfgang Grandegger +// +// Copyright (C) 2005 by Digi International Inc. +// All rights reserved. +// +// Modified by fengjh at rising.com.cn +// +// 2006.11 +// +// Code cleanup by Sergei Poselenov, +// Converted to new style by Wolfgang Grandegger +// Alarm and periodic interrupt added by Dmitry Rakhchev +// Support to enable Capacitor loading using device tree added by Alexander Reinert +// +// +// This driver software is distributed as is, without any warranty of any kind, +// either express or implied as further specified in the GNU Public License. This +// software may be used and distributed according to the terms of the GNU Public +// License, version 2 as published by the Free Software Foundation. +// See the file COPYING in the main directory of this archive for more details. +// +// You should have received a copy of the GNU General Public License along with +// this program. If not, see . +//====================================================================== + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +// RX-8130 Register definitions +#define RX8130_REG_SEC 0x10 +#define RX8130_REG_MIN 0x11 +#define RX8130_REG_HOUR 0x12 +#define RX8130_REG_WDAY 0x13 +#define RX8130_REG_MDAY 0x14 +#define RX8130_REG_MONTH 0x15 +#define RX8130_REG_YEAR 0x16 + +#define RX8130_REG_ALMIN 0x17 +#define RX8130_REG_ALHOUR 0x18 +#define RX8130_REG_ALWDAY 0x19 +#define RX8130_REG_TCOUNT0 0x1A +#define RX8130_REG_TCOUNT1 0x1B +#define RX8130_REG_EXT 0x1C +#define RX8130_REG_FLAG 0x1D +#define RX8130_REG_CTRL0 0x1E +#define RX8130_REG_CTRL1 0x1F + +#define RX8130_REG_END 0x23 + +// Extension Register (1Ch) bit positions +#define RX8130_BIT_EXT_TSEL (7 << 0) +#define RX8130_BIT_EXT_WADA (1 << 3) +#define RX8130_BIT_EXT_TE (1 << 4) +#define RX8130_BIT_EXT_USEL (1 << 5) +#define RX8130_BIT_EXT_FSEL (3 << 6) + +// Flag Register (1Dh) bit positions +#define RX8130_BIT_FLAG_VLF (1 << 1) +#define RX8130_BIT_FLAG_AF (1 << 3) +#define RX8130_BIT_FLAG_TF (1 << 4) +#define RX8130_BIT_FLAG_UF (1 << 5) + +// Control 0 Register (1Еh) bit positions +#define RX8130_BIT_CTRL_TSTP (1 << 2) +#define RX8130_BIT_CTRL_AIE (1 << 3) +#define RX8130_BIT_CTRL_TIE (1 << 4) +#define RX8130_BIT_CTRL_UIE (1 << 5) +#define RX8130_BIT_CTRL_STOP (1 << 6) +#define RX8130_BIT_CTRL_TEST (1 << 7) + +// Control 1 Register (1Fh) bit positions +#define RX8130_BIT_CTRL_BFVSEL0 (1 << 0) +#define RX8130_BIT_CTRL_BFVSEL1 (1 << 1) +#define RX8130_BIT_CTRL_RSVSEL (1 << 2) +#define RX8130_BIT_CTRL_INIEN (1 << 4) +#define RX8130_BIT_CTRL_CHGEN (1 << 5) +#define RX8130_BIT_CTRL_SMPTSEL0 (1 << 6) +#define RX8130_BIT_CTRL_SMPTSEL1 (1 << 7) + +static const struct i2c_device_id rx8130_id[] = { + {"rx8130", 0}, + {"rx8130-legacy", 0}, + {}}; +MODULE_DEVICE_TABLE(i2c, rx8130_id); + +static const struct of_device_id rx8130_of_match[] = { + { + .compatible = "epson,rx8130-legacy", + }, + {}}; +MODULE_DEVICE_TABLE(of, rx8130_of_match); + +struct rx8130_data +{ + struct i2c_client *client; + struct rtc_device *rtc; + struct work_struct work; + u8 ctrlreg; + unsigned exiting : 1; + bool enable_external_capacitor; +}; + +typedef struct +{ + u8 number; + u8 value; +} reg_data; + +#define SE_RTC_REG_READ _IOWR('p', 0x20, reg_data) +#define SE_RTC_REG_WRITE _IOW('p', 0x21, reg_data) + +//---------------------------------------------------------------------- +// rx8130_read_reg() +// reads a rx8130 register (see Register defines) +// See also rx8130_read_regs() to read multiple registers. +// +//---------------------------------------------------------------------- +static int rx8130_read_reg(struct i2c_client *client, int number, u8 *value) +{ + int ret = i2c_smbus_read_byte_data(client, number); + + //check for error + if (ret < 0) + { + dev_err(&client->dev, "Unable to read register #%d\n", number); + return ret; + } + + *value = ret; + return 0; +} + +//---------------------------------------------------------------------- +// rx8130_read_regs() +// reads a specified number of rx8130 registers (see Register defines) +// See also rx8130_read_reg() to read single register. +// +//---------------------------------------------------------------------- +static int rx8130_read_regs(struct i2c_client *client, int number, u8 length, u8 *values) +{ + int ret = i2c_smbus_read_i2c_block_data(client, number, length, values); + + //check for length error + if (ret != length) + { + dev_err(&client->dev, "Unable to read registers #%d..#%d\n", number, number + length - 1); + return ret < 0 ? ret : -EIO; + } + + return 0; +} + +//---------------------------------------------------------------------- +// rx8130_write_reg() +// writes a rx8130 register (see Register defines) +// See also rx8130_write_regs() to write multiple registers. +// +//---------------------------------------------------------------------- +static int rx8130_write_reg(struct i2c_client *client, int number, u8 value) +{ + int ret = i2c_smbus_write_byte_data(client, number, value); + + //check for error + if (ret) + dev_err(&client->dev, "Unable to write register #%d\n", number); + + return ret; +} + +//---------------------------------------------------------------------- +// rx8130_write_regs() +// writes a specified number of rx8130 registers (see Register defines) +// See also rx8130_write_reg() to write a single register. +// +//---------------------------------------------------------------------- +static int rx8130_write_regs(struct i2c_client *client, int number, u8 length, u8 *values) +{ + int ret = i2c_smbus_write_i2c_block_data(client, number, length, values); + + //check for error + if (ret) + dev_err(&client->dev, "Unable to write registers #%d..#%d\n", number, number + length - 1); + + return ret; +} + +//---------------------------------------------------------------------- +// rx8130_irq() +// irq handler +// +//---------------------------------------------------------------------- +static irqreturn_t rx8130_irq(int irq, void *dev_id) +{ + struct i2c_client *client = dev_id; + struct rx8130_data *rx8130 = i2c_get_clientdata(client); + + disable_irq_nosync(irq); + schedule_work(&rx8130->work); + + return IRQ_HANDLED; +} + +//---------------------------------------------------------------------- +// rx8130_work() +// +//---------------------------------------------------------------------- +static void rx8130_work(struct work_struct *work) +{ + struct rx8130_data *rx8130 = container_of(work, struct rx8130_data, work); + struct i2c_client *client = rx8130->client; + struct mutex *lock = &rx8130->rtc->ops_lock; + u8 status; + + mutex_lock(lock); + + if (rx8130_read_reg(client, RX8130_REG_FLAG, &status)) + goto out; + + // check VLF + if ((status & RX8130_BIT_FLAG_VLF)) + dev_warn(&client->dev, "Frequency stop was detected, probably due to a supply voltage drop\n"); + + dev_dbg(&client->dev, "%s: RX8130_REG_FLAG: %xh\n", __func__, status); + + // periodic "fixed-cycle" timer + if (status & RX8130_BIT_FLAG_TF) + { + status &= ~RX8130_BIT_FLAG_TF; + local_irq_disable(); + rtc_update_irq(rx8130->rtc, 1, RTC_PF | RTC_IRQF); + local_irq_enable(); + } + + // alarm function + if (status & RX8130_BIT_FLAG_AF) + { + status &= ~RX8130_BIT_FLAG_AF; + local_irq_disable(); + rtc_update_irq(rx8130->rtc, 1, RTC_AF | RTC_IRQF); + local_irq_enable(); + } + + // time update function + if (status & RX8130_BIT_FLAG_UF) + { + status &= ~RX8130_BIT_FLAG_UF; + local_irq_disable(); + rtc_update_irq(rx8130->rtc, 1, RTC_UF | RTC_IRQF); + local_irq_enable(); + } + + // acknowledge IRQ + rx8130_write_reg(client, RX8130_REG_FLAG, status); //clear flags + +out: + if (!rx8130->exiting) + enable_irq(client->irq); + + mutex_unlock(lock); +} + +//---------------------------------------------------------------------- +// rx8130_get_time() +// gets the current time from the rx8130 registers +// +//---------------------------------------------------------------------- +static int rx8130_get_time(struct device *dev, struct rtc_time *dt) +{ + struct rx8130_data *rx8130 = dev_get_drvdata(dev); + u8 date[7]; + int err; + + err = rx8130_read_regs(rx8130->client, RX8130_REG_SEC, 7, date); + if (err) + return err; + + dev_dbg(dev, "%s: read 0x%02x 0x%02x " + "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", + __func__, + date[0], date[1], date[2], date[3], date[4], date[5], date[6]); + + //Note: need to subtract 0x10 for index as register offset starts at 0x10 + dt->tm_sec = bcd2bin(date[RX8130_REG_SEC - 0x10] & 0x7f); + dt->tm_min = bcd2bin(date[RX8130_REG_MIN - 0x10] & 0x7f); + dt->tm_hour = bcd2bin(date[RX8130_REG_HOUR - 0x10] & 0x3f); //only 24-hour clock + dt->tm_mday = bcd2bin(date[RX8130_REG_MDAY - 0x10] & 0x3f); + dt->tm_mon = bcd2bin(date[RX8130_REG_MONTH - 0x10] & 0x1f) - 1; + dt->tm_year = bcd2bin(date[RX8130_REG_YEAR - 0x10]); + dt->tm_wday = bcd2bin(date[RX8130_REG_WDAY - 0x10] & 0x7f); + + if (dt->tm_year < 70) + dt->tm_year += 100; + + dev_dbg(dev, "%s: date %ds %dm %dh %dmd %dm %dy\n", __func__, + dt->tm_sec, dt->tm_min, dt->tm_hour, + dt->tm_mday, dt->tm_mon, dt->tm_year); + + return rtc_valid_tm(dt); +} + +//---------------------------------------------------------------------- +// rx8130_set_time() +// Sets the current time in the rx8130 registers +// +// Note: If STOP is not set/cleared, the clock will start when the seconds +// register is written +// +//---------------------------------------------------------------------- +static int rx8130_set_time(struct device *dev, struct rtc_time *dt) +{ + struct rx8130_data *rx8130 = dev_get_drvdata(dev); + u8 date[7]; + u8 ctrl; + int ret; + + //set STOP bit before changing clock/calendar + rx8130_read_reg(rx8130->client, RX8130_REG_CTRL0, &ctrl); + rx8130->ctrlreg = ctrl | RX8130_BIT_CTRL_STOP; + rx8130_write_reg(rx8130->client, RX8130_REG_CTRL0, rx8130->ctrlreg); + + dev_dbg(dev, "%s: date %ds %dm %dh %dmd %dm %dy\n", __func__, + dt->tm_sec, dt->tm_min, dt->tm_hour, + dt->tm_mday, dt->tm_mon, dt->tm_year); + + //Note: need to subtract 0x10 for index as register offset starts at 0x10 + date[RX8130_REG_SEC - 0x10] = bin2bcd(dt->tm_sec); + date[RX8130_REG_MIN - 0x10] = bin2bcd(dt->tm_min); + date[RX8130_REG_HOUR - 0x10] = bin2bcd(dt->tm_hour); //only 24hr time + + date[RX8130_REG_MDAY - 0x10] = bin2bcd(dt->tm_mday); + date[RX8130_REG_MONTH - 0x10] = bin2bcd(dt->tm_mon + 1); + date[RX8130_REG_YEAR - 0x10] = bin2bcd(dt->tm_year % 100); + date[RX8130_REG_WDAY - 0x10] = bin2bcd(dt->tm_wday); + + dev_dbg(dev, "%s: write 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", + __func__, date[0], date[1], date[2], date[3], date[4], date[5], date[6]); + + ret = rx8130_write_regs(rx8130->client, RX8130_REG_SEC, 7, date); + + //clear STOP bit after changing clock/calendar + rx8130_read_reg(rx8130->client, RX8130_REG_CTRL0, &ctrl); + rx8130->ctrlreg = ctrl & ~RX8130_BIT_CTRL_STOP; + rx8130_write_reg(rx8130->client, RX8130_REG_CTRL0, rx8130->ctrlreg); + + return ret; +} + +//---------------------------------------------------------------------- +// rx8130_init_client() +// initializes the rx8130 +// +//---------------------------------------------------------------------- +static int rx8130_init_client(struct i2c_client *client, int *need_reset) +{ + struct rx8130_data *rx8130 = i2c_get_clientdata(client); + u8 ctrl[3]; + int need_clear = 0; + int err; + + //get current extension, flag, control register values + dev_dbg(&client->dev, "Trying to read RX8130_REG_EXT\n"); + err = rx8130_read_regs(rx8130->client, RX8130_REG_EXT, 3, ctrl); + if (err) + goto out; + + //set extension register, TE to 0, FSEL1-0 and TSEL2-0 for desired frequency + ctrl[0] &= ~RX8130_BIT_EXT_TE; //set TE to 0 + ctrl[0] &= ~RX8130_BIT_EXT_FSEL; //set to 0 (off) for this case + ctrl[0] |= 0x02; //set TSEL for 1Hz + err = rx8130_write_reg(client, RX8130_REG_EXT, ctrl[0]); + if (err) + goto out; + + //clear "test bit" + rx8130->ctrlreg = (ctrl[2] & ~RX8130_BIT_CTRL_TEST); + + if (rx8130->enable_external_capacitor) + { + // enable charging of external capacitor + dev_info(&client->dev, "Enabling charging of external capacitor\n"); + ctrl[2] |= RX8130_BIT_CTRL_CHGEN; + ctrl[2] |= RX8130_BIT_CTRL_INIEN; + ctrl[2] |= RX8130_BIT_CTRL_BFVSEL0; + err = rx8130_write_reg(client, RX8130_REG_CTRL1, ctrl[2]); + if (err) + goto out; + } + + //check for VLF Flag (set at power-on) + if ((ctrl[1] & RX8130_BIT_FLAG_VLF)) + { + dev_warn(&client->dev, "Frequency stop was detected, probably due to a supply voltage drop\n"); + *need_reset = 1; + } + + //check for Alarm Flag + if (ctrl[1] & RX8130_BIT_FLAG_AF) + { + dev_warn(&client->dev, "Alarm was detected\n"); + need_clear = 1; + } + + //check for Periodic Timer Flag + if (ctrl[1] & RX8130_BIT_FLAG_TF) + { + dev_warn(&client->dev, "Periodic timer was detected\n"); + need_clear = 1; + } + + //check for Update Timer Flag + if (ctrl[1] & RX8130_BIT_FLAG_UF) + { + dev_warn(&client->dev, "Update timer was detected\n"); + need_clear = 1; + } + + //reset or clear needed? + if (*need_reset || need_clear) + { + //clear flag register + err = rx8130_write_reg(client, RX8130_REG_FLAG, 0x00); + if (err) + goto out; + + //clear ctrl register + err = rx8130_write_reg(client, RX8130_REG_CTRL0, 0x00); + if (err) + goto out; + } +out: + return err; +} + +//---------------------------------------------------------------------- +// rx8130_read_alarm() +// reads current Alarm +//---------------------------------------------------------------------- +static int rx8130_read_alarm(struct device *dev, struct rtc_wkalrm *t) +{ + struct rx8130_data *rx8130 = dev_get_drvdata(dev); + struct i2c_client *client = rx8130->client; + u8 alarmvals[3]; //minute, hour, week/day values + u8 ctrl[3]; //extension, flag, control values + int err; + + if (client->irq <= 0) + return -EINVAL; + + //get current minute, hour, week/day alarm values + err = rx8130_read_regs(client, RX8130_REG_ALMIN, 3, alarmvals); + if (err) + return err; + dev_dbg(dev, "%s: minutes:0x%02x hours:0x%02x week/day:0x%02x\n", + __func__, alarmvals[0], alarmvals[1], alarmvals[2]); + + //get current extension, flag, control register values + err = rx8130_read_regs(client, RX8130_REG_EXT, 3, ctrl); + if (err) + return err; + dev_dbg(dev, "%s: extension:0x%02x flag:0x%02x control:0x%02x \n", + __func__, ctrl[0], ctrl[1], ctrl[2]); + + // Hardware alarm precision is 1 minute + t->time.tm_sec = 0; + t->time.tm_min = bcd2bin(alarmvals[0] & 0x7f); //0x7f filters AE bit currently + t->time.tm_hour = bcd2bin(alarmvals[1] & 0x3f); //0x3f filters AE bit currently, also 24hr only + + t->time.tm_wday = -1; + t->time.tm_mday = -1; + t->time.tm_mon = -1; + t->time.tm_year = -1; + + dev_dbg(dev, "%s: date: %ds %dm %dh %dmd %dm %dy\n", + __func__, + t->time.tm_sec, t->time.tm_min, t->time.tm_hour, + t->time.tm_mday, t->time.tm_mon, t->time.tm_year); + + t->enabled = !!(rx8130->ctrlreg & RX8130_BIT_CTRL_AIE); //check if interrupt is enabled + t->pending = (ctrl[1] & RX8130_BIT_FLAG_AF) && t->enabled; //check if flag is triggered + + return err; +} + +//---------------------------------------------------------------------- +// rx8130_set_alarm() +// sets Alarm +//---------------------------------------------------------------------- +static int rx8130_set_alarm(struct device *dev, struct rtc_wkalrm *t) +{ + struct i2c_client *client = to_i2c_client(dev); + struct rx8130_data *rx8130 = dev_get_drvdata(dev); + u8 alarmvals[3]; //minute, hour, day + u8 extreg; //extension register + u8 flagreg; //flag register + int err; + + if (client->irq <= 0) + return -EINVAL; + + //get current extension register + err = rx8130_read_reg(client, RX8130_REG_EXT, &extreg); + if (err < 0) + return err; + + //get current flag register + err = rx8130_read_reg(client, RX8130_REG_FLAG, &flagreg); + if (err < 0) + return err; + + // Hardware alarm precision is 1 minute + alarmvals[0] = bin2bcd(t->time.tm_min); + alarmvals[1] = bin2bcd(t->time.tm_hour); + alarmvals[2] = bin2bcd(t->time.tm_mday); + dev_dbg(dev, "%s: write 0x%02x 0x%02x 0x%02x\n", __func__, alarmvals[0], alarmvals[1], alarmvals[2]); + + //check interrupt enable and disable + if (rx8130->ctrlreg & (RX8130_BIT_CTRL_AIE | RX8130_BIT_CTRL_UIE)) + { + rx8130->ctrlreg &= ~(RX8130_BIT_CTRL_AIE | RX8130_BIT_CTRL_UIE); + err = rx8130_write_reg(rx8130->client, RX8130_REG_CTRL0, rx8130->ctrlreg); + if (err) + return err; + } + + //write the new minute and hour values + //Note:assume minute and hour values will be enabled. Bit 7 of each of the + // minute, hour, week/day register can be set which will "disable" the + // register from triggering an alarm. See the RX8130 spec for more information + err = rx8130_write_regs(rx8130->client, RX8130_REG_ALMIN, 2, alarmvals); + if (err) + return err; + + //set Week/Day bit + // Week setting is typically not used, so we will assume "day" setting + extreg |= RX8130_BIT_EXT_WADA; //set to "day of month" + err = rx8130_write_reg(rx8130->client, RX8130_REG_EXT, extreg); + if (err) + return err; + + //set Day of Month register + if (alarmvals[2] == 0) + { + alarmvals[2] |= 0x80; //turn on AE bit to ignore day of month (no zero day) + err = rx8130_write_reg(rx8130->client, RX8130_REG_ALWDAY, alarmvals[2]); + } + else + { + err = rx8130_write_reg(rx8130->client, RX8130_REG_ALWDAY, alarmvals[2]); + } + if (err) + return err; + + //clear Alarm Flag + flagreg &= ~(RX8130_BIT_FLAG_AF | RX8130_BIT_FLAG_UF); + err = rx8130_write_reg(rx8130->client, RX8130_REG_FLAG, flagreg); + if (err) + return err; + + //re-enable interrupt if required + if (t->enabled) + { + + if (rx8130->rtc->uie_rtctimer.enabled) + rx8130->ctrlreg |= RX8130_BIT_CTRL_UIE; //set update interrupt enable + if (rx8130->rtc->aie_timer.enabled) + rx8130->ctrlreg |= (RX8130_BIT_CTRL_AIE | RX8130_BIT_CTRL_UIE); //set alarm interrupt enable + + err = rx8130_write_reg(rx8130->client, RX8130_REG_CTRL0, rx8130->ctrlreg); + if (err) + return err; + } + + return 0; +} + +//---------------------------------------------------------------------- +// rx8130_alarm_irq_enable() +// sets enables Alarm IRQ +//---------------------------------------------------------------------- +static int rx8130_alarm_irq_enable(struct device *dev, unsigned int enabled) +{ + struct i2c_client *client = to_i2c_client(dev); + struct rx8130_data *rx8130 = dev_get_drvdata(dev); + u8 flagreg; + u8 ctrl; + int err; + + //get the current ctrl settings + ctrl = rx8130->ctrlreg; + + if (enabled) + { + if (rx8130->rtc->uie_rtctimer.enabled) + ctrl |= RX8130_BIT_CTRL_UIE; //set update interrupt enable + if (rx8130->rtc->aie_timer.enabled) + ctrl |= (RX8130_BIT_CTRL_AIE | RX8130_BIT_CTRL_UIE); //set alarm interrupt enable + } + else + { + if (!rx8130->rtc->uie_rtctimer.enabled) + ctrl &= ~RX8130_BIT_CTRL_UIE; //clear update interrupt enable + if (!rx8130->rtc->aie_timer.enabled) + { + if (rx8130->rtc->uie_rtctimer.enabled) + ctrl &= ~RX8130_BIT_CTRL_AIE; + else + ctrl &= ~(RX8130_BIT_CTRL_AIE | RX8130_BIT_CTRL_UIE); //clear alarm interrupt enable + } + } + + //clear alarm flag + err = rx8130_read_reg(client, RX8130_REG_FLAG, &flagreg); + if (err < 0) + return err; + flagreg &= ~RX8130_BIT_FLAG_AF; + err = rx8130_write_reg(rx8130->client, RX8130_REG_FLAG, flagreg); + if (err) + return err; + + //update the Control register if the setting changed + if (ctrl != rx8130->ctrlreg) + { + rx8130->ctrlreg = ctrl; + err = rx8130_write_reg(rx8130->client, RX8130_REG_CTRL0, rx8130->ctrlreg); + if (err) + return err; + } + + return 0; +} + +//--------------------------------------------------------------------------- +// rx8130_ioctl() +// +//--------------------------------------------------------------------------- +static int rx8130_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) +{ + struct i2c_client *client = to_i2c_client(dev); + //struct rx8130_data *rx8130 = dev_get_drvdata(dev); + //struct mutex *lock = &rx8130->rtc->ops_lock; + int ret = 0; + int tmp; + void __user *argp = (void __user *)arg; + reg_data reg; + + dev_dbg(dev, "%s: cmd=%x\n", __func__, cmd); + + switch (cmd) + { + case SE_RTC_REG_READ: + if (copy_from_user(®, argp, sizeof(reg))) + return -EFAULT; + if (reg.number < RX8130_REG_SEC || reg.number > RX8130_REG_END) + return -EFAULT; + //mutex_lock(lock); + ret = rx8130_read_reg(client, reg.number, ®.value); + //mutex_unlock(lock); + if (!ret) + return copy_to_user(argp, ®, sizeof(reg)) ? -EFAULT : 0; + break; + + case SE_RTC_REG_WRITE: + if (copy_from_user(®, argp, sizeof(reg))) + return -EFAULT; + if (reg.number < RX8130_REG_SEC || reg.number > RX8130_REG_END) + return -EFAULT; + //mutex_lock(lock); + ret = rx8130_write_reg(client, reg.number, reg.value); + //mutex_unlock(lock); + break; + + case RTC_VL_READ: + //mutex_lock(lock); + ret = rx8130_read_reg(client, RX8130_REG_FLAG, ®.value); + //mutex_unlock(lock); + if (!ret) + { + tmp = !!(reg.value & RX8130_BIT_FLAG_VLF); + return copy_to_user(argp, &tmp, sizeof(tmp)) ? -EFAULT : 0; + } + break; + + case RTC_VL_CLR: + //mutex_lock(lock); + ret = rx8130_read_reg(client, RX8130_REG_FLAG, ®.value); + if (!ret) + { + reg.value &= ~RX8130_BIT_FLAG_VLF; + ret = rx8130_write_reg(client, RX8130_REG_FLAG, reg.value); + } + //mutex_unlock(lock); + break; + + default: + return -ENOIOCTLCMD; + } + + return ret; +} + +static struct rtc_class_ops rx8130_rtc_ops = { + .read_time = rx8130_get_time, + .set_time = rx8130_set_time, + .read_alarm = rx8130_read_alarm, + .set_alarm = rx8130_set_alarm, + .alarm_irq_enable = rx8130_alarm_irq_enable, + .ioctl = rx8130_ioctl, +}; + +//---------------------------------------------------------------------- +// rx8130_probe() +// probe routine for the rx8130 driver +// +// Todo: - maybe change kzalloc to use devm_kzalloc +// - +//---------------------------------------------------------------------- +static int rx8130_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); + struct rx8130_data *rx8130; + int err, need_reset = 0; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_I2C_BLOCK)) + { + dev_err(&adapter->dev, "doesn't support required functionality\n"); + err = -EIO; + goto errout; + } + + rx8130 = kzalloc(sizeof(*rx8130), GFP_KERNEL); + if (!rx8130) + { + dev_err(&adapter->dev, "failed to alloc memory\n"); + err = -ENOMEM; + goto errout; + } + + rx8130->client = client; + i2c_set_clientdata(client, rx8130); + INIT_WORK(&rx8130->work, rx8130_work); + +#ifdef CONFIG_OF + rx8130->enable_external_capacitor = of_property_read_bool(client->dev.of_node, "enable-external-capacitor"); +#endif + + err = rx8130_init_client(client, &need_reset); + if (err) + goto errout_free; + + if (need_reset) + { + struct rtc_time tm; + dev_info(&client->dev, "bad conditions detected, resetting date\n"); + rtc_time64_to_tm(0, &tm); // set to 1970/1/1 + + rx8130_set_time(&client->dev, &tm); + } + + rx8130->rtc = devm_rtc_device_register(&client->dev, client->name, &rx8130_rtc_ops, THIS_MODULE); + + if (IS_ERR(rx8130->rtc)) + { + err = PTR_ERR(rx8130->rtc); + dev_err(&client->dev, "unable to register the class device\n"); + goto errout_free; + } + + if (client->irq > 0) + { + dev_info(&client->dev, "IRQ %d supplied\n", client->irq); + err = devm_request_threaded_irq(&client->dev, client->irq, NULL, rx8130_irq, IRQF_TRIGGER_LOW | IRQF_ONESHOT, "rx8130", client); + + if (err) + { + dev_err(&client->dev, "unable to request IRQ\n"); + goto errout_reg; + } + } + + rx8130->rtc->irq_freq = 1; + rx8130->rtc->max_user_freq = 1; + + return 0; + +errout_reg: +errout_free: + kfree(rx8130); + +errout: + dev_err(&adapter->dev, "probing for rx8130 failed\n"); + return err; +} + +//---------------------------------------------------------------------- +// rx8130_remove() +// remove routine for the rx8130 driver +// +// Todo: - maybe change kzalloc to devm_kzalloc +// - +//---------------------------------------------------------------------- +static int rx8130_remove(struct i2c_client *client) +{ + struct rx8130_data *rx8130 = i2c_get_clientdata(client); + struct mutex *lock = &rx8130->rtc->ops_lock; + + if (client->irq > 0) + { + mutex_lock(lock); + rx8130->exiting = 1; + mutex_unlock(lock); + + free_irq(client->irq, client); + cancel_work_sync(&rx8130->work); + } + + kfree(rx8130); + return 0; +} + +static struct i2c_driver rx8130_driver = { + .driver = { + .name = "rtc-rx8130", + .of_match_table = of_match_ptr(rx8130_of_match), + .owner = THIS_MODULE, + }, + .probe = rx8130_probe, + .remove = rx8130_remove, + .id_table = rx8130_id, +}; + +module_i2c_driver(rx8130_driver); + +MODULE_AUTHOR("Val Krutov "); +MODULE_DESCRIPTION("RX8130CE RTC driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION("1.5"); diff --git a/buildroot-external/package/rx8130-rtc/rx8130-rtc.mk b/buildroot-external/package/rx8130-rtc/rx8130-rtc.mk new file mode 100644 index 00000000000..a47ce0906a1 --- /dev/null +++ b/buildroot-external/package/rx8130-rtc/rx8130-rtc.mk @@ -0,0 +1,18 @@ +############################################################# +# +# Kernel module for the Epson RTC module RX-8130 CE +# (which is used on a RPI-RF-MOD) +# +# Copyright(C) SEIKO EPSON CORPORATION 2014. All rights reserved. +# +############################################################# + +RX8130_RTC_VERSION = 1.1.0 +RX8130_RTC_LICENSE = GPL2 +#RX8130_RTC_LICENSE_FILES = COPYING +RX8130_RTC_SITE = $(BR2_EXTERNAL_HASSOS_PATH)/package/rx8130-rtc +RX8130_RTC_SITE_METHOD = local +RX8130_RTC_MODULE_SUBDIRS = kernel-modules/rtc_rx8130ce + +$(eval $(kernel-module)) +$(eval $(generic-package)) From 4335837615b90eac2d26cda2cd2f1dd33de2215a Mon Sep 17 00:00:00 2001 From: Jens Maus Date: Tue, 9 Mar 2021 20:52:13 +0100 Subject: [PATCH 04/22] added generic_raw_uart package (low-latency raw uart kernel driver) --- .../0001-kernel-Makefile.patch | 39 +++++++++++++++ .../0002-dts-disable-gpio-pin.patch | 17 +++++++ .../0003-dts-tinkerboard.patch | 20 ++++++++ .../package/generic_raw_uart/Config.in | 7 +++ .../generic_raw_uart/generic_raw_uart.mk | 47 +++++++++++++++++++ 5 files changed, 130 insertions(+) create mode 100644 buildroot-external/package/generic_raw_uart/0001-kernel-Makefile.patch create mode 100644 buildroot-external/package/generic_raw_uart/0002-dts-disable-gpio-pin.patch create mode 100644 buildroot-external/package/generic_raw_uart/0003-dts-tinkerboard.patch create mode 100644 buildroot-external/package/generic_raw_uart/Config.in create mode 100644 buildroot-external/package/generic_raw_uart/generic_raw_uart.mk diff --git a/buildroot-external/package/generic_raw_uart/0001-kernel-Makefile.patch b/buildroot-external/package/generic_raw_uart/0001-kernel-Makefile.patch new file mode 100644 index 00000000000..adab383b523 --- /dev/null +++ b/buildroot-external/package/generic_raw_uart/0001-kernel-Makefile.patch @@ -0,0 +1,39 @@ +--- ./kernel/Makefile.orig 2020-12-14 13:09:44.406823210 +0100 ++++ ./kernel/Makefile 2021-01-14 11:37:37.524474444 +0100 +@@ -1,17 +1,26 @@ +-obj-m += eq3_char_loop.o +-obj-m += plat_eq3ccu2.o ++#obj-m += eq3_char_loop.o ++#obj-m += plat_eq3ccu2.o + obj-m += generic_raw_uart.o ++ifeq ($(CONFIG_ARCH_BCM2835),y) + obj-m += pl011_raw_uart.o ++endif ++ifeq ($(CONFIG_ARCH_ROCKCHIP),y) + obj-m += dw_apb_raw_uart.o ++endif ++ifeq ($(CONFIG_ARCH_MESON64_ODROIDC2),y) + obj-m += meson_raw_uart.o +-obj-m += fake_hmrf.o ++endif ++#obj-m += fake_hmrf.o + obj-m += rpi_rf_mod_led.o + obj-m += dummy_rx8130.o +-obj-m += led_trigger_timer.o ++#obj-m += led_trigger_timer.o + obj-m += hb_rf_usb.o + obj-m += hb_rf_usb-2.o + obj-m += hb_rf_eth.o +-obj-m += rtc-rx8130.o ++#obj-m += rtc-rx8130.o ++ ++# disable ++ifeq (0,1) + + ifeq ($(KERNELRELEASE),) + KERNELRELEASE := $(shell uname -r) +@@ -32,3 +41,4 @@ + clean: + $(MAKE) -C $(KERNEL_DIR) M=$(PWD) clean + ++endif diff --git a/buildroot-external/package/generic_raw_uart/0002-dts-disable-gpio-pin.patch b/buildroot-external/package/generic_raw_uart/0002-dts-disable-gpio-pin.patch new file mode 100644 index 00000000000..3529c953ddf --- /dev/null +++ b/buildroot-external/package/generic_raw_uart/0002-dts-disable-gpio-pin.patch @@ -0,0 +1,17 @@ +--- ./dts/pivccu-raspberrypi.dts.orig 2018-12-22 21:01:28.756992536 +0100 ++++ ./dts/pivccu-raspberrypi.dts 2018-12-26 22:56:26.807677174 +0100 +@@ -7,10 +7,10 @@ + target = <&uart0>; + __overlay__ { + compatible = "pivccu,pl011"; +- pivccu,reset_pin = <&gpio 18 0>; +- pivccu,red_pin = <&gpio 16 0>; +- pivccu,green_pin = <&gpio 20 0>; +- pivccu,blue_pin = <&gpio 21 0>; ++ pivccu,reset_pin = <0>; ++ pivccu,red_pin = <0>; ++ pivccu,green_pin = <0>; ++ pivccu,blue_pin = <0>; + }; + }; + }; diff --git a/buildroot-external/package/generic_raw_uart/0003-dts-tinkerboard.patch b/buildroot-external/package/generic_raw_uart/0003-dts-tinkerboard.patch new file mode 100644 index 00000000000..80e549460b8 --- /dev/null +++ b/buildroot-external/package/generic_raw_uart/0003-dts-tinkerboard.patch @@ -0,0 +1,20 @@ +--- ./dts/pivccu-tinkerboard.dts.orig 2019-03-11 13:29:51.226401633 +0100 ++++ ./dts/pivccu-tinkerboard.dts 2020-06-05 11:20:29.433644667 +0200 +@@ -0,0 +1,17 @@ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "asus,rk3288-tinker", "rockchip,rk3288"; ++ fragment@0 { ++ target = <&uart1>; ++ __overlay__ { ++ compatible = "pivccu,dw_apb"; ++ status = "okay"; ++ pivccu,reset_pin = <0>; ++ pivccu,red_pin = <0>; ++ pivccu,green_pin = <0>; ++ pivccu,blue_pin = <0>; ++ }; ++ }; ++}; diff --git a/buildroot-external/package/generic_raw_uart/Config.in b/buildroot-external/package/generic_raw_uart/Config.in new file mode 100644 index 00000000000..81f38f64164 --- /dev/null +++ b/buildroot-external/package/generic_raw_uart/Config.in @@ -0,0 +1,7 @@ +config BR2_PACKAGE_GENERIC_RAW_UART + bool "Support for Generic RAW UART kernel module" + help + Adds support for generic-raw-uart kernel module + + Alexander Reinert + https://github.com/alexreinert/piVCCU/tree/master/kernel diff --git a/buildroot-external/package/generic_raw_uart/generic_raw_uart.mk b/buildroot-external/package/generic_raw_uart/generic_raw_uart.mk new file mode 100644 index 00000000000..09feeb5d91d --- /dev/null +++ b/buildroot-external/package/generic_raw_uart/generic_raw_uart.mk @@ -0,0 +1,47 @@ +############################################################# +# +# Generic raw uart kernel module for low-latency uart +# communication with a RPI-RF-MOD/HM-MOD-RPI-PCB +# +# Copyright (c) 2020 Alexander Reinert +# https://github.com/alexreinert/piVCCU/tree/master/kernel +# +# Uses parts of bcm2835_raw_uart.c +# Copyright (c) 2015 eQ-3 Entwicklung GmbH +# https://github.com/eq-3/occu/tree/master/KernelDrivers +# https://github.com/jens-maus/RaspberryMatic/tree/master/buildroot-external/package/bcm2835_raw_uart +# +############################################################# + +GENERIC_RAW_UART_VERSION = 0fc14a2131da3b14d91407ef803ded5dc3a9ff80 +GENERIC_RAW_UART_SITE = $(call github,alexreinert,piVCCU,$(GENERIC_RAW_UART_VERSION)) +GENERIC_RAW_UART_LICENSE = GPL2 +GENERIC_RAW_UART_DEPENDENCIES = host-dtc +#GENERIC_RAW_UART_LICENSE_FILES = LICENSE +GENERIC_RAW_UART_MODULE_SUBDIRS = kernel +GENERIC_RAW_UART_INSTALL_IMAGES = YES + +# RaspberryPi DTS file +ifneq (,$(findstring raspberrypi,$(BR2_PACKAGE_HASSIO_MACHINE))) + GENERIC_RAW_UART_DTS_FILE = pivccu-raspberrypi +endif + +# Tinkerboard DTS file +ifneq (,$(findstring tinker,$(BR2_PACKAGE_HASSIO_MACHINE))) + GENERIC_RAW_UART_DTS_FILE = pivccu-tinkerboard +endif + +define GENERIC_RAW_UART_BUILD_CMDS + if [[ -n "$(GENERIC_RAW_UART_DTS_FILE)" ]]; then \ + $(HOST_DIR)/bin/dtc -@ -I dts -O dtb -W no-unit_address_vs_reg -o $(@D)/dts/$(GENERIC_RAW_UART_DTS_FILE).dtbo $(@D)/dts/$(GENERIC_RAW_UART_DTS_FILE).dts; \ + fi +endef + +define GENERIC_RAW_UART_INSTALL_IMAGES_CMDS + if [[ -n "$(GENERIC_RAW_UART_DTS_FILE)" ]]; then \ + $(INSTALL) -D -m 0644 $(@D)/dts/$(GENERIC_RAW_UART_DTS_FILE).dtbo $(BINARIES_DIR)/; \ + fi +endef + +$(eval $(kernel-module)) +$(eval $(generic-package)) From 844dc84dc6a6c3283c433fdc03b9090727bf78fe Mon Sep 17 00:00:00 2001 From: Jens Maus Date: Tue, 9 Mar 2021 20:53:38 +0100 Subject: [PATCH 05/22] added new eq3_char_loop, rpi-rf-mod, rx8130-rtc and generic_raw_uart package to global buildroot-external Config.in --- buildroot-external/Config.in | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/buildroot-external/Config.in b/buildroot-external/Config.in index dc2248faeb7..47fd9748cfe 100644 --- a/buildroot-external/Config.in +++ b/buildroot-external/Config.in @@ -6,3 +6,7 @@ source "$BR2_EXTERNAL_HASSOS_PATH/package/qemu-guest-agent/Config.in" source "$BR2_EXTERNAL_HASSOS_PATH/package/intel-e1000e/Config.in" source "$BR2_EXTERNAL_HASSOS_PATH/package/rpi-eeprom/Config.in" source "$BR2_EXTERNAL_HASSOS_PATH/package/rtl8812au/Config.in" +source "$BR2_EXTERNAL_HASSOS_PATH/package/eq3_char_loop/Config.in" +source "$BR2_EXTERNAL_HASSOS_PATH/package/generic_raw_uart/Config.in" +source "$BR2_EXTERNAL_HASSOS_PATH/package/rpi-rf-mod/Config.in" +source "$BR2_EXTERNAL_HASSOS_PATH/package/rx8130-rtc/Config.in" From 791d4df912636165c1946c088aa044adad833b64 Mon Sep 17 00:00:00 2001 From: Jens Maus Date: Tue, 9 Mar 2021 20:57:57 +0100 Subject: [PATCH 06/22] added GPIOLIB and GPIO_SYSFS required for RPI-RF-MOD/HM-MOD-RPI-PCB support. --- buildroot-external/kernel/device-support.config | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/buildroot-external/kernel/device-support.config b/buildroot-external/kernel/device-support.config index bc10ec30f41..a3a97d084fb 100644 --- a/buildroot-external/kernel/device-support.config +++ b/buildroot-external/kernel/device-support.config @@ -156,6 +156,10 @@ CONFIG_SND_HDA_CODEC_ANALOG=m CONFIG_SND_HDA_CODEC_VIA=m CONFIG_SND_HDA_CODEC_HDMI=m +# GPIO support +CONFIG_GPIOLIB=y +CONFIG_GPIO_SYSFS=y + # Can Bus support CONFIG_CAN=m CONFIG_CAN_RAW=m From 854f4ae7e160e00cb21cce63322bfa3464e0e0a8 Mon Sep 17 00:00:00 2001 From: Jens Maus Date: Tue, 9 Mar 2021 21:03:04 +0100 Subject: [PATCH 07/22] modified raspberrypi defconfig file to enable packages required for RPI-RF-MOD/HM-MOD-RPI-PCB support. Added commented section to /boot/config.txt to allow users to enable GPIO support for RPI-RF-MOD or HM-MOD-RPI-PCB and modified hassos-hook.sh to put the necessary device tree overlays in /boot/overlays --- buildroot-external/board/raspberrypi/boot-env.txt | 7 +++++++ buildroot-external/board/raspberrypi/hassos-hook.sh | 1 + buildroot-external/configs/rpi0_w_defconfig | 3 +++ buildroot-external/configs/rpi2_defconfig | 3 +++ buildroot-external/configs/rpi3_64_defconfig | 3 +++ buildroot-external/configs/rpi3_defconfig | 3 +++ buildroot-external/configs/rpi4_64_defconfig | 3 +++ buildroot-external/configs/rpi4_defconfig | 3 +++ buildroot-external/configs/rpi_defconfig | 3 +++ 9 files changed, 29 insertions(+) diff --git a/buildroot-external/board/raspberrypi/boot-env.txt b/buildroot-external/board/raspberrypi/boot-env.txt index 65f6b39e2ce..e14db7143bc 100644 --- a/buildroot-external/board/raspberrypi/boot-env.txt +++ b/buildroot-external/board/raspberrypi/boot-env.txt @@ -60,6 +60,13 @@ kernel=u-boot.bin # Uncomment this to enable the lirc-rpi module #dtoverlay=lirc-rpi +# Uncomment this to enable GPIO support for RPI-RF-MOD/HM-MOD-RPI-PCB +#enable_uart=1 +#dtparam=i2c_arm=on +#dtoverlay=miniuart-bt +#dtoverlay=pivccu-raspberrypi +#dtoverlay=rpi-rf-mod + # Additional overlays and parameters are documented /boot/overlays/README # Enable audio (loads snd_bcm2835) diff --git a/buildroot-external/board/raspberrypi/hassos-hook.sh b/buildroot-external/board/raspberrypi/hassos-hook.sh index 583e70a399f..dda9d21d04b 100755 --- a/buildroot-external/board/raspberrypi/hassos-hook.sh +++ b/buildroot-external/board/raspberrypi/hassos-hook.sh @@ -10,6 +10,7 @@ function hassos_pre_image() { cp "${BINARIES_DIR}"/*.dtb "${BOOT_DATA}/" cp -r "${BINARIES_DIR}/rpi-firmware/"* "${BOOT_DATA}/" cp "${BOARD_DIR}/../boot-env.txt" "${BOOT_DATA}/config.txt" + cp "${BINARIES_DIR}"/*.dtbo "${BOOT_DATA}/overlays/" # EEPROM update for Raspberry Pi 4/Compute Module 4 if grep -Eq "^BR2_PACKAGE_RPI_EEPROM=y$" "${BR2_CONFIG}"; then diff --git a/buildroot-external/configs/rpi0_w_defconfig b/buildroot-external/configs/rpi0_w_defconfig index 6624111788c..19cd6440e9c 100644 --- a/buildroot-external/configs/rpi0_w_defconfig +++ b/buildroot-external/configs/rpi0_w_defconfig @@ -105,3 +105,6 @@ BR2_PACKAGE_APPARMOR_PROFILES=y BR2_PACKAGE_BLUETOOTH_BCM43XX=y BR2_PACKAGE_DOSFSTOOLS=y BR2_PACKAGE_DOSFSTOOLS_FSCK_FAT=y +BR2_PACKAGE_GENERIC_RAW_UART=y +BR2_PACKAGE_EQ3_CHAR_LOOP=y +BR2_PACKAGE_RPI_RF_MOD=y diff --git a/buildroot-external/configs/rpi2_defconfig b/buildroot-external/configs/rpi2_defconfig index 8ef4c54dd75..04867a4c25f 100644 --- a/buildroot-external/configs/rpi2_defconfig +++ b/buildroot-external/configs/rpi2_defconfig @@ -104,3 +104,6 @@ BR2_PACKAGE_APPARMOR=y BR2_PACKAGE_APPARMOR_PROFILES=y BR2_PACKAGE_DOSFSTOOLS=y BR2_PACKAGE_DOSFSTOOLS_FSCK_FAT=y +BR2_PACKAGE_GENERIC_RAW_UART=y +BR2_PACKAGE_EQ3_CHAR_LOOP=y +BR2_PACKAGE_RPI_RF_MOD=y diff --git a/buildroot-external/configs/rpi3_64_defconfig b/buildroot-external/configs/rpi3_64_defconfig index 9ca8bd8b2a5..4d83ead3816 100644 --- a/buildroot-external/configs/rpi3_64_defconfig +++ b/buildroot-external/configs/rpi3_64_defconfig @@ -105,3 +105,6 @@ BR2_PACKAGE_APPARMOR_PROFILES=y BR2_PACKAGE_BLUETOOTH_BCM43XX=y BR2_PACKAGE_DOSFSTOOLS=y BR2_PACKAGE_DOSFSTOOLS_FSCK_FAT=y +BR2_PACKAGE_GENERIC_RAW_UART=y +BR2_PACKAGE_EQ3_CHAR_LOOP=y +BR2_PACKAGE_RPI_RF_MOD=y diff --git a/buildroot-external/configs/rpi3_defconfig b/buildroot-external/configs/rpi3_defconfig index cbd68c21032..4bdb8ae673a 100644 --- a/buildroot-external/configs/rpi3_defconfig +++ b/buildroot-external/configs/rpi3_defconfig @@ -105,3 +105,6 @@ BR2_PACKAGE_APPARMOR_PROFILES=y BR2_PACKAGE_BLUETOOTH_BCM43XX=y BR2_PACKAGE_DOSFSTOOLS=y BR2_PACKAGE_DOSFSTOOLS_FSCK_FAT=y +BR2_PACKAGE_GENERIC_RAW_UART=y +BR2_PACKAGE_EQ3_CHAR_LOOP=y +BR2_PACKAGE_RPI_RF_MOD=y diff --git a/buildroot-external/configs/rpi4_64_defconfig b/buildroot-external/configs/rpi4_64_defconfig index e3e00d0982f..6b6b33be687 100644 --- a/buildroot-external/configs/rpi4_64_defconfig +++ b/buildroot-external/configs/rpi4_64_defconfig @@ -108,3 +108,6 @@ BR2_PACKAGE_APPARMOR_PROFILES=y BR2_PACKAGE_BLUETOOTH_BCM43XX=y BR2_PACKAGE_DOSFSTOOLS=y BR2_PACKAGE_DOSFSTOOLS_FSCK_FAT=y +BR2_PACKAGE_GENERIC_RAW_UART=y +BR2_PACKAGE_EQ3_CHAR_LOOP=y +BR2_PACKAGE_RPI_RF_MOD=y diff --git a/buildroot-external/configs/rpi4_defconfig b/buildroot-external/configs/rpi4_defconfig index b45e275a3bf..5f4fc847574 100644 --- a/buildroot-external/configs/rpi4_defconfig +++ b/buildroot-external/configs/rpi4_defconfig @@ -106,3 +106,6 @@ BR2_PACKAGE_APPARMOR_PROFILES=y BR2_PACKAGE_BLUETOOTH_BCM43XX=y BR2_PACKAGE_DOSFSTOOLS=y BR2_PACKAGE_DOSFSTOOLS_FSCK_FAT=y +BR2_PACKAGE_GENERIC_RAW_UART=y +BR2_PACKAGE_EQ3_CHAR_LOOP=y +BR2_PACKAGE_RPI_RF_MOD=y diff --git a/buildroot-external/configs/rpi_defconfig b/buildroot-external/configs/rpi_defconfig index 8450294842c..2f6680319d1 100644 --- a/buildroot-external/configs/rpi_defconfig +++ b/buildroot-external/configs/rpi_defconfig @@ -104,3 +104,6 @@ BR2_PACKAGE_APPARMOR=y BR2_PACKAGE_APPARMOR_PROFILES=y BR2_PACKAGE_DOSFSTOOLS=y BR2_PACKAGE_DOSFSTOOLS_FSCK_FAT=y +BR2_PACKAGE_GENERIC_RAW_UART=y +BR2_PACKAGE_EQ3_CHAR_LOOP=y +BR2_PACKAGE_RPI_RF_MOD=y From 1535c176ed099399e841bccc9bc20e66d1a39545 Mon Sep 17 00:00:00 2001 From: Jens Maus Date: Tue, 9 Mar 2021 21:06:14 +0100 Subject: [PATCH 08/22] added basic RPI-RF-MOD/HM-MOD-RPI-PCB support for Tinkerboard. --- buildroot-external/board/asus/hassos-hook.sh | 3 +++ buildroot-external/configs/tinker_defconfig | 3 +++ 2 files changed, 6 insertions(+) diff --git a/buildroot-external/board/asus/hassos-hook.sh b/buildroot-external/board/asus/hassos-hook.sh index bb0170f2b5b..ab9afe81299 100755 --- a/buildroot-external/board/asus/hassos-hook.sh +++ b/buildroot-external/board/asus/hassos-hook.sh @@ -10,6 +10,9 @@ function hassos_pre_image() { "${BINARIES_DIR}/rk3288-tinker.dtb" \ "${BINARIES_DIR}/rk3288-tinker-s.dtb" + mkdir -p "${BOOT_DATA}/overlays" + cp "${BINARIES_DIR}"/*.dtbo "${BOOT_DATA}/overlays/" + echo "console=tty1" > "${BOOT_DATA}/cmdline.txt" # SPL diff --git a/buildroot-external/configs/tinker_defconfig b/buildroot-external/configs/tinker_defconfig index 63971576977..a419fb2de00 100644 --- a/buildroot-external/configs/tinker_defconfig +++ b/buildroot-external/configs/tinker_defconfig @@ -110,3 +110,6 @@ BR2_PACKAGE_APPARMOR_PROFILES=y BR2_PACKAGE_BLUETOOTH_RTL8723=y BR2_PACKAGE_DOSFSTOOLS=y BR2_PACKAGE_DOSFSTOOLS_FSCK_FAT=y +BR2_PACKAGE_GENERIC_RAW_UART=y +BR2_PACKAGE_EQ3_CHAR_LOOP=y +BR2_PACKAGE_RPI_RF_MOD=y From e9054fa00d565b45ab59846194c5b94972c25c3b Mon Sep 17 00:00:00 2001 From: Jens Maus Date: Tue, 9 Mar 2021 21:06:51 +0100 Subject: [PATCH 09/22] added packages for RPI-RF-MOD/HM-MOD-RPI-PCB support to generic_x86_64 and ova defconfig files to be able to use HB-RF-XXX devices to connect the rf modules via ethernet or usb accordingly. --- buildroot-external/configs/generic_x86_64_defconfig | 3 +++ buildroot-external/configs/ova_defconfig | 3 +++ 2 files changed, 6 insertions(+) diff --git a/buildroot-external/configs/generic_x86_64_defconfig b/buildroot-external/configs/generic_x86_64_defconfig index ec7993ab3a2..777f8362893 100644 --- a/buildroot-external/configs/generic_x86_64_defconfig +++ b/buildroot-external/configs/generic_x86_64_defconfig @@ -108,3 +108,6 @@ BR2_PACKAGE_APPARMOR_PROFILES=y BR2_PACKAGE_INTEL_E1000E=y BR2_PACKAGE_DOSFSTOOLS=y BR2_PACKAGE_DOSFSTOOLS_FSCK_FAT=y +BR2_PACKAGE_GENERIC_RAW_UART=y +BR2_PACKAGE_EQ3_CHAR_LOOP=y +BR2_PACKAGE_RPI_RF_MOD=y diff --git a/buildroot-external/configs/ova_defconfig b/buildroot-external/configs/ova_defconfig index a6fccf2c9c4..bd281b0a80d 100644 --- a/buildroot-external/configs/ova_defconfig +++ b/buildroot-external/configs/ova_defconfig @@ -98,3 +98,6 @@ BR2_PACKAGE_APPARMOR=y BR2_PACKAGE_APPARMOR_PROFILES=y BR2_PACKAGE_DOSFSTOOLS=y BR2_PACKAGE_DOSFSTOOLS_FSCK_FAT=y +BR2_PACKAGE_GENERIC_RAW_UART=y +BR2_PACKAGE_EQ3_CHAR_LOOP=y +BR2_PACKAGE_RPI_RF_MOD=y From bac6349771347851fc140b7056fef2ad02bb7773 Mon Sep 17 00:00:00 2001 From: Jens Maus Date: Tue, 9 Mar 2021 21:08:16 +0100 Subject: [PATCH 10/22] added basic support for RPI-RF-MOD/HM-MOD-RPI-PCB to odroid defconfig files. --- buildroot-external/configs/odroid_c2_defconfig | 3 +++ buildroot-external/configs/odroid_c4_defconfig | 3 +++ buildroot-external/configs/odroid_n2_defconfig | 3 +++ buildroot-external/configs/odroid_xu4_defconfig | 3 +++ 4 files changed, 12 insertions(+) diff --git a/buildroot-external/configs/odroid_c2_defconfig b/buildroot-external/configs/odroid_c2_defconfig index 35a4ec85689..f5bb95ddf72 100644 --- a/buildroot-external/configs/odroid_c2_defconfig +++ b/buildroot-external/configs/odroid_c2_defconfig @@ -106,3 +106,6 @@ BR2_PACKAGE_HARDKERNEL_BOOT_ODROID_C2=y BR2_PACKAGE_DOSFSTOOLS=y BR2_PACKAGE_DOSFSTOOLS_FSCK_FAT=y BR2_PACKAGE_RTL8812AU=y +BR2_PACKAGE_GENERIC_RAW_UART=y +BR2_PACKAGE_EQ3_CHAR_LOOP=y +BR2_PACKAGE_RPI_RF_MOD=y diff --git a/buildroot-external/configs/odroid_c4_defconfig b/buildroot-external/configs/odroid_c4_defconfig index 8a95e88d689..c5f431b0cb3 100644 --- a/buildroot-external/configs/odroid_c4_defconfig +++ b/buildroot-external/configs/odroid_c4_defconfig @@ -104,3 +104,6 @@ BR2_PACKAGE_APPARMOR_PROFILES=y BR2_PACKAGE_HARDKERNEL_BOOT=y BR2_PACKAGE_HARDKERNEL_BOOT_ODROID_C4=y BR2_PACKAGE_RTL8812AU=y +BR2_PACKAGE_GENERIC_RAW_UART=y +BR2_PACKAGE_EQ3_CHAR_LOOP=y +BR2_PACKAGE_RPI_RF_MOD=y diff --git a/buildroot-external/configs/odroid_n2_defconfig b/buildroot-external/configs/odroid_n2_defconfig index 36d09a599d0..f16c629ead6 100644 --- a/buildroot-external/configs/odroid_n2_defconfig +++ b/buildroot-external/configs/odroid_n2_defconfig @@ -106,3 +106,6 @@ BR2_PACKAGE_HARDKERNEL_BOOT_ODROID_N2=y BR2_PACKAGE_DOSFSTOOLS=y BR2_PACKAGE_DOSFSTOOLS_FSCK_FAT=y BR2_PACKAGE_RTL8812AU=y +BR2_PACKAGE_GENERIC_RAW_UART=y +BR2_PACKAGE_EQ3_CHAR_LOOP=y +BR2_PACKAGE_RPI_RF_MOD=y diff --git a/buildroot-external/configs/odroid_xu4_defconfig b/buildroot-external/configs/odroid_xu4_defconfig index 43171c2ba36..d3284317295 100644 --- a/buildroot-external/configs/odroid_xu4_defconfig +++ b/buildroot-external/configs/odroid_xu4_defconfig @@ -109,3 +109,6 @@ BR2_PACKAGE_HARDKERNEL_BOOT_ODROID_XU4=y BR2_PACKAGE_DOSFSTOOLS=y BR2_PACKAGE_DOSFSTOOLS_FSCK_FAT=y BR2_PACKAGE_RTL8812AU=y +BR2_PACKAGE_GENERIC_RAW_UART=y +BR2_PACKAGE_EQ3_CHAR_LOOP=y +BR2_PACKAGE_RPI_RF_MOD=y From 3f502f7157dbfd1ce24dced8e61e1a0a4c639cb0 Mon Sep 17 00:00:00 2001 From: Jens Maus Date: Sun, 14 Mar 2021 20:53:23 +0100 Subject: [PATCH 11/22] integrated changes according to https://github.com/home-assistant/operating-system/pull/1266#discussion_r593279953 Now a new config option (BR2_PACKAGE_GENERIC_RAW_UART_DTS) have to be used together with selection of the respective target platform so that the generic_raw_uart package compiles the selected device tree overlay. --- buildroot-external/configs/rpi0_w_defconfig | 2 ++ buildroot-external/configs/rpi2_defconfig | 2 ++ buildroot-external/configs/rpi3_64_defconfig | 2 ++ buildroot-external/configs/rpi3_defconfig | 2 ++ buildroot-external/configs/rpi4_64_defconfig | 2 ++ buildroot-external/configs/rpi4_defconfig | 2 ++ buildroot-external/configs/rpi_defconfig | 2 ++ buildroot-external/configs/tinker_defconfig | 2 ++ .../package/generic_raw_uart/Config.in | 27 +++++++++++++++++++ .../generic_raw_uart/generic_raw_uart.mk | 10 +++---- 10 files changed, 47 insertions(+), 6 deletions(-) diff --git a/buildroot-external/configs/rpi0_w_defconfig b/buildroot-external/configs/rpi0_w_defconfig index 19cd6440e9c..cc1a3897734 100644 --- a/buildroot-external/configs/rpi0_w_defconfig +++ b/buildroot-external/configs/rpi0_w_defconfig @@ -106,5 +106,7 @@ BR2_PACKAGE_BLUETOOTH_BCM43XX=y BR2_PACKAGE_DOSFSTOOLS=y BR2_PACKAGE_DOSFSTOOLS_FSCK_FAT=y BR2_PACKAGE_GENERIC_RAW_UART=y +BR2_PACKAGE_GENERIC_RAW_UART_DTS=y +BR2_PACKAGE_GENERIC_RAW_UART_DTS_RPI=y BR2_PACKAGE_EQ3_CHAR_LOOP=y BR2_PACKAGE_RPI_RF_MOD=y diff --git a/buildroot-external/configs/rpi2_defconfig b/buildroot-external/configs/rpi2_defconfig index 04867a4c25f..0f93e8227ca 100644 --- a/buildroot-external/configs/rpi2_defconfig +++ b/buildroot-external/configs/rpi2_defconfig @@ -105,5 +105,7 @@ BR2_PACKAGE_APPARMOR_PROFILES=y BR2_PACKAGE_DOSFSTOOLS=y BR2_PACKAGE_DOSFSTOOLS_FSCK_FAT=y BR2_PACKAGE_GENERIC_RAW_UART=y +BR2_PACKAGE_GENERIC_RAW_UART_DTS=y +BR2_PACKAGE_GENERIC_RAW_UART_DTS_RPI=y BR2_PACKAGE_EQ3_CHAR_LOOP=y BR2_PACKAGE_RPI_RF_MOD=y diff --git a/buildroot-external/configs/rpi3_64_defconfig b/buildroot-external/configs/rpi3_64_defconfig index 4d83ead3816..87c76b02fd8 100644 --- a/buildroot-external/configs/rpi3_64_defconfig +++ b/buildroot-external/configs/rpi3_64_defconfig @@ -106,5 +106,7 @@ BR2_PACKAGE_BLUETOOTH_BCM43XX=y BR2_PACKAGE_DOSFSTOOLS=y BR2_PACKAGE_DOSFSTOOLS_FSCK_FAT=y BR2_PACKAGE_GENERIC_RAW_UART=y +BR2_PACKAGE_GENERIC_RAW_UART_DTS=y +BR2_PACKAGE_GENERIC_RAW_UART_DTS_RPI=y BR2_PACKAGE_EQ3_CHAR_LOOP=y BR2_PACKAGE_RPI_RF_MOD=y diff --git a/buildroot-external/configs/rpi3_defconfig b/buildroot-external/configs/rpi3_defconfig index 4bdb8ae673a..fd698d8cbac 100644 --- a/buildroot-external/configs/rpi3_defconfig +++ b/buildroot-external/configs/rpi3_defconfig @@ -106,5 +106,7 @@ BR2_PACKAGE_BLUETOOTH_BCM43XX=y BR2_PACKAGE_DOSFSTOOLS=y BR2_PACKAGE_DOSFSTOOLS_FSCK_FAT=y BR2_PACKAGE_GENERIC_RAW_UART=y +BR2_PACKAGE_GENERIC_RAW_UART_DTS=y +BR2_PACKAGE_GENERIC_RAW_UART_DTS_RPI=y BR2_PACKAGE_EQ3_CHAR_LOOP=y BR2_PACKAGE_RPI_RF_MOD=y diff --git a/buildroot-external/configs/rpi4_64_defconfig b/buildroot-external/configs/rpi4_64_defconfig index 969f22a3f95..23a35358888 100644 --- a/buildroot-external/configs/rpi4_64_defconfig +++ b/buildroot-external/configs/rpi4_64_defconfig @@ -110,5 +110,7 @@ BR2_PACKAGE_BLUETOOTH_BCM43XX=y BR2_PACKAGE_DOSFSTOOLS=y BR2_PACKAGE_DOSFSTOOLS_FSCK_FAT=y BR2_PACKAGE_GENERIC_RAW_UART=y +BR2_PACKAGE_GENERIC_RAW_UART_DTS=y +BR2_PACKAGE_GENERIC_RAW_UART_DTS_RPI=y BR2_PACKAGE_EQ3_CHAR_LOOP=y BR2_PACKAGE_RPI_RF_MOD=y diff --git a/buildroot-external/configs/rpi4_defconfig b/buildroot-external/configs/rpi4_defconfig index 5f4fc847574..232869172fa 100644 --- a/buildroot-external/configs/rpi4_defconfig +++ b/buildroot-external/configs/rpi4_defconfig @@ -107,5 +107,7 @@ BR2_PACKAGE_BLUETOOTH_BCM43XX=y BR2_PACKAGE_DOSFSTOOLS=y BR2_PACKAGE_DOSFSTOOLS_FSCK_FAT=y BR2_PACKAGE_GENERIC_RAW_UART=y +BR2_PACKAGE_GENERIC_RAW_UART_DTS=y +BR2_PACKAGE_GENERIC_RAW_UART_DTS_RPI=y BR2_PACKAGE_EQ3_CHAR_LOOP=y BR2_PACKAGE_RPI_RF_MOD=y diff --git a/buildroot-external/configs/rpi_defconfig b/buildroot-external/configs/rpi_defconfig index 2f6680319d1..ae96712c5ec 100644 --- a/buildroot-external/configs/rpi_defconfig +++ b/buildroot-external/configs/rpi_defconfig @@ -105,5 +105,7 @@ BR2_PACKAGE_APPARMOR_PROFILES=y BR2_PACKAGE_DOSFSTOOLS=y BR2_PACKAGE_DOSFSTOOLS_FSCK_FAT=y BR2_PACKAGE_GENERIC_RAW_UART=y +BR2_PACKAGE_GENERIC_RAW_UART_DTS=y +BR2_PACKAGE_GENERIC_RAW_UART_DTS_RPI=y BR2_PACKAGE_EQ3_CHAR_LOOP=y BR2_PACKAGE_RPI_RF_MOD=y diff --git a/buildroot-external/configs/tinker_defconfig b/buildroot-external/configs/tinker_defconfig index a419fb2de00..a8f97e25d27 100644 --- a/buildroot-external/configs/tinker_defconfig +++ b/buildroot-external/configs/tinker_defconfig @@ -111,5 +111,7 @@ BR2_PACKAGE_BLUETOOTH_RTL8723=y BR2_PACKAGE_DOSFSTOOLS=y BR2_PACKAGE_DOSFSTOOLS_FSCK_FAT=y BR2_PACKAGE_GENERIC_RAW_UART=y +BR2_PACKAGE_GENERIC_RAW_UART_DTS=y +BR2_PACKAGE_GENERIC_RAW_UART_DTS_TINKER=y BR2_PACKAGE_EQ3_CHAR_LOOP=y BR2_PACKAGE_RPI_RF_MOD=y diff --git a/buildroot-external/package/generic_raw_uart/Config.in b/buildroot-external/package/generic_raw_uart/Config.in index 81f38f64164..6d5bf26fda7 100644 --- a/buildroot-external/package/generic_raw_uart/Config.in +++ b/buildroot-external/package/generic_raw_uart/Config.in @@ -5,3 +5,30 @@ config BR2_PACKAGE_GENERIC_RAW_UART Alexander Reinert https://github.com/alexreinert/piVCCU/tree/master/kernel + +if BR2_PACKAGE_GENERIC_RAW_UART + +config BR2_PACKAGE_GENERIC_RAW_UART_DTS + bool "Compile Device Tree Overlay" + +if BR2_PACKAGE_GENERIC_RAW_UART_DTS + +choice + prompt "For Target" + default BR2_PACKAGE_GENERIC_RAW_UART_DTS_RPI + +config BR2_PACKAGE_GENERIC_RAW_UART_DTS_RPI + bool "RaspberryPi" + help + For the RaspberryPi + +config BR2_PACKAGE_GENERIC_RAW_UART_DTS_TINKER + bool "ASUS Tinkerboard" + help + For the ASUS Tinkerboard + +endchoice + +endif + +endif diff --git a/buildroot-external/package/generic_raw_uart/generic_raw_uart.mk b/buildroot-external/package/generic_raw_uart/generic_raw_uart.mk index 09feeb5d91d..bd1ea6b79af 100644 --- a/buildroot-external/package/generic_raw_uart/generic_raw_uart.mk +++ b/buildroot-external/package/generic_raw_uart/generic_raw_uart.mk @@ -21,13 +21,11 @@ GENERIC_RAW_UART_DEPENDENCIES = host-dtc GENERIC_RAW_UART_MODULE_SUBDIRS = kernel GENERIC_RAW_UART_INSTALL_IMAGES = YES -# RaspberryPi DTS file -ifneq (,$(findstring raspberrypi,$(BR2_PACKAGE_HASSIO_MACHINE))) +ifeq ($(BR2_PACKAGE_GENERIC_RAW_UART_DTS_RPI),y) + # RaspberryPi DTS file GENERIC_RAW_UART_DTS_FILE = pivccu-raspberrypi -endif - -# Tinkerboard DTS file -ifneq (,$(findstring tinker,$(BR2_PACKAGE_HASSIO_MACHINE))) +else ifeq ($(BR2_PACKAGE_GENERIC_RAW_UART_DTS_TINKER),y) + # ASUS Tinkerboard DTS file GENERIC_RAW_UART_DTS_FILE = pivccu-tinkerboard endif From 447911f765171bede2bd889b4b52983fdc9b9abc Mon Sep 17 00:00:00 2001 From: Jens Maus Date: Fri, 19 Mar 2021 12:34:05 +0100 Subject: [PATCH 12/22] removed the dedicated rx8130-rtc buildroot package in favor of using the mainline rtc-ds1307 kernel module which in fact also comes with supercap charging functionality in recent 5.10.x kernels. Thus there does not seem to be a reason for the seperate kernel module anymore which is used on a RPI-RF-MOD. This refs https://github.com/home-assistant/operating-system/pull/1266#pullrequestreview-610908610 --- buildroot-external/Config.in | 1 - .../0004-dts-mainline-rx8130.patch | 15 + .../package/rpi-rf-mod/Config.in | 1 - .../rpi-rf-mod/dts/rpi-rf-mod-tinker.dts | 4 +- .../package/rpi-rf-mod/dts/rpi-rf-mod.dts | 4 +- .../package/rx8130-rtc/Config.in | 2 - .../kernel-modules/rtc_rx8130ce/Makefile | 7 - .../kernel-modules/rtc_rx8130ce/rtc-rx8130.c | 856 ------------------ .../package/rx8130-rtc/rx8130-rtc.mk | 18 - 9 files changed, 19 insertions(+), 889 deletions(-) create mode 100644 buildroot-external/package/generic_raw_uart/0004-dts-mainline-rx8130.patch delete mode 100644 buildroot-external/package/rx8130-rtc/Config.in delete mode 100755 buildroot-external/package/rx8130-rtc/kernel-modules/rtc_rx8130ce/Makefile delete mode 100644 buildroot-external/package/rx8130-rtc/kernel-modules/rtc_rx8130ce/rtc-rx8130.c delete mode 100644 buildroot-external/package/rx8130-rtc/rx8130-rtc.mk diff --git a/buildroot-external/Config.in b/buildroot-external/Config.in index 51e51e0ddfa..49bd108aa18 100644 --- a/buildroot-external/Config.in +++ b/buildroot-external/Config.in @@ -10,4 +10,3 @@ source "$BR2_EXTERNAL_HASSOS_PATH/package/os-agent/Config.in" source "$BR2_EXTERNAL_HASSOS_PATH/package/eq3_char_loop/Config.in" source "$BR2_EXTERNAL_HASSOS_PATH/package/generic_raw_uart/Config.in" source "$BR2_EXTERNAL_HASSOS_PATH/package/rpi-rf-mod/Config.in" -source "$BR2_EXTERNAL_HASSOS_PATH/package/rx8130-rtc/Config.in" diff --git a/buildroot-external/package/generic_raw_uart/0004-dts-mainline-rx8130.patch b/buildroot-external/package/generic_raw_uart/0004-dts-mainline-rx8130.patch new file mode 100644 index 00000000000..ca2172062f8 --- /dev/null +++ b/buildroot-external/package/generic_raw_uart/0004-dts-mainline-rx8130.patch @@ -0,0 +1,15 @@ +--- ./dts/pivccu-raspberrypi.dts.orig 2019-07-04 13:54:53.271472462 +0200 ++++ ./dts/pivccu-raspberrypi.dts 2021-03-18 22:10:52.040233559 +0100 +@@ -23,10 +23,10 @@ + status = "okay"; + + rx8130@32 { +- compatible = "epson,rx8130-legacy"; ++ compatible = "epson,rx8130"; + reg = <0x32>; + status = "okay"; +- enable-external-capacitor; ++ aux-voltage-chargeable = <1>; + }; + }; + }; diff --git a/buildroot-external/package/rpi-rf-mod/Config.in b/buildroot-external/package/rpi-rf-mod/Config.in index e4a6356b847..8820ad0e182 100644 --- a/buildroot-external/package/rpi-rf-mod/Config.in +++ b/buildroot-external/package/rpi-rf-mod/Config.in @@ -1,3 +1,2 @@ config BR2_PACKAGE_RPI_RF_MOD - select BR2_PACKAGE_RX8130_RTC bool "Support for RPI-RF-MOD/HM-MOD-RPI-PCB GPIO HAT" diff --git a/buildroot-external/package/rpi-rf-mod/dts/rpi-rf-mod-tinker.dts b/buildroot-external/package/rpi-rf-mod/dts/rpi-rf-mod-tinker.dts index ff7412c5afe..5b34d062645 100644 --- a/buildroot-external/package/rpi-rf-mod/dts/rpi-rf-mod-tinker.dts +++ b/buildroot-external/package/rpi-rf-mod/dts/rpi-rf-mod-tinker.dts @@ -73,10 +73,10 @@ status = "okay"; rx8130@32 { - compatible = "epson,rx8130-legacy"; + compatible = "epson,rx8130"; reg = <0x32>; status = "okay"; - enable-external-capacitor; + aux-voltage-chargeable = <1>; }; }; }; diff --git a/buildroot-external/package/rpi-rf-mod/dts/rpi-rf-mod.dts b/buildroot-external/package/rpi-rf-mod/dts/rpi-rf-mod.dts index 0f3324740c0..3bef5fce492 100644 --- a/buildroot-external/package/rpi-rf-mod/dts/rpi-rf-mod.dts +++ b/buildroot-external/package/rpi-rf-mod/dts/rpi-rf-mod.dts @@ -64,10 +64,10 @@ status = "okay"; rx8130@32 { - compatible = "epson,rx8130-legacy"; + compatible = "epson,rx8130"; reg = <0x32>; status = "okay"; - enable-external-capacitor; + aux-voltage-chargeable = <1>; }; }; }; diff --git a/buildroot-external/package/rx8130-rtc/Config.in b/buildroot-external/package/rx8130-rtc/Config.in deleted file mode 100644 index bc6430bd47c..00000000000 --- a/buildroot-external/package/rx8130-rtc/Config.in +++ /dev/null @@ -1,2 +0,0 @@ -config BR2_PACKAGE_RX8130_RTC - bool "Support for Epson RX8130CE real time clock" diff --git a/buildroot-external/package/rx8130-rtc/kernel-modules/rtc_rx8130ce/Makefile b/buildroot-external/package/rx8130-rtc/kernel-modules/rtc_rx8130ce/Makefile deleted file mode 100755 index 0a5cd567d1f..00000000000 --- a/buildroot-external/package/rx8130-rtc/kernel-modules/rtc_rx8130ce/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -obj-m += rtc-rx8130.o - -all: - make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules - -clean: - make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean diff --git a/buildroot-external/package/rx8130-rtc/kernel-modules/rtc_rx8130ce/rtc-rx8130.c b/buildroot-external/package/rx8130-rtc/kernel-modules/rtc_rx8130ce/rtc-rx8130.c deleted file mode 100644 index bdb8796f0c6..00000000000 --- a/buildroot-external/package/rx8130-rtc/kernel-modules/rtc_rx8130ce/rtc-rx8130.c +++ /dev/null @@ -1,856 +0,0 @@ -//====================================================================== -// Driver for the Epson RTC module RX-8130 CE -// -// Copyright(C) SEIKO EPSON CORPORATION 2014. All rights reserved. -// -// Derived from RX-8025 driver: -// Copyright (C) 2009 Wolfgang Grandegger -// -// Copyright (C) 2005 by Digi International Inc. -// All rights reserved. -// -// Modified by fengjh at rising.com.cn -// -// 2006.11 -// -// Code cleanup by Sergei Poselenov, -// Converted to new style by Wolfgang Grandegger -// Alarm and periodic interrupt added by Dmitry Rakhchev -// Support to enable Capacitor loading using device tree added by Alexander Reinert -// -// -// This driver software is distributed as is, without any warranty of any kind, -// either express or implied as further specified in the GNU Public License. This -// software may be used and distributed according to the terms of the GNU Public -// License, version 2 as published by the Free Software Foundation. -// See the file COPYING in the main directory of this archive for more details. -// -// You should have received a copy of the GNU General Public License along with -// this program. If not, see . -//====================================================================== - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -// RX-8130 Register definitions -#define RX8130_REG_SEC 0x10 -#define RX8130_REG_MIN 0x11 -#define RX8130_REG_HOUR 0x12 -#define RX8130_REG_WDAY 0x13 -#define RX8130_REG_MDAY 0x14 -#define RX8130_REG_MONTH 0x15 -#define RX8130_REG_YEAR 0x16 - -#define RX8130_REG_ALMIN 0x17 -#define RX8130_REG_ALHOUR 0x18 -#define RX8130_REG_ALWDAY 0x19 -#define RX8130_REG_TCOUNT0 0x1A -#define RX8130_REG_TCOUNT1 0x1B -#define RX8130_REG_EXT 0x1C -#define RX8130_REG_FLAG 0x1D -#define RX8130_REG_CTRL0 0x1E -#define RX8130_REG_CTRL1 0x1F - -#define RX8130_REG_END 0x23 - -// Extension Register (1Ch) bit positions -#define RX8130_BIT_EXT_TSEL (7 << 0) -#define RX8130_BIT_EXT_WADA (1 << 3) -#define RX8130_BIT_EXT_TE (1 << 4) -#define RX8130_BIT_EXT_USEL (1 << 5) -#define RX8130_BIT_EXT_FSEL (3 << 6) - -// Flag Register (1Dh) bit positions -#define RX8130_BIT_FLAG_VLF (1 << 1) -#define RX8130_BIT_FLAG_AF (1 << 3) -#define RX8130_BIT_FLAG_TF (1 << 4) -#define RX8130_BIT_FLAG_UF (1 << 5) - -// Control 0 Register (1Еh) bit positions -#define RX8130_BIT_CTRL_TSTP (1 << 2) -#define RX8130_BIT_CTRL_AIE (1 << 3) -#define RX8130_BIT_CTRL_TIE (1 << 4) -#define RX8130_BIT_CTRL_UIE (1 << 5) -#define RX8130_BIT_CTRL_STOP (1 << 6) -#define RX8130_BIT_CTRL_TEST (1 << 7) - -// Control 1 Register (1Fh) bit positions -#define RX8130_BIT_CTRL_BFVSEL0 (1 << 0) -#define RX8130_BIT_CTRL_BFVSEL1 (1 << 1) -#define RX8130_BIT_CTRL_RSVSEL (1 << 2) -#define RX8130_BIT_CTRL_INIEN (1 << 4) -#define RX8130_BIT_CTRL_CHGEN (1 << 5) -#define RX8130_BIT_CTRL_SMPTSEL0 (1 << 6) -#define RX8130_BIT_CTRL_SMPTSEL1 (1 << 7) - -static const struct i2c_device_id rx8130_id[] = { - {"rx8130", 0}, - {"rx8130-legacy", 0}, - {}}; -MODULE_DEVICE_TABLE(i2c, rx8130_id); - -static const struct of_device_id rx8130_of_match[] = { - { - .compatible = "epson,rx8130-legacy", - }, - {}}; -MODULE_DEVICE_TABLE(of, rx8130_of_match); - -struct rx8130_data -{ - struct i2c_client *client; - struct rtc_device *rtc; - struct work_struct work; - u8 ctrlreg; - unsigned exiting : 1; - bool enable_external_capacitor; -}; - -typedef struct -{ - u8 number; - u8 value; -} reg_data; - -#define SE_RTC_REG_READ _IOWR('p', 0x20, reg_data) -#define SE_RTC_REG_WRITE _IOW('p', 0x21, reg_data) - -//---------------------------------------------------------------------- -// rx8130_read_reg() -// reads a rx8130 register (see Register defines) -// See also rx8130_read_regs() to read multiple registers. -// -//---------------------------------------------------------------------- -static int rx8130_read_reg(struct i2c_client *client, int number, u8 *value) -{ - int ret = i2c_smbus_read_byte_data(client, number); - - //check for error - if (ret < 0) - { - dev_err(&client->dev, "Unable to read register #%d\n", number); - return ret; - } - - *value = ret; - return 0; -} - -//---------------------------------------------------------------------- -// rx8130_read_regs() -// reads a specified number of rx8130 registers (see Register defines) -// See also rx8130_read_reg() to read single register. -// -//---------------------------------------------------------------------- -static int rx8130_read_regs(struct i2c_client *client, int number, u8 length, u8 *values) -{ - int ret = i2c_smbus_read_i2c_block_data(client, number, length, values); - - //check for length error - if (ret != length) - { - dev_err(&client->dev, "Unable to read registers #%d..#%d\n", number, number + length - 1); - return ret < 0 ? ret : -EIO; - } - - return 0; -} - -//---------------------------------------------------------------------- -// rx8130_write_reg() -// writes a rx8130 register (see Register defines) -// See also rx8130_write_regs() to write multiple registers. -// -//---------------------------------------------------------------------- -static int rx8130_write_reg(struct i2c_client *client, int number, u8 value) -{ - int ret = i2c_smbus_write_byte_data(client, number, value); - - //check for error - if (ret) - dev_err(&client->dev, "Unable to write register #%d\n", number); - - return ret; -} - -//---------------------------------------------------------------------- -// rx8130_write_regs() -// writes a specified number of rx8130 registers (see Register defines) -// See also rx8130_write_reg() to write a single register. -// -//---------------------------------------------------------------------- -static int rx8130_write_regs(struct i2c_client *client, int number, u8 length, u8 *values) -{ - int ret = i2c_smbus_write_i2c_block_data(client, number, length, values); - - //check for error - if (ret) - dev_err(&client->dev, "Unable to write registers #%d..#%d\n", number, number + length - 1); - - return ret; -} - -//---------------------------------------------------------------------- -// rx8130_irq() -// irq handler -// -//---------------------------------------------------------------------- -static irqreturn_t rx8130_irq(int irq, void *dev_id) -{ - struct i2c_client *client = dev_id; - struct rx8130_data *rx8130 = i2c_get_clientdata(client); - - disable_irq_nosync(irq); - schedule_work(&rx8130->work); - - return IRQ_HANDLED; -} - -//---------------------------------------------------------------------- -// rx8130_work() -// -//---------------------------------------------------------------------- -static void rx8130_work(struct work_struct *work) -{ - struct rx8130_data *rx8130 = container_of(work, struct rx8130_data, work); - struct i2c_client *client = rx8130->client; - struct mutex *lock = &rx8130->rtc->ops_lock; - u8 status; - - mutex_lock(lock); - - if (rx8130_read_reg(client, RX8130_REG_FLAG, &status)) - goto out; - - // check VLF - if ((status & RX8130_BIT_FLAG_VLF)) - dev_warn(&client->dev, "Frequency stop was detected, probably due to a supply voltage drop\n"); - - dev_dbg(&client->dev, "%s: RX8130_REG_FLAG: %xh\n", __func__, status); - - // periodic "fixed-cycle" timer - if (status & RX8130_BIT_FLAG_TF) - { - status &= ~RX8130_BIT_FLAG_TF; - local_irq_disable(); - rtc_update_irq(rx8130->rtc, 1, RTC_PF | RTC_IRQF); - local_irq_enable(); - } - - // alarm function - if (status & RX8130_BIT_FLAG_AF) - { - status &= ~RX8130_BIT_FLAG_AF; - local_irq_disable(); - rtc_update_irq(rx8130->rtc, 1, RTC_AF | RTC_IRQF); - local_irq_enable(); - } - - // time update function - if (status & RX8130_BIT_FLAG_UF) - { - status &= ~RX8130_BIT_FLAG_UF; - local_irq_disable(); - rtc_update_irq(rx8130->rtc, 1, RTC_UF | RTC_IRQF); - local_irq_enable(); - } - - // acknowledge IRQ - rx8130_write_reg(client, RX8130_REG_FLAG, status); //clear flags - -out: - if (!rx8130->exiting) - enable_irq(client->irq); - - mutex_unlock(lock); -} - -//---------------------------------------------------------------------- -// rx8130_get_time() -// gets the current time from the rx8130 registers -// -//---------------------------------------------------------------------- -static int rx8130_get_time(struct device *dev, struct rtc_time *dt) -{ - struct rx8130_data *rx8130 = dev_get_drvdata(dev); - u8 date[7]; - int err; - - err = rx8130_read_regs(rx8130->client, RX8130_REG_SEC, 7, date); - if (err) - return err; - - dev_dbg(dev, "%s: read 0x%02x 0x%02x " - "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", - __func__, - date[0], date[1], date[2], date[3], date[4], date[5], date[6]); - - //Note: need to subtract 0x10 for index as register offset starts at 0x10 - dt->tm_sec = bcd2bin(date[RX8130_REG_SEC - 0x10] & 0x7f); - dt->tm_min = bcd2bin(date[RX8130_REG_MIN - 0x10] & 0x7f); - dt->tm_hour = bcd2bin(date[RX8130_REG_HOUR - 0x10] & 0x3f); //only 24-hour clock - dt->tm_mday = bcd2bin(date[RX8130_REG_MDAY - 0x10] & 0x3f); - dt->tm_mon = bcd2bin(date[RX8130_REG_MONTH - 0x10] & 0x1f) - 1; - dt->tm_year = bcd2bin(date[RX8130_REG_YEAR - 0x10]); - dt->tm_wday = bcd2bin(date[RX8130_REG_WDAY - 0x10] & 0x7f); - - if (dt->tm_year < 70) - dt->tm_year += 100; - - dev_dbg(dev, "%s: date %ds %dm %dh %dmd %dm %dy\n", __func__, - dt->tm_sec, dt->tm_min, dt->tm_hour, - dt->tm_mday, dt->tm_mon, dt->tm_year); - - return rtc_valid_tm(dt); -} - -//---------------------------------------------------------------------- -// rx8130_set_time() -// Sets the current time in the rx8130 registers -// -// Note: If STOP is not set/cleared, the clock will start when the seconds -// register is written -// -//---------------------------------------------------------------------- -static int rx8130_set_time(struct device *dev, struct rtc_time *dt) -{ - struct rx8130_data *rx8130 = dev_get_drvdata(dev); - u8 date[7]; - u8 ctrl; - int ret; - - //set STOP bit before changing clock/calendar - rx8130_read_reg(rx8130->client, RX8130_REG_CTRL0, &ctrl); - rx8130->ctrlreg = ctrl | RX8130_BIT_CTRL_STOP; - rx8130_write_reg(rx8130->client, RX8130_REG_CTRL0, rx8130->ctrlreg); - - dev_dbg(dev, "%s: date %ds %dm %dh %dmd %dm %dy\n", __func__, - dt->tm_sec, dt->tm_min, dt->tm_hour, - dt->tm_mday, dt->tm_mon, dt->tm_year); - - //Note: need to subtract 0x10 for index as register offset starts at 0x10 - date[RX8130_REG_SEC - 0x10] = bin2bcd(dt->tm_sec); - date[RX8130_REG_MIN - 0x10] = bin2bcd(dt->tm_min); - date[RX8130_REG_HOUR - 0x10] = bin2bcd(dt->tm_hour); //only 24hr time - - date[RX8130_REG_MDAY - 0x10] = bin2bcd(dt->tm_mday); - date[RX8130_REG_MONTH - 0x10] = bin2bcd(dt->tm_mon + 1); - date[RX8130_REG_YEAR - 0x10] = bin2bcd(dt->tm_year % 100); - date[RX8130_REG_WDAY - 0x10] = bin2bcd(dt->tm_wday); - - dev_dbg(dev, "%s: write 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", - __func__, date[0], date[1], date[2], date[3], date[4], date[5], date[6]); - - ret = rx8130_write_regs(rx8130->client, RX8130_REG_SEC, 7, date); - - //clear STOP bit after changing clock/calendar - rx8130_read_reg(rx8130->client, RX8130_REG_CTRL0, &ctrl); - rx8130->ctrlreg = ctrl & ~RX8130_BIT_CTRL_STOP; - rx8130_write_reg(rx8130->client, RX8130_REG_CTRL0, rx8130->ctrlreg); - - return ret; -} - -//---------------------------------------------------------------------- -// rx8130_init_client() -// initializes the rx8130 -// -//---------------------------------------------------------------------- -static int rx8130_init_client(struct i2c_client *client, int *need_reset) -{ - struct rx8130_data *rx8130 = i2c_get_clientdata(client); - u8 ctrl[3]; - int need_clear = 0; - int err; - - //get current extension, flag, control register values - dev_dbg(&client->dev, "Trying to read RX8130_REG_EXT\n"); - err = rx8130_read_regs(rx8130->client, RX8130_REG_EXT, 3, ctrl); - if (err) - goto out; - - //set extension register, TE to 0, FSEL1-0 and TSEL2-0 for desired frequency - ctrl[0] &= ~RX8130_BIT_EXT_TE; //set TE to 0 - ctrl[0] &= ~RX8130_BIT_EXT_FSEL; //set to 0 (off) for this case - ctrl[0] |= 0x02; //set TSEL for 1Hz - err = rx8130_write_reg(client, RX8130_REG_EXT, ctrl[0]); - if (err) - goto out; - - //clear "test bit" - rx8130->ctrlreg = (ctrl[2] & ~RX8130_BIT_CTRL_TEST); - - if (rx8130->enable_external_capacitor) - { - // enable charging of external capacitor - dev_info(&client->dev, "Enabling charging of external capacitor\n"); - ctrl[2] |= RX8130_BIT_CTRL_CHGEN; - ctrl[2] |= RX8130_BIT_CTRL_INIEN; - ctrl[2] |= RX8130_BIT_CTRL_BFVSEL0; - err = rx8130_write_reg(client, RX8130_REG_CTRL1, ctrl[2]); - if (err) - goto out; - } - - //check for VLF Flag (set at power-on) - if ((ctrl[1] & RX8130_BIT_FLAG_VLF)) - { - dev_warn(&client->dev, "Frequency stop was detected, probably due to a supply voltage drop\n"); - *need_reset = 1; - } - - //check for Alarm Flag - if (ctrl[1] & RX8130_BIT_FLAG_AF) - { - dev_warn(&client->dev, "Alarm was detected\n"); - need_clear = 1; - } - - //check for Periodic Timer Flag - if (ctrl[1] & RX8130_BIT_FLAG_TF) - { - dev_warn(&client->dev, "Periodic timer was detected\n"); - need_clear = 1; - } - - //check for Update Timer Flag - if (ctrl[1] & RX8130_BIT_FLAG_UF) - { - dev_warn(&client->dev, "Update timer was detected\n"); - need_clear = 1; - } - - //reset or clear needed? - if (*need_reset || need_clear) - { - //clear flag register - err = rx8130_write_reg(client, RX8130_REG_FLAG, 0x00); - if (err) - goto out; - - //clear ctrl register - err = rx8130_write_reg(client, RX8130_REG_CTRL0, 0x00); - if (err) - goto out; - } -out: - return err; -} - -//---------------------------------------------------------------------- -// rx8130_read_alarm() -// reads current Alarm -//---------------------------------------------------------------------- -static int rx8130_read_alarm(struct device *dev, struct rtc_wkalrm *t) -{ - struct rx8130_data *rx8130 = dev_get_drvdata(dev); - struct i2c_client *client = rx8130->client; - u8 alarmvals[3]; //minute, hour, week/day values - u8 ctrl[3]; //extension, flag, control values - int err; - - if (client->irq <= 0) - return -EINVAL; - - //get current minute, hour, week/day alarm values - err = rx8130_read_regs(client, RX8130_REG_ALMIN, 3, alarmvals); - if (err) - return err; - dev_dbg(dev, "%s: minutes:0x%02x hours:0x%02x week/day:0x%02x\n", - __func__, alarmvals[0], alarmvals[1], alarmvals[2]); - - //get current extension, flag, control register values - err = rx8130_read_regs(client, RX8130_REG_EXT, 3, ctrl); - if (err) - return err; - dev_dbg(dev, "%s: extension:0x%02x flag:0x%02x control:0x%02x \n", - __func__, ctrl[0], ctrl[1], ctrl[2]); - - // Hardware alarm precision is 1 minute - t->time.tm_sec = 0; - t->time.tm_min = bcd2bin(alarmvals[0] & 0x7f); //0x7f filters AE bit currently - t->time.tm_hour = bcd2bin(alarmvals[1] & 0x3f); //0x3f filters AE bit currently, also 24hr only - - t->time.tm_wday = -1; - t->time.tm_mday = -1; - t->time.tm_mon = -1; - t->time.tm_year = -1; - - dev_dbg(dev, "%s: date: %ds %dm %dh %dmd %dm %dy\n", - __func__, - t->time.tm_sec, t->time.tm_min, t->time.tm_hour, - t->time.tm_mday, t->time.tm_mon, t->time.tm_year); - - t->enabled = !!(rx8130->ctrlreg & RX8130_BIT_CTRL_AIE); //check if interrupt is enabled - t->pending = (ctrl[1] & RX8130_BIT_FLAG_AF) && t->enabled; //check if flag is triggered - - return err; -} - -//---------------------------------------------------------------------- -// rx8130_set_alarm() -// sets Alarm -//---------------------------------------------------------------------- -static int rx8130_set_alarm(struct device *dev, struct rtc_wkalrm *t) -{ - struct i2c_client *client = to_i2c_client(dev); - struct rx8130_data *rx8130 = dev_get_drvdata(dev); - u8 alarmvals[3]; //minute, hour, day - u8 extreg; //extension register - u8 flagreg; //flag register - int err; - - if (client->irq <= 0) - return -EINVAL; - - //get current extension register - err = rx8130_read_reg(client, RX8130_REG_EXT, &extreg); - if (err < 0) - return err; - - //get current flag register - err = rx8130_read_reg(client, RX8130_REG_FLAG, &flagreg); - if (err < 0) - return err; - - // Hardware alarm precision is 1 minute - alarmvals[0] = bin2bcd(t->time.tm_min); - alarmvals[1] = bin2bcd(t->time.tm_hour); - alarmvals[2] = bin2bcd(t->time.tm_mday); - dev_dbg(dev, "%s: write 0x%02x 0x%02x 0x%02x\n", __func__, alarmvals[0], alarmvals[1], alarmvals[2]); - - //check interrupt enable and disable - if (rx8130->ctrlreg & (RX8130_BIT_CTRL_AIE | RX8130_BIT_CTRL_UIE)) - { - rx8130->ctrlreg &= ~(RX8130_BIT_CTRL_AIE | RX8130_BIT_CTRL_UIE); - err = rx8130_write_reg(rx8130->client, RX8130_REG_CTRL0, rx8130->ctrlreg); - if (err) - return err; - } - - //write the new minute and hour values - //Note:assume minute and hour values will be enabled. Bit 7 of each of the - // minute, hour, week/day register can be set which will "disable" the - // register from triggering an alarm. See the RX8130 spec for more information - err = rx8130_write_regs(rx8130->client, RX8130_REG_ALMIN, 2, alarmvals); - if (err) - return err; - - //set Week/Day bit - // Week setting is typically not used, so we will assume "day" setting - extreg |= RX8130_BIT_EXT_WADA; //set to "day of month" - err = rx8130_write_reg(rx8130->client, RX8130_REG_EXT, extreg); - if (err) - return err; - - //set Day of Month register - if (alarmvals[2] == 0) - { - alarmvals[2] |= 0x80; //turn on AE bit to ignore day of month (no zero day) - err = rx8130_write_reg(rx8130->client, RX8130_REG_ALWDAY, alarmvals[2]); - } - else - { - err = rx8130_write_reg(rx8130->client, RX8130_REG_ALWDAY, alarmvals[2]); - } - if (err) - return err; - - //clear Alarm Flag - flagreg &= ~(RX8130_BIT_FLAG_AF | RX8130_BIT_FLAG_UF); - err = rx8130_write_reg(rx8130->client, RX8130_REG_FLAG, flagreg); - if (err) - return err; - - //re-enable interrupt if required - if (t->enabled) - { - - if (rx8130->rtc->uie_rtctimer.enabled) - rx8130->ctrlreg |= RX8130_BIT_CTRL_UIE; //set update interrupt enable - if (rx8130->rtc->aie_timer.enabled) - rx8130->ctrlreg |= (RX8130_BIT_CTRL_AIE | RX8130_BIT_CTRL_UIE); //set alarm interrupt enable - - err = rx8130_write_reg(rx8130->client, RX8130_REG_CTRL0, rx8130->ctrlreg); - if (err) - return err; - } - - return 0; -} - -//---------------------------------------------------------------------- -// rx8130_alarm_irq_enable() -// sets enables Alarm IRQ -//---------------------------------------------------------------------- -static int rx8130_alarm_irq_enable(struct device *dev, unsigned int enabled) -{ - struct i2c_client *client = to_i2c_client(dev); - struct rx8130_data *rx8130 = dev_get_drvdata(dev); - u8 flagreg; - u8 ctrl; - int err; - - //get the current ctrl settings - ctrl = rx8130->ctrlreg; - - if (enabled) - { - if (rx8130->rtc->uie_rtctimer.enabled) - ctrl |= RX8130_BIT_CTRL_UIE; //set update interrupt enable - if (rx8130->rtc->aie_timer.enabled) - ctrl |= (RX8130_BIT_CTRL_AIE | RX8130_BIT_CTRL_UIE); //set alarm interrupt enable - } - else - { - if (!rx8130->rtc->uie_rtctimer.enabled) - ctrl &= ~RX8130_BIT_CTRL_UIE; //clear update interrupt enable - if (!rx8130->rtc->aie_timer.enabled) - { - if (rx8130->rtc->uie_rtctimer.enabled) - ctrl &= ~RX8130_BIT_CTRL_AIE; - else - ctrl &= ~(RX8130_BIT_CTRL_AIE | RX8130_BIT_CTRL_UIE); //clear alarm interrupt enable - } - } - - //clear alarm flag - err = rx8130_read_reg(client, RX8130_REG_FLAG, &flagreg); - if (err < 0) - return err; - flagreg &= ~RX8130_BIT_FLAG_AF; - err = rx8130_write_reg(rx8130->client, RX8130_REG_FLAG, flagreg); - if (err) - return err; - - //update the Control register if the setting changed - if (ctrl != rx8130->ctrlreg) - { - rx8130->ctrlreg = ctrl; - err = rx8130_write_reg(rx8130->client, RX8130_REG_CTRL0, rx8130->ctrlreg); - if (err) - return err; - } - - return 0; -} - -//--------------------------------------------------------------------------- -// rx8130_ioctl() -// -//--------------------------------------------------------------------------- -static int rx8130_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) -{ - struct i2c_client *client = to_i2c_client(dev); - //struct rx8130_data *rx8130 = dev_get_drvdata(dev); - //struct mutex *lock = &rx8130->rtc->ops_lock; - int ret = 0; - int tmp; - void __user *argp = (void __user *)arg; - reg_data reg; - - dev_dbg(dev, "%s: cmd=%x\n", __func__, cmd); - - switch (cmd) - { - case SE_RTC_REG_READ: - if (copy_from_user(®, argp, sizeof(reg))) - return -EFAULT; - if (reg.number < RX8130_REG_SEC || reg.number > RX8130_REG_END) - return -EFAULT; - //mutex_lock(lock); - ret = rx8130_read_reg(client, reg.number, ®.value); - //mutex_unlock(lock); - if (!ret) - return copy_to_user(argp, ®, sizeof(reg)) ? -EFAULT : 0; - break; - - case SE_RTC_REG_WRITE: - if (copy_from_user(®, argp, sizeof(reg))) - return -EFAULT; - if (reg.number < RX8130_REG_SEC || reg.number > RX8130_REG_END) - return -EFAULT; - //mutex_lock(lock); - ret = rx8130_write_reg(client, reg.number, reg.value); - //mutex_unlock(lock); - break; - - case RTC_VL_READ: - //mutex_lock(lock); - ret = rx8130_read_reg(client, RX8130_REG_FLAG, ®.value); - //mutex_unlock(lock); - if (!ret) - { - tmp = !!(reg.value & RX8130_BIT_FLAG_VLF); - return copy_to_user(argp, &tmp, sizeof(tmp)) ? -EFAULT : 0; - } - break; - - case RTC_VL_CLR: - //mutex_lock(lock); - ret = rx8130_read_reg(client, RX8130_REG_FLAG, ®.value); - if (!ret) - { - reg.value &= ~RX8130_BIT_FLAG_VLF; - ret = rx8130_write_reg(client, RX8130_REG_FLAG, reg.value); - } - //mutex_unlock(lock); - break; - - default: - return -ENOIOCTLCMD; - } - - return ret; -} - -static struct rtc_class_ops rx8130_rtc_ops = { - .read_time = rx8130_get_time, - .set_time = rx8130_set_time, - .read_alarm = rx8130_read_alarm, - .set_alarm = rx8130_set_alarm, - .alarm_irq_enable = rx8130_alarm_irq_enable, - .ioctl = rx8130_ioctl, -}; - -//---------------------------------------------------------------------- -// rx8130_probe() -// probe routine for the rx8130 driver -// -// Todo: - maybe change kzalloc to use devm_kzalloc -// - -//---------------------------------------------------------------------- -static int rx8130_probe(struct i2c_client *client, const struct i2c_device_id *id) -{ - struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); - struct rx8130_data *rx8130; - int err, need_reset = 0; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_I2C_BLOCK)) - { - dev_err(&adapter->dev, "doesn't support required functionality\n"); - err = -EIO; - goto errout; - } - - rx8130 = kzalloc(sizeof(*rx8130), GFP_KERNEL); - if (!rx8130) - { - dev_err(&adapter->dev, "failed to alloc memory\n"); - err = -ENOMEM; - goto errout; - } - - rx8130->client = client; - i2c_set_clientdata(client, rx8130); - INIT_WORK(&rx8130->work, rx8130_work); - -#ifdef CONFIG_OF - rx8130->enable_external_capacitor = of_property_read_bool(client->dev.of_node, "enable-external-capacitor"); -#endif - - err = rx8130_init_client(client, &need_reset); - if (err) - goto errout_free; - - if (need_reset) - { - struct rtc_time tm; - dev_info(&client->dev, "bad conditions detected, resetting date\n"); - rtc_time64_to_tm(0, &tm); // set to 1970/1/1 - - rx8130_set_time(&client->dev, &tm); - } - - rx8130->rtc = devm_rtc_device_register(&client->dev, client->name, &rx8130_rtc_ops, THIS_MODULE); - - if (IS_ERR(rx8130->rtc)) - { - err = PTR_ERR(rx8130->rtc); - dev_err(&client->dev, "unable to register the class device\n"); - goto errout_free; - } - - if (client->irq > 0) - { - dev_info(&client->dev, "IRQ %d supplied\n", client->irq); - err = devm_request_threaded_irq(&client->dev, client->irq, NULL, rx8130_irq, IRQF_TRIGGER_LOW | IRQF_ONESHOT, "rx8130", client); - - if (err) - { - dev_err(&client->dev, "unable to request IRQ\n"); - goto errout_reg; - } - } - - rx8130->rtc->irq_freq = 1; - rx8130->rtc->max_user_freq = 1; - - return 0; - -errout_reg: -errout_free: - kfree(rx8130); - -errout: - dev_err(&adapter->dev, "probing for rx8130 failed\n"); - return err; -} - -//---------------------------------------------------------------------- -// rx8130_remove() -// remove routine for the rx8130 driver -// -// Todo: - maybe change kzalloc to devm_kzalloc -// - -//---------------------------------------------------------------------- -static int rx8130_remove(struct i2c_client *client) -{ - struct rx8130_data *rx8130 = i2c_get_clientdata(client); - struct mutex *lock = &rx8130->rtc->ops_lock; - - if (client->irq > 0) - { - mutex_lock(lock); - rx8130->exiting = 1; - mutex_unlock(lock); - - free_irq(client->irq, client); - cancel_work_sync(&rx8130->work); - } - - kfree(rx8130); - return 0; -} - -static struct i2c_driver rx8130_driver = { - .driver = { - .name = "rtc-rx8130", - .of_match_table = of_match_ptr(rx8130_of_match), - .owner = THIS_MODULE, - }, - .probe = rx8130_probe, - .remove = rx8130_remove, - .id_table = rx8130_id, -}; - -module_i2c_driver(rx8130_driver); - -MODULE_AUTHOR("Val Krutov "); -MODULE_DESCRIPTION("RX8130CE RTC driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION("1.5"); diff --git a/buildroot-external/package/rx8130-rtc/rx8130-rtc.mk b/buildroot-external/package/rx8130-rtc/rx8130-rtc.mk deleted file mode 100644 index a47ce0906a1..00000000000 --- a/buildroot-external/package/rx8130-rtc/rx8130-rtc.mk +++ /dev/null @@ -1,18 +0,0 @@ -############################################################# -# -# Kernel module for the Epson RTC module RX-8130 CE -# (which is used on a RPI-RF-MOD) -# -# Copyright(C) SEIKO EPSON CORPORATION 2014. All rights reserved. -# -############################################################# - -RX8130_RTC_VERSION = 1.1.0 -RX8130_RTC_LICENSE = GPL2 -#RX8130_RTC_LICENSE_FILES = COPYING -RX8130_RTC_SITE = $(BR2_EXTERNAL_HASSOS_PATH)/package/rx8130-rtc -RX8130_RTC_SITE_METHOD = local -RX8130_RTC_MODULE_SUBDIRS = kernel-modules/rtc_rx8130ce - -$(eval $(kernel-module)) -$(eval $(generic-package)) From a5a6360ae30e6782a1cc690d4852ae20c444d279 Mon Sep 17 00:00:00 2001 From: Jens Maus Date: Fri, 19 Mar 2021 13:03:53 +0100 Subject: [PATCH 13/22] removed BR2_PACKAGE_HASSIO_MACHINE use in rpi-rf-mod buildroot package and replaced it by dedciated TARGET_RPI/TINKER config options to match the way this is done in other buildroot packages in HAos. --- buildroot-external/configs/rpi0_w_defconfig | 1 + buildroot-external/configs/rpi2_defconfig | 1 + buildroot-external/configs/rpi3_64_defconfig | 1 + buildroot-external/configs/rpi3_defconfig | 1 + buildroot-external/configs/rpi4_64_defconfig | 1 + buildroot-external/configs/rpi4_defconfig | 1 + buildroot-external/configs/rpi_defconfig | 1 + buildroot-external/configs/tinker_defconfig | 1 + .../package/rpi-rf-mod/Config.in | 20 +++++++++++++++++++ .../package/rpi-rf-mod/rpi-rf-mod.mk | 14 ++++++------- 10 files changed, 34 insertions(+), 8 deletions(-) diff --git a/buildroot-external/configs/rpi0_w_defconfig b/buildroot-external/configs/rpi0_w_defconfig index ab3ecc2eba1..e66c463d37c 100644 --- a/buildroot-external/configs/rpi0_w_defconfig +++ b/buildroot-external/configs/rpi0_w_defconfig @@ -111,3 +111,4 @@ BR2_PACKAGE_GENERIC_RAW_UART_DTS=y BR2_PACKAGE_GENERIC_RAW_UART_DTS_RPI=y BR2_PACKAGE_EQ3_CHAR_LOOP=y BR2_PACKAGE_RPI_RF_MOD=y +BR2_PACKAGE_RPI_RF_MOD_TARGET_RPI=y diff --git a/buildroot-external/configs/rpi2_defconfig b/buildroot-external/configs/rpi2_defconfig index 9096a54d2a1..ff0a315dc74 100644 --- a/buildroot-external/configs/rpi2_defconfig +++ b/buildroot-external/configs/rpi2_defconfig @@ -110,3 +110,4 @@ BR2_PACKAGE_GENERIC_RAW_UART_DTS=y BR2_PACKAGE_GENERIC_RAW_UART_DTS_RPI=y BR2_PACKAGE_EQ3_CHAR_LOOP=y BR2_PACKAGE_RPI_RF_MOD=y +BR2_PACKAGE_RPI_RF_MOD_TARGET_RPI diff --git a/buildroot-external/configs/rpi3_64_defconfig b/buildroot-external/configs/rpi3_64_defconfig index 973fe502087..928558f8e36 100644 --- a/buildroot-external/configs/rpi3_64_defconfig +++ b/buildroot-external/configs/rpi3_64_defconfig @@ -111,3 +111,4 @@ BR2_PACKAGE_GENERIC_RAW_UART_DTS=y BR2_PACKAGE_GENERIC_RAW_UART_DTS_RPI=y BR2_PACKAGE_EQ3_CHAR_LOOP=y BR2_PACKAGE_RPI_RF_MOD=y +BR2_PACKAGE_RPI_RF_MOD_TARGET_RPI=y diff --git a/buildroot-external/configs/rpi3_defconfig b/buildroot-external/configs/rpi3_defconfig index 55f9833a2a1..04e20aa160e 100644 --- a/buildroot-external/configs/rpi3_defconfig +++ b/buildroot-external/configs/rpi3_defconfig @@ -111,3 +111,4 @@ BR2_PACKAGE_GENERIC_RAW_UART_DTS=y BR2_PACKAGE_GENERIC_RAW_UART_DTS_RPI=y BR2_PACKAGE_EQ3_CHAR_LOOP=y BR2_PACKAGE_RPI_RF_MOD=y +BR2_PACKAGE_RPI_RF_MOD_TARGET_RPI=y diff --git a/buildroot-external/configs/rpi4_64_defconfig b/buildroot-external/configs/rpi4_64_defconfig index aef922e8f9d..3971e51ef17 100644 --- a/buildroot-external/configs/rpi4_64_defconfig +++ b/buildroot-external/configs/rpi4_64_defconfig @@ -115,3 +115,4 @@ BR2_PACKAGE_GENERIC_RAW_UART_DTS=y BR2_PACKAGE_GENERIC_RAW_UART_DTS_RPI=y BR2_PACKAGE_EQ3_CHAR_LOOP=y BR2_PACKAGE_RPI_RF_MOD=y +BR2_PACKAGE_RPI_RF_MOD_TARGET_RPI=y diff --git a/buildroot-external/configs/rpi4_defconfig b/buildroot-external/configs/rpi4_defconfig index 27af89bc758..65dee95f944 100644 --- a/buildroot-external/configs/rpi4_defconfig +++ b/buildroot-external/configs/rpi4_defconfig @@ -112,3 +112,4 @@ BR2_PACKAGE_GENERIC_RAW_UART_DTS=y BR2_PACKAGE_GENERIC_RAW_UART_DTS_RPI=y BR2_PACKAGE_EQ3_CHAR_LOOP=y BR2_PACKAGE_RPI_RF_MOD=y +BR2_PACKAGE_RPI_RF_MOD_TARGET_RPI=y diff --git a/buildroot-external/configs/rpi_defconfig b/buildroot-external/configs/rpi_defconfig index a07c4c82de0..feae918b35f 100644 --- a/buildroot-external/configs/rpi_defconfig +++ b/buildroot-external/configs/rpi_defconfig @@ -110,3 +110,4 @@ BR2_PACKAGE_GENERIC_RAW_UART_DTS=y BR2_PACKAGE_GENERIC_RAW_UART_DTS_RPI=y BR2_PACKAGE_EQ3_CHAR_LOOP=y BR2_PACKAGE_RPI_RF_MOD=y +BR2_PACKAGE_RPI_RF_MOD_TARGET_RPI=y diff --git a/buildroot-external/configs/tinker_defconfig b/buildroot-external/configs/tinker_defconfig index fc4bcad046a..0d2fa65a7a3 100644 --- a/buildroot-external/configs/tinker_defconfig +++ b/buildroot-external/configs/tinker_defconfig @@ -116,3 +116,4 @@ BR2_PACKAGE_GENERIC_RAW_UART_DTS=y BR2_PACKAGE_GENERIC_RAW_UART_DTS_TINKER=y BR2_PACKAGE_EQ3_CHAR_LOOP=y BR2_PACKAGE_RPI_RF_MOD=y +BR2_PACKAGE_RPI_RF_MOD_TARGET_TINKER=y diff --git a/buildroot-external/package/rpi-rf-mod/Config.in b/buildroot-external/package/rpi-rf-mod/Config.in index 8820ad0e182..dacd20957b3 100644 --- a/buildroot-external/package/rpi-rf-mod/Config.in +++ b/buildroot-external/package/rpi-rf-mod/Config.in @@ -1,2 +1,22 @@ config BR2_PACKAGE_RPI_RF_MOD bool "Support for RPI-RF-MOD/HM-MOD-RPI-PCB GPIO HAT" + +if BR2_PACKAGE_RPI_RF_MOD + +choice + prompt "For Target" + default BR2_PACKAGE_RPI_RF_MOD_TARGET_RPI + +config BR2_PACKAGE_RPI_RF_MOD_TARGET_RPI + bool "RaspberryPi" + help + For the RaspberryPi + +config BR2_PACKAGE_RPI_RF_MOD_TARGET_TINKER + bool "ASUS Tinkerboard" + help + For the ASUS Tinkerboard + +endchoice + +endif diff --git a/buildroot-external/package/rpi-rf-mod/rpi-rf-mod.mk b/buildroot-external/package/rpi-rf-mod/rpi-rf-mod.mk index f52e5e09188..850db215b22 100644 --- a/buildroot-external/package/rpi-rf-mod/rpi-rf-mod.mk +++ b/buildroot-external/package/rpi-rf-mod/rpi-rf-mod.mk @@ -14,14 +14,12 @@ RPI_RF_MOD_SITE_METHOD = local RPI_RF_MOD_LICENSE = Apache-2.0 #RPI_RF_MOD_LICENSE_FILES = LICENSE -# RaspberryPi DTS file -ifneq (,$(findstring raspberrypi,$(BR2_PACKAGE_HASSIO_MACHINE))) - RPI_RF_MOD_DTS_FILE = rpi-rf-mod -endif - -# Tinkerboard DTS file -ifneq (,$(findstring tinker,$(BR2_PACKAGE_HASSIO_MACHINE))) - RPI_RF_MOD_DTS_FILE = rpi-rf-mod-tinker +ifeq ($(BR2_PACKAGE_RPI_RF_MOD_TARGET_RPI),y) + # RaspberryPi DTS file + RPI_RF_MOD_DTS_FILE = rpi-rf-mod +else ifeq ($(BR2_PACKAGE_RPI_RF_MOD_TARGET_TINKER),y) + # ASUS Tinkerboard DTS file + RPI_RF_MOD_DTS_FILE = rpi-rf-mod-tinker endif define RPI_RF_MOD_BUILD_CMDS From 52b33805aea8924a8864b8571ab360296f2119d4 Mon Sep 17 00:00:00 2001 From: Jens Maus Date: Fri, 19 Mar 2021 13:20:35 +0100 Subject: [PATCH 14/22] typo fix --- buildroot-external/configs/rpi2_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildroot-external/configs/rpi2_defconfig b/buildroot-external/configs/rpi2_defconfig index ff0a315dc74..0ae9445a5a4 100644 --- a/buildroot-external/configs/rpi2_defconfig +++ b/buildroot-external/configs/rpi2_defconfig @@ -110,4 +110,4 @@ BR2_PACKAGE_GENERIC_RAW_UART_DTS=y BR2_PACKAGE_GENERIC_RAW_UART_DTS_RPI=y BR2_PACKAGE_EQ3_CHAR_LOOP=y BR2_PACKAGE_RPI_RF_MOD=y -BR2_PACKAGE_RPI_RF_MOD_TARGET_RPI +BR2_PACKAGE_RPI_RF_MOD_TARGET_RPI=y From 684cc50494dca59a10e163dc230f16fea2c0eb0e Mon Sep 17 00:00:00 2001 From: Jens Maus Date: Tue, 23 Mar 2021 22:42:56 +0100 Subject: [PATCH 15/22] removed the generic_raw_uart package dts patches which were setting the reset_pin,red/greeen/blue_pin pointer to zero. In addition, the rpi-rf-mod package is now a meta package taking care to define all required dependencies in its Config.in. --- .../board/raspberrypi/boot-env.txt | 1 - .../configs/generic_x86_64_defconfig | 2 -- .../configs/odroid_c2_defconfig | 2 -- .../configs/odroid_c4_defconfig | 2 -- .../configs/odroid_n2_defconfig | 2 -- .../configs/odroid_xu4_defconfig | 2 -- buildroot-external/configs/ova_defconfig | 2 -- buildroot-external/configs/rpi0_w_defconfig | 6 +---- buildroot-external/configs/rpi2_defconfig | 6 +---- buildroot-external/configs/rpi3_64_defconfig | 6 +---- buildroot-external/configs/rpi3_defconfig | 6 +---- buildroot-external/configs/rpi4_64_defconfig | 6 +---- buildroot-external/configs/rpi4_defconfig | 6 +---- buildroot-external/configs/rpi_defconfig | 6 +---- buildroot-external/configs/tinker_defconfig | 7 ++--- .../0002-dts-disable-gpio-pin.patch | 17 ------------ .../0003-dts-tinkerboard.patch | 20 -------------- .../0004-dts-mainline-rx8130.patch | 15 ----------- .../package/generic_raw_uart/Config.in | 27 ------------------- .../generic_raw_uart/generic_raw_uart.mk | 22 --------------- .../package/rpi-rf-mod/Config.in | 17 +++++++++--- .../rpi-rf-mod/dts/rpi-rf-mod-tinker.dts | 22 ++++++++++++--- .../package/rpi-rf-mod/dts/rpi-rf-mod.dts | 15 ++++++++++- .../package/rpi-rf-mod/rpi-rf-mod.mk | 18 ++++++++----- 24 files changed, 65 insertions(+), 170 deletions(-) delete mode 100644 buildroot-external/package/generic_raw_uart/0002-dts-disable-gpio-pin.patch delete mode 100644 buildroot-external/package/generic_raw_uart/0003-dts-tinkerboard.patch delete mode 100644 buildroot-external/package/generic_raw_uart/0004-dts-mainline-rx8130.patch diff --git a/buildroot-external/board/raspberrypi/boot-env.txt b/buildroot-external/board/raspberrypi/boot-env.txt index e14db7143bc..8d6c716d641 100644 --- a/buildroot-external/board/raspberrypi/boot-env.txt +++ b/buildroot-external/board/raspberrypi/boot-env.txt @@ -64,7 +64,6 @@ kernel=u-boot.bin #enable_uart=1 #dtparam=i2c_arm=on #dtoverlay=miniuart-bt -#dtoverlay=pivccu-raspberrypi #dtoverlay=rpi-rf-mod # Additional overlays and parameters are documented /boot/overlays/README diff --git a/buildroot-external/configs/generic_x86_64_defconfig b/buildroot-external/configs/generic_x86_64_defconfig index bc728098216..118d88b1c24 100644 --- a/buildroot-external/configs/generic_x86_64_defconfig +++ b/buildroot-external/configs/generic_x86_64_defconfig @@ -109,6 +109,4 @@ BR2_PACKAGE_LIBCURL_CURL=y BR2_PACKAGE_INTEL_E1000E=y BR2_PACKAGE_DOSFSTOOLS=y BR2_PACKAGE_DOSFSTOOLS_FSCK_FAT=y -BR2_PACKAGE_GENERIC_RAW_UART=y -BR2_PACKAGE_EQ3_CHAR_LOOP=y BR2_PACKAGE_RPI_RF_MOD=y diff --git a/buildroot-external/configs/odroid_c2_defconfig b/buildroot-external/configs/odroid_c2_defconfig index 8ed4adb198c..173885b6e9c 100644 --- a/buildroot-external/configs/odroid_c2_defconfig +++ b/buildroot-external/configs/odroid_c2_defconfig @@ -107,6 +107,4 @@ BR2_PACKAGE_HARDKERNEL_BOOT_ODROID_C2=y BR2_PACKAGE_DOSFSTOOLS=y BR2_PACKAGE_DOSFSTOOLS_FSCK_FAT=y BR2_PACKAGE_RTL8812AU=y -BR2_PACKAGE_GENERIC_RAW_UART=y -BR2_PACKAGE_EQ3_CHAR_LOOP=y BR2_PACKAGE_RPI_RF_MOD=y diff --git a/buildroot-external/configs/odroid_c4_defconfig b/buildroot-external/configs/odroid_c4_defconfig index 77aa7ede9ec..dda4841e167 100644 --- a/buildroot-external/configs/odroid_c4_defconfig +++ b/buildroot-external/configs/odroid_c4_defconfig @@ -105,6 +105,4 @@ BR2_PACKAGE_LIBCURL_CURL=y BR2_PACKAGE_HARDKERNEL_BOOT=y BR2_PACKAGE_HARDKERNEL_BOOT_ODROID_C4=y BR2_PACKAGE_RTL8812AU=y -BR2_PACKAGE_GENERIC_RAW_UART=y -BR2_PACKAGE_EQ3_CHAR_LOOP=y BR2_PACKAGE_RPI_RF_MOD=y diff --git a/buildroot-external/configs/odroid_n2_defconfig b/buildroot-external/configs/odroid_n2_defconfig index c3e9a27541c..07f1f192772 100644 --- a/buildroot-external/configs/odroid_n2_defconfig +++ b/buildroot-external/configs/odroid_n2_defconfig @@ -107,6 +107,4 @@ BR2_PACKAGE_HARDKERNEL_BOOT_ODROID_N2=y BR2_PACKAGE_DOSFSTOOLS=y BR2_PACKAGE_DOSFSTOOLS_FSCK_FAT=y BR2_PACKAGE_RTL8812AU=y -BR2_PACKAGE_GENERIC_RAW_UART=y -BR2_PACKAGE_EQ3_CHAR_LOOP=y BR2_PACKAGE_RPI_RF_MOD=y diff --git a/buildroot-external/configs/odroid_xu4_defconfig b/buildroot-external/configs/odroid_xu4_defconfig index de5d853bc05..7649b0e273e 100644 --- a/buildroot-external/configs/odroid_xu4_defconfig +++ b/buildroot-external/configs/odroid_xu4_defconfig @@ -110,6 +110,4 @@ BR2_PACKAGE_HARDKERNEL_BOOT_ODROID_XU4=y BR2_PACKAGE_DOSFSTOOLS=y BR2_PACKAGE_DOSFSTOOLS_FSCK_FAT=y BR2_PACKAGE_RTL8812AU=y -BR2_PACKAGE_GENERIC_RAW_UART=y -BR2_PACKAGE_EQ3_CHAR_LOOP=y BR2_PACKAGE_RPI_RF_MOD=y diff --git a/buildroot-external/configs/ova_defconfig b/buildroot-external/configs/ova_defconfig index a56b8de3f5b..c42c9c907f0 100644 --- a/buildroot-external/configs/ova_defconfig +++ b/buildroot-external/configs/ova_defconfig @@ -99,6 +99,4 @@ BR2_PACKAGE_APPARMOR_PROFILES=y BR2_PACKAGE_LIBCURL_CURL=y BR2_PACKAGE_DOSFSTOOLS=y BR2_PACKAGE_DOSFSTOOLS_FSCK_FAT=y -BR2_PACKAGE_GENERIC_RAW_UART=y -BR2_PACKAGE_EQ3_CHAR_LOOP=y BR2_PACKAGE_RPI_RF_MOD=y diff --git a/buildroot-external/configs/rpi0_w_defconfig b/buildroot-external/configs/rpi0_w_defconfig index e66c463d37c..45c4f21814d 100644 --- a/buildroot-external/configs/rpi0_w_defconfig +++ b/buildroot-external/configs/rpi0_w_defconfig @@ -106,9 +106,5 @@ BR2_PACKAGE_LIBCURL_CURL=y BR2_PACKAGE_BLUETOOTH_BCM43XX=y BR2_PACKAGE_DOSFSTOOLS=y BR2_PACKAGE_DOSFSTOOLS_FSCK_FAT=y -BR2_PACKAGE_GENERIC_RAW_UART=y -BR2_PACKAGE_GENERIC_RAW_UART_DTS=y -BR2_PACKAGE_GENERIC_RAW_UART_DTS_RPI=y -BR2_PACKAGE_EQ3_CHAR_LOOP=y BR2_PACKAGE_RPI_RF_MOD=y -BR2_PACKAGE_RPI_RF_MOD_TARGET_RPI=y +BR2_PACKAGE_RPI_RF_MOD_DTS=y diff --git a/buildroot-external/configs/rpi2_defconfig b/buildroot-external/configs/rpi2_defconfig index 0ae9445a5a4..3e2c8da3be6 100644 --- a/buildroot-external/configs/rpi2_defconfig +++ b/buildroot-external/configs/rpi2_defconfig @@ -105,9 +105,5 @@ BR2_PACKAGE_APPARMOR_PROFILES=y BR2_PACKAGE_LIBCURL_CURL=y BR2_PACKAGE_DOSFSTOOLS=y BR2_PACKAGE_DOSFSTOOLS_FSCK_FAT=y -BR2_PACKAGE_GENERIC_RAW_UART=y -BR2_PACKAGE_GENERIC_RAW_UART_DTS=y -BR2_PACKAGE_GENERIC_RAW_UART_DTS_RPI=y -BR2_PACKAGE_EQ3_CHAR_LOOP=y BR2_PACKAGE_RPI_RF_MOD=y -BR2_PACKAGE_RPI_RF_MOD_TARGET_RPI=y +BR2_PACKAGE_RPI_RF_MOD_DTS=y diff --git a/buildroot-external/configs/rpi3_64_defconfig b/buildroot-external/configs/rpi3_64_defconfig index 928558f8e36..9460144c6ce 100644 --- a/buildroot-external/configs/rpi3_64_defconfig +++ b/buildroot-external/configs/rpi3_64_defconfig @@ -106,9 +106,5 @@ BR2_PACKAGE_LIBCURL_CURL=y BR2_PACKAGE_BLUETOOTH_BCM43XX=y BR2_PACKAGE_DOSFSTOOLS=y BR2_PACKAGE_DOSFSTOOLS_FSCK_FAT=y -BR2_PACKAGE_GENERIC_RAW_UART=y -BR2_PACKAGE_GENERIC_RAW_UART_DTS=y -BR2_PACKAGE_GENERIC_RAW_UART_DTS_RPI=y -BR2_PACKAGE_EQ3_CHAR_LOOP=y BR2_PACKAGE_RPI_RF_MOD=y -BR2_PACKAGE_RPI_RF_MOD_TARGET_RPI=y +BR2_PACKAGE_RPI_RF_MOD_DTS=y diff --git a/buildroot-external/configs/rpi3_defconfig b/buildroot-external/configs/rpi3_defconfig index 04e20aa160e..eb7cfdfa4bb 100644 --- a/buildroot-external/configs/rpi3_defconfig +++ b/buildroot-external/configs/rpi3_defconfig @@ -106,9 +106,5 @@ BR2_PACKAGE_LIBCURL_CURL=y BR2_PACKAGE_BLUETOOTH_BCM43XX=y BR2_PACKAGE_DOSFSTOOLS=y BR2_PACKAGE_DOSFSTOOLS_FSCK_FAT=y -BR2_PACKAGE_GENERIC_RAW_UART=y -BR2_PACKAGE_GENERIC_RAW_UART_DTS=y -BR2_PACKAGE_GENERIC_RAW_UART_DTS_RPI=y -BR2_PACKAGE_EQ3_CHAR_LOOP=y BR2_PACKAGE_RPI_RF_MOD=y -BR2_PACKAGE_RPI_RF_MOD_TARGET_RPI=y +BR2_PACKAGE_RPI_RF_MOD_DTS=y diff --git a/buildroot-external/configs/rpi4_64_defconfig b/buildroot-external/configs/rpi4_64_defconfig index 3971e51ef17..801508ff8cf 100644 --- a/buildroot-external/configs/rpi4_64_defconfig +++ b/buildroot-external/configs/rpi4_64_defconfig @@ -110,9 +110,5 @@ BR2_PACKAGE_LIBCURL_CURL=y BR2_PACKAGE_BLUETOOTH_BCM43XX=y BR2_PACKAGE_DOSFSTOOLS=y BR2_PACKAGE_DOSFSTOOLS_FSCK_FAT=y -BR2_PACKAGE_GENERIC_RAW_UART=y -BR2_PACKAGE_GENERIC_RAW_UART_DTS=y -BR2_PACKAGE_GENERIC_RAW_UART_DTS_RPI=y -BR2_PACKAGE_EQ3_CHAR_LOOP=y BR2_PACKAGE_RPI_RF_MOD=y -BR2_PACKAGE_RPI_RF_MOD_TARGET_RPI=y +BR2_PACKAGE_RPI_RF_MOD_DTS=y diff --git a/buildroot-external/configs/rpi4_defconfig b/buildroot-external/configs/rpi4_defconfig index 65dee95f944..22fbd204c47 100644 --- a/buildroot-external/configs/rpi4_defconfig +++ b/buildroot-external/configs/rpi4_defconfig @@ -107,9 +107,5 @@ BR2_PACKAGE_LIBCURL_CURL=y BR2_PACKAGE_BLUETOOTH_BCM43XX=y BR2_PACKAGE_DOSFSTOOLS=y BR2_PACKAGE_DOSFSTOOLS_FSCK_FAT=y -BR2_PACKAGE_GENERIC_RAW_UART=y -BR2_PACKAGE_GENERIC_RAW_UART_DTS=y -BR2_PACKAGE_GENERIC_RAW_UART_DTS_RPI=y -BR2_PACKAGE_EQ3_CHAR_LOOP=y BR2_PACKAGE_RPI_RF_MOD=y -BR2_PACKAGE_RPI_RF_MOD_TARGET_RPI=y +BR2_PACKAGE_RPI_RF_MOD_DTS=y diff --git a/buildroot-external/configs/rpi_defconfig b/buildroot-external/configs/rpi_defconfig index feae918b35f..fcbc7ff0f75 100644 --- a/buildroot-external/configs/rpi_defconfig +++ b/buildroot-external/configs/rpi_defconfig @@ -105,9 +105,5 @@ BR2_PACKAGE_APPARMOR_PROFILES=y BR2_PACKAGE_LIBCURL_CURL=y BR2_PACKAGE_DOSFSTOOLS=y BR2_PACKAGE_DOSFSTOOLS_FSCK_FAT=y -BR2_PACKAGE_GENERIC_RAW_UART=y -BR2_PACKAGE_GENERIC_RAW_UART_DTS=y -BR2_PACKAGE_GENERIC_RAW_UART_DTS_RPI=y -BR2_PACKAGE_EQ3_CHAR_LOOP=y BR2_PACKAGE_RPI_RF_MOD=y -BR2_PACKAGE_RPI_RF_MOD_TARGET_RPI=y +BR2_PACKAGE_RPI_RF_MOD_DTS=y diff --git a/buildroot-external/configs/tinker_defconfig b/buildroot-external/configs/tinker_defconfig index 0d2fa65a7a3..d981b8eec46 100644 --- a/buildroot-external/configs/tinker_defconfig +++ b/buildroot-external/configs/tinker_defconfig @@ -111,9 +111,6 @@ BR2_PACKAGE_LIBCURL_CURL=y BR2_PACKAGE_BLUETOOTH_RTL8723=y BR2_PACKAGE_DOSFSTOOLS=y BR2_PACKAGE_DOSFSTOOLS_FSCK_FAT=y -BR2_PACKAGE_GENERIC_RAW_UART=y -BR2_PACKAGE_GENERIC_RAW_UART_DTS=y -BR2_PACKAGE_GENERIC_RAW_UART_DTS_TINKER=y -BR2_PACKAGE_EQ3_CHAR_LOOP=y BR2_PACKAGE_RPI_RF_MOD=y -BR2_PACKAGE_RPI_RF_MOD_TARGET_TINKER=y +BR2_PACKAGE_RPI_RF_MOD_DTS=y +BR2_PACKAGE_RPI_RF_MOD_DTS_TINKER=y diff --git a/buildroot-external/package/generic_raw_uart/0002-dts-disable-gpio-pin.patch b/buildroot-external/package/generic_raw_uart/0002-dts-disable-gpio-pin.patch deleted file mode 100644 index 3529c953ddf..00000000000 --- a/buildroot-external/package/generic_raw_uart/0002-dts-disable-gpio-pin.patch +++ /dev/null @@ -1,17 +0,0 @@ ---- ./dts/pivccu-raspberrypi.dts.orig 2018-12-22 21:01:28.756992536 +0100 -+++ ./dts/pivccu-raspberrypi.dts 2018-12-26 22:56:26.807677174 +0100 -@@ -7,10 +7,10 @@ - target = <&uart0>; - __overlay__ { - compatible = "pivccu,pl011"; -- pivccu,reset_pin = <&gpio 18 0>; -- pivccu,red_pin = <&gpio 16 0>; -- pivccu,green_pin = <&gpio 20 0>; -- pivccu,blue_pin = <&gpio 21 0>; -+ pivccu,reset_pin = <0>; -+ pivccu,red_pin = <0>; -+ pivccu,green_pin = <0>; -+ pivccu,blue_pin = <0>; - }; - }; - }; diff --git a/buildroot-external/package/generic_raw_uart/0003-dts-tinkerboard.patch b/buildroot-external/package/generic_raw_uart/0003-dts-tinkerboard.patch deleted file mode 100644 index 80e549460b8..00000000000 --- a/buildroot-external/package/generic_raw_uart/0003-dts-tinkerboard.patch +++ /dev/null @@ -1,20 +0,0 @@ ---- ./dts/pivccu-tinkerboard.dts.orig 2019-03-11 13:29:51.226401633 +0100 -+++ ./dts/pivccu-tinkerboard.dts 2020-06-05 11:20:29.433644667 +0200 -@@ -0,0 +1,17 @@ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "asus,rk3288-tinker", "rockchip,rk3288"; -+ fragment@0 { -+ target = <&uart1>; -+ __overlay__ { -+ compatible = "pivccu,dw_apb"; -+ status = "okay"; -+ pivccu,reset_pin = <0>; -+ pivccu,red_pin = <0>; -+ pivccu,green_pin = <0>; -+ pivccu,blue_pin = <0>; -+ }; -+ }; -+}; diff --git a/buildroot-external/package/generic_raw_uart/0004-dts-mainline-rx8130.patch b/buildroot-external/package/generic_raw_uart/0004-dts-mainline-rx8130.patch deleted file mode 100644 index ca2172062f8..00000000000 --- a/buildroot-external/package/generic_raw_uart/0004-dts-mainline-rx8130.patch +++ /dev/null @@ -1,15 +0,0 @@ ---- ./dts/pivccu-raspberrypi.dts.orig 2019-07-04 13:54:53.271472462 +0200 -+++ ./dts/pivccu-raspberrypi.dts 2021-03-18 22:10:52.040233559 +0100 -@@ -23,10 +23,10 @@ - status = "okay"; - - rx8130@32 { -- compatible = "epson,rx8130-legacy"; -+ compatible = "epson,rx8130"; - reg = <0x32>; - status = "okay"; -- enable-external-capacitor; -+ aux-voltage-chargeable = <1>; - }; - }; - }; diff --git a/buildroot-external/package/generic_raw_uart/Config.in b/buildroot-external/package/generic_raw_uart/Config.in index 6d5bf26fda7..81f38f64164 100644 --- a/buildroot-external/package/generic_raw_uart/Config.in +++ b/buildroot-external/package/generic_raw_uart/Config.in @@ -5,30 +5,3 @@ config BR2_PACKAGE_GENERIC_RAW_UART Alexander Reinert https://github.com/alexreinert/piVCCU/tree/master/kernel - -if BR2_PACKAGE_GENERIC_RAW_UART - -config BR2_PACKAGE_GENERIC_RAW_UART_DTS - bool "Compile Device Tree Overlay" - -if BR2_PACKAGE_GENERIC_RAW_UART_DTS - -choice - prompt "For Target" - default BR2_PACKAGE_GENERIC_RAW_UART_DTS_RPI - -config BR2_PACKAGE_GENERIC_RAW_UART_DTS_RPI - bool "RaspberryPi" - help - For the RaspberryPi - -config BR2_PACKAGE_GENERIC_RAW_UART_DTS_TINKER - bool "ASUS Tinkerboard" - help - For the ASUS Tinkerboard - -endchoice - -endif - -endif diff --git a/buildroot-external/package/generic_raw_uart/generic_raw_uart.mk b/buildroot-external/package/generic_raw_uart/generic_raw_uart.mk index bd1ea6b79af..249e17846ee 100644 --- a/buildroot-external/package/generic_raw_uart/generic_raw_uart.mk +++ b/buildroot-external/package/generic_raw_uart/generic_raw_uart.mk @@ -16,30 +16,8 @@ GENERIC_RAW_UART_VERSION = 0fc14a2131da3b14d91407ef803ded5dc3a9ff80 GENERIC_RAW_UART_SITE = $(call github,alexreinert,piVCCU,$(GENERIC_RAW_UART_VERSION)) GENERIC_RAW_UART_LICENSE = GPL2 -GENERIC_RAW_UART_DEPENDENCIES = host-dtc #GENERIC_RAW_UART_LICENSE_FILES = LICENSE GENERIC_RAW_UART_MODULE_SUBDIRS = kernel -GENERIC_RAW_UART_INSTALL_IMAGES = YES - -ifeq ($(BR2_PACKAGE_GENERIC_RAW_UART_DTS_RPI),y) - # RaspberryPi DTS file - GENERIC_RAW_UART_DTS_FILE = pivccu-raspberrypi -else ifeq ($(BR2_PACKAGE_GENERIC_RAW_UART_DTS_TINKER),y) - # ASUS Tinkerboard DTS file - GENERIC_RAW_UART_DTS_FILE = pivccu-tinkerboard -endif - -define GENERIC_RAW_UART_BUILD_CMDS - if [[ -n "$(GENERIC_RAW_UART_DTS_FILE)" ]]; then \ - $(HOST_DIR)/bin/dtc -@ -I dts -O dtb -W no-unit_address_vs_reg -o $(@D)/dts/$(GENERIC_RAW_UART_DTS_FILE).dtbo $(@D)/dts/$(GENERIC_RAW_UART_DTS_FILE).dts; \ - fi -endef - -define GENERIC_RAW_UART_INSTALL_IMAGES_CMDS - if [[ -n "$(GENERIC_RAW_UART_DTS_FILE)" ]]; then \ - $(INSTALL) -D -m 0644 $(@D)/dts/$(GENERIC_RAW_UART_DTS_FILE).dtbo $(BINARIES_DIR)/; \ - fi -endef $(eval $(kernel-module)) $(eval $(generic-package)) diff --git a/buildroot-external/package/rpi-rf-mod/Config.in b/buildroot-external/package/rpi-rf-mod/Config.in index dacd20957b3..c6b4fba9bd2 100644 --- a/buildroot-external/package/rpi-rf-mod/Config.in +++ b/buildroot-external/package/rpi-rf-mod/Config.in @@ -1,18 +1,25 @@ config BR2_PACKAGE_RPI_RF_MOD - bool "Support for RPI-RF-MOD/HM-MOD-RPI-PCB GPIO HAT" + select BR2_PACKAGE_EQ3_CHAR_LOOP + select BR2_PACKAGE_GENERIC_RAW_UART + bool "Support for RPI-RF-MOD/HM-MOD-RPI-PCB GPIO HAT" if BR2_PACKAGE_RPI_RF_MOD +config BR2_PACKAGE_RPI_RF_MOD_DTS + bool "Compile Device Tree Overlay" + +if BR2_PACKAGE_RPI_RF_MOD_DTS + choice prompt "For Target" - default BR2_PACKAGE_RPI_RF_MOD_TARGET_RPI + default BR2_PACKAGE_RPI_RF_MOD_DTS_RPI -config BR2_PACKAGE_RPI_RF_MOD_TARGET_RPI +config BR2_PACKAGE_RPI_RF_MOD_DTS_RPI bool "RaspberryPi" help For the RaspberryPi -config BR2_PACKAGE_RPI_RF_MOD_TARGET_TINKER +config BR2_PACKAGE_RPI_RF_MOD_DTS_TINKER bool "ASUS Tinkerboard" help For the ASUS Tinkerboard @@ -20,3 +27,5 @@ config BR2_PACKAGE_RPI_RF_MOD_TARGET_TINKER endchoice endif + +endif diff --git a/buildroot-external/package/rpi-rf-mod/dts/rpi-rf-mod-tinker.dts b/buildroot-external/package/rpi-rf-mod/dts/rpi-rf-mod-tinker.dts index 5b34d062645..cb3cd485637 100644 --- a/buildroot-external/package/rpi-rf-mod/dts/rpi-rf-mod-tinker.dts +++ b/buildroot-external/package/rpi-rf-mod/dts/rpi-rf-mod-tinker.dts @@ -5,7 +5,7 @@ ** Device Tree Overlay for eQ-3 RPI-RF-MOD and ** HM-MOD-RPI-PCB for ASUS Tinkerboard ** -** Copyright (c) 2019-2020 Jens Maus +** Copyright (c) 2019-2021 Jens Maus ** Licensed under Apache 2.0 ** */ @@ -81,21 +81,35 @@ }; }; + // fragment to define uart/serial dependencies for + // generic_raw_uart + fragment@3 { + target = <&uart1>; + __overlay__ { + compatible = "pivccu,dw_apb"; + status = "okay"; + pivccu,reset_pin = <&gpio6 0 0>; + pivccu,red_pin = <&gpio7 7 0>; + pivccu,green_pin = <&gpio6 3 0>; + pivccu,blue_pin = <&gpio6 4 0>; + }; + }; + // we have to disable uart2,uart3,i2s on the Tinkerboard or // otherwise the gpio-leds cannot use the pins for the RPI-RF-MOD - fragment@3 { + fragment@4 { target = <&uart2>; __overlay__ { status = "disabled"; }; }; - fragment@4 { + fragment@5 { target = <&uart3>; __overlay__ { status = "disabled"; }; }; - fragment@5 { + fragment@6 { target = <&i2s>; __overlay__ { status = "disabled"; diff --git a/buildroot-external/package/rpi-rf-mod/dts/rpi-rf-mod.dts b/buildroot-external/package/rpi-rf-mod/dts/rpi-rf-mod.dts index 3bef5fce492..2758bb5475b 100644 --- a/buildroot-external/package/rpi-rf-mod/dts/rpi-rf-mod.dts +++ b/buildroot-external/package/rpi-rf-mod/dts/rpi-rf-mod.dts @@ -5,7 +5,7 @@ ** Device Tree Overlay for eQ-3 RPI-RF-MOD and ** HM-MOD-RPI-PCB for RaspberryPi ** -** Copyright (c) 2018-2019 Jens Maus +** Copyright (c) 2018-2021 Jens Maus ** Licensed under Apache 2.0 ** */ @@ -71,4 +71,17 @@ }; }; }; + + // fragment to define uart/serial dependencies for + // generic_raw_uart + fragment@3 { + target = <&uart0>; + __overlay__ { + compatible = "pivccu,pl011"; + pivccu,reset_pin = <&gpio 18 0>; + pivccu,red_pin = <&gpio 16 0>; + pivccu,green_pin = <&gpio 20 0>; + pivccu,blue_pin = <&gpio 21 0>; + }; + }; }; diff --git a/buildroot-external/package/rpi-rf-mod/rpi-rf-mod.mk b/buildroot-external/package/rpi-rf-mod/rpi-rf-mod.mk index 850db215b22..1faa0f46043 100644 --- a/buildroot-external/package/rpi-rf-mod/rpi-rf-mod.mk +++ b/buildroot-external/package/rpi-rf-mod/rpi-rf-mod.mk @@ -1,36 +1,40 @@ ############################################################# # -# Device tree overlay support for RPI-RF-MOD/HM-MOD-RPI-PCB -# rf modules for HomeMatic/homematicIP connectivity. +# Meta package for RPI-RF-MOD/HM-MOD-RPI-PCB device support +# for HomeMatic/homematicIP connectivity. +# +# This includes compiling of required device tree overlays for +# selected platforms # # Copyright (c) 2018-2021 Jens Maus # https://github.com/jens-maus/RaspberryMatic/tree/master/buildroot-external/package/rpi-rf-mod # ############################################################# -RPI_RF_MOD_VERSION = 1.4.0 +RPI_RF_MOD_VERSION = 1.5.0 RPI_RF_MOD_SITE = $(BR2_EXTERNAL_HASSOS_PATH)/package/rpi-rf-mod RPI_RF_MOD_SITE_METHOD = local RPI_RF_MOD_LICENSE = Apache-2.0 +RPI_RF_MOD_DEPENDENCIES = host-dtc #RPI_RF_MOD_LICENSE_FILES = LICENSE -ifeq ($(BR2_PACKAGE_RPI_RF_MOD_TARGET_RPI),y) +ifeq ($(BR2_PACKAGE_RPI_RF_MOD_DTS_RPI),y) # RaspberryPi DTS file RPI_RF_MOD_DTS_FILE = rpi-rf-mod -else ifeq ($(BR2_PACKAGE_RPI_RF_MOD_TARGET_TINKER),y) +else ifeq ($(BR2_PACKAGE_RPI_RF_MOD_DTS_TINKER),y) # ASUS Tinkerboard DTS file RPI_RF_MOD_DTS_FILE = rpi-rf-mod-tinker endif define RPI_RF_MOD_BUILD_CMDS if [[ -n "$(RPI_RF_MOD_DTS_FILE)" ]]; then \ - $(HOST_DIR)/bin/dtc -@ -I dts -O dtb -W no-unit_address_vs_reg -o $(@D)/dts/$(RPI_RF_MOD_DTS_FILE).dtbo $(@D)/dts/$(RPI_RF_MOD_DTS_FILE).dts; \ + $(HOST_DIR)/bin/dtc -@ -I dts -O dtb -W no-unit_address_vs_reg -o $(@D)/dts/rpi-rf-mod.dtbo $(@D)/dts/$(RPI_RF_MOD_DTS_FILE).dts; \ fi endef define RPI_RF_MOD_INSTALL_TARGET_CMDS if [[ -n "$(RPI_RF_MOD_DTS_FILE)" ]]; then \ - $(INSTALL) -D -m 0644 $(@D)/dts/$(RPI_RF_MOD_DTS_FILE).dtbo $(BINARIES_DIR)/; \ + $(INSTALL) -D -m 0644 $(@D)/dts/rpi-rf-mod.dtbo $(BINARIES_DIR)/; \ fi endef From ecfef271d13b803423c11b769d9e994b840779a3 Mon Sep 17 00:00:00 2001 From: Jens Maus Date: Fri, 26 Mar 2021 18:17:20 +0100 Subject: [PATCH 16/22] updated generic_raw_uart to latest master version and updated rpi-rf-mod package to use 'alt_reset_pin' device tree node entry to implement different reset pins for RPI-RF-MOD and HM-MOD-RPI-PCB. --- .../package/generic_raw_uart/generic_raw_uart.mk | 4 ++-- .../package/rpi-rf-mod/dts/rpi-rf-mod-tinker.dts | 12 +++++++----- .../package/rpi-rf-mod/dts/rpi-rf-mod.dts | 12 +++++++----- buildroot-external/package/rpi-rf-mod/rpi-rf-mod.mk | 2 +- 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/buildroot-external/package/generic_raw_uart/generic_raw_uart.mk b/buildroot-external/package/generic_raw_uart/generic_raw_uart.mk index 249e17846ee..863d4586659 100644 --- a/buildroot-external/package/generic_raw_uart/generic_raw_uart.mk +++ b/buildroot-external/package/generic_raw_uart/generic_raw_uart.mk @@ -3,7 +3,7 @@ # Generic raw uart kernel module for low-latency uart # communication with a RPI-RF-MOD/HM-MOD-RPI-PCB # -# Copyright (c) 2020 Alexander Reinert +# Copyright (c) 2021 Alexander Reinert # https://github.com/alexreinert/piVCCU/tree/master/kernel # # Uses parts of bcm2835_raw_uart.c @@ -13,7 +13,7 @@ # ############################################################# -GENERIC_RAW_UART_VERSION = 0fc14a2131da3b14d91407ef803ded5dc3a9ff80 +GENERIC_RAW_UART_VERSION = dab76ddd1d568cc4925dc778e43d70fccffdc0e8 GENERIC_RAW_UART_SITE = $(call github,alexreinert,piVCCU,$(GENERIC_RAW_UART_VERSION)) GENERIC_RAW_UART_LICENSE = GPL2 #GENERIC_RAW_UART_LICENSE_FILES = LICENSE diff --git a/buildroot-external/package/rpi-rf-mod/dts/rpi-rf-mod-tinker.dts b/buildroot-external/package/rpi-rf-mod/dts/rpi-rf-mod-tinker.dts index cb3cd485637..1886b7ca73c 100644 --- a/buildroot-external/package/rpi-rf-mod/dts/rpi-rf-mod-tinker.dts +++ b/buildroot-external/package/rpi-rf-mod/dts/rpi-rf-mod-tinker.dts @@ -72,7 +72,7 @@ #size-cells = <0>; status = "okay"; - rx8130@32 { + rpi_rf_mod_rtc: rx8130@32 { compatible = "epson,rx8130"; reg = <0x32>; status = "okay"; @@ -88,10 +88,12 @@ __overlay__ { compatible = "pivccu,dw_apb"; status = "okay"; - pivccu,reset_pin = <&gpio6 0 0>; - pivccu,red_pin = <&gpio7 7 0>; - pivccu,green_pin = <&gpio6 3 0>; - pivccu,blue_pin = <&gpio6 4 0>; + pivccu,reset_pin = <&gpio6 0 0>; // HM-MOD-RPI-PCB + pivccu,alt_reset_pin = <&gpio6 1 0>;// RPI-RF-MOD + pivccu,red_pin = <&gpio7 7 0>; // RPI-RF-MOD + pivccu,green_pin = <&gpio6 3 0>; // RPI-RF-MOD + pivccu,blue_pin = <&gpio6 4 0>; // RPI-RF-MOD + pivccu,rtc = <&rpi_rf_mod_rtc>; // RPI-RF-MOD }; }; diff --git a/buildroot-external/package/rpi-rf-mod/dts/rpi-rf-mod.dts b/buildroot-external/package/rpi-rf-mod/dts/rpi-rf-mod.dts index 2758bb5475b..5ca9a3d0280 100644 --- a/buildroot-external/package/rpi-rf-mod/dts/rpi-rf-mod.dts +++ b/buildroot-external/package/rpi-rf-mod/dts/rpi-rf-mod.dts @@ -63,7 +63,7 @@ #size-cells = <0>; status = "okay"; - rx8130@32 { + rpi_rf_mod_rtc: rx8130@32 { compatible = "epson,rx8130"; reg = <0x32>; status = "okay"; @@ -78,10 +78,12 @@ target = <&uart0>; __overlay__ { compatible = "pivccu,pl011"; - pivccu,reset_pin = <&gpio 18 0>; - pivccu,red_pin = <&gpio 16 0>; - pivccu,green_pin = <&gpio 20 0>; - pivccu,blue_pin = <&gpio 21 0>; + pivccu,reset_pin = <&gpio 18 0>; // HM-MOD-RPI-PCB + pivccu,alt_reset_pin = <&gpio 19 0>; // RPI-RF-MOD + pivccu,red_pin = <&gpio 16 0>; // RPI-RF-MOD + pivccu,green_pin = <&gpio 20 0>; // RPI-RF-MOD + pivccu,blue_pin = <&gpio 21 0>; // RPI-RF-MOD + pivccu,rtc = <&rpi_rf_mod_rtc>; // RPI-RF-MOD }; }; }; diff --git a/buildroot-external/package/rpi-rf-mod/rpi-rf-mod.mk b/buildroot-external/package/rpi-rf-mod/rpi-rf-mod.mk index 1faa0f46043..b9b07aca789 100644 --- a/buildroot-external/package/rpi-rf-mod/rpi-rf-mod.mk +++ b/buildroot-external/package/rpi-rf-mod/rpi-rf-mod.mk @@ -11,7 +11,7 @@ # ############################################################# -RPI_RF_MOD_VERSION = 1.5.0 +RPI_RF_MOD_VERSION = 1.6.0 RPI_RF_MOD_SITE = $(BR2_EXTERNAL_HASSOS_PATH)/package/rpi-rf-mod RPI_RF_MOD_SITE_METHOD = local RPI_RF_MOD_LICENSE = Apache-2.0 From b6b887b1308329eb6c07211c780f93895e282962 Mon Sep 17 00:00:00 2001 From: Jens Maus Date: Wed, 31 Mar 2021 23:38:28 +0200 Subject: [PATCH 17/22] added device tree overlay support for ASUS tinkerboard and added bootEnv.txt loading support to uboot boot script. --- buildroot-external/board/asus/hassos-hook.sh | 1 + .../board/asus/tinker/boot-env.txt | 2 ++ .../patches/uboot/add-overlay-support.patch | 13 +++++++++ .../board/asus/tinker/uboot-boot.ush | 27 +++++++++++++++++-- buildroot-external/configs/tinker_defconfig | 1 + 5 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 buildroot-external/board/asus/tinker/boot-env.txt create mode 100644 buildroot-external/board/asus/tinker/patches/uboot/add-overlay-support.patch diff --git a/buildroot-external/board/asus/hassos-hook.sh b/buildroot-external/board/asus/hassos-hook.sh index ab9afe81299..3dff006f859 100755 --- a/buildroot-external/board/asus/hassos-hook.sh +++ b/buildroot-external/board/asus/hassos-hook.sh @@ -12,6 +12,7 @@ function hassos_pre_image() { mkdir -p "${BOOT_DATA}/overlays" cp "${BINARIES_DIR}"/*.dtbo "${BOOT_DATA}/overlays/" + cp "${BOARD_DIR}/boot-env.txt" "${BOOT_DATA}/bootEnv.txt" echo "console=tty1" > "${BOOT_DATA}/cmdline.txt" diff --git a/buildroot-external/board/asus/tinker/boot-env.txt b/buildroot-external/board/asus/tinker/boot-env.txt new file mode 100644 index 00000000000..c65c9d8c7ab --- /dev/null +++ b/buildroot-external/board/asus/tinker/boot-env.txt @@ -0,0 +1,2 @@ +# add device tree overlay for RPI-RF-MOD/HM-MOD-RPI-PCB +#overlays=rpi-rf-mod diff --git a/buildroot-external/board/asus/tinker/patches/uboot/add-overlay-support.patch b/buildroot-external/board/asus/tinker/patches/uboot/add-overlay-support.patch new file mode 100644 index 00000000000..57e3ee30ce2 --- /dev/null +++ b/buildroot-external/board/asus/tinker/patches/uboot/add-overlay-support.patch @@ -0,0 +1,13 @@ +diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig +index 8a23c76d..bb1e3cb7 100644 +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -1321,6 +1321,8 @@ config ARCH_ROCKCHIP + select DM_SPI_FLASH + select DM_USB if USB + select ENABLE_ARM_SOC_BOOT0_HOOK ++ select OF_LIBFDT ++ select OF_LIBFDT_OVERLAY + select OF_CONTROL + select SPI + select SPL_DM if SPL diff --git a/buildroot-external/board/asus/tinker/uboot-boot.ush b/buildroot-external/board/asus/tinker/uboot-boot.ush index 9cab62b3f92..d915e43b273 100644 --- a/buildroot-external/board/asus/tinker/uboot-boot.ush +++ b/buildroot-external/board/asus/tinker/uboot-boot.ush @@ -23,14 +23,37 @@ setenv bootargs_hassos "zram.enabled=1 zram.num_devices=3 apparmor=1 security=ap setenv bootargs_a "root=PARTUUID=8d3d53e3-6d49-4c38-8349-aff6859e82fd rootfstype=squashfs ro rootwait" setenv bootargs_b "root=PARTUUID=a3ec664e-32ce-4665-95ea-7ae90ce9aa20 rootfstype=squashfs ro rootwait" +# Load environment from bootEnv.txt +if test -e mmc ${devnum}:1 bootEnv.txt; then + fatload mmc ${devnum}:1 ${ramdisk_addr_r} bootEnv.txt + env import -t ${ramdisk_addr_r} ${filesize} +fi + # Load extraargs fileenv mmc ${devnum}:1 ${ramdisk_addr_r} cmdline.txt cmdline # Load device tree if test "$devnum" = "0"; then - fatload mmc ${devnum}:1 ${fdt_addr_r} rk3288-tinker-s.dtb + setenv fdtfile "rk3288-tinker-s.dtb" else - fatload mmc ${devnum}:1 ${fdt_addr_r} rk3288-tinker.dtb + setenv fdtfile "rk3288-tinker.dtb" +fi + +echo "Loading standard device tree ${fdtfile}" +fatload mmc ${devnum}:1 ${fdt_addr_r} ${fdtfile} +fdt addr ${fdt_addr_r} + +# load dt overlays +fdt resize 65536 +for overlay_file in ${overlays}; do + if fatload mmc ${devnum}:1 ${ramdisk_addr_r} overlays/${overlay_file}.dtbo; then + echo "Applying kernel provided DT overlay ${overlay_file}.dtbo" + fdt apply ${ramdisk_addr_r} || setenv overlay_error "true" + fi +done +if test "${overlay_error}" = "true"; then + echo "Error applying DT overlays, restoring original DT" + fatload mmc ${devnum}:1 ${fdt_addr_r} ${fdtfile} fi setenv bootargs diff --git a/buildroot-external/configs/tinker_defconfig b/buildroot-external/configs/tinker_defconfig index 83f28a484b7..5b05a3ca698 100644 --- a/buildroot-external/configs/tinker_defconfig +++ b/buildroot-external/configs/tinker_defconfig @@ -31,6 +31,7 @@ BR2_LINUX_KERNEL_CONFIG_FRAGMENT_FILES="$(BR2_EXTERNAL_HASSOS_PATH)/kernel/hasso BR2_LINUX_KERNEL_LZ4=y BR2_LINUX_KERNEL_DTS_SUPPORT=y BR2_LINUX_KERNEL_INTREE_DTS_NAME="rk3288-tinker rk3288-tinker-s" +BR2_LINUX_KERNEL_DTB_OVERLAY_SUPPORT=y BR2_LINUX_KERNEL_NEEDS_HOST_OPENSSL=y BR2_LINUX_KERNEL_NEEDS_HOST_LIBELF=y BR2_PACKAGE_BUSYBOX_CONFIG="$(BR2_EXTERNAL_HASSOS_PATH)/busybox.config" From e9b51904857b4198b506bd02891a4b364da173ad Mon Sep 17 00:00:00 2001 From: Jens Maus Date: Thu, 1 Apr 2021 00:07:58 +0200 Subject: [PATCH 18/22] improved comment for enabling RPI-RF-MOD/HM-MOD-RPI-PCB support --- buildroot-external/board/asus/tinker/boot-env.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildroot-external/board/asus/tinker/boot-env.txt b/buildroot-external/board/asus/tinker/boot-env.txt index c65c9d8c7ab..1870a8e1059 100644 --- a/buildroot-external/board/asus/tinker/boot-env.txt +++ b/buildroot-external/board/asus/tinker/boot-env.txt @@ -1,2 +1,2 @@ -# add device tree overlay for RPI-RF-MOD/HM-MOD-RPI-PCB +# Uncomment this to enable GPIO support for RPI-RF-MOD/HM-MOD-RPI-PCB #overlays=rpi-rf-mod From 7dd3560c3226f49973a4cbf993d315b19c24d292 Mon Sep 17 00:00:00 2001 From: Jens Maus Date: Fri, 2 Apr 2021 17:14:51 +0200 Subject: [PATCH 19/22] explicitly enable CONFIG_OF_LIBFDT_OVERLAY rather than via a patch against the U-boot Kconfig file. --- .../tinker/patches/uboot/add-overlay-support.patch | 13 ------------- buildroot-external/board/asus/tinker/uboot.config | 1 + 2 files changed, 1 insertion(+), 13 deletions(-) delete mode 100644 buildroot-external/board/asus/tinker/patches/uboot/add-overlay-support.patch diff --git a/buildroot-external/board/asus/tinker/patches/uboot/add-overlay-support.patch b/buildroot-external/board/asus/tinker/patches/uboot/add-overlay-support.patch deleted file mode 100644 index 57e3ee30ce2..00000000000 --- a/buildroot-external/board/asus/tinker/patches/uboot/add-overlay-support.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig -index 8a23c76d..bb1e3cb7 100644 ---- a/arch/arm/Kconfig -+++ b/arch/arm/Kconfig -@@ -1321,6 +1321,8 @@ config ARCH_ROCKCHIP - select DM_SPI_FLASH - select DM_USB if USB - select ENABLE_ARM_SOC_BOOT0_HOOK -+ select OF_LIBFDT -+ select OF_LIBFDT_OVERLAY - select OF_CONTROL - select SPI - select SPL_DM if SPL diff --git a/buildroot-external/board/asus/tinker/uboot.config b/buildroot-external/board/asus/tinker/uboot.config index 3f90be22197..13e696205f4 100644 --- a/buildroot-external/board/asus/tinker/uboot.config +++ b/buildroot-external/board/asus/tinker/uboot.config @@ -1,2 +1,3 @@ # CONFIG_USB_STORAGE is not set # CONFIG_DOS_PARTITION is not set +CONFIG_OF_LIBFDT_OVERLAY=y From 4d404cc05202aac5fd025c87baa53625df9c446d Mon Sep 17 00:00:00 2001 From: Jens Maus Date: Fri, 2 Apr 2021 17:20:11 +0200 Subject: [PATCH 20/22] modified eq3_char_loop package to use the upstream sources from eq-3/occu repository directly and patch all required changes to get version 1.1 rather than directly maintaining its sources downstream. --- .../package/eq3_char_loop/0001-Makefile.patch | 4 + .../eq3_char_loop/0002-version1_1.patch | 109 ++ .../package/eq3_char_loop/Makefile | 1 - .../package/eq3_char_loop/eq3_char_loop.c | 996 ------------------ .../package/eq3_char_loop/eq3_char_loop.mk | 7 +- 5 files changed, 116 insertions(+), 1001 deletions(-) create mode 100644 buildroot-external/package/eq3_char_loop/0001-Makefile.patch create mode 100644 buildroot-external/package/eq3_char_loop/0002-version1_1.patch delete mode 100644 buildroot-external/package/eq3_char_loop/Makefile delete mode 100644 buildroot-external/package/eq3_char_loop/eq3_char_loop.c diff --git a/buildroot-external/package/eq3_char_loop/0001-Makefile.patch b/buildroot-external/package/eq3_char_loop/0001-Makefile.patch new file mode 100644 index 00000000000..f9244973130 --- /dev/null +++ b/buildroot-external/package/eq3_char_loop/0001-Makefile.patch @@ -0,0 +1,4 @@ +--- ./KernelDrivers/Makefile.orig 2021-04-02 17:01:07.029932165 +0200 ++++ ./KernelDrivers/Makefile 2020-06-04 14:36:10.188174788 +0200 +@@ -0,0 +1 @@ ++obj-m += eq3_char_loop.o diff --git a/buildroot-external/package/eq3_char_loop/0002-version1_1.patch b/buildroot-external/package/eq3_char_loop/0002-version1_1.patch new file mode 100644 index 00000000000..7b2208ddaa9 --- /dev/null +++ b/buildroot-external/package/eq3_char_loop/0002-version1_1.patch @@ -0,0 +1,109 @@ +--- ./KernelDrivers/eq3_char_loop.c.orig 2017-05-14 22:57:19.109181928 +0200 ++++ ./KernelDrivers/eq3_char_loop.c 2020-06-04 14:36:10.188174788 +0200 +@@ -48,8 +48,8 @@ + /* Use 'L' as magic number */ + #define EQ3LOOP_IOC_MAGIC 'L' + +-#define EQ3LOOP_IOCSCREATESLAVE _IOW(EQ3LOOP_IOC_MAGIC, 1, unsigned long) +-#define EQ3LOOP_IOCGEVENTS _IOR(EQ3LOOP_IOC_MAGIC, 2, unsigned long) ++#define EQ3LOOP_IOCSCREATESLAVE _IOW(EQ3LOOP_IOC_MAGIC, 1, uint32_t) ++#define EQ3LOOP_IOCGEVENTS _IOR(EQ3LOOP_IOC_MAGIC, 2, uint32_t) + + #define EVENT_BIT_SLAVE_OPENED 0 + #define EVENT_BIT_SLAVE_CLOSED 1 +@@ -62,6 +62,12 @@ + + #define DUMP_READWRITE 0 + ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0)) ++ #define _access_ok(__type, __addr, __size) access_ok(__addr, __size) ++#else ++ #define _access_ok(__type, __addr, __size) access_ok(__type, __addr, __size) ++#endif ++ + struct eq3loop_channel_data + { + struct circ_buf master2slave_buf; +@@ -353,7 +359,7 @@ + { + ret=-EFAULT; + count_to_end = CIRC_SPACE( head, channel->master2slave_buf.tail, BUFSIZE); +- printk( KERN_ERR EQ3LOOP_DRIVER_NAME ": eq3loop_write_master() %s: not enought space in the buffers. free space = %i, required space = %i", channel->name,count_to_end,count ); ++ printk( KERN_ERR EQ3LOOP_DRIVER_NAME ": eq3loop_write_master() %s: not enough space in buffers. free space = %zu, required space = %zu", channel->name,count_to_end,count ); + goto out; + } + /* ok, space is free, write something */ +@@ -389,7 +395,7 @@ + up (&channel->sem); + if(ret < 0) + { +- printk( KERN_INFO EQ3LOOP_DRIVER_NAME ": eq3loop_write_master() retrun error:"); ++ printk( KERN_INFO EQ3LOOP_DRIVER_NAME ": eq3loop_write_master() return error: %d", ret); + } + if( ret > 0 || CIRC_CNT(channel->master2slave_buf.head,channel->master2slave_buf.tail,BUFSIZE) ) + { +@@ -456,9 +462,9 @@ + * "write" is reversed + */ + if (_IOC_DIR(cmd) & _IOC_READ) +- ret = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd)); ++ ret = !_access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd)); + else if (_IOC_DIR(cmd) & _IOC_WRITE) +- ret = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd)); ++ ret = !_access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd)); + if (ret) return -EFAULT; + + switch(cmd) { +@@ -500,7 +506,7 @@ + switch(cmd) { + + case TCGETS: +- if( access_ok(VERIFY_READ, (void *)arg, sizeof(struct termios) ) ) ++ if( _access_ok(VERIFY_READ, (void *)arg, sizeof(struct termios) ) ) + { + ret = copy_to_user( (void*)arg, &channel->termios, sizeof(struct termios) ); + } else { +@@ -508,7 +514,7 @@ + } + break; + case TCSETS: +- if( access_ok(VERIFY_WRITE, (void *)arg, sizeof(struct termios) ) ) ++ if( _access_ok(VERIFY_WRITE, (void *)arg, sizeof(struct termios) ) ) + { + ret = copy_from_user( &channel->termios, (void*)arg, sizeof(struct termios) ); + } else { +@@ -533,6 +539,12 @@ + break; + case TIOCMSET: + break; ++ case TIOCSERGETLSR: ++ ret = -ENOIOCTLCMD; ++ break; ++ case TIOCGICOUNT: ++ ret = -ENOIOCTLCMD; ++ break; + default: + ret = -ENOTTY; + break; +@@ -541,6 +553,7 @@ + if( ret == -ENOTTY ) + { + printk( KERN_NOTICE EQ3LOOP_DRIVER_NAME ": eq3loop_ioctl_slave() %s: unhandled ioctl 0x%04X\n", channel->name, cmd ); ++ ret = -ENOIOCTLCMD; + } + return ret; + } +@@ -908,6 +921,7 @@ + .ioctl = eq3loop_ioctl, + #else + .unlocked_ioctl = eq3loop_ioctl, ++ .compat_ioctl = eq3loop_ioctl, + #endif + }; + +@@ -979,4 +993,4 @@ + module_exit(eq3loop_exit); + MODULE_DESCRIPTION("eQ-3 IPC loopback char driver"); + MODULE_LICENSE("GPL"); +- ++MODULE_VERSION("1.1"); diff --git a/buildroot-external/package/eq3_char_loop/Makefile b/buildroot-external/package/eq3_char_loop/Makefile deleted file mode 100644 index 60251373355..00000000000 --- a/buildroot-external/package/eq3_char_loop/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-m += eq3_char_loop.o diff --git a/buildroot-external/package/eq3_char_loop/eq3_char_loop.c b/buildroot-external/package/eq3_char_loop/eq3_char_loop.c deleted file mode 100644 index 08f562946ce..00000000000 --- a/buildroot-external/package/eq3_char_loop/eq3_char_loop.c +++ /dev/null @@ -1,996 +0,0 @@ -/* -* eQ-3 char loopback driver for HomeMatic / HomeMatic IP dual stack implementations -* -* Copyright (c) 2015 by eQ-3 Entwicklung GmbH -* Author: Lars Reemts, lars.reemts@finalbit.de -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -* -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define EQ3LOOP_NUMBER_OF_CHANNELS 4 -#define EQ3LOOP_DRIVER_NAME "eq3loop" - -/* Use 'L' as magic number */ -#define EQ3LOOP_IOC_MAGIC 'L' - -#define EQ3LOOP_IOCSCREATESLAVE _IOW(EQ3LOOP_IOC_MAGIC, 1, uint32_t) -#define EQ3LOOP_IOCGEVENTS _IOR(EQ3LOOP_IOC_MAGIC, 2, uint32_t) - -#define EVENT_BIT_SLAVE_OPENED 0 -#define EVENT_BIT_SLAVE_CLOSED 1 -#define STATE_BIT_SLAVE_OPENED 15 - -#define CONNECTION_TYPE_MASTER 0 -#define CONNECTION_TYPE_SLAVE 1 - -#define BUFSIZE 1024 //just use buffer size power of 2. otherwise the size and index calculation dosn't work - -#define DUMP_READWRITE 0 - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0)) - #define _access_ok(__type, __addr, __size) access_ok(__addr, __size) -#else - #define _access_ok(__type, __addr, __size) access_ok(__type, __addr, __size) -#endif - -struct eq3loop_channel_data -{ - struct circ_buf master2slave_buf; - struct circ_buf slave2master_buf; - unsigned char _master2slave_buf[BUFSIZE]; - unsigned char _slave2master_buf[BUFSIZE]; - - wait_queue_head_t master2slaveq; - wait_queue_head_t slave2masterq; - struct semaphore sem; //semaphore for accessing this struct. - volatile long unsigned int pending_events; - volatile long unsigned int slave_open_count; - volatile long unsigned int created; - dev_t devnode; - char name[32]; - struct termios termios; -}; - -struct eq3loop_control_data { - dev_t devnode; - struct cdev cdev; - struct class * class; - struct eq3loop_channel_data channels[EQ3LOOP_NUMBER_OF_CHANNELS]; - struct semaphore sem; //semaphore for accessing this struct. -}; - -struct eq3loop_connection_data -{ - int connection_type; - struct eq3loop_channel_data* channel; - ssize_t (*read) (struct eq3loop_channel_data *, struct file *, char __user *, size_t, loff_t *); - ssize_t (*write) (struct eq3loop_channel_data *, struct file *, const char __user *, size_t, loff_t *); - long (*ioctl) (struct eq3loop_channel_data *, struct file *, unsigned int cmd, unsigned long arg); - int (*close) (struct eq3loop_channel_data *, struct file *); - unsigned int (*poll) (struct eq3loop_channel_data *, struct file*, poll_table* wait); -}; - -static struct eq3loop_control_data* control_data; - -static ssize_t eq3loop_read_slave(struct eq3loop_channel_data* channel, struct file *filp, char *buf, size_t count, loff_t *offset) -{ - ssize_t ret = 0; - int count_to_end,tail; - if (down_interruptible(&channel->sem)){ - return -ERESTARTSYS; - } - - - if( !channel->created ) - { - ret = -ENODEV; - goto out; - } - while( channel->created && !CIRC_CNT( channel->master2slave_buf.head, channel->master2slave_buf.tail, BUFSIZE)) { /* nothing to read */ - up(&channel->sem); /* release the lock */ - if (filp->f_flags & O_NONBLOCK) { - return -EAGAIN; - } - if (wait_event_interruptible(channel->master2slaveq, (!channel->created) || CIRC_CNT( channel->master2slave_buf.head, channel->master2slave_buf.tail, BUFSIZE))){ - return -ERESTARTSYS; /* signal: tell the fs layer to handle it */ - } - /* otherwise loop, but first reacquire the lock */ - if (down_interruptible(&channel->sem)){ - return -ERESTARTSYS; - } - } - - if( !channel->created ) - { - ret = -ENODEV; - goto out; - } - tail = channel->master2slave_buf.tail; - /* ok, data is there, return something */ - count = min((int)count, CIRC_CNT( channel->master2slave_buf.head, tail, BUFSIZE)); - count_to_end = min((int)count,CIRC_CNT_TO_END(channel->master2slave_buf.head,tail,BUFSIZE)); - - #if DUMP_READWRITE - { - int i; - printk( KERN_INFO EQ3LOOP_DRIVER_NAME ": eq3loop_read_slave() %s:", channel->name ); - for( i=0; imaster2slave_buf.buf[(tail + i) & (BUFSIZE - 1)] ); - } - } - #endif - - - if (copy_to_user(buf, channel->master2slave_buf.buf + tail, count_to_end)) { - ret = -EFAULT; - goto out; - } - tail = (tail + count_to_end) & (BUFSIZE - 1); - - if (copy_to_user(buf + count_to_end, channel->master2slave_buf.buf + tail, count - count_to_end)) { - ret = -EFAULT; - goto out; - } - tail = (tail + (count - count_to_end)) & (BUFSIZE - 1); - smp_mb(); - channel->master2slave_buf.tail = tail; - ret = count; - -out: - up (&channel->sem); - - if( ret > 0 ) - { - wake_up_interruptible( &channel->master2slaveq ); - } - else - { - printk( KERN_ERR EQ3LOOP_DRIVER_NAME ": eq3loop_read_slave() %s: error while reading from slave", channel->name ); - } - return ret; -} - -static ssize_t eq3loop_read_master(struct eq3loop_channel_data* channel, struct file *filp, char *buf, size_t count, loff_t *offset) -{ - ssize_t ret = 0; - int count_to_end,tail; - if (down_interruptible(&channel->sem)) - return -ERESTARTSYS; - - while( channel->slave_open_count && (!CIRC_CNT( channel->slave2master_buf.head, channel->slave2master_buf.tail, BUFSIZE))) { /* slave open but nothing to read */ - up(&channel->sem); /* release the lock */ - if (filp->f_flags & O_NONBLOCK) - return -EAGAIN; - if (wait_event_interruptible(channel->slave2masterq, (!channel->slave_open_count) || CIRC_CNT( channel->slave2master_buf.head, channel->slave2master_buf.tail, BUFSIZE))) - return -ERESTARTSYS; /* signal: tell the fs layer to handle it */ - /* otherwise loop, but first reacquire the lock */ - if (down_interruptible(&channel->sem)) - return -ERESTARTSYS; - } - if( channel->slave_open_count ) - { - tail = channel->slave2master_buf.tail; - /* ok, data is there, return something */ - count = min((int)count, CIRC_CNT( channel->slave2master_buf.head, tail, BUFSIZE)); - count_to_end = min((int)count,CIRC_CNT_TO_END(channel->slave2master_buf.head, tail, BUFSIZE)); - - #if DUMP_READWRITE - { - int i; - printk( KERN_INFO EQ3LOOP_DRIVER_NAME ": eq3loop_read_master() %s:", channel->name ); - for( i=0; islave2master_buf.buf[(tail + i) & (BUFSIZE - 1)] ); - } - } - #endif - - - if (copy_to_user(buf, channel->slave2master_buf.buf + tail, count_to_end)) { - ret = -EFAULT; - goto out; - } - tail = (tail + count_to_end) & (BUFSIZE - 1); - if (copy_to_user(buf + count_to_end, channel->slave2master_buf.buf + tail, count - count_to_end)) { - ret = -EFAULT; - goto out; - } - tail = (tail + (count - count_to_end)) & (BUFSIZE - 1); - smp_mb(); - channel->slave2master_buf.tail = tail; - ret = count; - } - - -out: - up (&channel->sem); - - if( ret > 0 ) - { - wake_up_interruptible( &channel->slave2masterq ); - } - - return ret; -} - -static ssize_t eq3loop_read(struct file *filp, char *buf, size_t count, loff_t *offset) -{ - struct eq3loop_connection_data *conn = filp->private_data; - if( conn && conn->read ) - { - return conn->read( conn->channel, filp, buf, count, offset ); - } - return -EFAULT; -} - -static ssize_t eq3loop_write_slave(struct eq3loop_channel_data* channel, struct file *filp, const char *buf, size_t count, loff_t *offset) -{ - int head; - ssize_t ret=0; - ssize_t count_to_end; - if (down_interruptible(&channel->sem)) - return -ERESTARTSYS; - - while(!CIRC_SPACE( channel->slave2master_buf.head, channel->slave2master_buf.tail, BUFSIZE)) { /* no space to write */ - up(&channel->sem); /* release the lock */ - if (filp->f_flags & O_NONBLOCK) - return -EAGAIN; - if (wait_event_interruptible(channel->slave2masterq, (!channel->created) || CIRC_SPACE( channel->slave2master_buf.head, channel->slave2master_buf.tail, BUFSIZE))) - return -ERESTARTSYS; /* signal: tell the fs layer to handle it */ - /* otherwise loop, but first reacquire the lock */ - if (down_interruptible(&channel->sem)) - return -ERESTARTSYS; - } - - if( !channel->created ) - { - ret = -ENODEV; - goto out; - } - head = channel->slave2master_buf.head; - if(CIRC_SPACE( head, channel->slave2master_buf.tail, BUFSIZE) < count) - { - ret=-EFAULT; - goto out; - } - - /* ok, space is free, write something */ - count_to_end = min((int)count, CIRC_SPACE_TO_END( head, channel->slave2master_buf.tail, BUFSIZE)); - - if(copy_from_user(channel->slave2master_buf.buf + head, buf, count_to_end)){ - ret=-EFAULT; - goto out; - } - head = (head + count_to_end) & (BUFSIZE - 1); - - if(copy_from_user(channel->slave2master_buf.buf + head, buf+count_to_end, count - count_to_end)){ - ret=-EFAULT; - goto out; - } - head = (head + (count - count_to_end)) & (BUFSIZE - 1); - #if DUMP_READWRITE - { - int i; - if(head < channel->slave2master_buf.head) - { - printk( KERN_INFO EQ3LOOP_DRIVER_NAME ": eq3loop_write_slave() reach end of circular buffer" ); - } - printk( KERN_INFO EQ3LOOP_DRIVER_NAME ": eq3loop_write_slave() %s:", channel->name ); - for( i=0; islave2master_buf.buf[(channel->slave2master_buf.head + i)& (BUFSIZE - 1)] ); - } - } - #endif - - - smp_mb(); - channel->slave2master_buf.head = head; - - ret = count; - -out: - up (&channel->sem); - - if( ret > 0 ) - { - wake_up_interruptible( &channel->slave2masterq ); - } - - return ret; -} - -static ssize_t eq3loop_write_master(struct eq3loop_channel_data* channel, struct file *filp, const char *buf, size_t count, loff_t *offset) -{ - ssize_t ret=0; - int head; - ssize_t count_to_end; - if (down_interruptible(&channel->sem)) - return -ERESTARTSYS; - - while(!CIRC_SPACE( channel->master2slave_buf.head, channel->master2slave_buf.tail, BUFSIZE)) { /* no space to write */ - up(&channel->sem); /* release the lock */ - if (filp->f_flags & O_NONBLOCK) - return -EAGAIN; - if (wait_event_interruptible(channel->master2slaveq, (!channel->slave_open_count) || CIRC_SPACE( channel->master2slave_buf.head, channel->master2slave_buf.tail, BUFSIZE))) - return -ERESTARTSYS; /* signal: tell the fs layer to handle it */ - /* otherwise loop, but first reacquire the lock */ - if (down_interruptible(&channel->sem)) - return -ERESTARTSYS; - } - head = channel->master2slave_buf.head; - if(CIRC_SPACE( head, channel->master2slave_buf.tail, BUFSIZE) < count) - { - ret=-EFAULT; - count_to_end = CIRC_SPACE( head, channel->master2slave_buf.tail, BUFSIZE); - printk( KERN_ERR EQ3LOOP_DRIVER_NAME ": eq3loop_write_master() %s: not enough space in buffers. free space = %zu, required space = %zu", channel->name,count_to_end,count ); - goto out; - } - /* ok, space is free, write something */ - count_to_end = min((int)count, CIRC_SPACE_TO_END( head, channel->master2slave_buf.tail, BUFSIZE)); - - if(copy_from_user(channel->master2slave_buf.buf + head, buf, count_to_end)){ - ret=-EFAULT; - printk( KERN_ERR EQ3LOOP_DRIVER_NAME ": eq3loop_write_master() %s: unable to copy buffer",channel->name ); - goto out; - } - head = (head + count_to_end) & (BUFSIZE - 1); - if(copy_from_user(channel->master2slave_buf.buf + head, buf+count_to_end,count - count_to_end)){ - ret=-EFAULT; - printk( KERN_ERR EQ3LOOP_DRIVER_NAME ": eq3loop_write_master() %s: unable to copy buffer",channel->name ); - goto out; - } - head = (head + (count - count_to_end)) & (BUFSIZE - 1); - #if DUMP_READWRITE - { - int i; - printk( KERN_INFO EQ3LOOP_DRIVER_NAME ": eq3loop_write_master() %s:", channel->name ); - for( i=0; imaster2slave_buf.buf[(channel->master2slave_buf.head + i)&(BUFSIZE - 1)] ); - } - } - #endif - smp_mb(); - channel->master2slave_buf.head = head; - ret = count; - -out: - up (&channel->sem); - if(ret < 0) - { - printk( KERN_INFO EQ3LOOP_DRIVER_NAME ": eq3loop_write_master() return error: %d", ret); - } - if( ret > 0 || CIRC_CNT(channel->master2slave_buf.head,channel->master2slave_buf.tail,BUFSIZE) ) - { - //send a signal to reading procces if return is ok or data in the buffer - wake_up_interruptible( &channel->master2slaveq ); - } - - return ret; -} - -static ssize_t eq3loop_write(struct file *filp, const char *buf, size_t count, loff_t *offset) -{ - struct eq3loop_connection_data *conn = filp->private_data; - if( conn && conn->write ) - { - return conn->write( conn->channel, filp, buf, count, offset ); - } - return -EFAULT; -} - -static long eq3loop_create_slave_dev( struct file *filp, const char* name ); - -static long eq3loop_ioctl_ctrl(struct file *filp, unsigned int cmd, unsigned long arg) -{ - char buffer[64]; - long ret = 0; - - /* - * extract the type and number bitfields, and don't decode - * wrong cmds: return ENOTTY (inappropriate ioctl) before access_ok() - */ - if (_IOC_TYPE(cmd) != EQ3LOOP_IOC_MAGIC) return -ENOTTY; - - - switch(cmd) { - - case EQ3LOOP_IOCSCREATESLAVE: - ret = strncpy_from_user( buffer, (char*)arg, sizeof(buffer) ); - if( ret <= 0 ) - { - return -EFAULT; - } - return eq3loop_create_slave_dev( filp, buffer ); - default: - return -ENOTTY; - } -} - -static long eq3loop_ioctl_master(struct eq3loop_channel_data* channel, struct file *filp, unsigned int cmd, unsigned long arg) -{ - long ret = 0; - unsigned long temp = 0; - - /* - * extract the type and number bitfields, and don't decode - * wrong cmds: return ENOTTY (inappropriate ioctl) before access_ok() - */ - if (_IOC_TYPE(cmd) != EQ3LOOP_IOC_MAGIC) return -ENOTTY; - - /* - * the direction is a bitmask, and VERIFY_WRITE catches R/W - * transfers. `Type' is user-oriented, while - * access_ok is kernel-oriented, so the concept of "read" and - * "write" is reversed - */ - if (_IOC_DIR(cmd) & _IOC_READ) - ret = !_access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd)); - else if (_IOC_DIR(cmd) & _IOC_WRITE) - ret = !_access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd)); - if (ret) return -EFAULT; - - switch(cmd) { - - case EQ3LOOP_IOCGEVENTS: - if( test_and_clear_bit( EVENT_BIT_SLAVE_OPENED, &channel->pending_events ) ) - { - temp |= (1<pending_events ) ) - { - temp |= (1<pending_events ) ) - { - temp |= (1<pending_events = temp; - smp_mb(); - } - break; - default: - return -ENOTTY; - } - return ret; -} - -static long eq3loop_ioctl_slave(struct eq3loop_channel_data* channel, struct file *filp, unsigned int cmd, unsigned long arg) -{ - long ret = 0; - int temp; - - if (down_interruptible(&channel->sem)) - return -ERESTARTSYS; - - switch(cmd) { - - case TCGETS: - if( _access_ok(VERIFY_READ, (void *)arg, sizeof(struct termios) ) ) - { - ret = copy_to_user( (void*)arg, &channel->termios, sizeof(struct termios) ); - } else { - ret = -EFAULT; - } - break; - case TCSETS: - if( _access_ok(VERIFY_WRITE, (void *)arg, sizeof(struct termios) ) ) - { - ret = copy_from_user( &channel->termios, (void*)arg, sizeof(struct termios) ); - } else { - ret = -EFAULT; - } - break; - case TIOCINQ: - temp = CIRC_CNT( channel->master2slave_buf.head, channel->master2slave_buf.tail, BUFSIZE); - ret = __put_user( temp, (int*)arg ); - break; - case TIOCOUTQ: - temp = CIRC_CNT( channel->slave2master_buf.head, channel->slave2master_buf.tail, BUFSIZE); - ret = __put_user( temp, (int*)arg ); - break; - case TIOCEXCL: - break; - case TCFLSH: - break; - case TIOCMGET: - temp = TIOCM_DSR | TIOCM_CD | TIOCM_CTS; - ret = __put_user( temp, (int*)arg ); - break; - case TIOCMSET: - break; - case TIOCSERGETLSR: - ret = -ENOIOCTLCMD; - break; - case TIOCGICOUNT: - ret = -ENOIOCTLCMD; - break; - default: - ret = -ENOTTY; - break; - } - up (&channel->sem ); - if( ret == -ENOTTY ) - { - printk( KERN_NOTICE EQ3LOOP_DRIVER_NAME ": eq3loop_ioctl_slave() %s: unhandled ioctl 0x%04X\n", channel->name, cmd ); - ret = -ENOIOCTLCMD; - } - return ret; -} - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11)) -static int eq3loop_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) -#else -static long eq3loop_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -#endif -{ - struct eq3loop_connection_data *conn = filp->private_data; - if( !conn ) - { - return eq3loop_ioctl_ctrl( filp, cmd, arg ); - } - if( conn->ioctl ) - { - return conn->ioctl( conn->channel, filp, cmd, arg ); - } - - return -EFAULT; -} - - -static int eq3loop_close_slave(struct eq3loop_channel_data* channel, struct file *filp) -{ - int ret = 0; - - printk( KERN_INFO EQ3LOOP_DRIVER_NAME ": eq3loop_close_slave() %s\n", channel->name ); - - if (down_interruptible(&channel->sem)) - return -ERESTARTSYS; - - if( channel->slave_open_count ) - { - channel->slave_open_count--; - } - - kfree( filp->private_data ); - - set_bit( EVENT_BIT_SLAVE_CLOSED, &channel->pending_events ); - clear_bit( STATE_BIT_SLAVE_OPENED, &channel->pending_events ); - - if( !channel->created ) - { - printk( KERN_INFO EQ3LOOP_DRIVER_NAME ": eq3loop_close_slave() %s destroy device\n", channel->name ); - device_destroy(control_data->class, channel->devnode); - } - - up( &channel->sem ); - smp_mb(); - wake_up_interruptible( &channel->slave2masterq ); - return ret; -} - -static int eq3loop_close_master(struct eq3loop_channel_data* channel, struct file *filp) -{ - int ret = 0; - - printk( KERN_INFO EQ3LOOP_DRIVER_NAME ": eq3loop_close_master() %s\n", channel->name ); - - if (down_interruptible(&channel->sem)) - return -ERESTARTSYS; - - if (down_interruptible(&control_data->sem)) - { - ret = -ERESTARTSYS; - goto out; - } - - channel->created = 0; - - up( &control_data->sem ); - - kfree( filp->private_data ); - - if( !channel->slave_open_count ) - { - printk( KERN_INFO EQ3LOOP_DRIVER_NAME ": eq3loop_close_master() %s destroy device\n", channel->name ); - device_destroy(control_data->class, channel->devnode); - } - -out: - up( &channel->sem ); - wake_up_interruptible( &channel->master2slaveq ); - return ret; -} - -static int eq3loop_close(struct inode *inode, struct file *filp) -{ - struct eq3loop_connection_data *conn = filp->private_data; - if( !conn ) - { - return 0; - } - if( conn->close ) - { - return conn->close( conn->channel, filp ); - } - - return -ENODEV; -} - -static unsigned int eq3loop_poll_master(struct eq3loop_channel_data* channel, struct file* filp, poll_table* wait) -{ - unsigned int mask=0; - unsigned long requested_events = poll_requested_events( wait ); - - //printk( KERN_INFO EQ3LOOP_DRIVER_NAME ": eq3loop_poll_master() %s requested=0x%lX\n", channel->name, requested_events ); - - if( requested_events & ( POLLIN | POLLPRI | POLLERR ) ) - { - poll_wait(filp, &channel->slave2masterq, wait); - } - if( requested_events & POLLOUT ) - { - poll_wait(filp, &channel->master2slaveq, wait); - } - - if (down_interruptible(&channel->sem)) - return -ERESTARTSYS; - - if( channel->slave_open_count ) - { - if( CIRC_SPACE( channel->master2slave_buf.head, channel->master2slave_buf.tail, BUFSIZE) ) - { - mask |= POLLOUT | POLLWRNORM; - } - - if( CIRC_CNT( channel->slave2master_buf.head, channel->slave2master_buf.tail, BUFSIZE) ) - { - mask |= POLLIN | POLLRDNORM; - } - } - - if( test_bit( EVENT_BIT_SLAVE_OPENED, &channel->pending_events ) || test_bit( EVENT_BIT_SLAVE_CLOSED, &channel->pending_events ) ) - { - mask |= POLLPRI; - } - - - - up( &channel->sem ); - - return mask; -} - -static unsigned int eq3loop_poll_slave(struct eq3loop_channel_data* channel, struct file* filp, poll_table* wait) -{ - unsigned int mask=0; - unsigned long requested_events = poll_requested_events( wait ); - - if( requested_events & POLLIN ) - { - poll_wait(filp, &channel->master2slaveq, wait); - } - if( requested_events & POLLOUT ) - { - poll_wait(filp, &channel->slave2masterq, wait); - } - - if (down_interruptible(&channel->sem)) - return -ERESTARTSYS; - - if( CIRC_CNT( channel->master2slave_buf.head, channel->master2slave_buf.tail, BUFSIZE) ) - { - mask |= POLLIN | POLLRDNORM; - } - - if( CIRC_SPACE( channel->slave2master_buf.head, channel->slave2master_buf.tail, BUFSIZE) ) - { - mask |= POLLOUT | POLLWRNORM; - } - - if( !channel->created ) - { - mask |= POLLERR; - } - - up( &channel->sem ); - - return mask; -} - -static unsigned int eq3loop_poll(struct file* filp, poll_table* wait) -{ - struct eq3loop_connection_data *conn = filp->private_data; - if( !conn ) - { - return -EINVAL; - } - if( conn->poll ) - { - return conn->poll( conn->channel, filp, wait ); - } - - return -EINVAL; -} - - -static long eq3loop_create_slave_dev( struct file *filp, const char* name ) -{ - int channel_index = 0; - long ret = 0; - struct eq3loop_channel_data* channel; - struct eq3loop_connection_data* conn; - - if (down_interruptible(&control_data->sem)) - return -ERESTARTSYS; - - while( (channel_index < EQ3LOOP_NUMBER_OF_CHANNELS) && (control_data->channels[channel_index].created) ) - { - channel_index++; - } - if( channel_index >= EQ3LOOP_NUMBER_OF_CHANNELS ) - { - ret = -EINVAL; - goto out; - } - - channel = control_data->channels + channel_index; - memset( channel, 0, sizeof( struct eq3loop_channel_data ) ); - channel->devnode = MKDEV(MAJOR(control_data->devnode), MINOR(control_data->devnode) + channel_index + 1); - strncpy( channel->name, name, sizeof(channel->name)-1 ); - - if( !device_create(control_data->class, NULL, channel->devnode, "%s", name) ) - { - ret = -EBUSY; - goto out; - } - - printk( KERN_INFO EQ3LOOP_DRIVER_NAME ": created slave %s\n", name ); - - conn = kzalloc( sizeof(struct eq3loop_connection_data), GFP_KERNEL ); - if( !conn ) - { - ret = -ENOMEM; - goto out; - } - - sema_init(&channel->sem, 1); - init_waitqueue_head(&channel->master2slaveq); - init_waitqueue_head(&channel->slave2masterq); - - - channel->master2slave_buf.buf = channel->_master2slave_buf; - channel->slave2master_buf.buf = channel->_slave2master_buf; - - smp_mb(); - - channel->created = 1; - - -out: - up(&control_data->sem); - - if( !ret ) - { - conn->connection_type = CONNECTION_TYPE_MASTER; - conn->channel = channel; - conn->read = eq3loop_read_master; - conn->write = eq3loop_write_master; - conn->ioctl = eq3loop_ioctl_master; - conn->close = eq3loop_close_master; - conn->poll = eq3loop_poll_master; - filp->private_data = conn; - } - return ret; -} - -static int eq3loop_open_ctrl(struct file *filp) -{ - return 0; -} - -static int eq3loop_open_slave(struct eq3loop_channel_data* channel, struct file *filp) -{ - int ret = 0; - struct eq3loop_connection_data* conn; - - printk( KERN_INFO EQ3LOOP_DRIVER_NAME ": eq3loop_open_slave() %s\n", channel->name ); - - if (down_interruptible(&channel->sem)) - return -ERESTARTSYS; - - if( !channel->created ) - { - ret = -ENODEV; - goto out; - } - - if( channel->slave_open_count ) - { - ret = -EBUSY; - goto out; - } - - conn = kzalloc( sizeof(struct eq3loop_connection_data), GFP_KERNEL ); - if( !conn ) - { - ret = -ENOMEM; - goto out; - } - - channel->slave_open_count++; - - set_bit( EVENT_BIT_SLAVE_OPENED, &channel->pending_events ); - set_bit( STATE_BIT_SLAVE_OPENED, &channel->pending_events ); - - channel->master2slave_buf.head = 0; - channel->master2slave_buf.tail = 0; - - smp_mb(); - -out: - up( &channel->sem ); - - if( !ret ) - { - conn->connection_type = CONNECTION_TYPE_SLAVE; - conn->channel = channel; - conn->read = eq3loop_read_slave; - conn->write = eq3loop_write_slave; - conn->ioctl = eq3loop_ioctl_slave; - conn->close = eq3loop_close_slave; - conn->poll = eq3loop_poll_slave; - filp->private_data = conn; - wake_up_interruptible( &channel->slave2masterq ); - } - return ret; -} - - -static int eq3loop_open(struct inode *inode, struct file *filp) -{ - if( !control_data ) - { - return -ENODEV; - } - - if( inode->i_rdev == MKDEV(MAJOR(control_data->devnode), MINOR(control_data->devnode)) ) - { - return eq3loop_open_ctrl( filp ); - }else{ - unsigned int channel_index = MINOR( inode->i_rdev ) - MINOR(control_data->devnode) - 1; - if( channel_index >= EQ3LOOP_NUMBER_OF_CHANNELS ) - { - return -ENODEV; - } - return eq3loop_open_slave( &control_data->channels[channel_index], filp ); - } - - return -ENODEV; -} - -static struct file_operations eq3loop_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .read = eq3loop_read, - .write = eq3loop_write, - .open = eq3loop_open, - .release = eq3loop_close, - .poll = eq3loop_poll, -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11)) - .ioctl = eq3loop_ioctl, -#else - .unlocked_ioctl = eq3loop_ioctl, - .compat_ioctl = eq3loop_ioctl, -#endif -}; - -static int __init eq3loop_init(void) -{ - int ret = 0; - - control_data = kzalloc(sizeof(struct eq3loop_control_data), GFP_KERNEL); - if (!control_data) { - ret = -ENOMEM; - goto out; - } - - ret = alloc_chrdev_region(&control_data->devnode, 0, EQ3LOOP_NUMBER_OF_CHANNELS + 1, EQ3LOOP_DRIVER_NAME); - if( ret ) - { - printk(KERN_ERR EQ3LOOP_DRIVER_NAME ": Unable to get device number region\n"); - goto out_free; - } - - cdev_init(&control_data->cdev, &eq3loop_fops); - control_data->cdev.owner=THIS_MODULE; - control_data->cdev.ops=&eq3loop_fops; - ret=cdev_add(&control_data->cdev, control_data->devnode, EQ3LOOP_NUMBER_OF_CHANNELS + 1); - if(ret){ - printk(KERN_ERR EQ3LOOP_DRIVER_NAME ": Unable to add driver\n"); - goto out_unregister_chrdev_region; - } - control_data->class=class_create(THIS_MODULE, EQ3LOOP_DRIVER_NAME); - if(IS_ERR(control_data->class)){ - ret = -EIO; - printk(KERN_ERR EQ3LOOP_DRIVER_NAME ": Unable to register driver class\n"); - goto out_cdev_del; - } - - sema_init(&control_data->sem, 1); - - device_create(control_data->class, NULL, MKDEV(MAJOR(control_data->devnode), MINOR(control_data->devnode)), "%s", EQ3LOOP_DRIVER_NAME); - - goto out; - - out_cdev_del: - cdev_del(&control_data->cdev); - - out_unregister_chrdev_region: - unregister_chrdev_region(control_data->devnode, EQ3LOOP_NUMBER_OF_CHANNELS + 1); - - out_free: - kfree(control_data); -out: - return ret; -} - -static void __exit eq3loop_exit(void) -{ - - unregister_chrdev_region(control_data->devnode, EQ3LOOP_NUMBER_OF_CHANNELS + 1); - device_destroy(control_data->class, MKDEV(MAJOR(control_data->devnode), MINOR(control_data->devnode))); - class_destroy(control_data->class); - cdev_del(&control_data->cdev); - - kfree(control_data); - - control_data = NULL; - -} - -module_init(eq3loop_init); -module_exit(eq3loop_exit); -MODULE_DESCRIPTION("eQ-3 IPC loopback char driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION("1.1"); diff --git a/buildroot-external/package/eq3_char_loop/eq3_char_loop.mk b/buildroot-external/package/eq3_char_loop/eq3_char_loop.mk index c5c67f2a695..9aca0095e90 100644 --- a/buildroot-external/package/eq3_char_loop/eq3_char_loop.mk +++ b/buildroot-external/package/eq3_char_loop/eq3_char_loop.mk @@ -8,12 +8,11 @@ # ############################################################# -EQ3_CHAR_LOOP_VERSION = 1.1.0 -EQ3_CHAR_LOOP_SITE = $(BR2_EXTERNAL_HASSOS_PATH)/package/eq3_char_loop -EQ3_CHAR_LOOP_SITE_METHOD = local +EQ3_CHAR_LOOP_VERSION = 8cb51174c2bc8c4b33df50a96b82c90e8092f79c +EQ3_CHAR_LOOP_SITE = $(call github,eq-3,occu,$(EQ3_CHAR_LOOP_VERSION)) EQ3_CHAR_LOOP_LICENSE = GPL2 #EQ3_CHAR_LOOP_LICENSE_FILES = LICENSE -EQ3_CHAR_LOOP_MODULE_SUBDIRS = . +EQ3_CHAR_LOOP_MODULE_SUBDIRS = KernelDrivers $(eval $(kernel-module)) $(eval $(generic-package)) From d3670fcb8b7a31b880e2efd5a936a3cf645182a1 Mon Sep 17 00:00:00 2001 From: Jens Maus Date: Fri, 2 Apr 2021 17:31:10 +0200 Subject: [PATCH 21/22] modified the rpi-rf-mod package to fetch the dts sources upstream rather than maintaining them downstream. --- .../rpi-rf-mod/dts/rpi-rf-mod-tinker.dts | 120 ------------------ .../package/rpi-rf-mod/dts/rpi-rf-mod.dts | 89 ------------- .../package/rpi-rf-mod/rpi-rf-mod.mk | 9 +- 3 files changed, 4 insertions(+), 214 deletions(-) delete mode 100644 buildroot-external/package/rpi-rf-mod/dts/rpi-rf-mod-tinker.dts delete mode 100644 buildroot-external/package/rpi-rf-mod/dts/rpi-rf-mod.dts diff --git a/buildroot-external/package/rpi-rf-mod/dts/rpi-rf-mod-tinker.dts b/buildroot-external/package/rpi-rf-mod/dts/rpi-rf-mod-tinker.dts deleted file mode 100644 index 1886b7ca73c..00000000000 --- a/buildroot-external/package/rpi-rf-mod/dts/rpi-rf-mod-tinker.dts +++ /dev/null @@ -1,120 +0,0 @@ -/dts-v1/; -/plugin/; - -/* -** Device Tree Overlay for eQ-3 RPI-RF-MOD and -** HM-MOD-RPI-PCB for ASUS Tinkerboard -** -** Copyright (c) 2019-2021 Jens Maus -** Licensed under Apache 2.0 -** -*/ - -/ { - compatible = "asus,rk3288-tinker", "rockchip,rk3288"; - - // fragment to ensure we have the correct gpio pin - // setup for the RPI-RF-MOD and HM-MOD-RPI-PCB - fragment@0 { - target = <&pinctrl>; - __overlay__ { - rpi_rf_mod { - rpi_rf_mod_pins: rpi-rf-mod-pins { - rockchip,pins = <6 1 0 &pcfg_pull_none>, // GPIO6A1: reset - <7 23 0 &pcfg_pull_up>, // GPIO7C7: button - <7 7 0 &pcfg_output_low>, // GPIO7A7: red LED - <6 3 0 &pcfg_output_low>, // GPIO6A3: green LED - <6 4 0 &pcfg_output_low>; // GPIO6A4: blue LED - }; - }; - hm_mod_rpi_pcb { - hm_mod_rpi_pcb_pins: hm-mod-rpi-pcb-pins { - rockchip,pins = <6 0 0 &pcfg_pull_none>; // GPIO6A0: reset - }; - }; - }; - }; - - // fragment to define dedicated led nodes for - // each separate led supported by the RPI-RF-MOD - fragment@1 { - target-path = "/gpio-leds"; - __overlay__ { - pinctrl-names = "default"; - pinctrl-0 = <&rpi_rf_mod_pins>, <&hm_mod_rpi_pcb_pins>; - rpi-rf-mod-red { - label = "rpi_rf_mod:red"; - gpios = <&gpio7 7 0>; - default-state = "keep"; - linux,default-trigger = "none"; - }; - rpi-rf-mod-green { - label = "rpi_rf_mod:green"; - gpios = <&gpio6 3 0>; - default-state = "keep"; - linux,default-trigger = "none"; - }; - rpi-rf-mod-blue { - label = "rpi_rf_mod:blue"; - gpios = <&gpio6 4 0>; - default-state = "keep"; - linux,default-trigger = "none"; - }; - }; - }; - - // fragment to define settings for the rx8130 RTC clock - // of the RPI-RF-MOD - fragment@2 { - target = <&i2c1>; - __overlay__ { - #address-cells = <1>; - #size-cells = <0>; - status = "okay"; - - rpi_rf_mod_rtc: rx8130@32 { - compatible = "epson,rx8130"; - reg = <0x32>; - status = "okay"; - aux-voltage-chargeable = <1>; - }; - }; - }; - - // fragment to define uart/serial dependencies for - // generic_raw_uart - fragment@3 { - target = <&uart1>; - __overlay__ { - compatible = "pivccu,dw_apb"; - status = "okay"; - pivccu,reset_pin = <&gpio6 0 0>; // HM-MOD-RPI-PCB - pivccu,alt_reset_pin = <&gpio6 1 0>;// RPI-RF-MOD - pivccu,red_pin = <&gpio7 7 0>; // RPI-RF-MOD - pivccu,green_pin = <&gpio6 3 0>; // RPI-RF-MOD - pivccu,blue_pin = <&gpio6 4 0>; // RPI-RF-MOD - pivccu,rtc = <&rpi_rf_mod_rtc>; // RPI-RF-MOD - }; - }; - - // we have to disable uart2,uart3,i2s on the Tinkerboard or - // otherwise the gpio-leds cannot use the pins for the RPI-RF-MOD - fragment@4 { - target = <&uart2>; - __overlay__ { - status = "disabled"; - }; - }; - fragment@5 { - target = <&uart3>; - __overlay__ { - status = "disabled"; - }; - }; - fragment@6 { - target = <&i2s>; - __overlay__ { - status = "disabled"; - }; - }; -}; diff --git a/buildroot-external/package/rpi-rf-mod/dts/rpi-rf-mod.dts b/buildroot-external/package/rpi-rf-mod/dts/rpi-rf-mod.dts deleted file mode 100644 index 5ca9a3d0280..00000000000 --- a/buildroot-external/package/rpi-rf-mod/dts/rpi-rf-mod.dts +++ /dev/null @@ -1,89 +0,0 @@ -/dts-v1/; -/plugin/; - -/* -** Device Tree Overlay for eQ-3 RPI-RF-MOD and -** HM-MOD-RPI-PCB for RaspberryPi -** -** Copyright (c) 2018-2021 Jens Maus -** Licensed under Apache 2.0 -** -*/ - -/ { - compatible = "brcm,bcm2708"; - - // fragment to ensure we have the correct gpio pin - // setup for the RPI-RF-MOD - fragment@0 { - target = <&gpio>; - __overlay__ { - rpi_rf_mod_pins: rpi_rf_mod_pins { - brcm,pins = <19 18 12 16 20 21>; // 19=reset, 18=reset (HM-MOD), 12=button, 16=red, 20=green, 21=blue - brcm,pull = <0 0 2 0 0 0>; // 19,18=no-pullup, 12=pullup, 16,20,21=no-pullup - brcm,function = <0 0 0 1 1 1>; // 19,18,12=input, 16,20,21=output - }; - }; - }; - - // fragment to define dedicated led nodes for - // each separate led supported by the RPI-RF-MOD - fragment@1 { - target = <&leds>; - __overlay__ { - pinctrl-names = "default"; - pinctrl-0 = <&rpi_rf_mod_pins>; - rpi_rf_mod_red: rpi_rf_mod_red { - label = "rpi_rf_mod:red"; - gpios = <&gpio 16 0>; - default-state = "keep"; - linux,default-trigger = "none"; - }; - rpi_rf_mod_green: rpi_rf_mod_green { - label = "rpi_rf_mod:green"; - gpios = <&gpio 20 0>; - default-state = "keep"; - linux,default-trigger = "none"; - }; - rpi_rf_mod_blue: rpi_rf_mod_blue { - label = "rpi_rf_mod:blue"; - gpios = <&gpio 21 0>; - default-state = "keep"; - linux,default-trigger = "none"; - }; - }; - }; - - // fragment to define settings for the rx8130 RTC clock - // of the RPI-RF-MOD - fragment@2 { - target = <&i2c1>; - __overlay__ { - #address-cells = <1>; - #size-cells = <0>; - status = "okay"; - - rpi_rf_mod_rtc: rx8130@32 { - compatible = "epson,rx8130"; - reg = <0x32>; - status = "okay"; - aux-voltage-chargeable = <1>; - }; - }; - }; - - // fragment to define uart/serial dependencies for - // generic_raw_uart - fragment@3 { - target = <&uart0>; - __overlay__ { - compatible = "pivccu,pl011"; - pivccu,reset_pin = <&gpio 18 0>; // HM-MOD-RPI-PCB - pivccu,alt_reset_pin = <&gpio 19 0>; // RPI-RF-MOD - pivccu,red_pin = <&gpio 16 0>; // RPI-RF-MOD - pivccu,green_pin = <&gpio 20 0>; // RPI-RF-MOD - pivccu,blue_pin = <&gpio 21 0>; // RPI-RF-MOD - pivccu,rtc = <&rpi_rf_mod_rtc>; // RPI-RF-MOD - }; - }; -}; diff --git a/buildroot-external/package/rpi-rf-mod/rpi-rf-mod.mk b/buildroot-external/package/rpi-rf-mod/rpi-rf-mod.mk index b9b07aca789..e37fcd822b1 100644 --- a/buildroot-external/package/rpi-rf-mod/rpi-rf-mod.mk +++ b/buildroot-external/package/rpi-rf-mod/rpi-rf-mod.mk @@ -11,9 +11,8 @@ # ############################################################# -RPI_RF_MOD_VERSION = 1.6.0 -RPI_RF_MOD_SITE = $(BR2_EXTERNAL_HASSOS_PATH)/package/rpi-rf-mod -RPI_RF_MOD_SITE_METHOD = local +RPI_RF_MOD_VERSION = 97bd31203445d14e3d97e1d6e7a0bcf93b400c2e +RPI_RF_MOD_SITE = $(call github,jens-maus,RaspberryMatic,$(RPI_RF_MOD_VERSION)) RPI_RF_MOD_LICENSE = Apache-2.0 RPI_RF_MOD_DEPENDENCIES = host-dtc #RPI_RF_MOD_LICENSE_FILES = LICENSE @@ -28,13 +27,13 @@ endif define RPI_RF_MOD_BUILD_CMDS if [[ -n "$(RPI_RF_MOD_DTS_FILE)" ]]; then \ - $(HOST_DIR)/bin/dtc -@ -I dts -O dtb -W no-unit_address_vs_reg -o $(@D)/dts/rpi-rf-mod.dtbo $(@D)/dts/$(RPI_RF_MOD_DTS_FILE).dts; \ + $(HOST_DIR)/bin/dtc -@ -I dts -O dtb -W no-unit_address_vs_reg -o $(@D)/buildroot-external/package/rpi-rf-mod/dts/rpi-rf-mod.dtbo $(@D)/buildroot-external/package/rpi-rf-mod/dts/$(RPI_RF_MOD_DTS_FILE).dts; \ fi endef define RPI_RF_MOD_INSTALL_TARGET_CMDS if [[ -n "$(RPI_RF_MOD_DTS_FILE)" ]]; then \ - $(INSTALL) -D -m 0644 $(@D)/dts/rpi-rf-mod.dtbo $(BINARIES_DIR)/; \ + $(INSTALL) -D -m 0644 $(@D)/buildroot-external/package/rpi-rf-mod/dts/rpi-rf-mod.dtbo $(BINARIES_DIR)/; \ fi endef From 314764057cd908de2e70bca4ba097e6f99d355a4 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Wed, 7 Apr 2021 14:39:53 +0200 Subject: [PATCH 22/22] Rename bootEnv.txt to haos-config.txt --- buildroot-external/board/asus/hassos-hook.sh | 2 +- buildroot-external/board/asus/tinker/uboot-boot.ush | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/buildroot-external/board/asus/hassos-hook.sh b/buildroot-external/board/asus/hassos-hook.sh index 3dff006f859..cb6b8e60458 100755 --- a/buildroot-external/board/asus/hassos-hook.sh +++ b/buildroot-external/board/asus/hassos-hook.sh @@ -12,7 +12,7 @@ function hassos_pre_image() { mkdir -p "${BOOT_DATA}/overlays" cp "${BINARIES_DIR}"/*.dtbo "${BOOT_DATA}/overlays/" - cp "${BOARD_DIR}/boot-env.txt" "${BOOT_DATA}/bootEnv.txt" + cp "${BOARD_DIR}/boot-env.txt" "${BOOT_DATA}/haos-config.txt" echo "console=tty1" > "${BOOT_DATA}/cmdline.txt" diff --git a/buildroot-external/board/asus/tinker/uboot-boot.ush b/buildroot-external/board/asus/tinker/uboot-boot.ush index d915e43b273..d3f86d055f7 100644 --- a/buildroot-external/board/asus/tinker/uboot-boot.ush +++ b/buildroot-external/board/asus/tinker/uboot-boot.ush @@ -23,9 +23,9 @@ setenv bootargs_hassos "zram.enabled=1 zram.num_devices=3 apparmor=1 security=ap setenv bootargs_a "root=PARTUUID=8d3d53e3-6d49-4c38-8349-aff6859e82fd rootfstype=squashfs ro rootwait" setenv bootargs_b "root=PARTUUID=a3ec664e-32ce-4665-95ea-7ae90ce9aa20 rootfstype=squashfs ro rootwait" -# Load environment from bootEnv.txt -if test -e mmc ${devnum}:1 bootEnv.txt; then - fatload mmc ${devnum}:1 ${ramdisk_addr_r} bootEnv.txt +# Load environment from haos-config.txt +if test -e mmc ${devnum}:1 haos-config.txt; then + fatload mmc ${devnum}:1 ${ramdisk_addr_r} haos-config.txt env import -t ${ramdisk_addr_r} ${filesize} fi