build/patch/kernel/sun8i-default/matrix-support-Matrix-starter-kit.patch
2016-10-12 21:24:54 +02:00

1991 lines
51 KiB
Diff

From 9d43538162796100f16026a6ee26d826dd82320f Mon Sep 17 00:00:00 2001
From: wwd <ericrock@foxmail.com>
Date: Mon, 16 May 2016 13:20:02 +0800
Subject: [PATCH] matrix: support Matrix starter kit
---
arch/arm/configs/sun8iw7p1smp_defconfig | 204 +++++++++++-
arch/arm/mach-sunxi/sun8i.c | 55 ++++
drivers/char/Kconfig | 24 ++
drivers/char/Makefile | 5 +
drivers/char/matrix_gpio_int.c | 309 +++++++++++++++++
drivers/char/matrix_hcsr04.c | 184 +++++++++++
drivers/char/matrix_pwm.c | 206 ++++++++++++
drivers/char/matrix_rotary_encoder.c | 205 ++++++++++++
drivers/input/misc/adxl34x.c | 33 +-
drivers/staging/iio/Kconfig | 1 +
drivers/staging/iio/Makefile | 1 +
drivers/staging/iio/humidity/Kconfig | 15 +
drivers/staging/iio/humidity/Makefile | 5 +
drivers/staging/iio/humidity/dht11.c | 366 +++++++++++++++++++++
drivers/staging/iio/industrialio-core.c | 1 +
drivers/staging/iio/types.h | 1 +
drivers/w1/masters/Makefile | 2 +-
drivers/w1/masters/w1-gpio-board.c | 59 ++++
drivers/w1/masters/w1-gpio.c | 13 +-
.../sun8iw7p1/configs/nanopi-h3/sys_config.fex | 9 +-
21 files changed, 1684 insertions(+), 28 deletions(-)
create mode 100644 drivers/char/matrix_gpio_int.c
create mode 100644 drivers/char/matrix_hcsr04.c
create mode 100644 drivers/char/matrix_pwm.c
create mode 100644 drivers/char/matrix_rotary_encoder.c
create mode 100644 drivers/staging/iio/humidity/Kconfig
create mode 100644 drivers/staging/iio/humidity/Makefile
create mode 100644 drivers/staging/iio/humidity/dht11.c
create mode 100644 drivers/w1/masters/w1-gpio-board.c
diff --git a/arch/arm/configs/sun8iw7p1smp_defconfig b/arch/arm/configs/sun8iw7p1smp_defconfig
index bc86f3d..8cec706 100644
--- a/arch/arm/configs/sun8iw7p1smp_defconfig
+++ b/arch/arm/configs/sun8iw7p1smp_defconfig
@@ -1079,7 +1079,7 @@ CONFIG_BLK_DEV_CRYPTOLOOP=y
# CONFIG_DS1682 is not set
# CONFIG_TI_DAC7512 is not set
CONFIG_UID_STAT=y
-# CONFIG_BMP085 is not set
+CONFIG_BMP085=m
# CONFIG_USB_SWITCH_FSA9480 is not set
# CONFIG_SUNXI_BROM_READ is not set
# CONFIG_C2PORT is not set
@@ -1396,7 +1396,9 @@ CONFIG_INPUT_UINPUT=y
# CONFIG_INPUT_GPIO is not set
# CONFIG_INPUT_PCF8574 is not set
# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
-# CONFIG_INPUT_ADXL34X is not set
+CONFIG_INPUT_ADXL34X=m
+CONFIG_INPUT_ADXL34X_I2C=m
+# CONFIG_INPUT_ADXL34X_SPI is not set
# CONFIG_INPUT_CMA3000 is not set
# CONFIG_INPUT_SHAFT_ENCODER is not set
@@ -1461,6 +1463,10 @@ CONFIG_SERIAL_SUNXI_CONSOLE=y
# CONFIG_DCC_TTY is not set
# CONFIG_RAMOOPS is not set
# CONFIG_SUNXI_D7S is not set
+CONFIG_MATRIX_GPIO_INT=m
+CONFIG_MATRIX_PWM=m
+CONFIG_MATRIX_ROTARY_ENCODER=m
+CONFIG_MATRIX_HCSR04=m
# CONFIG_IR_CUT is not set
CONFIG_SUNXI_CMATESET=y
# CONFIG_SUNXI_ARISC_TEST is not set
@@ -1475,7 +1481,7 @@ CONFIG_SUNXI_SOC_INFO=y
CONFIG_I2C=y
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_COMPAT=y
-# CONFIG_I2C_CHARDEV is not set
+CONFIG_I2C_CHARDEV=y
# CONFIG_I2C_MUX is not set
CONFIG_I2C_HELPER_AUTO=y
CONFIG_I2C_ALGOBIT=y
@@ -1530,7 +1536,7 @@ CONFIG_SPI_SUNXI=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_SPIDEV is not set
+CONFIG_SPI_SPIDEV=y
# CONFIG_SPI_TLE62X0 is not set
# CONFIG_HSI is not set
@@ -1602,7 +1608,29 @@ CONFIG_GPIO_SYSFS=y
# MODULbus GPIO expanders:
#
CONFIG_GPIO_SUNXI=m
-# CONFIG_W1 is not set
+CONFIG_W1=y
+
+#
+# 1-wire Bus Masters
+#
+# CONFIG_W1_MASTER_DS2490 is not set
+# CONFIG_W1_MASTER_DS2482 is not set
+# CONFIG_W1_MASTER_DS1WM is not set
+CONFIG_W1_MASTER_GPIO=m
+
+#
+# 1-wire Slaves
+#
+CONFIG_W1_SLAVE_THERM=y
+# CONFIG_W1_SLAVE_SMEM is not set
+# CONFIG_W1_SLAVE_DS2408 is not set
+# CONFIG_W1_SLAVE_DS2423 is not set
+# CONFIG_W1_SLAVE_DS2431 is not set
+# CONFIG_W1_SLAVE_DS2433 is not set
+# CONFIG_W1_SLAVE_DS2760 is not set
+# CONFIG_W1_SLAVE_DS2780 is not set
+# CONFIG_W1_SLAVE_DS2781 is not set
+# CONFIG_W1_SLAVE_BQ27000 is not set
# CONFIG_POWER_SUPPLY is not set
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
@@ -1677,7 +1705,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_NTC_THERMISTOR is not set
# CONFIG_SENSORS_PC87360 is not set
# CONFIG_SENSORS_PC87427 is not set
-# CONFIG_SENSORS_PCF8591 is not set
+CONFIG_SENSORS_PCF8591=m
# CONFIG_PMBUS is not set
# CONFIG_DA380 is not set
# CONFIG_SENSORS_SHT15 is not set
@@ -1809,7 +1837,8 @@ CONFIG_BCMA_POSSIBLE=y
# CONFIG_MFD_AAT2870_CORE is not set
# CONFIG_MFD_RC5T583 is not set
# CONFIG_REGULATOR is not set
-# CONFIG_PWM is not set
+CONFIG_PWM=y
+CONFIG_PWM_SUNXI=y
CONFIG_MEDIA_SUPPORT=y
#
@@ -2574,7 +2603,7 @@ CONFIG_RTC_INTF_DEV=y
#
# I2C RTC drivers
#
-# CONFIG_RTC_DRV_DS1307 is not set
+CONFIG_RTC_DRV_DS1307=m
# CONFIG_RTC_DRV_DS1374 is not set
# CONFIG_RTC_DRV_DS1672 is not set
# CONFIG_RTC_DRV_DS3232 is not set
@@ -2658,7 +2687,164 @@ CONFIG_SUNXI_DMA=y
#
# Microsoft Hyper-V guest support
#
-# CONFIG_STAGING is not set
+CONFIG_STAGING=y
+# CONFIG_USBIP_CORE is not set
+# CONFIG_ECHO is not set
+# CONFIG_ASUS_OLED is not set
+# CONFIG_RTLLIB is not set
+# CONFIG_R8712U is not set
+# CONFIG_RTS5139 is not set
+# CONFIG_TRANZPORT is not set
+# CONFIG_LINE6_USB is not set
+# CONFIG_USB_SERIAL_QUATECH2 is not set
+# CONFIG_USB_SERIAL_QUATECH_USB2 is not set
+# CONFIG_VT6656 is not set
+CONFIG_IIO=y
+# CONFIG_IIO_ST_HWMON is not set
+# CONFIG_IIO_BUFFER is not set
+# CONFIG_IIO_TRIGGER is not set
+
+#
+# Accelerometers
+#
+# CONFIG_ADIS16201 is not set
+# CONFIG_ADIS16203 is not set
+# CONFIG_ADIS16204 is not set
+# CONFIG_ADIS16209 is not set
+# CONFIG_ADIS16220 is not set
+# CONFIG_ADIS16240 is not set
+# CONFIG_KXSD9 is not set
+# CONFIG_LIS3L02DQ is not set
+
+#
+# Analog to digital converters
+#
+# CONFIG_AD7291 is not set
+# CONFIG_AD7298 is not set
+# CONFIG_AD7606 is not set
+# CONFIG_AD799X is not set
+# CONFIG_AD7476 is not set
+# CONFIG_AD7887 is not set
+# CONFIG_AD7780 is not set
+# CONFIG_AD7793 is not set
+# CONFIG_AD7816 is not set
+# CONFIG_AD7192 is not set
+# CONFIG_ADT7310 is not set
+# CONFIG_ADT7410 is not set
+# CONFIG_AD7280 is not set
+# CONFIG_MAX1363 is not set
+
+#
+# Analog digital bi-direction converters
+#
+# CONFIG_ADT7316 is not set
+
+#
+# Capacitance to digital converters
+#
+# CONFIG_AD7150 is not set
+# CONFIG_AD7152 is not set
+# CONFIG_AD7746 is not set
+
+#
+# Digital to analog converters
+#
+# CONFIG_AD5064 is not set
+# CONFIG_AD5360 is not set
+# CONFIG_AD5380 is not set
+# CONFIG_AD5421 is not set
+# CONFIG_AD5624R_SPI is not set
+# CONFIG_AD5446 is not set
+# CONFIG_AD5504 is not set
+# CONFIG_AD5764 is not set
+# CONFIG_AD5791 is not set
+# CONFIG_AD5686 is not set
+# CONFIG_MAX517 is not set
+
+#
+# Direct Digital Synthesis
+#
+# CONFIG_AD5930 is not set
+# CONFIG_AD9832 is not set
+# CONFIG_AD9834 is not set
+# CONFIG_AD9850 is not set
+# CONFIG_AD9852 is not set
+# CONFIG_AD9910 is not set
+# CONFIG_AD9951 is not set
+
+#
+# Digital gyroscope sensors
+#
+# CONFIG_ADIS16060 is not set
+# CONFIG_ADIS16080 is not set
+# CONFIG_ADIS16130 is not set
+# CONFIG_ADIS16260 is not set
+# CONFIG_ADXRS450 is not set
+
+#
+# Humidity sensors
+#
+CONFIG_DHT11=m
+
+#
+# Network Analyzer, Impedance Converters
+#
+# CONFIG_AD5933 is not set
+CONFIG_INV_SENSOR=y
+
+#
+# Light sensors
+#
+# CONFIG_SENSORS_ISL29018 is not set
+# CONFIG_SENSORS_TSL2563 is not set
+# CONFIG_TSL2583 is not set
+
+#
+# Magnetometer sensors
+#
+# CONFIG_SENSORS_HMC5843 is not set
+
+#
+# Active energy metering IC
+#
+# CONFIG_ADE7753 is not set
+# CONFIG_ADE7754 is not set
+# CONFIG_ADE7758 is not set
+# CONFIG_ADE7759 is not set
+# CONFIG_ADE7854 is not set
+
+#
+# Resolver to digital converters
+#
+# CONFIG_AD2S90 is not set
+# CONFIG_AD2S1200 is not set
+# CONFIG_AD2S1210 is not set
+
+#
+# Triggers - standalone
+#
+# CONFIG_IIO_SIMPLE_DUMMY is not set
+# CONFIG_ZSMALLOC is not set
+# CONFIG_FB_SM7XX is not set
+# CONFIG_USB_ENESTORAGE is not set
+# CONFIG_BCM_WIMAX is not set
+# CONFIG_FT1000 is not set
+
+#
+# Speakup console speech
+#
+# CONFIG_SPEAKUP is not set
+# CONFIG_TOUCHSCREEN_CLEARPAD_TM1217 is not set
+# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set
+# CONFIG_STAGING_MEDIA is not set
+
+#
+# Android
+#
+# CONFIG_ANDROID is not set
+# CONFIG_PHONE is not set
+# CONFIG_USB_WPAN_HCD is not set
+# CONFIG_SUNXIOOPS is not set
CONFIG_CLKDEV_LOOKUP=y
CONFIG_HAVE_CLK_PREPARE=y
CONFIG_COMMON_CLK=y
diff --git a/arch/arm/mach-sunxi/sun8i.c b/arch/arm/mach-sunxi/sun8i.c
index 2c35075..7700d04 100755
--- a/arch/arm/mach-sunxi/sun8i.c
+++ b/arch/arm/mach-sunxi/sun8i.c
@@ -117,6 +117,40 @@ static struct i2c_board_info i2c_ina219_devs[] __initdata = {
};
#endif
+/*------------------------------------------------------------------------------
+ * Matrix device
+ */
+#if defined(CONFIG_INPUT_ADXL34X_I2C_MODULE)
+#define ADXL34X_I2C_BUS (0)
+static struct i2c_board_info __initdata adxl34x_i2c_bdi = {
+ I2C_BOARD_INFO("adxl34x", 0x1d),
+ .irq = -1,
+};
+#endif
+
+#if defined(CONFIG_BMP085_MODULE)
+#define BMP085_I2C_BUS (0)
+static struct i2c_board_info __initdata bmp085_i2c_bdi = {
+ I2C_BOARD_INFO("bmp085", 0x77),
+ .irq = -1,
+};
+#endif
+
+#if defined(CONFIG_RTC_DRV_DS1307_MODULE)
+#define DS1307_I2C_BUS (0)
+static struct i2c_board_info __initdata ds1307_i2c_bdi = {
+ I2C_BOARD_INFO("ds1307", 0X68),
+ .irq = -1,
+};
+#endif
+
+#if defined(CONFIG_SENSORS_PCF8591_MODULE)
+#define PCF8591_I2C_BUS (0)
+static struct i2c_board_info __initdata pcf8591_i2c_bdi = {
+ I2C_BOARD_INFO("pcf8591", 0x48),
+};
+#endif
+
#if defined(CONFIG_ION) || defined(CONFIG_ION_MODULE)
#define DEFAULT_SUNXI_ION_RESERVE_SIZE 96
#define ION_CARVEOUT_INIT_MAX 4
@@ -461,6 +495,27 @@ static void __init sunxi_dev_init(void)
}
printk("ina219 device registered\n");
#endif
+
+#if defined(CONFIG_INPUT_ADXL34X_I2C_MODULE)
+ printk("plat: add adxl34x device\n");
+ i2c_register_board_info(ADXL34X_I2C_BUS, &adxl34x_i2c_bdi, 1);
+#endif
+
+#if defined(CONFIG_BMP085_MODULE)
+ printk("plat: add bmp085 device\n");
+ i2c_register_board_info(BMP085_I2C_BUS, &bmp085_i2c_bdi, 1);
+#endif
+
+#if defined(CONFIG_RTC_DRV_DS1307_MODULE)
+ printk("plat: add ds1307 device\n");
+ i2c_register_board_info(DS1307_I2C_BUS, &ds1307_i2c_bdi, 1);
+#endif
+
+#if defined(CONFIG_SENSORS_PCF8591_MODULE)
+ printk("plat: add pcf8591 device\n");
+ i2c_register_board_info(PCF8591_I2C_BUS, &pcf8591_i2c_bdi, 1);
+#endif
+
#ifdef CONFIG_ANDROID_RAM_CONSOLE
/* ram console platform device initialize*/
ram_console_device_init();
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 6614788..5090528 100755
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -636,6 +636,30 @@ config SUNXI_D7S
---help---
Sunxi display 7 segment for h3.
+config MATRIX_GPIO_INT
+ tristate "Matrix GPIO int sensor module"
+ default m
+ ---help---
+ Driver for Matrix GPIO int sensor module.
+
+config MATRIX_PWM
+ tristate "Matrix PWM module"
+ default m
+ ---help---
+ Driver for Matrix PWM module.
+
+config MATRIX_ROTARY_ENCODER
+ tristate "Matrix rotary encoder"
+ default m
+ ---help---
+ Driver for Matrix rotary encoder.
+
+config MATRIX_HCSR04
+ tristate "Matrix hcsr04"
+ default m
+ ---help---
+ Driver for Matrix hcsr04.
+
source "drivers/char/sunxi_g2d/Kconfig"
source "drivers/char/sunxi_ir_cut/Kconfig"
source "drivers/char/cma_test/Kconfig"
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 399be2b..f0bda58 100755
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -82,3 +82,8 @@ obj-y += sunxi-di/
obj-${CONFIG_ID} += sunxi_id/
obj-${CONFIG_RESET_KEY} += sunxi_key/
obj-$(CONFIG_IR_CUT) += sunxi_ir_cut/
+
+obj-$(CONFIG_MATRIX_GPIO_INT) += matrix_gpio_int.o
+obj-$(CONFIG_MATRIX_PWM) += matrix_pwm.o
+obj-$(CONFIG_MATRIX_ROTARY_ENCODER) += matrix_rotary_encoder.o
+obj-$(CONFIG_MATRIX_HCSR04) += matrix_hcsr04.o
\ No newline at end of file
diff --git a/drivers/char/matrix_gpio_int.c b/drivers/char/matrix_gpio_int.c
new file mode 100644
index 0000000..cbe29ca
--- /dev/null
+++ b/drivers/char/matrix_gpio_int.c
@@ -0,0 +1,309 @@
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/poll.h>
+#include <linux/sched.h>
+#include <linux/irq.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <linux/interrupt.h>
+#include <asm/uaccess.h>
+#include <linux/platform_device.h>
+#include <linux/cdev.h>
+#include <linux/miscdevice.h>
+#include <linux/gpio.h>
+
+#define DEVICE_NAME "sensor"
+#define MAX_SENDEV_NUM 8
+
+struct sensor {
+ int gpio;
+ int int_type;
+};
+
+
+struct sensor_desc {
+ int ID;
+ int gpio;
+ int int_type;
+ char *name;
+ int is_used;
+ struct timer_list timer;
+};
+
+static size_t sensor_num = -1; // number of sensor has been registered
+static int is_started = 0;
+static struct semaphore lock;
+
+static struct sensor_desc sensor_dev[MAX_SENDEV_NUM] = {
+ { 0, -1, -1, "gpio_int_sensor1"},
+ { 1, -1, -1, "gpio_int_sensor2"},
+ { 2, -1, -1, "gpio_int_sensor3"},
+ { 3, -1, -1, "gpio_int_sensor4"},
+ { 4, -1, -1, "gpio_int_sensor5"},
+ { 5, -1, -1, "gpio_int_sensor6"},
+ { 6, -1, -1, "gpio_int_sensor7"},
+ { 7, -1, -1, "gpio_int_sensor8"},
+};
+
+static volatile char sensor_dev_value[MAX_SENDEV_NUM] = {
+};
+
+static DECLARE_WAIT_QUEUE_HEAD(sensor_dev_waitq);
+
+static volatile int ev_press = 0;
+
+// static int timer_counter = 0;
+static void gpio_int_sensors_timer(unsigned long _data)
+{
+
+ struct sensor_desc *bdata = (struct sensor_desc *)_data;
+ int ID;
+ unsigned tmp = gpio_get_value(bdata->gpio);
+ ID = bdata->ID;
+
+ // printk("%s %d value=%d int_type=%d\n", __FUNCTION__, timer_counter++, tmp, bdata->int_type);
+ if (bdata->int_type == IRQ_TYPE_EDGE_RISING) {
+ if(tmp == 1) {
+ sensor_dev_value[ID] = 1;
+ ev_press = 1;
+ wake_up_interruptible(&sensor_dev_waitq);
+ }
+ } else if (bdata->int_type == IRQ_TYPE_EDGE_FALLING) {
+ if(tmp == 0) {
+ sensor_dev_value[ID] = 1;
+ ev_press = 1;
+ wake_up_interruptible(&sensor_dev_waitq);
+ }
+ } else if (bdata->int_type == IRQ_TYPE_EDGE_BOTH) {
+ sensor_dev_value[ID] = tmp;
+ ev_press = 1;
+ wake_up_interruptible(&sensor_dev_waitq);
+ }
+}
+
+// static int int_counter=0;
+static irqreturn_t gpio_int_sensor_interrupt(int irq, void *dev_id)
+{
+ // printk("%s %d\n", __FUNCTION__, int_counter++);
+ struct sensor_desc *bdata = (struct sensor_desc *)dev_id;
+ mod_timer(&bdata->timer, jiffies + msecs_to_jiffies(100));
+ return IRQ_HANDLED;
+}
+
+static int start_all_sensor(void)
+{
+ int irq;
+ int i;
+ int err = 0;
+
+ for (i = 0; i < sensor_num; i++) {
+ if (!sensor_dev[i].gpio)
+ continue;
+
+ setup_timer(&sensor_dev[i].timer, gpio_int_sensors_timer,
+ (unsigned long)&sensor_dev[i]);
+
+ err = gpio_request(sensor_dev[i].gpio, "gpio_int_sensor");
+ if (err) {
+ printk("%s gpio_request %d fail\n", __FUNCTION__, sensor_dev[i].gpio);
+ break;
+ }
+
+ irq = gpio_to_irq(sensor_dev[i].gpio);
+ err = request_irq(irq, gpio_int_sensor_interrupt, IRQ_TYPE_EDGE_FALLING,
+ sensor_dev[i].name, (void *)&sensor_dev[i]);
+ if (err) {
+ printk("%s request_irq %d fail\n", __FUNCTION__, irq);
+ break;
+ }
+ }
+
+ if (err) {
+ i--;
+ for (; i >= 0; i--) {
+ if (!sensor_dev[i].gpio)
+ continue;
+
+ gpio_free(sensor_dev[i].gpio);
+ irq = gpio_to_irq(sensor_dev[i].gpio);
+ disable_irq(irq);
+ free_irq(irq, (void *)&sensor_dev[i]);
+
+ del_timer_sync(&sensor_dev[i].timer);
+ }
+
+ return -EBUSY;
+ }
+
+ ev_press = 0;
+ return 0;
+}
+
+static int gpio_int_sensors_open(struct inode *inode, struct file *file)
+{
+ if (down_trylock(&lock))
+ return -EBUSY;
+ sensor_num = 0;
+ is_started = 0;
+ return 0;
+}
+
+static int stop_all_sensor(void)
+{
+ int irq, i;
+
+ for (i = 0; i < sensor_num; i++) {
+ if (!sensor_dev[i].gpio)
+ continue;
+
+ gpio_free(sensor_dev[i].gpio);
+ irq = gpio_to_irq(sensor_dev[i].gpio);
+ free_irq(irq, (void *)&sensor_dev[i]);
+
+ del_timer_sync(&sensor_dev[i].timer);
+ }
+ return 0;
+}
+
+static int gpio_int_sensors_close(struct inode *inode, struct file *file)
+{
+ // printk("%s sensor_num=%d is_started=%d\n",__FUNCTION__, sensor_num, is_started);
+ if (is_started && sensor_num > 0) {
+ stop_all_sensor();
+ }
+ sensor_num = -1;
+ is_started = 0;
+ ev_press = 0;
+ up(&lock);
+ return 0;
+}
+
+// static int read_counter = 0;
+static int gpio_int_sensors_read(struct file *filp, char __user *buff,
+ size_t count, loff_t *offp)
+{
+ unsigned long err;
+ int i = 0;
+
+ if (!ev_press) {
+ if (filp->f_flags & O_NONBLOCK)
+ return -EAGAIN;
+ else
+ wait_event_interruptible(sensor_dev_waitq, ev_press);
+ }
+
+ ev_press = 0;
+
+ err = copy_to_user((void *)buff, (const void *)(&sensor_dev_value),
+ min(sensor_num, count));
+ for (i = 0; i<sensor_num; i++) {
+ sensor_dev_value[i] = 0;
+ }
+
+ return err ? -EFAULT : min(sensor_num, count);
+}
+
+static unsigned int gpio_int_sensors_poll( struct file *file,
+ struct poll_table_struct *wait)
+{
+ unsigned int mask = 0;
+
+ poll_wait(file, &sensor_dev_waitq, wait);
+ if (ev_press)
+ mask |= POLLIN | POLLRDNORM;
+
+ return mask;
+}
+
+static long gpio_int_sensors_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+#define ADD_SENSOR (0)
+#define DEL_SENSOR (1)
+#define START_ALL_SENSOR (4)
+#define STOP_ALL_SENSOR (8)
+
+ struct sensor sen;
+ void __user *argp;
+ int del_dev;
+ int ret;
+
+ //printk("%s cmd=%d\n", __func__, cmd);
+ switch(cmd) {
+ case ADD_SENSOR:
+ if (is_started != 0 || sensor_num >= MAX_SENDEV_NUM)
+ return -EBUSY;
+ argp = (void __user *)arg;
+ if (copy_from_user(&sen, argp, sizeof sen))
+ return -EINVAL;
+ sensor_dev[sensor_num].gpio = sen.gpio;
+ sensor_dev[sensor_num].int_type= sen.int_type;
+ sensor_num++;
+ break;
+ case DEL_SENSOR:
+ del_dev = (int)arg;
+ // printk("%s del_dev=%d\n", __func__, del_dev);
+ if (is_started != 0 || sensor_num <= 0 || del_dev != sensor_num)
+ return -EINVAL;
+ sensor_dev[sensor_num].gpio = -1;
+ sensor_dev[sensor_num].int_type= -1;
+ sensor_num--;
+ break;
+ case START_ALL_SENSOR:
+ if (is_started != 0 || sensor_num <= 0)
+ return -EBUSY;
+ if((ret = start_all_sensor()) < 0)
+ return ret;
+ is_started = 1;
+ break;
+ case STOP_ALL_SENSOR:
+ if (is_started != 1 || sensor_num <= 0)
+ return -EBUSY;
+ stop_all_sensor();
+ is_started = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+
+static struct file_operations dev_fops = {
+ .owner = THIS_MODULE,
+ .open = gpio_int_sensors_open,
+ .release = gpio_int_sensors_close,
+ .read = gpio_int_sensors_read,
+ .poll = gpio_int_sensors_poll,
+ .unlocked_ioctl = gpio_int_sensors_ioctl,
+};
+
+static struct miscdevice misc = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = DEVICE_NAME,
+ .fops = &dev_fops,
+};
+
+static int __init sensor_dev_init(void)
+{
+ printk("Matirx GPIO Int sensor init\n");
+ sema_init(&lock, 1);
+ return misc_register(&misc);
+}
+
+static void __exit sensor_dev_exit(void)
+{
+ printk("Matirx GPIO Int sensor exit\n");
+ misc_deregister(&misc);
+}
+
+module_init(sensor_dev_init);
+module_exit(sensor_dev_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("FriendlyARM Inc.");
+
diff --git a/drivers/char/matrix_hcsr04.c b/drivers/char/matrix_hcsr04.c
new file mode 100644
index 0000000..3f4961b
--- /dev/null
+++ b/drivers/char/matrix_hcsr04.c
@@ -0,0 +1,184 @@
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/hrtimer.h>
+#include <linux/ktime.h>
+#include <linux/device.h>
+#include <linux/kdev_t.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("DA BAI");
+MODULE_DESCRIPTION("Driver for HC-SR04 ultrasonic sensor");
+
+// #define HCSR04_IRQ_DEUBG
+struct HCSR04_resource {
+ int pin;
+};
+
+static int HCSR04_PIN = -1;
+static int hasResource = 0;
+static int irq_num = 0;
+static int irq_time[3];
+static int valid_value = 0;
+static DECLARE_WAIT_QUEUE_HEAD(hcsr_waitq);
+
+static int hcsr04_hwexit(void);
+static int hcsr04_hwinit(void);
+static ssize_t hcsr04_value_read(struct class *class, struct class_attribute *attr, char *buf);
+static irqreturn_t gpio_isr(int irq, void *data);
+
+static ssize_t hcsr04_value_write(struct class *class, struct class_attribute *attr, const char *buf, size_t len)
+{
+ struct HCSR04_resource *res;
+ if (len == 4) {
+ res = (struct HCSR04_resource *)buf;
+
+ if (res->pin != -1 && hasResource == 0) {
+ HCSR04_PIN = res->pin;
+ if (hcsr04_hwinit() == -1) {
+ return -1;
+ }
+ hasResource = 1;
+ } else if (res->pin == -1 && hasResource == 1) {
+ if (hcsr04_hwexit() == -1) {
+ return -1;
+ }
+ hasResource = 0;
+ }
+ }
+ return len;
+}
+
+// This function is called when you read /sys/class/hcsr04/value
+static ssize_t hcsr04_value_read(struct class *class, struct class_attribute *attr, char *buf)
+{
+ int ret = -1;
+ int gpio_irq=-1;
+
+ if (hasResource == 0) {
+ return 0;
+ }
+ irq_num = 0;
+ valid_value = 0;
+ gpio_direction_output(HCSR04_PIN, 0);
+ udelay(50);
+ gpio_set_value(HCSR04_PIN, 1);
+ udelay(50);
+ gpio_set_value(HCSR04_PIN, 0);
+ udelay(50);
+
+ ret = gpio_to_irq(HCSR04_PIN);
+ if (ret < 0) {
+ printk(KERN_ERR"%s fail to gpio_to_irq\n", __func__);
+ goto fail;
+ } else {
+ gpio_irq = ret;
+ }
+
+ ret = request_irq(gpio_irq, gpio_isr, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING , "hc-sr04", NULL);
+ if (ret) {
+ printk(KERN_ERR"%s fail to request_irq\n", __func__);
+ goto fail;
+ }
+
+ if(wait_event_interruptible_timeout(hcsr_waitq, valid_value, HZ) == 0) {
+ printk(KERN_ERR"%s timeout\n", __func__);
+ free_irq(gpio_irq, NULL);
+ goto fail;
+ }
+ free_irq(gpio_irq, NULL);
+#ifdef HCSR04_IRQ_DEUBG
+ printk("%s irq_time[1]=%d irq_time[0]=%d %d\n", __func__, irq_time[1], irq_time[0], irq_time[1]-irq_time[0]);
+#endif
+ return sprintf(buf, "%d\n", irq_time[1]-irq_time[0]);
+ fail:
+ return sprintf(buf, "%d\n", -1);;
+}
+
+// Sysfs definitions for hcsr04 class
+static struct class_attribute hcsr04_class_attrs[] = {
+ __ATTR(value, S_IRUGO | S_IWUSR, hcsr04_value_read, hcsr04_value_write),
+ __ATTR_NULL,
+};
+
+// Name of directory created in /sys/class
+static struct class hcsr04_class = {
+ .name = "hcsr04",
+ .owner = THIS_MODULE,
+ .class_attrs = hcsr04_class_attrs,
+};
+
+// Interrupt handler on ECHO signal
+static irqreturn_t gpio_isr(int irq, void *data)
+{
+ if (valid_value == 0) {
+ if((irq_num == 0 && gpio_get_value(HCSR04_PIN) != 1) ||
+ (irq_num == 1 && gpio_get_value(HCSR04_PIN) != 0) ||
+ (irq_num == 2 && gpio_get_value(HCSR04_PIN) != 1)
+ ) {
+ return IRQ_HANDLED;
+ }
+ irq_time[irq_num] = ktime_to_us(ktime_get());
+ if(irq_num == 2) {
+#ifdef HCSR04_IRQ_DEUBG
+ int i = 0;
+ for(i=0; i<3; i++)
+ printk("%d:%d\n", i, irq_time[i]);
+#endif
+ valid_value = 1;
+ wake_up_interruptible(&hcsr_waitq);
+ return IRQ_HANDLED;
+ }
+ irq_num++;
+ }
+ return IRQ_HANDLED;
+}
+
+static int hcsr04_hwinit(void)
+{
+ int rtc;
+
+ rtc=gpio_request(HCSR04_PIN, "HCSR04");
+ if (rtc!=0) {
+ printk(KERN_INFO "Error %d\n",__LINE__);
+ goto fail;
+ }
+ return 0;
+
+ fail:
+ return -1;
+}
+
+static int hcsr04_init(void)
+{
+ printk(KERN_INFO "HC-SR04 driver v0.32 initializing.\n");
+
+ if (class_register(&hcsr04_class)<0)
+ goto fail;
+ return 0;
+
+ fail:
+ return -1;
+
+}
+
+static int hcsr04_hwexit(void)
+{
+ gpio_free(HCSR04_PIN);
+ return 0;
+}
+
+static void hcsr04_exit(void)
+{
+ class_unregister(&hcsr04_class);
+ printk(KERN_INFO "HC-SR04 disabled.\n");
+}
+
+module_init(hcsr04_init);
+module_exit(hcsr04_exit);
+
diff --git a/drivers/char/matrix_pwm.c b/drivers/char/matrix_pwm.c
new file mode 100644
index 0000000..5cdd951
--- /dev/null
+++ b/drivers/char/matrix_pwm.c
@@ -0,0 +1,206 @@
+/*
+ * linux/drivers/char/matrix_pwm.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/fs.h>
+#include <linux/backlight.h>
+#include <linux/err.h>
+#include <linux/pwm.h>
+#include <linux/slab.h>
+#include <linux/miscdevice.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+
+#include <mach/platform.h>
+#include <asm/uaccess.h>
+
+#define DEVICE_NAME "pwm"
+#define PWM_NUM (2)
+#define PWM_IOCTL_SET_FREQ (0x1)
+#define PWM_IOCTL_STOP (0x0)
+#define NS_IN_1HZ (1000000000UL)
+
+static int is_pwm_working[PWM_NUM] = {0, 0};
+static struct pwm_device *matrix_pwm[PWM_NUM];
+static struct semaphore lock;
+
+static int pwm_set_freq(int index, int pin, unsigned long freq, int duty)
+{
+ int ret=0;
+ int period_ns = NS_IN_1HZ / freq;
+ int duty_ns = period_ns / 1000 * duty;
+
+ printk("%s %d %d\n", __func__, period_ns, duty_ns);
+ if ((ret = pwm_config(matrix_pwm[index], duty_ns, period_ns))) {
+ printk("fail to pwm_config\n");
+ return ret;
+ }
+ if ((ret = pwm_enable(matrix_pwm[index]))) {
+ printk("fail to pwm_enable\n");
+ return ret;
+ }
+ return ret;
+}
+
+static void pwm_stop(int index, int pin)
+{
+ pwm_config(matrix_pwm[index], 0, NS_IN_1HZ / 100);
+ pwm_disable(matrix_pwm[index]);
+}
+
+static int matrix_pwm_hw_init(int index, int pin)
+{
+ int ret=0;
+
+#if 0
+ ret = gpio_request(pin, DEVICE_NAME);
+ if (ret) {
+ printk("request gpio %d for pwm failed\n", pin);
+ return ret;
+ }
+ gpio_direction_output(pin, 0);
+#endif
+
+ matrix_pwm[index] = pwm_request(index, DEVICE_NAME);
+ if (IS_ERR(matrix_pwm[index])) {
+ printk("request pwm%d failed\n", index);
+#if 0
+ gpio_free(pin);
+#endif
+ return -ENODEV;
+ }
+
+ pwm_stop(index, pin);
+ return ret;
+}
+
+static void matrix_pwm_hw_exit(int index,int pin)
+{
+ pwm_stop(index, pin);
+ pwm_free(matrix_pwm[index]);
+#if 0
+ gpio_free(pin);
+#endif
+}
+
+static int matrix_pwm_open(struct inode *inode, struct file *file) {
+ if (!down_trylock(&lock))
+ return 0;
+ else
+ return -EBUSY;
+}
+
+static int matrix_pwm_close(struct inode *inode, struct file *file) {
+ up(&lock);
+ return 0;
+}
+
+static long matrix_pwm_ioctl(struct file *filep, unsigned int cmd,unsigned long arg)
+{
+ int pwm_id;
+ int param[3];
+ int gpio;
+ int freq;
+ int duty;
+ int ret;
+
+ switch (cmd) {
+ case PWM_IOCTL_SET_FREQ:
+ if (copy_from_user(param, (void __user *)arg, sizeof(param)))
+ return -EINVAL;
+ gpio = param[0];
+ freq = param[1];
+ duty = param[2];
+ if (gpio == (SUNXI_PA_BASE + 5)) {
+ pwm_id = 0;
+ } else if (gpio == (SUNXI_PA_BASE + 6)) {
+ pwm_id = 1;
+ } else {
+ printk("Invalid pwm gpio %d\n", gpio);
+ return -EINVAL;
+ }
+
+ if (duty < 0 || duty > 1000) {
+ printk("Invalid pwm duty %d\n", duty);
+ return -EINVAL;
+ }
+
+ if (is_pwm_working[pwm_id] == 1) {
+ matrix_pwm_hw_exit(pwm_id, gpio);
+ }
+
+ if ((ret = matrix_pwm_hw_init(pwm_id, gpio))) {
+ return ret;
+ }
+ is_pwm_working[pwm_id] = 1;
+ if ((ret = pwm_set_freq(pwm_id, gpio, freq, duty))) {
+ return ret;
+ }
+ break;
+ case PWM_IOCTL_STOP:
+ if (copy_from_user(&gpio, (void __user *)arg, sizeof(gpio)))
+ return -EINVAL;
+ if (gpio == (SUNXI_PA_BASE + 5)) {
+ pwm_id = 0;
+ } else if (gpio == (SUNXI_PA_BASE + 6)) {
+ pwm_id = 1;
+ } else {
+ printk("Invalid pwm gpio %d\n", gpio);
+ return -EINVAL;
+ }
+ if (is_pwm_working[pwm_id] == 1) {
+ matrix_pwm_hw_exit(pwm_id, gpio);
+ is_pwm_working[pwm_id] = 0;
+ }
+ break;
+ default:
+ printk("%s unsupported pwm ioctl %d", __FUNCTION__, cmd);
+ break;
+ }
+
+ return 0;
+}
+
+static struct file_operations matrix_pwm_ops = {
+ .owner = THIS_MODULE,
+ .open = matrix_pwm_open,
+ .release = matrix_pwm_close,
+ .unlocked_ioctl = matrix_pwm_ioctl,
+};
+
+static struct miscdevice matrix_misc_dev = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = DEVICE_NAME,
+ .fops = &matrix_pwm_ops,
+};
+
+static int __init matrix_pwm_init(void)
+{
+ int ret;
+ ret = misc_register(&matrix_misc_dev);
+ printk("Matirx PWM init\n");
+
+ sema_init(&lock, 1);
+ return ret;
+}
+
+static void __exit matrix_pwm_exit(void) {
+ misc_deregister(&matrix_misc_dev);
+ printk("Matirx PWM exit\n");
+}
+
+module_init(matrix_pwm_init);
+module_exit(matrix_pwm_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("FriendlyARM Inc.");
+MODULE_DESCRIPTION("FriendlyARM Matrix PWM Driver");
+
diff --git a/drivers/char/matrix_rotary_encoder.c b/drivers/char/matrix_rotary_encoder.c
new file mode 100644
index 0000000..97fcb76
--- /dev/null
+++ b/drivers/char/matrix_rotary_encoder.c
@@ -0,0 +1,205 @@
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/hrtimer.h>
+#include <linux/ktime.h>
+#include <linux/device.h>
+#include <linux/kdev_t.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/of_device.h>
+
+#include <asm/mach/irq.h>
+#include <mach/platform.h>
+
+static int has_init = 0;
+static int sw_pin = -1; // func: int
+static int sia_pin = -1; // func: int
+static int sib_pin = -1; // func: input
+static int sia_irq = -1;
+static int sw_irq = -1;
+static int counter = 0;
+static int sw = 0;
+
+static void rotary_sensor_hw_exit(void);
+static int rotary_sensor_hw_init(void );
+
+
+static ssize_t rotary_sensor_sw_read(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ if ( sw_pin != -1 && sia_pin != -1 && sib_pin != -1) {
+ return sprintf(buf, "%d\n", sw);
+ }
+ return -1;
+}
+
+static ssize_t rotary_sensor_value_read(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ if ( sw_pin != -1 && sia_pin != -1 && sib_pin != -1) {
+ return sprintf(buf, "%d\n", counter);
+ }
+ return -1;
+}
+
+static ssize_t rotary_sensor_gpio_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d,%d,%d\n", sw_pin, sia_pin, sib_pin);
+}
+
+static ssize_t rotary_sensor_gpio_store(struct device *device, struct device_attribute *attr, const char *buf, size_t count)
+{
+ if ( has_init ==0 ) {
+ sscanf(buf,"%d,%d,%d ", &sw_pin, &sia_pin, &sib_pin);
+ printk(KERN_ERR"buf=%s\n", buf);
+ if (rotary_sensor_hw_init()) {
+ has_init = 0;
+ return -1;
+ }
+ else {
+ has_init = 1;
+ }
+ } else {
+ rotary_sensor_hw_exit();
+ has_init = 0;
+ }
+
+ return count;
+}
+static struct device_attribute value_attr = __ATTR(value, S_IRUGO, rotary_sensor_value_read, NULL);
+static struct device_attribute sw_attr = __ATTR(sw,S_IRUGO, rotary_sensor_sw_read, NULL);
+static struct device_attribute gpio_attr = __ATTR(gpio, S_IRUGO|S_IWUGO, rotary_sensor_gpio_show, rotary_sensor_gpio_store);
+
+/* sys attribte group */
+static struct attribute *attrs[] = {
+ &value_attr.attr, &sw_attr.attr, &gpio_attr.attr, NULL,
+};
+
+static struct attribute_group attr_group = {
+ .attrs = (struct attribute **)attrs,
+};
+
+
+static irqreturn_t sw_isr(int irq, void *data)
+{
+ if (gpio_get_value(sw_pin) == 1) {
+ sw = 0;
+ } else {
+ sw = 1;
+ }
+ // printk("%s sw=%d\n", __func__, sw);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t rotate_isr(int irq, void *data)
+{
+ if (gpio_get_value(sib_pin) == 1) {
+ counter++;
+ } else {
+ counter--;
+ }
+ // printk("%s value=%d\n", __func__, counter);
+ return IRQ_HANDLED;
+}
+
+static void rotary_sensor_hw_exit(void)
+{
+ if (sia_irq != -1)
+ free_irq(sia_irq, NULL);
+ if (sw_irq != -1)
+ free_irq(sw_irq, NULL);
+ if (sib_pin != -1)
+ gpio_free(sib_pin);
+ if (sia_pin != -1)
+ gpio_free(sia_pin);
+ if (sw_pin != -1)
+ gpio_free(sw_pin);
+ sw_pin = sia_pin = sib_pin = -1;
+}
+
+static int rotary_sensor_hw_init(void )
+{
+ int ret = -1;
+
+ ret = gpio_request(sw_pin, "sw");
+ if (ret) {
+ printk(KERN_ERR"gpio request sw_pin fail:%d\n", sw_pin);
+ return -1;
+ }
+ ret = gpio_request(sia_pin, "sia_pin");
+ if (ret) {
+ printk(KERN_ERR"gpio request sia_pin fail:%d\n", sia_pin);
+ goto fail_gpio_sw;
+ }
+ ret = gpio_request(sib_pin, "sib_pin");
+ if (ret) {
+ printk(KERN_ERR"gpio request sib_pin fail:%d\n", sia_pin);
+ goto fail_gpio_sia;
+ }
+
+ sw_irq = gpio_to_irq(sw_pin);
+ ret = request_irq(sw_irq, sw_isr, IRQ_TYPE_EDGE_BOTH, "rotary_sensor_sw", NULL);
+ if (ret) {
+ printk(KERN_ERR"%s fail to request_irq, gpio=%d irq=%d\n", __func__, sw_pin, sw_irq);
+ goto fail_gpio_sib;
+ }
+
+ sia_irq = gpio_to_irq(sia_pin);
+ ret = request_irq(sia_irq, rotate_isr, IRQ_TYPE_EDGE_FALLING , "rotary_sensor_sia", NULL);
+ if (ret) {
+ printk(KERN_ERR"%s fail to request_irq, gpio=%d irq=%d\n", __func__, sia_pin, sia_irq);
+ goto fail_irq_sw;
+ }
+
+ gpio_direction_input(sib_pin);
+
+ return ret;
+
+fail_irq_sw:
+ free_irq(sw_irq, NULL);
+fail_gpio_sib:
+ gpio_free(sib_pin);
+fail_gpio_sia:
+ gpio_free(sia_pin);
+fail_gpio_sw:
+ gpio_free(sw_pin);
+ return ret;
+
+}
+static struct kobject *kobj = NULL;
+static int rotary_sensor_init(void)
+{
+ int ret = 0;
+ printk(KERN_INFO "Matrix-rotary_encoder init.\n");
+
+ kobj = kobject_create_and_add("rotary_encoder", &platform_bus.kobj);
+ if (!kobj) {
+ pr_err("%s: failed to kobject_create_and_add for rotary_encoder\n", __func__);
+ return -EINVAL;
+ }
+
+ ret = sysfs_create_group(kobj, &attr_group);
+ if (ret) {
+ pr_err("%s: failed to sysfs_create_group for rotary_encoder\n", __func__);
+ kobject_del(kobj);
+ return -EINVAL;
+ }
+ return ret;
+}
+
+static void rotary_sensor_exit(void)
+{
+ printk(KERN_INFO "Matrix-rotary_encoder exit.\n");
+ sysfs_remove_group(kobj, &attr_group);
+ kobject_put(kobj);
+ kobj = NULL;
+}
+
+module_init(rotary_sensor_init);
+module_exit(rotary_sensor_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("FriendlyARM");
+MODULE_DESCRIPTION("Driver for Matrix-Rotary_Sensor");
diff --git a/drivers/input/misc/adxl34x.c b/drivers/input/misc/adxl34x.c
index 1cf72fe..81fbe55 100644
--- a/drivers/input/misc/adxl34x.c
+++ b/drivers/input/misc/adxl34x.c
@@ -223,7 +223,7 @@ static const struct adxl34x_platform_data adxl34x_default_init = {
.free_fall_threshold = 8,
.free_fall_time = 0x20,
.data_rate = 8,
- .data_range = ADXL_FULL_RES,
+ .data_range = ADXL_FULL_RES | INT_INVERT,
.ev_type = EV_ABS,
.ev_code_x = ABS_X, /* EV_REL */
@@ -236,6 +236,9 @@ static const struct adxl34x_platform_data adxl34x_default_init = {
.watermark = 0,
};
+static irqreturn_t adxl34x_irq(int irq, void *handle);
+static int adxl34x_read_without_int(int irq, void* handle);
+
static void adxl34x_get_triple(struct adxl34x *ac, struct axis_triple *axis)
{
short buf[3];
@@ -296,6 +299,14 @@ static void adxl34x_do_tap(struct adxl34x *ac,
adxl34x_send_key_events(ac, pdata, status, false);
}
+static int adxl34x_read_without_int(int irq, void* handle)
+{
+ if (adxl34x_irq(irq, handle) != IRQ_HANDLED) {
+ return -1;
+ }
+ return 0;
+}
+
static irqreturn_t adxl34x_irq(int irq, void *handle)
{
struct adxl34x *ac = handle;
@@ -486,6 +497,10 @@ static ssize_t adxl34x_calibrate_show(struct device *dev,
struct adxl34x *ac = dev_get_drvdata(dev);
ssize_t count;
+ if (adxl34x_read_without_int(0, ac)) {
+ return 0;
+ }
+
mutex_lock(&ac->mutex);
count = sprintf(buf, "%d,%d,%d\n",
ac->hwcal.x * 4 + ac->swcal.x,
@@ -607,6 +622,9 @@ static ssize_t adxl34x_position_show(struct device *dev,
struct adxl34x *ac = dev_get_drvdata(dev);
ssize_t count;
+ if (adxl34x_read_without_int(0, ac)) {
+ return 0;
+ }
mutex_lock(&ac->mutex);
count = sprintf(buf, "(%d, %d, %d)\n",
ac->saved.x, ac->saved.y, ac->saved.z);
@@ -810,14 +828,16 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq,
ac->fifo_delay = false;
ac->bops->write(dev, POWER_CTL, 0);
-
+ // not use int
+#if 0
err = request_threaded_irq(ac->irq, NULL, adxl34x_irq,
- IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
dev_name(dev), ac);
if (err) {
dev_err(dev, "irq %d busy?\n", ac->irq);
goto err_free_mem;
}
+#endif
err = sysfs_create_group(&dev->kobj, &adxl34x_attr_group);
if (err)
@@ -884,6 +904,13 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq,
ac->pdata.power_mode &= (PCTL_AUTO_SLEEP | PCTL_LINK);
+ __adxl34x_enable(ac);
+#if 0
+ int start = 0x1D;
+ for(; start < 0x3C; start++) {
+ printk("reg[%x]=%x\n", start, AC_READ(ac, start));
+ }
+#endif
return ac;
err_remove_attr:
diff --git a/drivers/staging/iio/humidity/Makefile b/drivers/staging/iio/humidity/Makefile
new file mode 100644
index 0000000..d5d36c0
--- /dev/null
+++ b/drivers/staging/iio/humidity/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for IIO humidity sensor drivers
+#
+
+obj-$(CONFIG_DHT11) += dht11.o
diff --git a/drivers/staging/iio/humidity/dht11.c b/drivers/staging/iio/humidity/dht11.c
new file mode 100644
index 0000000..a751a54
--- /dev/null
+++ b/drivers/staging/iio/humidity/dht11.c
@@ -0,0 +1,366 @@
+/*
+ * DHT11/DHT22 bit banging GPIO driver
+ *
+ * Copyright (c) Harald Geyer <harald@ccbib.org>
+ *
+ * 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.
+ */
+
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/printk.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/sysfs.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/wait.h>
+#include <linux/bitops.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-sunxi.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/kthread.h>
+
+#include <mach/platform.h>
+
+#include "../iio.h"
+
+//#define DHT11_DEBUG 1
+#define DRIVER_NAME "dht11"
+
+#define DHT11_DATA_VALID_TIME 2000000000 /* 2s in ns */
+
+#define DHT11_EDGES_PREAMBLE 4
+#define DHT11_BITS_PER_READ 40
+#define DHT11_EDGES_PER_READ (2*DHT11_BITS_PER_READ + DHT11_EDGES_PREAMBLE)
+
+/* Data transmission timing (nano seconds) */
+#define DHT11_START_TRANSMISSION 18 /* ms */
+#define DHT11_SENSOR_RESPONSE 80000
+#define DHT11_START_BIT 50000
+#define DHT11_DATA_BIT_LOW 27000
+#define DHT11_DATA_BIT_HIGH 70000
+
+#define DATA_START_FLAG_MIN (50000)
+#define DATA_START_FLAG_MAX (60000)
+#define DATA_ONE_MIN (65000)
+#define DATA_ONE_MAX (75000)
+#define DATA_ZERO_MIN (20000)
+#define DATA_ZERO_MAX (30000)
+
+
+struct dht11 {
+ struct device *dev;
+
+ int gpio;
+ int irq;
+
+ struct completion completion;
+
+ s64 timestamp;
+ int temperature;
+ int humidity;
+
+ /* num_edges: -1 means "no transmission in progress" */
+ int num_edges;
+ struct {s64 ts; int value; } edges[DHT11_EDGES_PER_READ];
+};
+
+static int gpio = -1;
+static int dht11_read_flag = 0;
+static unsigned char dht11_decode_byte(int *timing)
+{
+ unsigned char ret = 0;
+ int i;
+
+ for (i = 0; i < 8; ++i) {
+ ret <<= 1;
+ ret +=timing[i];
+ }
+
+ return ret;
+}
+
+static int dht11_decode(struct dht11 *dht11, int *timing)
+{
+ unsigned char temp_int, temp_dec, hum_int, hum_dec, checksum;
+
+#ifdef DHT11_DEBUG
+ int i = 0;
+ for(i=0; i<DHT11_BITS_PER_READ; i++)
+ printk(KERN_ERR"%02d %d\n", i, timing[i]);
+#endif
+ hum_int = dht11_decode_byte(timing);
+ hum_dec = dht11_decode_byte(&timing[8]);
+ temp_int = dht11_decode_byte(&timing[16]);
+ temp_dec = dht11_decode_byte(&timing[24]);
+ checksum = dht11_decode_byte(&timing[32]);
+
+#ifdef DHT11_DEBUG
+ printk(KERN_ERR"%d + %d + %d + %d = %d\n", hum_int, hum_dec, temp_int, temp_dec, checksum);
+#endif
+ if (((hum_int + hum_dec + temp_int + temp_dec) & 0xff) != checksum) {
+ dev_err(dht11->dev,
+ "checksum error %d %d %d %d %d\n",
+ hum_int, hum_dec, temp_int, temp_dec, checksum);
+ return -EIO;
+ }
+
+ dht11->timestamp = iio_get_time_ns();
+ if (hum_int < 20) { /* DHT22 */
+ dht11->temperature = (((temp_int & 0x7f) << 8) + temp_dec) *
+ ((temp_int & 0x80) ? -100 : 100);
+ dht11->humidity = ((hum_int << 8) + hum_dec) * 100;
+ } else if (temp_dec == 0 && hum_dec == 0) { /* DHT11 */
+ dht11->temperature = temp_int * 1000;
+ dht11->humidity = hum_int * 1000;
+ } else {
+ dev_err(dht11->dev,
+ "Don't know how to decode data: %d %d %d %d\n",
+ hum_int, hum_dec, temp_int, temp_dec);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int dht11_read_thread(void *__dev)
+{
+ struct dht11 *dht11 = (struct dht11 *)__dev;
+ int value = 0;
+
+#ifdef DHT11_DEBUG
+ printk(KERN_INFO"%s start\n", __func__);
+#endif
+ if (gpio_direction_output(dht11->gpio, 0))
+ return -1;
+ msleep(DHT11_START_TRANSMISSION);
+ gpio_direction_input(dht11->gpio);
+ dht11->edges[dht11->num_edges].value = gpio_get_value(dht11->gpio);
+ dht11->edges[dht11->num_edges].ts = iio_get_time_ns();
+ while (dht11->num_edges < DHT11_EDGES_PER_READ && dht11_read_flag == 1) {
+ value = gpio_get_value(dht11->gpio);
+ if (dht11->edges[dht11->num_edges].value != value) {
+ dht11->num_edges++;
+ dht11->edges[dht11->num_edges].ts = iio_get_time_ns();
+ dht11->edges[dht11->num_edges].value = value;
+ if (dht11->num_edges == DHT11_EDGES_PER_READ)
+ complete(&dht11->completion);
+ }
+ }
+ return 0;
+}
+
+static int dht11_read_raw(struct iio_dev *iio_dev,
+ const struct iio_chan_spec *chan,
+ int *val, int *val2, long m)
+{
+ struct dht11 *dht11 = iio_priv(iio_dev);
+ int ret;
+ int i, j;
+ int timing[DHT11_BITS_PER_READ], time;
+ struct task_struct *th;
+
+ if (dht11->timestamp + DHT11_DATA_VALID_TIME < iio_get_time_ns()) {
+ dht11->num_edges = 0;
+ dht11->completion.done = 0;
+ th = kthread_create(dht11_read_thread, dht11, "dht11-read");
+ if (IS_ERR(th)) {
+ ret = -1;
+ goto err;
+ }
+ dht11_read_flag = 1;
+ wake_up_process(th);
+ ret = wait_for_completion_killable_timeout(&dht11->completion, HZ);
+ dht11_read_flag = 0;
+ if(th)
+ kthread_stop(th);
+ if (ret == 0) {
+ dev_err(&iio_dev->dev, "dht11 read raw timeout\n");
+ ret = -1;
+ //goto err;
+ }
+ for(i=0,j=0; i<dht11->num_edges; i++) {
+ if (i != 0) {
+#ifdef DHT11_DEBUG
+ printk(KERN_DEBUG"%02d ts=%lld value=%d pass=%lld\n", i, dht11->edges[i].ts, dht11->edges[i].value, dht11->edges[i].ts - dht11->edges[i-1].ts);
+#endif
+ time = dht11->edges[i].ts - dht11->edges[i-1].ts;
+ }
+ if (i > 3) {
+ if ((i%2) == 0) { // one bit start always about 50us
+ if (time<DATA_START_FLAG_MIN || time>DATA_START_FLAG_MAX) {
+ printk(KERN_ERR"bit start without 50us, time=%d\n", time);
+ ret = -EINVAL;
+ goto err;
+ }
+ } else {
+ time = dht11->edges[i].ts - dht11->edges[i-1].ts;
+ if (time > DATA_ZERO_MIN && time < DATA_ZERO_MAX)
+ timing[j] = 0;
+ else if (time > DATA_ONE_MIN && time < DATA_ONE_MAX)
+ timing[j]= 1;
+ else {
+ printk(KERN_ERR"bit value is not 1 or 0, time=%d\n", time);
+ ret = -EINVAL;
+ goto err;
+ }
+ j++;
+ }
+ }
+ }
+
+ ret = dht11_decode(dht11, timing);
+ if (ret)
+ goto err;
+ }
+
+ ret = IIO_VAL_INT;
+ if (chan->type == IIO_TEMP)
+ *val = dht11->temperature;
+ else if (chan->type == IIO_HUMIDITYRELATIVE)
+ *val = dht11->humidity;
+ else
+ ret = -EINVAL;
+err:
+ dht11->num_edges = -1;
+ return ret;
+}
+
+static const struct iio_info dht11_iio_info = {
+ .driver_module = THIS_MODULE,
+ .read_raw = dht11_read_raw,
+};
+
+static const struct iio_chan_spec dht11_chan_spec[] = {
+ {
+ .type = IIO_TEMP,
+ .processed_val = IIO_PROCESSED,
+ },
+ {
+ .type = IIO_HUMIDITYRELATIVE,
+ .processed_val = IIO_PROCESSED,
+ }
+};
+
+static const struct of_device_id dht11_dt_ids[] = {
+ { .compatible = "dht11", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, dht11_dt_ids);
+
+static int dht11_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct dht11 *dht11;
+ struct iio_dev *iio;
+ int ret = -1;
+
+ iio = iio_allocate_device(sizeof(*dht11));
+ if (!iio) {
+ dev_err(dev, "Failed to allocate IIO device\n");
+ return -ENOMEM;
+ }
+
+ dht11 = iio_priv(iio);
+ dht11->dev = dev;
+ dht11->gpio = gpio;
+
+ ret = gpio_request(dht11->gpio, pdev->name);
+ if (ret)
+ return ret;
+
+ dht11->timestamp = iio_get_time_ns() - DHT11_DATA_VALID_TIME - 1;
+ dht11->num_edges = -1;
+
+ platform_set_drvdata(pdev, iio);
+
+ init_completion(&dht11->completion);
+ iio->name = pdev->name;
+ iio->dev.parent = &pdev->dev;
+ iio->info = &dht11_iio_info;
+ iio->modes = INDIO_DIRECT_MODE;
+ iio->channels = dht11_chan_spec;
+ iio->num_channels = ARRAY_SIZE(dht11_chan_spec);
+
+ return iio_device_register(iio);
+}
+
+static int dht11_remove(struct platform_device *pdev)
+{
+ struct iio_dev *iio = platform_get_drvdata(pdev);
+ struct dht11 *dht11 = iio_priv(iio);
+
+ iio_device_unregister(iio);
+ gpio_free(dht11->gpio);
+ iio_free_device(iio);
+ return 0;
+}
+
+static struct platform_driver dht11_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = dht11_dt_ids,
+ },
+ .probe = dht11_probe,
+ .remove = dht11_remove,
+};
+
+void matrix_dht11_device_release(struct device *dev)
+{
+}
+
+static struct platform_device dht11_device = {
+ .name = "dht11",
+ .id = -1,
+ .num_resources = 0,
+ .dev = {
+ .release = matrix_dht11_device_release,
+ }
+};
+
+static int __init dht11_init(void)
+{
+ int ret = -1;
+
+ printk("plat: add device matrix-dht11, gpio=%d\n", gpio);
+ if ((ret = platform_device_register(&dht11_device))) {
+ return ret;
+ }
+
+ if ((ret = platform_driver_register(&dht11_driver))) {
+ platform_device_unregister(&dht11_device);
+ }
+ return ret;
+}
+
+static void __exit dht11_exit(void)
+{
+ platform_driver_unregister(&dht11_driver);
+ platform_device_unregister(&dht11_device);
+ gpio = -1;
+}
+
+module_init(dht11_init);
+module_exit(dht11_exit);
+MODULE_AUTHOR("Harald Geyer <harald@ccbib.org>");
+MODULE_DESCRIPTION("DHT11 humidity/temperature sensor driver");
+MODULE_LICENSE("GPL v2");
+module_param(gpio, int, 0644);
diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c
index e16500a..7e4421e 100755
--- a/drivers/staging/iio/industrialio-core.c
+++ b/drivers/staging/iio/industrialio-core.c
@@ -68,6 +68,7 @@ static const char * const iio_chan_type_name_spec[] = {
[IIO_ANGL] = "angl",
[IIO_TIMESTAMP] = "timestamp",
[IIO_CAPACITANCE] = "capacitance",
+ [IIO_HUMIDITYRELATIVE] = "humidityrelative",
[IIO_QUATERNION] = "quaternion",
};
diff --git a/drivers/staging/iio/types.h b/drivers/staging/iio/types.h
index 291c783..616c141 100755
--- a/drivers/staging/iio/types.h
+++ b/drivers/staging/iio/types.h
@@ -27,6 +27,7 @@ enum iio_chan_type {
IIO_ANGL,
IIO_TIMESTAMP,
IIO_CAPACITANCE,
+ IIO_HUMIDITYRELATIVE,
IIO_QUATERNION,
};
diff --git a/drivers/w1/masters/Makefile b/drivers/w1/masters/Makefile
index c5a3e96..88ee685 100644
--- a/drivers/w1/masters/Makefile
+++ b/drivers/w1/masters/Makefile
@@ -8,5 +8,5 @@ obj-$(CONFIG_W1_MASTER_DS2482) += ds2482.o
obj-$(CONFIG_W1_MASTER_MXC) += mxc_w1.o
obj-$(CONFIG_W1_MASTER_DS1WM) += ds1wm.o
-obj-$(CONFIG_W1_MASTER_GPIO) += w1-gpio.o
+obj-$(CONFIG_W1_MASTER_GPIO) += w1-gpio.o w1-gpio-board.o
obj-$(CONFIG_HDQ_MASTER_OMAP) += omap_hdq.o
diff --git a/drivers/w1/masters/w1-gpio-board.c b/drivers/w1/masters/w1-gpio-board.c
new file mode 100644
index 0000000..11aa1e4
--- /dev/null
+++ b/drivers/w1/masters/w1-gpio-board.c
@@ -0,0 +1,59 @@
+/*
+ * w1-gpio-board.c - Board driver for GPIO w1 bus master
+ *
+ * Copyright (C) 2016 FriendlyARM (www.friendlyarm.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/w1-gpio.h>
+#include <linux/gpio.h>
+
+#include <mach/platform.h>
+
+static int gpio = -1;
+module_param(gpio, int, 0644);
+
+
+static struct w1_gpio_platform_data w1_gpio_pdata = {
+ .pin = -1,
+ .is_open_drain = 0,
+};
+
+static void w1_device_release(struct device *dev) {
+ // nothing here yet
+}
+
+static struct platform_device matrix_w1_device = {
+ .name = "w1-gpio",
+ .id = -1,
+ .dev = {
+ .release = w1_device_release,
+ .platform_data = &w1_gpio_pdata,
+ }
+};
+
+
+static int __init w1_gpio_board_init(void)
+{
+ w1_gpio_pdata.pin = gpio;
+ printk("plat: add device w1-gpio, gpio=%d\n", w1_gpio_pdata.pin);
+ return platform_device_register(&matrix_w1_device);
+}
+
+static void __exit w1_gpio_board_exit(void)
+{
+ platform_device_unregister(&matrix_w1_device);
+}
+
+module_init(w1_gpio_board_init);
+module_exit(w1_gpio_board_exit);
+
+MODULE_DESCRIPTION("Board driver for GPIO w1 bus master");
+MODULE_AUTHOR("FriendlyARM");
+MODULE_LICENSE("GPL");
diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c
index df600d1..28f8d7d 100644
--- a/drivers/w1/masters/w1-gpio.c
+++ b/drivers/w1/masters/w1-gpio.c
@@ -42,7 +42,7 @@ static u8 w1_gpio_read_bit(void *data)
return gpio_get_value(pdata->pin) ? 1 : 0;
}
-static int __init w1_gpio_probe(struct platform_device *pdev)
+static int w1_gpio_probe(struct platform_device *pdev)
{
struct w1_bus_master *master;
struct w1_gpio_platform_data *pdata = pdev->dev.platform_data;
@@ -56,8 +56,10 @@ static int __init w1_gpio_probe(struct platform_device *pdev)
return -ENOMEM;
err = gpio_request(pdata->pin, "w1");
- if (err)
+ if (err) {
+ dev_err(&pdev->dev, "failed to request GPIO %d\n", pdata->pin);
goto free_master;
+ }
master->data = pdata;
master->read_bit = w1_gpio_read_bit;
@@ -89,7 +91,7 @@ static int __init w1_gpio_probe(struct platform_device *pdev)
return err;
}
-static int __exit w1_gpio_remove(struct platform_device *pdev)
+static int w1_gpio_remove(struct platform_device *pdev)
{
struct w1_bus_master *master = platform_get_drvdata(pdev);
struct w1_gpio_platform_data *pdata = pdev->dev.platform_data;
@@ -136,14 +138,15 @@ static struct platform_driver w1_gpio_driver = {
.name = "w1-gpio",
.owner = THIS_MODULE,
},
- .remove = __exit_p(w1_gpio_remove),
+ .probe = w1_gpio_probe,
+ .remove = w1_gpio_remove,
.suspend = w1_gpio_suspend,
.resume = w1_gpio_resume,
};
static int __init w1_gpio_init(void)
{
- return platform_driver_probe(&w1_gpio_driver, w1_gpio_probe);
+ return platform_driver_register(&w1_gpio_driver);
}
static void __exit w1_gpio_exit(void)