Skip to content

Commit

Permalink
Merge pull request raspberrypi#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
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 All @@ -42,6 +45,16 @@ static u8 w1_gpio_read_bit(void *data)
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)
{
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;
}

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 All @@ -81,9 +101,9 @@ static int __init w1_gpio_probe(struct platform_device *pdev)

return 0;

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

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 = {
.driver = {
.name = "w1-gpio",
.owner = THIS_MODULE,
},
.remove = __exit_p(w1_gpio_remove),
.name = "w1-gpio",
.owner = THIS_MODULE,
},
.remove = __exit_p(w1_gpio_remove),
.suspend = w1_gpio_suspend,
.resume = w1_gpio_resume,
};
Expand Down
145 changes: 72 additions & 73 deletions drivers/w1/w1.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,11 @@
#ifndef __W1_H
#define __W1_H

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

#define W1_SLAVE_ACTIVE 0

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

struct w1_master *master;
struct w1_family *family;
void *family_data;
struct device dev;
struct completion released;
struct w1_slave {
struct module *owner;
unsigned char name[W1_MAXNAMELEN];
struct list_head w1_slave_entry;
struct w1_reg_num reg_num;
atomic_t refcnt;
u8 rom[9];
u32 flags;
int ttl;

struct w1_master *master;
struct w1_family *family;
void *family_data;
struct device dev;
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
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
* reset_bus.
*/
struct w1_bus_master
{
struct w1_bus_master {
/** the first parameter in all the functions below */
void *data;
void *data;

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

/** 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
Expand All @@ -108,96 +100,103 @@ struct w1_bus_master
* touch_bit(1) = write-1 / read cycle
* @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.
* @return the byte read
*/
u8 (*read_byte)(void *);
u8(*read_byte) (void *);

/**
* 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
* @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 */
void (*write_block)(void *, const u8 *, int);
void (*write_block) (void *, const u8 *, int);

/**
* Combines two reads and a smart write for ROM searches
* @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
* @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.
* @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
* w1_master* is passed to the slave found callback.
*/
void (*search)(void *, struct w1_master *,
u8, w1_slave_found_callback);
void (*search) (void *, struct w1_master *,
u8, w1_slave_found_callback);
};

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

atomic_t refcnt;

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

atomic_t refcnt;

void *priv;
int priv_size;

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

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

struct device_driver *driver;
struct device dev;
struct device_driver *driver;
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 *);
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_devices(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb);
void w1_search(struct w1_master *dev, u8 search_type,
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);
void w1_slave_found(struct w1_master *dev, u64 rn);
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);

/* 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 *);
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);
}

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));
}

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);
}
Expand Down
Loading

0 comments on commit d8ace32

Please sign in to comment.