diff options
Diffstat (limited to 'target/linux/brcm2708/patches-4.1/0119-Merge-pull-request-1059-from-pelwell-rpi-4.0.y.patch')
-rw-r--r-- | target/linux/brcm2708/patches-4.1/0119-Merge-pull-request-1059-from-pelwell-rpi-4.0.y.patch | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/target/linux/brcm2708/patches-4.1/0119-Merge-pull-request-1059-from-pelwell-rpi-4.0.y.patch b/target/linux/brcm2708/patches-4.1/0119-Merge-pull-request-1059-from-pelwell-rpi-4.0.y.patch new file mode 100644 index 0000000..5ae3104 --- /dev/null +++ b/target/linux/brcm2708/patches-4.1/0119-Merge-pull-request-1059-from-pelwell-rpi-4.0.y.patch @@ -0,0 +1,190 @@ +From f58127f1cc42ee92a87fc7a88ea88071f1b48340 Mon Sep 17 00:00:00 2001 +From: Phil Elwell <pelwell@users.noreply.github.com> +Date: Mon, 13 Jul 2015 13:25:31 +0100 +Subject: [PATCH 119/203] Merge pull request #1059 from pelwell/rpi-4.0.y + +w1_therm: Back-port locking improvements from 4.2-rc1 +--- + Documentation/ABI/stable/sysfs-driver-w1_ds28ea00 | 6 ++ + Documentation/w1/slaves/w1_therm | 11 ++- + drivers/w1/slaves/w1_therm.c | 102 +++++++++++++++++++++- + 3 files changed, 117 insertions(+), 2 deletions(-) + create mode 100644 Documentation/ABI/stable/sysfs-driver-w1_ds28ea00 + +--- /dev/null ++++ b/Documentation/ABI/stable/sysfs-driver-w1_ds28ea00 +@@ -0,0 +1,6 @@ ++What: /sys/bus/w1/devices/.../w1_seq ++Date: Apr 2015 ++Contact: Matt Campbell <mattrcampbell@gmail.com> ++Description: Support for the DS28EA00 chain sequence function ++ see Documentation/w1/slaves/w1_therm for detailed information ++Users: any user space application which wants to communicate with DS28EA00 +--- a/Documentation/w1/slaves/w1_therm ++++ b/Documentation/w1/slaves/w1_therm +@@ -11,12 +11,14 @@ Author: Evgeniy Polyakov <johnpol@2ka.mi + Description + ----------- + +-w1_therm provides basic temperature conversion for ds18*20 devices. ++w1_therm provides basic temperature conversion for ds18*20 devices, and the ++ds28ea00 device. + supported family codes: + W1_THERM_DS18S20 0x10 + W1_THERM_DS1822 0x22 + W1_THERM_DS18B20 0x28 + W1_THERM_DS1825 0x3B ++W1_THERM_DS28EA00 0x42 + + Support is provided through the sysfs w1_slave file. Each open and + read sequence will initiate a temperature conversion then provide two +@@ -48,3 +50,10 @@ resistor). The DS18b20 temperature sens + maximum current draw of 1.5mA and that a 5k pullup resistor is not + sufficient. The strong pullup is designed to provide the additional + current required. ++ ++The DS28EA00 provides an additional two pins for implementing a sequence ++detection algorithm. This feature allows you to determine the physical ++location of the chip in the 1-wire bus without needing pre-existing ++knowledge of the bus ordering. Support is provided through the sysfs ++w1_seq file. The file will contain a single line with an integer value ++representing the device index in the bus starting at 0. +--- a/drivers/w1/slaves/w1_therm.c ++++ b/drivers/w1/slaves/w1_therm.c +@@ -92,13 +92,24 @@ static void w1_therm_remove_slave(struct + static ssize_t w1_slave_show(struct device *device, + struct device_attribute *attr, char *buf); + ++static ssize_t w1_seq_show(struct device *device, ++ struct device_attribute *attr, char *buf); ++ + static DEVICE_ATTR_RO(w1_slave); ++static DEVICE_ATTR_RO(w1_seq); + + static struct attribute *w1_therm_attrs[] = { + &dev_attr_w1_slave.attr, + NULL, + }; ++ ++static struct attribute *w1_ds28ea00_attrs[] = { ++ &dev_attr_w1_slave.attr, ++ &dev_attr_w1_seq.attr, ++ NULL, ++}; + ATTRIBUTE_GROUPS(w1_therm); ++ATTRIBUTE_GROUPS(w1_ds28ea00); + + static struct w1_family_ops w1_therm_fops = { + .add_slave = w1_therm_add_slave, +@@ -106,6 +117,12 @@ static struct w1_family_ops w1_therm_fop + .groups = w1_therm_groups, + }; + ++static struct w1_family_ops w1_ds28ea00_fops = { ++ .add_slave = w1_therm_add_slave, ++ .remove_slave = w1_therm_remove_slave, ++ .groups = w1_ds28ea00_groups, ++}; ++ + static struct w1_family w1_therm_family_DS18S20 = { + .fid = W1_THERM_DS18S20, + .fops = &w1_therm_fops, +@@ -123,7 +140,7 @@ static struct w1_family w1_therm_family_ + + static struct w1_family w1_therm_family_DS28EA00 = { + .fid = W1_THERM_DS28EA00, +- .fops = &w1_therm_fops, ++ .fops = &w1_ds28ea00_fops, + }; + + static struct w1_family w1_therm_family_DS1825 = { +@@ -316,6 +333,89 @@ post_unlock: + return ret; + } + ++#define W1_42_CHAIN 0x99 ++#define W1_42_CHAIN_OFF 0x3C ++#define W1_42_CHAIN_OFF_INV 0xC3 ++#define W1_42_CHAIN_ON 0x5A ++#define W1_42_CHAIN_ON_INV 0xA5 ++#define W1_42_CHAIN_DONE 0x96 ++#define W1_42_CHAIN_DONE_INV 0x69 ++#define W1_42_COND_READ 0x0F ++#define W1_42_SUCCESS_CONFIRM_BYTE 0xAA ++#define W1_42_FINISHED_BYTE 0xFF ++static ssize_t w1_seq_show(struct device *device, ++ struct device_attribute *attr, char *buf) ++{ ++ struct w1_slave *sl = dev_to_w1_slave(device); ++ ssize_t c = PAGE_SIZE; ++ int rv; ++ int i; ++ u8 ack; ++ u64 rn; ++ struct w1_reg_num *reg_num; ++ int seq = 0; ++ ++ mutex_lock(&sl->master->bus_mutex); ++ /* Place all devices in CHAIN state */ ++ if (w1_reset_bus(sl->master)) ++ goto error; ++ w1_write_8(sl->master, W1_SKIP_ROM); ++ w1_write_8(sl->master, W1_42_CHAIN); ++ w1_write_8(sl->master, W1_42_CHAIN_ON); ++ w1_write_8(sl->master, W1_42_CHAIN_ON_INV); ++ msleep(sl->master->pullup_duration); ++ ++ /* check for acknowledgment */ ++ ack = w1_read_8(sl->master); ++ if (ack != W1_42_SUCCESS_CONFIRM_BYTE) ++ goto error; ++ ++ /* In case the bus fails to send 0xFF, limit*/ ++ for (i = 0; i <= 64; i++) { ++ if (w1_reset_bus(sl->master)) ++ goto error; ++ ++ w1_write_8(sl->master, W1_42_COND_READ); ++ rv = w1_read_block(sl->master, (u8 *)&rn, 8); ++ reg_num = (struct w1_reg_num *) &rn; ++ if (reg_num->family == W1_42_FINISHED_BYTE) ++ break; ++ if (sl->reg_num.id == reg_num->id) ++ seq = i; ++ ++ w1_write_8(sl->master, W1_42_CHAIN); ++ w1_write_8(sl->master, W1_42_CHAIN_DONE); ++ w1_write_8(sl->master, W1_42_CHAIN_DONE_INV); ++ w1_read_block(sl->master, &ack, sizeof(ack)); ++ ++ /* check for acknowledgment */ ++ ack = w1_read_8(sl->master); ++ if (ack != W1_42_SUCCESS_CONFIRM_BYTE) ++ goto error; ++ ++ } ++ ++ /* Exit from CHAIN state */ ++ if (w1_reset_bus(sl->master)) ++ goto error; ++ w1_write_8(sl->master, W1_SKIP_ROM); ++ w1_write_8(sl->master, W1_42_CHAIN); ++ w1_write_8(sl->master, W1_42_CHAIN_OFF); ++ w1_write_8(sl->master, W1_42_CHAIN_OFF_INV); ++ ++ /* check for acknowledgment */ ++ ack = w1_read_8(sl->master); ++ if (ack != W1_42_SUCCESS_CONFIRM_BYTE) ++ goto error; ++ mutex_unlock(&sl->master->bus_mutex); ++ ++ c -= snprintf(buf + PAGE_SIZE - c, c, "%d\n", seq); ++ return PAGE_SIZE - c; ++error: ++ mutex_unlock(&sl->master->bus_mutex); ++ return -EIO; ++} ++ + static int __init w1_therm_init(void) + { + int err, i; |