Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions linux-3.4/drivers/w1/masters/w1-gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
#include "../w1.h"
#include "../w1_int.h"

static int w1_gpio_pullup = 0;
module_param_named(pullup, w1_gpio_pullup, int, 0);

static void w1_gpio_write_bit_dir(void *data, u8 bit)
{
struct w1_gpio_platform_data *pdata = data;
Expand Down Expand Up @@ -47,6 +50,16 @@ static u8 w1_gpio_read_bit(void *data)
return pin_val;
}

static void w1_gpio_bitbang_pullup(void *data, u8 on)
{
struct w1_gpio_platform_data *pdata = data;

if (on)
gpio_direction_output(pdata->pin, 1);
else
gpio_direction_input(pdata->pin);
}

static int __init w1_gpio_probe(struct platform_device *pdev)
{
struct w1_bus_master *master;
Expand Down Expand Up @@ -83,6 +96,13 @@ static int __init w1_gpio_probe(struct platform_device *pdev)
master->write_bit = w1_gpio_write_bit_dir;
}

if (w1_gpio_pullup)
if (pdata->is_open_drain)
printk(KERN_ERR "w1-gpio 'pullup' option "
"doesn't work with open drain GPIO\n");
else
master->bitbang_pullup = w1_gpio_bitbang_pullup;

err = w1_add_master_device(master);
if (err)
goto free_gpio;
Expand Down
7 changes: 7 additions & 0 deletions linux-3.4/drivers/w1/w1.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,12 @@ struct w1_bus_master
*/
u8 (*set_pullup)(void *, int);

/**
* Turns the pullup on/off in bitbanging mode, takes an on/off argument.
* @return -1=Error, 0=completed
*/
void (*bitbang_pullup)(void *, u8);

/** Really nice hardware can handles the different types of ROM search
* w1_master* is passed to the slave found callback.
*/
Expand Down Expand Up @@ -180,6 +186,7 @@ struct w1_master

struct task_struct *thread;
struct mutex mutex;
struct mutex bus_mutex;

struct device_driver *driver;
struct device dev;
Expand Down
8 changes: 8 additions & 0 deletions linux-3.4/drivers/w1/w1_int.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl,

INIT_LIST_HEAD(&dev->slist);
mutex_init(&dev->mutex);
mutex_init(&dev->bus_mutex);

memcpy(&dev->dev, device, sizeof(struct device));
dev_set_name(&dev->dev, "w1_bus_master%u", dev->id);
Expand Down Expand Up @@ -129,6 +130,13 @@ int w1_add_master_device(struct w1_bus_master *master)
master->set_pullup = NULL;
}

if (master->set_pullup && master->bitbang_pullup)
{
printk(KERN_ERR "w1_add_master_device: set_pullup should not "
"be set when bitbang_pullup is used, disabling\n");
master->set_pullup = NULL;
}

/* Lock until the device is added (or not) to w1_masters. */
mutex_lock(&w1_mlock);
/* Search for the first available id (starting at 1). */
Expand Down
36 changes: 29 additions & 7 deletions linux-3.4/drivers/w1/w1_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
static int w1_delay_parm = 1;
module_param_named(delay_coef, w1_delay_parm, int, 0);

static int w1_disable_irqs = 0;
module_param_named(disable_irqs, w1_disable_irqs, int, 0);

static u8 w1_crc8_table[] = {
0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65,
157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220,
Expand Down Expand Up @@ -79,6 +82,10 @@ static u8 w1_touch_bit(struct w1_master *dev, int bit)
*/
static void w1_write_bit(struct w1_master *dev, int bit)
{
unsigned long flags = 0;

if(w1_disable_irqs) local_irq_save(flags);

if (bit) {
dev->bus_master->write_bit(dev->bus_master->data, 0);
w1_delay(6);
Expand All @@ -90,6 +97,8 @@ static void w1_write_bit(struct w1_master *dev, int bit)
dev->bus_master->write_bit(dev->bus_master->data, 1);
w1_delay(10);
}

if(w1_disable_irqs) local_irq_restore(flags);
}

/**
Expand Down Expand Up @@ -118,10 +127,18 @@ static void w1_pre_write(struct w1_master *dev)
static void w1_post_write(struct w1_master *dev)
{
if (dev->pullup_duration) {
if (dev->enable_pullup && dev->bus_master->set_pullup)
dev->bus_master->set_pullup(dev->bus_master->data, 0);
else
if (dev->enable_pullup) {
if (dev->bus_master->set_pullup) {
dev->bus_master->set_pullup(dev->bus_master->data, 0);
} else if (dev->bus_master->bitbang_pullup) {
dev->bus_master->bitbang_pullup(dev->bus_master->data, 1);
msleep(dev->pullup_duration);
dev->bus_master->bitbang_pullup(dev->bus_master->data, 0);
}
} else {
msleep(dev->pullup_duration);
}

dev->pullup_duration = 0;
}
}
Expand Down Expand Up @@ -158,7 +175,7 @@ EXPORT_SYMBOL_GPL(w1_write_8);
static u8 w1_read_bit(struct w1_master *dev)
{
int result;
unsigned long flags;
unsigned long flags = 0;

/* sample timing is critical here */
local_irq_save(flags);
Expand Down Expand Up @@ -318,6 +335,9 @@ EXPORT_SYMBOL_GPL(w1_read_block);
int w1_reset_bus(struct w1_master *dev)
{
int result;
unsigned long flags = 0;

if(w1_disable_irqs) local_irq_save(flags);

if (dev->bus_master->reset_bus)
result = dev->bus_master->reset_bus(dev->bus_master->data) & 0x1;
Expand All @@ -330,19 +350,21 @@ int w1_reset_bus(struct w1_master *dev)
* cpu for such a short amount of time AND get it back in
* the maximum amount of time.
*/
w1_delay(480);
w1_delay(500);
dev->bus_master->write_bit(dev->bus_master->data, 1);
w1_delay(70);

result = dev->bus_master->read_bit(dev->bus_master->data) & 0x1;
/* minmum 70 (above) + 410 = 480 us
/* minmum 70 (above) + 430 = 500 us
* There aren't any timing requirements between a reset and
* the following transactions. Sleeping is safe here.
*/
/* w1_delay(410); min required time */
/* w1_delay(430); min required time */
msleep(1);
}

if(w1_disable_irqs) local_irq_restore(flags);

return result;
}
EXPORT_SYMBOL_GPL(w1_reset_bus);
Expand Down