Skip to content

Commit

Permalink
add gpiolib support to ucb1x00
Browse files Browse the repository at this point in the history
The old access methods to the gpios will be removed when
all users has been converted. (mainly ucb1x00-ts)
  • Loading branch information
Thomas Kunze authored and Thomas Kunze committed Nov 27, 2009
1 parent cc64717 commit 9ca3dc8
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 2 deletions.
1 change: 1 addition & 0 deletions arch/arm/mach-sa1100/include/mach/mcp.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ struct mcp_plat_data {
u32 mccr0;
u32 mccr1;
unsigned int sclk_rate;
int gpio_base;
};

#endif
1 change: 1 addition & 0 deletions drivers/mfd/mcp-sa11x0.c
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ static int mcp_sa11x0_probe(struct platform_device *pdev)
mcp->dma_audio_wr = DMA_Ser4MCP0Wr;
mcp->dma_telco_rd = DMA_Ser4MCP1Rd;
mcp->dma_telco_wr = DMA_Ser4MCP1Wr;
mcp->gpio_base = data->gpio_base;

platform_set_drvdata(pdev, mcp);

Expand Down
87 changes: 85 additions & 2 deletions drivers/mfd/ucb1x00-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@
#include <linux/device.h>
#include <linux/mutex.h>
#include <linux/mfd/ucb1x00.h>
#include <linux/gpio.h>

#include <mach/dma.h>
#include <mach/hardware.h>


static DEFINE_MUTEX(ucb1x00_mutex);
static LIST_HEAD(ucb1x00_drivers);
static LIST_HEAD(ucb1x00_devices);
Expand Down Expand Up @@ -108,6 +108,60 @@ unsigned int ucb1x00_io_read(struct ucb1x00 *ucb)
return ucb1x00_reg_read(ucb, UCB_IO_DATA);
}

static void ucb1x00_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio);
unsigned long flags;

spin_lock_irqsave(&ucb->io_lock, flags);
if (value)
ucb->io_out |= 1 << offset;
else
ucb->io_out &= ~(1 << offset);

ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out);
spin_unlock_irqrestore(&ucb->io_lock, flags);
}

static int ucb1x00_gpio_get(struct gpio_chip *chip, unsigned offset)
{
struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio);
return ucb1x00_reg_read(ucb, UCB_IO_DATA) & (1 << offset);
}

static int ucb1x00_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
{
struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio);
unsigned long flags;

spin_lock_irqsave(&ucb->io_lock, flags);
ucb->io_dir &= ~(1 << offset);
ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir);
spin_unlock_irqrestore(&ucb->io_lock, flags);

return 0;
}

static int ucb1x00_gpio_direction_output(struct gpio_chip *chip, unsigned offset
, int value)
{
struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio);
unsigned long flags;

spin_lock_irqsave(&ucb->io_lock, flags);
ucb->io_dir |= (1 << offset);
ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir);

if (value)
ucb->io_out |= 1 << offset;
else
ucb->io_out &= ~(1 << offset);
ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out);
spin_unlock_irqrestore(&ucb->io_lock, flags);

return 0;
}

/*
* UCB1300 data sheet says we must:
* 1. enable ADC => 5us (including reference startup time)
Expand Down Expand Up @@ -476,6 +530,7 @@ static int ucb1x00_probe(struct mcp *mcp)
struct ucb1x00_driver *drv;
unsigned int id;
int ret = -ENODEV;
int temp;

mcp_enable(mcp);
id = mcp_reg_read(mcp, UCB_ID);
Expand Down Expand Up @@ -508,12 +563,27 @@ static int ucb1x00_probe(struct mcp *mcp)
goto err_free;
}

ucb->gpio.base = -1;
if (mcp->gpio_base != 0) {
ucb->gpio.label = dev_name(&ucb->dev);
ucb->gpio.base = mcp->gpio_base;
ucb->gpio.ngpio = 10;
ucb->gpio.set = ucb1x00_gpio_set;
ucb->gpio.get = ucb1x00_gpio_get;
ucb->gpio.direction_input = ucb1x00_gpio_direction_input;
ucb->gpio.direction_output = ucb1x00_gpio_direction_output;
ret = gpiochip_add(&ucb->gpio);
if (ret)
goto err_free;
} else
dev_info(&ucb->dev, "gpio_base not set so no gpiolib support");

ret = request_irq(ucb->irq, ucb1x00_irq, IRQF_TRIGGER_RISING,
"UCB1x00", ucb);
if (ret) {
printk(KERN_ERR "ucb1x00: unable to grab irq%d: %d\n",
ucb->irq, ret);
goto err_free;
goto err_gpio;
}

mcp_set_drvdata(mcp, ucb);
Expand All @@ -522,17 +592,22 @@ static int ucb1x00_probe(struct mcp *mcp)
if (ret)
goto err_irq;


INIT_LIST_HEAD(&ucb->devs);
mutex_lock(&ucb1x00_mutex);
list_add(&ucb->node, &ucb1x00_devices);
list_for_each_entry(drv, &ucb1x00_drivers, node) {
ucb1x00_add_dev(ucb, drv);
}
mutex_unlock(&ucb1x00_mutex);

goto out;

err_irq:
free_irq(ucb->irq, ucb);
err_gpio:
if (ucb->gpio.base != -1)
temp = gpiochip_remove(&ucb->gpio);
err_free:
kfree(ucb);
err_disable:
Expand All @@ -545,6 +620,7 @@ static void ucb1x00_remove(struct mcp *mcp)
{
struct ucb1x00 *ucb = mcp_get_drvdata(mcp);
struct list_head *l, *n;
int ret;

mutex_lock(&ucb1x00_mutex);
list_del(&ucb->node);
Expand All @@ -554,6 +630,12 @@ static void ucb1x00_remove(struct mcp *mcp)
}
mutex_unlock(&ucb1x00_mutex);

if (ucb->gpio.base != -1) {
ret = gpiochip_remove(&ucb->gpio);
if (ret)
dev_err(&ucb->dev, "Can't remove gpio chip: %d\n", ret);
}

free_irq(ucb->irq, ucb);
device_unregister(&ucb->dev);
}
Expand Down Expand Up @@ -604,6 +686,7 @@ static int ucb1x00_resume(struct mcp *mcp)
struct ucb1x00 *ucb = mcp_get_drvdata(mcp);
struct ucb1x00_dev *dev;

ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir);
mutex_lock(&ucb1x00_mutex);
list_for_each_entry(dev, &ucb->devs, dev_node) {
if (dev->drv->resume)
Expand Down
1 change: 1 addition & 0 deletions include/linux/mfd/mcp.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ struct mcp {
dma_device_t dma_telco_rd;
dma_device_t dma_telco_wr;
struct device attached_device;
int gpio_base;
};

struct mcp_ops {
Expand Down
3 changes: 3 additions & 0 deletions include/linux/mfd/ucb1x00.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#define UCB1200_H

#include <linux/mfd/mcp.h>
#include <linux/gpio.h>

#define UCB_IO_DATA 0x00
#define UCB_IO_DIR 0x01

Expand Down Expand Up @@ -123,6 +125,7 @@ struct ucb1x00 {
struct device dev;
struct list_head node;
struct list_head devs;
struct gpio_chip gpio;
};

struct ucb1x00_driver;
Expand Down

0 comments on commit 9ca3dc8

Please sign in to comment.