Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add bitbanging pullups, use them for w1-gpio #186

Merged
merged 2 commits into from
Mar 8, 2013
Merged
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
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