Skip to content

Commit

Permalink
Merge pull request #186 from mkj/rpi-3.6.y
Browse files Browse the repository at this point in the history
Add bitbanging pullups, use them for w1-gpio
  • Loading branch information
popcornmix committed Mar 8, 2013
2 parents 5d9516c + 6e41bfa commit d8ace32
Show file tree
Hide file tree
Showing 4 changed files with 206 additions and 155 deletions.
32 changes: 26 additions & 6 deletions drivers/w1/masters/w1-gpio.c
Expand Up @@ -18,6 +18,9 @@
#include "../w1.h" #include "../w1.h"
#include "../w1_int.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) static void w1_gpio_write_bit_dir(void *data, u8 bit)
{ {
struct w1_gpio_platform_data *pdata = data; struct w1_gpio_platform_data *pdata = data;
Expand All @@ -42,6 +45,16 @@ static u8 w1_gpio_read_bit(void *data)
return gpio_get_value(pdata->pin) ? 1 : 0; return gpio_get_value(pdata->pin) ? 1 : 0;
} }


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) static int __init w1_gpio_probe(struct platform_device *pdev)
{ {
struct w1_bus_master *master; struct w1_bus_master *master;
Expand Down Expand Up @@ -70,6 +83,13 @@ static int __init w1_gpio_probe(struct platform_device *pdev)
master->write_bit = w1_gpio_write_bit_dir; 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); err = w1_add_master_device(master);
if (err) if (err)
goto free_gpio; goto free_gpio;
Expand All @@ -81,9 +101,9 @@ static int __init w1_gpio_probe(struct platform_device *pdev)


return 0; return 0;


free_gpio: free_gpio:
gpio_free(pdata->pin); gpio_free(pdata->pin);
free_master: free_master:
kfree(master); kfree(master);


return err; return err;
Expand Down Expand Up @@ -133,10 +153,10 @@ static int w1_gpio_resume(struct platform_device *pdev)


static struct platform_driver w1_gpio_driver = { static struct platform_driver w1_gpio_driver = {
.driver = { .driver = {
.name = "w1-gpio", .name = "w1-gpio",
.owner = THIS_MODULE, .owner = THIS_MODULE,
}, },
.remove = __exit_p(w1_gpio_remove), .remove = __exit_p(w1_gpio_remove),
.suspend = w1_gpio_suspend, .suspend = w1_gpio_suspend,
.resume = w1_gpio_resume, .resume = w1_gpio_resume,
}; };
Expand Down
145 changes: 72 additions & 73 deletions drivers/w1/w1.h
Expand Up @@ -22,16 +22,11 @@
#ifndef __W1_H #ifndef __W1_H
#define __W1_H #define __W1_H


struct w1_reg_num struct w1_reg_num {
{
#if defined(__LITTLE_ENDIAN_BITFIELD) #if defined(__LITTLE_ENDIAN_BITFIELD)
__u64 family:8, __u64 family:8, id:48, crc:8;
id:48,
crc:8;
#elif defined(__BIG_ENDIAN_BITFIELD) #elif defined(__BIG_ENDIAN_BITFIELD)
__u64 crc:8, __u64 crc:8, id:48, family:8;
id:48,
family:8;
#else #else
#error "Please fix <asm/byteorder.h>" #error "Please fix <asm/byteorder.h>"
#endif #endif
Expand Down Expand Up @@ -59,26 +54,24 @@ struct w1_reg_num


#define W1_SLAVE_ACTIVE 0 #define W1_SLAVE_ACTIVE 0


struct w1_slave struct w1_slave {
{ struct module *owner;
struct module *owner; unsigned char name[W1_MAXNAMELEN];
unsigned char name[W1_MAXNAMELEN]; struct list_head w1_slave_entry;
struct list_head w1_slave_entry; struct w1_reg_num reg_num;
struct w1_reg_num reg_num; atomic_t refcnt;
atomic_t refcnt; u8 rom[9];
u8 rom[9]; u32 flags;
u32 flags; int ttl;
int ttl;

struct w1_master *master;
struct w1_master *master; struct w1_family *family;
struct w1_family *family; void *family_data;
void *family_data; struct device dev;
struct device dev; struct completion released;
struct completion released;
}; };


typedef void (*w1_slave_found_callback)(struct w1_master *, u64); typedef void (*w1_slave_found_callback) (struct w1_master *, u64);



/** /**
* Note: read_bit and write_bit are very low level functions and should only * Note: read_bit and write_bit are very low level functions and should only
Expand All @@ -87,19 +80,18 @@ typedef void (*w1_slave_found_callback)(struct w1_master *, u64);
* Either define read_bit and write_bit OR define, at minimum, touch_bit and * Either define read_bit and write_bit OR define, at minimum, touch_bit and
* reset_bus. * reset_bus.
*/ */
struct w1_bus_master struct w1_bus_master {
{
/** the first parameter in all the functions below */ /** the first parameter in all the functions below */
void *data; void *data;


/** /**
* Sample the line level * Sample the line level
* @return the level read (0 or 1) * @return the level read (0 or 1)
*/ */
u8 (*read_bit)(void *); u8(*read_bit) (void *);


/** Sets the line level */ /** Sets the line level */
void (*write_bit)(void *, u8); void (*write_bit) (void *, u8);


/** /**
* touch_bit is the lowest-level function for devices that really * touch_bit is the lowest-level function for devices that really
Expand All @@ -108,96 +100,103 @@ struct w1_bus_master
* touch_bit(1) = write-1 / read cycle * touch_bit(1) = write-1 / read cycle
* @return the bit read (0 or 1) * @return the bit read (0 or 1)
*/ */
u8 (*touch_bit)(void *, u8); u8(*touch_bit) (void *, u8);


/** /**
* Reads a bytes. Same as 8 touch_bit(1) calls. * Reads a bytes. Same as 8 touch_bit(1) calls.
* @return the byte read * @return the byte read
*/ */
u8 (*read_byte)(void *); u8(*read_byte) (void *);


/** /**
* Writes a byte. Same as 8 touch_bit(x) calls. * Writes a byte. Same as 8 touch_bit(x) calls.
*/ */
void (*write_byte)(void *, u8); void (*write_byte) (void *, u8);


/** /**
* Same as a series of read_byte() calls * Same as a series of read_byte() calls
* @return the number of bytes read * @return the number of bytes read
*/ */
u8 (*read_block)(void *, u8 *, int); u8(*read_block) (void *, u8 *, int);


/** Same as a series of write_byte() calls */ /** Same as a series of write_byte() calls */
void (*write_block)(void *, const u8 *, int); void (*write_block) (void *, const u8 *, int);


/** /**
* Combines two reads and a smart write for ROM searches * Combines two reads and a smart write for ROM searches
* @return bit0=Id bit1=comp_id bit2=dir_taken * @return bit0=Id bit1=comp_id bit2=dir_taken
*/ */
u8 (*triplet)(void *, u8); u8(*triplet) (void *, u8);


/** /**
* long write-0 with a read for the presence pulse detection * long write-0 with a read for the presence pulse detection
* @return -1=Error, 0=Device present, 1=No device present * @return -1=Error, 0=Device present, 1=No device present
*/ */
u8 (*reset_bus)(void *); u8(*reset_bus) (void *);


/** /**
* Put out a strong pull-up pulse of the specified duration. * Put out a strong pull-up pulse of the specified duration.
* @return -1=Error, 0=completed * @return -1=Error, 0=completed
*/ */
u8 (*set_pullup)(void *, int); 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 /** Really nice hardware can handles the different types of ROM search
* w1_master* is passed to the slave found callback. * w1_master* is passed to the slave found callback.
*/ */
void (*search)(void *, struct w1_master *, void (*search) (void *, struct w1_master *,
u8, w1_slave_found_callback); u8, w1_slave_found_callback);
}; };


struct w1_master struct w1_master {
{ struct list_head w1_master_entry;
struct list_head w1_master_entry; struct module *owner;
struct module *owner; unsigned char name[W1_MAXNAMELEN];
unsigned char name[W1_MAXNAMELEN]; struct list_head slist;
struct list_head slist; int max_slave_count, slave_count;
int max_slave_count, slave_count; unsigned long attempts;
unsigned long attempts; int slave_ttl;
int slave_ttl; int initialized;
int initialized; u32 id;
u32 id; int search_count;
int search_count;

atomic_t refcnt;
atomic_t refcnt;

void *priv;
void *priv; int priv_size;
int priv_size;


/** 5V strong pullup enabled flag, 1 enabled, zero disabled. */ /** 5V strong pullup enabled flag, 1 enabled, zero disabled. */
int enable_pullup; int enable_pullup;
/** 5V strong pullup duration in milliseconds, zero disabled. */ /** 5V strong pullup duration in milliseconds, zero disabled. */
int pullup_duration; int pullup_duration;


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


struct device_driver *driver; struct device_driver *driver;
struct device dev; struct device dev;


struct w1_bus_master *bus_master; struct w1_bus_master *bus_master;


u32 seq; u32 seq;
}; };


int w1_create_master_attributes(struct w1_master *); int w1_create_master_attributes(struct w1_master *);
void w1_destroy_master_attributes(struct w1_master *master); void w1_destroy_master_attributes(struct w1_master *master);
void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb); void w1_search(struct w1_master *dev, u8 search_type,
void w1_search_devices(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb); w1_slave_found_callback cb);
void w1_search_devices(struct w1_master *dev, u8 search_type,
w1_slave_found_callback cb);
struct w1_slave *w1_search_slave(struct w1_reg_num *id); struct w1_slave *w1_search_slave(struct w1_reg_num *id);
void w1_slave_found(struct w1_master *dev, u64 rn); void w1_slave_found(struct w1_master *dev, u64 rn);
void w1_search_process_cb(struct w1_master *dev, u8 search_type, void w1_search_process_cb(struct w1_master *dev, u8 search_type,
w1_slave_found_callback cb); w1_slave_found_callback cb);
struct w1_master *w1_search_master_id(u32 id); struct w1_master *w1_search_master_id(u32 id);


/* Disconnect and reconnect devices in the given family. Used for finding /* Disconnect and reconnect devices in the given family. Used for finding
Expand All @@ -220,17 +219,17 @@ int w1_reset_select_slave(struct w1_slave *sl);
int w1_reset_resume_command(struct w1_master *); int w1_reset_resume_command(struct w1_master *);
void w1_next_pullup(struct w1_master *, int); void w1_next_pullup(struct w1_master *, int);


static inline struct w1_slave* dev_to_w1_slave(struct device *dev) static inline struct w1_slave *dev_to_w1_slave(struct device *dev)
{ {
return container_of(dev, struct w1_slave, dev); return container_of(dev, struct w1_slave, dev);
} }


static inline struct w1_slave* kobj_to_w1_slave(struct kobject *kobj) static inline struct w1_slave *kobj_to_w1_slave(struct kobject *kobj)
{ {
return dev_to_w1_slave(container_of(kobj, struct device, kobj)); return dev_to_w1_slave(container_of(kobj, struct device, kobj));
} }


static inline struct w1_master* dev_to_w1_master(struct device *dev) static inline struct w1_master *dev_to_w1_master(struct device *dev)
{ {
return container_of(dev, struct w1_master, dev); return container_of(dev, struct w1_master, dev);
} }
Expand Down

0 comments on commit d8ace32

Please sign in to comment.