Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/driver-2.6
This commit is contained in:
commit
92118c739d
@ -12,13 +12,20 @@ You can make this adapter from an old printer cable and solder things
|
|||||||
directly to the Butterfly. Or (if you have the parts and skills) you
|
directly to the Butterfly. Or (if you have the parts and skills) you
|
||||||
can come up with something fancier, providing ciruit protection to the
|
can come up with something fancier, providing ciruit protection to the
|
||||||
Butterfly and the printer port, or with a better power supply than two
|
Butterfly and the printer port, or with a better power supply than two
|
||||||
signal pins from the printer port.
|
signal pins from the printer port. Or for that matter, you can use
|
||||||
|
similar cables to talk to many AVR boards, even a breadboard.
|
||||||
|
|
||||||
|
This is more powerful than "ISP programming" cables since it lets kernel
|
||||||
|
SPI protocol drivers interact with the AVR, and could even let the AVR
|
||||||
|
issue interrupts to them. Later, your protocol driver should work
|
||||||
|
easily with a "real SPI controller", instead of this bitbanger.
|
||||||
|
|
||||||
|
|
||||||
The first cable connections will hook Linux up to one SPI bus, with the
|
The first cable connections will hook Linux up to one SPI bus, with the
|
||||||
AVR and a DataFlash chip; and to the AVR reset line. This is all you
|
AVR and a DataFlash chip; and to the AVR reset line. This is all you
|
||||||
need to reflash the firmware, and the pins are the standard Atmel "ISP"
|
need to reflash the firmware, and the pins are the standard Atmel "ISP"
|
||||||
connector pins (used also on non-Butterfly AVR boards).
|
connector pins (used also on non-Butterfly AVR boards). On the parport
|
||||||
|
side this is like "sp12" programming cables.
|
||||||
|
|
||||||
Signal Butterfly Parport (DB-25)
|
Signal Butterfly Parport (DB-25)
|
||||||
------ --------- ---------------
|
------ --------- ---------------
|
||||||
@ -40,10 +47,14 @@ by clearing PORTB.[0-3]); (b) configure the mtd_dataflash driver; and
|
|||||||
SELECT = J400.PB0/nSS = pin 17/C3,nSELECT
|
SELECT = J400.PB0/nSS = pin 17/C3,nSELECT
|
||||||
GND = J400.GND = pin 24/GND
|
GND = J400.GND = pin 24/GND
|
||||||
|
|
||||||
The "USI" controller, using J405, can be used for a second SPI bus. That
|
Or you could flash firmware making the AVR into an SPI slave (keeping the
|
||||||
would let you talk to the AVR over SPI, running firmware that makes it act
|
DataFlash in reset) and tweak the spi_butterfly driver to make it bind to
|
||||||
as an SPI slave, while letting either Linux or the AVR use the DataFlash.
|
the driver for your custom SPI-based protocol.
|
||||||
There are plenty of spare parport pins to wire this one up, such as:
|
|
||||||
|
The "USI" controller, using J405, can also be used for a second SPI bus.
|
||||||
|
That would let you talk to the AVR using custom SPI-with-USI firmware,
|
||||||
|
while letting either Linux or the AVR use the DataFlash. There are plenty
|
||||||
|
of spare parport pins to wire this one up, such as:
|
||||||
|
|
||||||
Signal Butterfly Parport (DB-25)
|
Signal Butterfly Parport (DB-25)
|
||||||
------ --------- ---------------
|
------ --------- ---------------
|
||||||
|
@ -19,6 +19,10 @@ extern void bus_remove_driver(struct device_driver *);
|
|||||||
extern void driver_detach(struct device_driver * drv);
|
extern void driver_detach(struct device_driver * drv);
|
||||||
extern int driver_probe_device(struct device_driver *, struct device *);
|
extern int driver_probe_device(struct device_driver *, struct device *);
|
||||||
|
|
||||||
|
extern void sysdev_shutdown(void);
|
||||||
|
extern int sysdev_suspend(pm_message_t state);
|
||||||
|
extern int sysdev_resume(void);
|
||||||
|
|
||||||
static inline struct class_device *to_class_dev(struct kobject *obj)
|
static inline struct class_device *to_class_dev(struct kobject *obj)
|
||||||
{
|
{
|
||||||
return container_of(obj, struct class_device, kobj);
|
return container_of(obj, struct class_device, kobj);
|
||||||
|
@ -9,10 +9,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
|
#include "../base.h"
|
||||||
#include "power.h"
|
#include "power.h"
|
||||||
|
|
||||||
extern int sysdev_resume(void);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* resume_device - Restore state for one device.
|
* resume_device - Restore state for one device.
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <asm/semaphore.h>
|
#include <asm/semaphore.h>
|
||||||
|
|
||||||
|
#include "../base.h"
|
||||||
#include "power.h"
|
#include "power.h"
|
||||||
|
|
||||||
#define to_dev(node) container_of(node, struct device, kobj.entry)
|
#define to_dev(node) container_of(node, struct device, kobj.entry)
|
||||||
@ -28,7 +29,6 @@ extern struct subsystem devices_subsys;
|
|||||||
* they only get one called once when interrupts are disabled.
|
* they only get one called once when interrupts are disabled.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern int sysdev_shutdown(void);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* device_shutdown - call ->shutdown() on each device to shutdown.
|
* device_shutdown - call ->shutdown() on each device to shutdown.
|
||||||
|
@ -9,10 +9,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
|
#include "../base.h"
|
||||||
#include "power.h"
|
#include "power.h"
|
||||||
|
|
||||||
extern int sysdev_suspend(pm_message_t state);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The entries in the dpm_active list are in a depth first order, simply
|
* The entries in the dpm_active list are in a depth first order, simply
|
||||||
* because children are guaranteed to be discovered after parents, and
|
* because children are guaranteed to be discovered after parents, and
|
||||||
|
@ -27,22 +27,30 @@
|
|||||||
|
|
||||||
static ssize_t state_show(struct device * dev, struct device_attribute *attr, char * buf)
|
static ssize_t state_show(struct device * dev, struct device_attribute *attr, char * buf)
|
||||||
{
|
{
|
||||||
return sprintf(buf, "%u\n", dev->power.power_state.event);
|
if (dev->power.power_state.event)
|
||||||
|
return sprintf(buf, "2\n");
|
||||||
|
else
|
||||||
|
return sprintf(buf, "0\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t state_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t n)
|
static ssize_t state_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t n)
|
||||||
{
|
{
|
||||||
pm_message_t state;
|
pm_message_t state;
|
||||||
char * rest;
|
int error = -EINVAL;
|
||||||
int error = 0;
|
|
||||||
|
|
||||||
state.event = simple_strtoul(buf, &rest, 10);
|
state.event = PM_EVENT_SUSPEND;
|
||||||
if (*rest)
|
/* Older apps expected to write "3" here - confused with PCI D3 */
|
||||||
return -EINVAL;
|
if ((n == 1) && !strcmp(buf, "3"))
|
||||||
if (state.event)
|
|
||||||
error = dpm_runtime_suspend(dev, state);
|
error = dpm_runtime_suspend(dev, state);
|
||||||
else
|
|
||||||
|
if ((n == 1) && !strcmp(buf, "2"))
|
||||||
|
error = dpm_runtime_suspend(dev, state);
|
||||||
|
|
||||||
|
if ((n == 1) && !strcmp(buf, "0")) {
|
||||||
dpm_runtime_resume(dev);
|
dpm_runtime_resume(dev);
|
||||||
|
error = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return error ? error : n;
|
return error ? error : n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,8 +21,11 @@
|
|||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <linux/pm.h>
|
#include <linux/pm.h>
|
||||||
|
#include <linux/device.h>
|
||||||
#include <asm/semaphore.h>
|
#include <asm/semaphore.h>
|
||||||
|
|
||||||
|
#include "base.h"
|
||||||
|
|
||||||
extern struct subsystem devices_subsys;
|
extern struct subsystem devices_subsys;
|
||||||
|
|
||||||
#define to_sysdev(k) container_of(k, struct sys_device, kobj)
|
#define to_sysdev(k) container_of(k, struct sys_device, kobj)
|
||||||
|
@ -980,7 +980,7 @@ extern int drm_put_head(drm_head_t * head);
|
|||||||
extern unsigned int drm_debug;
|
extern unsigned int drm_debug;
|
||||||
extern unsigned int drm_cards_limit;
|
extern unsigned int drm_cards_limit;
|
||||||
extern drm_head_t **drm_heads;
|
extern drm_head_t **drm_heads;
|
||||||
extern struct drm_sysfs_class *drm_class;
|
extern struct class *drm_class;
|
||||||
extern struct proc_dir_entry *drm_proc_root;
|
extern struct proc_dir_entry *drm_proc_root;
|
||||||
|
|
||||||
/* Proc support (drm_proc.h) */
|
/* Proc support (drm_proc.h) */
|
||||||
@ -1011,11 +1011,9 @@ extern void __drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah);
|
|||||||
extern void drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah);
|
extern void drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah);
|
||||||
|
|
||||||
/* sysfs support (drm_sysfs.c) */
|
/* sysfs support (drm_sysfs.c) */
|
||||||
struct drm_sysfs_class;
|
extern struct class *drm_sysfs_create(struct module *owner, char *name);
|
||||||
extern struct drm_sysfs_class *drm_sysfs_create(struct module *owner,
|
extern void drm_sysfs_destroy(struct class *cs);
|
||||||
char *name);
|
extern struct class_device *drm_sysfs_device_add(struct class *cs,
|
||||||
extern void drm_sysfs_destroy(struct drm_sysfs_class *cs);
|
|
||||||
extern struct class_device *drm_sysfs_device_add(struct drm_sysfs_class *cs,
|
|
||||||
drm_head_t *head);
|
drm_head_t *head);
|
||||||
extern void drm_sysfs_device_remove(struct class_device *class_dev);
|
extern void drm_sysfs_device_remove(struct class_device *class_dev);
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ module_param_named(cards_limit, drm_cards_limit, int, 0444);
|
|||||||
module_param_named(debug, drm_debug, int, 0600);
|
module_param_named(debug, drm_debug, int, 0600);
|
||||||
|
|
||||||
drm_head_t **drm_heads;
|
drm_head_t **drm_heads;
|
||||||
struct drm_sysfs_class *drm_class;
|
struct class *drm_class;
|
||||||
struct proc_dir_entry *drm_proc_root;
|
struct proc_dir_entry *drm_proc_root;
|
||||||
|
|
||||||
static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev,
|
static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev,
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* drm_sysfs.c - Modifications to drm_sysfs_class.c to support
|
* drm_sysfs.c - Modifications to drm_sysfs_class.c to support
|
||||||
* extra sysfs attribute from DRM. Normal drm_sysfs_class
|
* extra sysfs attribute from DRM. Normal drm_sysfs_class
|
||||||
@ -19,36 +20,6 @@
|
|||||||
#include "drm_core.h"
|
#include "drm_core.h"
|
||||||
#include "drmP.h"
|
#include "drmP.h"
|
||||||
|
|
||||||
struct drm_sysfs_class {
|
|
||||||
struct class_device_attribute attr;
|
|
||||||
struct class class;
|
|
||||||
};
|
|
||||||
#define to_drm_sysfs_class(d) container_of(d, struct drm_sysfs_class, class)
|
|
||||||
|
|
||||||
struct simple_dev {
|
|
||||||
dev_t dev;
|
|
||||||
struct class_device class_dev;
|
|
||||||
};
|
|
||||||
#define to_simple_dev(d) container_of(d, struct simple_dev, class_dev)
|
|
||||||
|
|
||||||
static void release_simple_dev(struct class_device *class_dev)
|
|
||||||
{
|
|
||||||
struct simple_dev *s_dev = to_simple_dev(class_dev);
|
|
||||||
kfree(s_dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t show_dev(struct class_device *class_dev, char *buf)
|
|
||||||
{
|
|
||||||
struct simple_dev *s_dev = to_simple_dev(class_dev);
|
|
||||||
return print_dev_t(buf, s_dev->dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void drm_sysfs_class_release(struct class *class)
|
|
||||||
{
|
|
||||||
struct drm_sysfs_class *cs = to_drm_sysfs_class(class);
|
|
||||||
kfree(cs);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Display the version of drm_core. This doesn't work right in current design */
|
/* Display the version of drm_core. This doesn't work right in current design */
|
||||||
static ssize_t version_show(struct class *dev, char *buf)
|
static ssize_t version_show(struct class *dev, char *buf)
|
||||||
{
|
{
|
||||||
@ -69,38 +40,16 @@ static CLASS_ATTR(version, S_IRUGO, version_show, NULL);
|
|||||||
* Note, the pointer created here is to be destroyed when finished by making a
|
* Note, the pointer created here is to be destroyed when finished by making a
|
||||||
* call to drm_sysfs_destroy().
|
* call to drm_sysfs_destroy().
|
||||||
*/
|
*/
|
||||||
struct drm_sysfs_class *drm_sysfs_create(struct module *owner, char *name)
|
struct class *drm_sysfs_create(struct module *owner, char *name)
|
||||||
{
|
{
|
||||||
struct drm_sysfs_class *cs;
|
struct class *class;
|
||||||
int retval;
|
|
||||||
|
|
||||||
cs = kmalloc(sizeof(*cs), GFP_KERNEL);
|
class = class_create(owner, name);
|
||||||
if (!cs) {
|
if (!class)
|
||||||
retval = -ENOMEM;
|
return class;
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
memset(cs, 0x00, sizeof(*cs));
|
|
||||||
|
|
||||||
cs->class.name = name;
|
class_create_file(class, &class_attr_version);
|
||||||
cs->class.class_release = drm_sysfs_class_release;
|
return class;
|
||||||
cs->class.release = release_simple_dev;
|
|
||||||
|
|
||||||
cs->attr.attr.name = "dev";
|
|
||||||
cs->attr.attr.mode = S_IRUGO;
|
|
||||||
cs->attr.attr.owner = owner;
|
|
||||||
cs->attr.show = show_dev;
|
|
||||||
cs->attr.store = NULL;
|
|
||||||
|
|
||||||
retval = class_register(&cs->class);
|
|
||||||
if (retval)
|
|
||||||
goto error;
|
|
||||||
class_create_file(&cs->class, &class_attr_version);
|
|
||||||
|
|
||||||
return cs;
|
|
||||||
|
|
||||||
error:
|
|
||||||
kfree(cs);
|
|
||||||
return ERR_PTR(retval);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -110,12 +59,13 @@ struct drm_sysfs_class *drm_sysfs_create(struct module *owner, char *name)
|
|||||||
* Note, the pointer to be destroyed must have been created with a call to
|
* Note, the pointer to be destroyed must have been created with a call to
|
||||||
* drm_sysfs_create().
|
* drm_sysfs_create().
|
||||||
*/
|
*/
|
||||||
void drm_sysfs_destroy(struct drm_sysfs_class *cs)
|
void drm_sysfs_destroy(struct class *class)
|
||||||
{
|
{
|
||||||
if ((cs == NULL) || (IS_ERR(cs)))
|
if ((class == NULL) || (IS_ERR(class)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
class_unregister(&cs->class);
|
class_remove_file(class, &class_attr_version);
|
||||||
|
class_destroy(class);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t show_dri(struct class_device *class_device, char *buf)
|
static ssize_t show_dri(struct class_device *class_device, char *buf)
|
||||||
@ -132,7 +82,7 @@ static struct class_device_attribute class_device_attrs[] = {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* drm_sysfs_device_add - adds a class device to sysfs for a character driver
|
* drm_sysfs_device_add - adds a class device to sysfs for a character driver
|
||||||
* @cs: pointer to the struct drm_sysfs_class that this device should be registered to.
|
* @cs: pointer to the struct class that this device should be registered to.
|
||||||
* @dev: the dev_t for the device to be added.
|
* @dev: the dev_t for the device to be added.
|
||||||
* @device: a pointer to a struct device that is assiociated with this class device.
|
* @device: a pointer to a struct device that is assiociated with this class device.
|
||||||
* @fmt: string for the class device's name
|
* @fmt: string for the class device's name
|
||||||
@ -141,46 +91,26 @@ static struct class_device_attribute class_device_attrs[] = {
|
|||||||
* class. A "dev" file will be created, showing the dev_t for the device. The
|
* class. A "dev" file will be created, showing the dev_t for the device. The
|
||||||
* pointer to the struct class_device will be returned from the call. Any further
|
* pointer to the struct class_device will be returned from the call. Any further
|
||||||
* sysfs files that might be required can be created using this pointer.
|
* sysfs files that might be required can be created using this pointer.
|
||||||
* Note: the struct drm_sysfs_class passed to this function must have previously been
|
* Note: the struct class passed to this function must have previously been
|
||||||
* created with a call to drm_sysfs_create().
|
* created with a call to drm_sysfs_create().
|
||||||
*/
|
*/
|
||||||
struct class_device *drm_sysfs_device_add(struct drm_sysfs_class *cs,
|
struct class_device *drm_sysfs_device_add(struct class *cs, drm_head_t *head)
|
||||||
drm_head_t *head)
|
|
||||||
{
|
{
|
||||||
struct simple_dev *s_dev = NULL;
|
struct class_device *class_dev;
|
||||||
int i, retval;
|
int i;
|
||||||
|
|
||||||
if ((cs == NULL) || (IS_ERR(cs))) {
|
class_dev = class_device_create(cs, NULL,
|
||||||
retval = -ENODEV;
|
MKDEV(DRM_MAJOR, head->minor),
|
||||||
goto error;
|
&(head->dev->pdev)->dev,
|
||||||
}
|
"card%d", head->minor);
|
||||||
|
if (!class_dev)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
s_dev = kmalloc(sizeof(*s_dev), GFP_KERNEL);
|
class_set_devdata(class_dev, head);
|
||||||
if (!s_dev) {
|
|
||||||
retval = -ENOMEM;
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
memset(s_dev, 0x00, sizeof(*s_dev));
|
|
||||||
|
|
||||||
s_dev->dev = MKDEV(DRM_MAJOR, head->minor);
|
|
||||||
s_dev->class_dev.dev = &(head->dev->pdev)->dev;
|
|
||||||
s_dev->class_dev.class = &cs->class;
|
|
||||||
|
|
||||||
snprintf(s_dev->class_dev.class_id, BUS_ID_SIZE, "card%d", head->minor);
|
|
||||||
retval = class_device_register(&s_dev->class_dev);
|
|
||||||
if (retval)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
class_device_create_file(&s_dev->class_dev, &cs->attr);
|
|
||||||
class_set_devdata(&s_dev->class_dev, head);
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++)
|
for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++)
|
||||||
class_device_create_file(&s_dev->class_dev, &class_device_attrs[i]);
|
class_device_create_file(class_dev, &class_device_attrs[i]);
|
||||||
return &s_dev->class_dev;
|
return class_dev;
|
||||||
|
|
||||||
error:
|
|
||||||
kfree(s_dev);
|
|
||||||
return ERR_PTR(retval);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -192,10 +122,9 @@ error:
|
|||||||
*/
|
*/
|
||||||
void drm_sysfs_device_remove(struct class_device *class_dev)
|
void drm_sysfs_device_remove(struct class_device *class_dev)
|
||||||
{
|
{
|
||||||
struct simple_dev *s_dev = to_simple_dev(class_dev);
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++)
|
for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++)
|
||||||
class_device_remove_file(&s_dev->class_dev, &class_device_attrs[i]);
|
class_device_remove_file(class_dev, &class_device_attrs[i]);
|
||||||
class_device_unregister(&s_dev->class_dev);
|
class_device_unregister(class_dev);
|
||||||
}
|
}
|
||||||
|
@ -1319,15 +1319,6 @@ static struct class ucm_class = {
|
|||||||
.release = ib_ucm_release_class_dev
|
.release = ib_ucm_release_class_dev
|
||||||
};
|
};
|
||||||
|
|
||||||
static ssize_t show_dev(struct class_device *class_dev, char *buf)
|
|
||||||
{
|
|
||||||
struct ib_ucm_device *dev;
|
|
||||||
|
|
||||||
dev = container_of(class_dev, struct ib_ucm_device, class_dev);
|
|
||||||
return print_dev_t(buf, dev->dev.dev);
|
|
||||||
}
|
|
||||||
static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL);
|
|
||||||
|
|
||||||
static ssize_t show_ibdev(struct class_device *class_dev, char *buf)
|
static ssize_t show_ibdev(struct class_device *class_dev, char *buf)
|
||||||
{
|
{
|
||||||
struct ib_ucm_device *dev;
|
struct ib_ucm_device *dev;
|
||||||
@ -1364,14 +1355,12 @@ static void ib_ucm_add_one(struct ib_device *device)
|
|||||||
|
|
||||||
ucm_dev->class_dev.class = &ucm_class;
|
ucm_dev->class_dev.class = &ucm_class;
|
||||||
ucm_dev->class_dev.dev = device->dma_device;
|
ucm_dev->class_dev.dev = device->dma_device;
|
||||||
|
ucm_dev->class_dev.devt = ucm_dev->dev.dev;
|
||||||
snprintf(ucm_dev->class_dev.class_id, BUS_ID_SIZE, "ucm%d",
|
snprintf(ucm_dev->class_dev.class_id, BUS_ID_SIZE, "ucm%d",
|
||||||
ucm_dev->devnum);
|
ucm_dev->devnum);
|
||||||
if (class_device_register(&ucm_dev->class_dev))
|
if (class_device_register(&ucm_dev->class_dev))
|
||||||
goto err_cdev;
|
goto err_cdev;
|
||||||
|
|
||||||
if (class_device_create_file(&ucm_dev->class_dev,
|
|
||||||
&class_device_attr_dev))
|
|
||||||
goto err_class;
|
|
||||||
if (class_device_create_file(&ucm_dev->class_dev,
|
if (class_device_create_file(&ucm_dev->class_dev,
|
||||||
&class_device_attr_ibdev))
|
&class_device_attr_ibdev))
|
||||||
goto err_class;
|
goto err_class;
|
||||||
|
@ -75,16 +75,6 @@ config SPI_BUTTERFLY
|
|||||||
inexpensive battery powered microcontroller evaluation board.
|
inexpensive battery powered microcontroller evaluation board.
|
||||||
This same cable can be used to flash new firmware.
|
This same cable can be used to flash new firmware.
|
||||||
|
|
||||||
config SPI_BUTTERFLY
|
|
||||||
tristate "Parallel port adapter for AVR Butterfly (DEVELOPMENT)"
|
|
||||||
depends on SPI_MASTER && PARPORT && EXPERIMENTAL
|
|
||||||
select SPI_BITBANG
|
|
||||||
help
|
|
||||||
This uses a custom parallel port cable to connect to an AVR
|
|
||||||
Butterfly <http://www.atmel.com/products/avr/butterfly>, an
|
|
||||||
inexpensive battery powered microcontroller evaluation board.
|
|
||||||
This same cable can be used to flash new firmware.
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Add new SPI master controllers in alphabetical order above this line
|
# Add new SPI master controllers in alphabetical order above this line
|
||||||
#
|
#
|
||||||
|
@ -163,21 +163,20 @@ static void butterfly_chipselect(struct spi_device *spi, int value)
|
|||||||
struct butterfly *pp = spidev_to_pp(spi);
|
struct butterfly *pp = spidev_to_pp(spi);
|
||||||
|
|
||||||
/* set default clock polarity */
|
/* set default clock polarity */
|
||||||
if (value)
|
if (value != BITBANG_CS_INACTIVE)
|
||||||
setsck(spi, spi->mode & SPI_CPOL);
|
setsck(spi, spi->mode & SPI_CPOL);
|
||||||
|
|
||||||
/* no chipselect on this USI link config */
|
/* no chipselect on this USI link config */
|
||||||
if (is_usidev(spi))
|
if (is_usidev(spi))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* here, value == "activate or not" */
|
/* here, value == "activate or not";
|
||||||
|
* most PARPORT_CONTROL_* bits are negated, so we must
|
||||||
/* most PARPORT_CONTROL_* bits are negated */
|
* morph it to value == "bit value to write in control register"
|
||||||
|
*/
|
||||||
if (spi_cs_bit == PARPORT_CONTROL_INIT)
|
if (spi_cs_bit == PARPORT_CONTROL_INIT)
|
||||||
value = !value;
|
value = !value;
|
||||||
|
|
||||||
/* here, value == "bit value to write in control register" */
|
|
||||||
|
|
||||||
parport_frob_control(pp->port, spi_cs_bit, value ? spi_cs_bit : 0);
|
parport_frob_control(pp->port, spi_cs_bit, value ? spi_cs_bit : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,7 +201,9 @@ butterfly_txrx_word_mode0(struct spi_device *spi,
|
|||||||
|
|
||||||
/* override default partitioning with cmdlinepart */
|
/* override default partitioning with cmdlinepart */
|
||||||
static struct mtd_partition partitions[] = { {
|
static struct mtd_partition partitions[] = { {
|
||||||
/* JFFS2 wants partitions of 4*N blocks for this device ... */
|
/* JFFS2 wants partitions of 4*N blocks for this device,
|
||||||
|
* so sectors 0 and 1 can't be partitions by themselves.
|
||||||
|
*/
|
||||||
|
|
||||||
/* sector 0 = 8 pages * 264 bytes/page (1 block)
|
/* sector 0 = 8 pages * 264 bytes/page (1 block)
|
||||||
* sector 1 = 248 pages * 264 bytes/page
|
* sector 1 = 248 pages * 264 bytes/page
|
||||||
@ -316,8 +317,9 @@ static void butterfly_attach(struct parport *p)
|
|||||||
if (status < 0)
|
if (status < 0)
|
||||||
goto clean2;
|
goto clean2;
|
||||||
|
|
||||||
/* Bus 1 lets us talk to at45db041b (firmware disables AVR)
|
/* Bus 1 lets us talk to at45db041b (firmware disables AVR SPI), AVR
|
||||||
* or AVR (firmware resets at45, acts as spi slave)
|
* (firmware resets at45, acts as spi slave) or neither (we ignore
|
||||||
|
* both, AVR uses AT45). Here we expect firmware for the first option.
|
||||||
*/
|
*/
|
||||||
pp->info[0].max_speed_hz = 15 * 1000 * 1000;
|
pp->info[0].max_speed_hz = 15 * 1000 * 1000;
|
||||||
strcpy(pp->info[0].modalias, "mtd_dataflash");
|
strcpy(pp->info[0].modalias, "mtd_dataflash");
|
||||||
@ -330,7 +332,9 @@ static void butterfly_attach(struct parport *p)
|
|||||||
pp->dataflash->dev.bus_id);
|
pp->dataflash->dev.bus_id);
|
||||||
|
|
||||||
#ifdef HAVE_USI
|
#ifdef HAVE_USI
|
||||||
/* even more custom AVR firmware */
|
/* Bus 2 is only for talking to the AVR, and it can work no
|
||||||
|
* matter who masters bus 1; needs appropriate AVR firmware.
|
||||||
|
*/
|
||||||
pp->info[1].max_speed_hz = 10 /* ?? */ * 1000 * 1000;
|
pp->info[1].max_speed_hz = 10 /* ?? */ * 1000 * 1000;
|
||||||
strcpy(pp->info[1].modalias, "butterfly");
|
strcpy(pp->info[1].modalias, "butterfly");
|
||||||
// pp->info[1].platform_data = ... TBD ... ;
|
// pp->info[1].platform_data = ... TBD ... ;
|
||||||
@ -378,13 +382,8 @@ static void butterfly_detach(struct parport *p)
|
|||||||
pp = butterfly;
|
pp = butterfly;
|
||||||
butterfly = NULL;
|
butterfly = NULL;
|
||||||
|
|
||||||
#ifdef HAVE_USI
|
/* stop() unregisters child devices too */
|
||||||
spi_unregister_device(pp->butterfly);
|
pdev = to_platform_device(pp->bitbang.master->cdev.dev);
|
||||||
pp->butterfly = NULL;
|
|
||||||
#endif
|
|
||||||
spi_unregister_device(pp->dataflash);
|
|
||||||
pp->dataflash = NULL;
|
|
||||||
|
|
||||||
status = spi_bitbang_stop(&pp->bitbang);
|
status = spi_bitbang_stop(&pp->bitbang);
|
||||||
|
|
||||||
/* turn off VCC */
|
/* turn off VCC */
|
||||||
@ -394,8 +393,6 @@ static void butterfly_detach(struct parport *p)
|
|||||||
parport_release(pp->pd);
|
parport_release(pp->pd);
|
||||||
parport_unregister_device(pp->pd);
|
parport_unregister_device(pp->pd);
|
||||||
|
|
||||||
pdev = to_platform_device(pp->bitbang.master->cdev.dev);
|
|
||||||
|
|
||||||
(void) spi_master_put(pp->bitbang.master);
|
(void) spi_master_put(pp->bitbang.master);
|
||||||
|
|
||||||
platform_device_unregister(pdev);
|
platform_device_unregister(pdev);
|
||||||
@ -420,4 +417,5 @@ static void __exit butterfly_exit(void)
|
|||||||
}
|
}
|
||||||
module_exit(butterfly_exit);
|
module_exit(butterfly_exit);
|
||||||
|
|
||||||
|
MODULE_DESCRIPTION("Parport Adapter driver for AVR Butterfly");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
@ -56,7 +56,7 @@ static u64 debugfs_u8_get(void *data)
|
|||||||
DEFINE_SIMPLE_ATTRIBUTE(fops_u8, debugfs_u8_get, debugfs_u8_set, "%llu\n");
|
DEFINE_SIMPLE_ATTRIBUTE(fops_u8, debugfs_u8_get, debugfs_u8_set, "%llu\n");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* debugfs_create_u8 - create a file in the debugfs filesystem that is used to read and write a unsigned 8 bit value.
|
* debugfs_create_u8 - create a file in the debugfs filesystem that is used to read and write an unsigned 8 bit value.
|
||||||
*
|
*
|
||||||
* @name: a pointer to a string containing the name of the file to create.
|
* @name: a pointer to a string containing the name of the file to create.
|
||||||
* @mode: the permission that the file should have
|
* @mode: the permission that the file should have
|
||||||
@ -98,7 +98,7 @@ static u64 debugfs_u16_get(void *data)
|
|||||||
DEFINE_SIMPLE_ATTRIBUTE(fops_u16, debugfs_u16_get, debugfs_u16_set, "%llu\n");
|
DEFINE_SIMPLE_ATTRIBUTE(fops_u16, debugfs_u16_get, debugfs_u16_set, "%llu\n");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* debugfs_create_u16 - create a file in the debugfs filesystem that is used to read and write a unsigned 8 bit value.
|
* debugfs_create_u16 - create a file in the debugfs filesystem that is used to read and write an unsigned 16 bit value.
|
||||||
*
|
*
|
||||||
* @name: a pointer to a string containing the name of the file to create.
|
* @name: a pointer to a string containing the name of the file to create.
|
||||||
* @mode: the permission that the file should have
|
* @mode: the permission that the file should have
|
||||||
@ -140,7 +140,7 @@ static u64 debugfs_u32_get(void *data)
|
|||||||
DEFINE_SIMPLE_ATTRIBUTE(fops_u32, debugfs_u32_get, debugfs_u32_set, "%llu\n");
|
DEFINE_SIMPLE_ATTRIBUTE(fops_u32, debugfs_u32_get, debugfs_u32_set, "%llu\n");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* debugfs_create_u32 - create a file in the debugfs filesystem that is used to read and write a unsigned 8 bit value.
|
* debugfs_create_u32 - create a file in the debugfs filesystem that is used to read and write an unsigned 32 bit value.
|
||||||
*
|
*
|
||||||
* @name: a pointer to a string containing the name of the file to create.
|
* @name: a pointer to a string containing the name of the file to create.
|
||||||
* @mode: the permission that the file should have
|
* @mode: the permission that the file should have
|
||||||
|
@ -72,6 +72,8 @@ static int get_kobj_path_length(struct kobject *kobj)
|
|||||||
* Add 1 to strlen for leading '/' of each level.
|
* Add 1 to strlen for leading '/' of each level.
|
||||||
*/
|
*/
|
||||||
do {
|
do {
|
||||||
|
if (kobject_name(parent) == NULL)
|
||||||
|
return 0;
|
||||||
length += strlen(kobject_name(parent)) + 1;
|
length += strlen(kobject_name(parent)) + 1;
|
||||||
parent = parent->parent;
|
parent = parent->parent;
|
||||||
} while (parent);
|
} while (parent);
|
||||||
@ -107,6 +109,8 @@ char *kobject_get_path(struct kobject *kobj, gfp_t gfp_mask)
|
|||||||
int len;
|
int len;
|
||||||
|
|
||||||
len = get_kobj_path_length(kobj);
|
len = get_kobj_path_length(kobj);
|
||||||
|
if (len == 0)
|
||||||
|
return NULL;
|
||||||
path = kmalloc(len, gfp_mask);
|
path = kmalloc(len, gfp_mask);
|
||||||
if (!path)
|
if (!path)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -162,6 +166,11 @@ int kobject_add(struct kobject * kobj)
|
|||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
if (!kobj->k_name)
|
if (!kobj->k_name)
|
||||||
kobj->k_name = kobj->name;
|
kobj->k_name = kobj->name;
|
||||||
|
if (!kobj->k_name) {
|
||||||
|
pr_debug("kobject attempted to be registered with no name!\n");
|
||||||
|
WARN_ON(1);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
parent = kobject_get(kobj->parent);
|
parent = kobject_get(kobj->parent);
|
||||||
|
|
||||||
pr_debug("kobject %s: registering. parent: %s, set: %s\n",
|
pr_debug("kobject %s: registering. parent: %s, set: %s\n",
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
#include <linux/kobject.h>
|
#include <linux/kobject.h>
|
||||||
#include <net/sock.h>
|
#include <net/sock.h>
|
||||||
|
|
||||||
#define BUFFER_SIZE 1024 /* buffer for the variables */
|
#define BUFFER_SIZE 2048 /* buffer for the variables */
|
||||||
#define NUM_ENVP 32 /* number of env pointers */
|
#define NUM_ENVP 32 /* number of env pointers */
|
||||||
|
|
||||||
#if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET)
|
#if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET)
|
||||||
|
Loading…
Reference in New Issue
Block a user