Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9ca3dc80 authored by Thomas Kunze's avatar Thomas Kunze Committed by Thomas Kunze
Browse files

add gpiolib support to ucb1x00

The old access methods to the gpios will be removed when
all users has been converted. (mainly ucb1x00-ts)
parent cc647172
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -16,6 +16,7 @@ struct mcp_plat_data {
	u32 mccr0;
	u32 mccr0;
	u32 mccr1;
	u32 mccr1;
	unsigned int sclk_rate;
	unsigned int sclk_rate;
	int gpio_base;
};
};


#endif
#endif
+1 −0
Original line number Original line Diff line number Diff line
@@ -163,6 +163,7 @@ static int mcp_sa11x0_probe(struct platform_device *pdev)
	mcp->dma_audio_wr	= DMA_Ser4MCP0Wr;
	mcp->dma_audio_wr	= DMA_Ser4MCP0Wr;
	mcp->dma_telco_rd	= DMA_Ser4MCP1Rd;
	mcp->dma_telco_rd	= DMA_Ser4MCP1Rd;
	mcp->dma_telco_wr	= DMA_Ser4MCP1Wr;
	mcp->dma_telco_wr	= DMA_Ser4MCP1Wr;
	mcp->gpio_base		= data->gpio_base;


	platform_set_drvdata(pdev, mcp);
	platform_set_drvdata(pdev, mcp);


+85 −2
Original line number Original line Diff line number Diff line
@@ -26,11 +26,11 @@
#include <linux/device.h>
#include <linux/device.h>
#include <linux/mutex.h>
#include <linux/mutex.h>
#include <linux/mfd/ucb1x00.h>
#include <linux/mfd/ucb1x00.h>
#include <linux/gpio.h>


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



static DEFINE_MUTEX(ucb1x00_mutex);
static DEFINE_MUTEX(ucb1x00_mutex);
static LIST_HEAD(ucb1x00_drivers);
static LIST_HEAD(ucb1x00_drivers);
static LIST_HEAD(ucb1x00_devices);
static LIST_HEAD(ucb1x00_devices);
@@ -108,6 +108,60 @@ unsigned int ucb1x00_io_read(struct ucb1x00 *ucb)
	return ucb1x00_reg_read(ucb, UCB_IO_DATA);
	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:
 * UCB1300 data sheet says we must:
 *  1. enable ADC	=> 5us (including reference startup time)
 *  1. enable ADC	=> 5us (including reference startup time)
@@ -476,6 +530,7 @@ static int ucb1x00_probe(struct mcp *mcp)
	struct ucb1x00_driver *drv;
	struct ucb1x00_driver *drv;
	unsigned int id;
	unsigned int id;
	int ret = -ENODEV;
	int ret = -ENODEV;
	int temp;


	mcp_enable(mcp);
	mcp_enable(mcp);
	id = mcp_reg_read(mcp, UCB_ID);
	id = mcp_reg_read(mcp, UCB_ID);
@@ -508,12 +563,27 @@ static int ucb1x00_probe(struct mcp *mcp)
		goto err_free;
		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,
	ret = request_irq(ucb->irq, ucb1x00_irq, IRQF_TRIGGER_RISING,
			  "UCB1x00", ucb);
			  "UCB1x00", ucb);
	if (ret) {
	if (ret) {
		printk(KERN_ERR "ucb1x00: unable to grab irq%d: %d\n",
		printk(KERN_ERR "ucb1x00: unable to grab irq%d: %d\n",
			ucb->irq, ret);
			ucb->irq, ret);
		goto err_free;
		goto err_gpio;
	}
	}


	mcp_set_drvdata(mcp, ucb);
	mcp_set_drvdata(mcp, ucb);
@@ -522,6 +592,7 @@ static int ucb1x00_probe(struct mcp *mcp)
	if (ret)
	if (ret)
		goto err_irq;
		goto err_irq;



	INIT_LIST_HEAD(&ucb->devs);
	INIT_LIST_HEAD(&ucb->devs);
	mutex_lock(&ucb1x00_mutex);
	mutex_lock(&ucb1x00_mutex);
	list_add(&ucb->node, &ucb1x00_devices);
	list_add(&ucb->node, &ucb1x00_devices);
@@ -529,10 +600,14 @@ static int ucb1x00_probe(struct mcp *mcp)
		ucb1x00_add_dev(ucb, drv);
		ucb1x00_add_dev(ucb, drv);
	}
	}
	mutex_unlock(&ucb1x00_mutex);
	mutex_unlock(&ucb1x00_mutex);

	goto out;
	goto out;


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


	mutex_lock(&ucb1x00_mutex);
	mutex_lock(&ucb1x00_mutex);
	list_del(&ucb->node);
	list_del(&ucb->node);
@@ -554,6 +630,12 @@ static void ucb1x00_remove(struct mcp *mcp)
	}
	}
	mutex_unlock(&ucb1x00_mutex);
	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);
	free_irq(ucb->irq, ucb);
	device_unregister(&ucb->dev);
	device_unregister(&ucb->dev);
}
}
@@ -604,6 +686,7 @@ static int ucb1x00_resume(struct mcp *mcp)
	struct ucb1x00 *ucb = mcp_get_drvdata(mcp);
	struct ucb1x00 *ucb = mcp_get_drvdata(mcp);
	struct ucb1x00_dev *dev;
	struct ucb1x00_dev *dev;


	ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir);
	mutex_lock(&ucb1x00_mutex);
	mutex_lock(&ucb1x00_mutex);
	list_for_each_entry(dev, &ucb->devs, dev_node) {
	list_for_each_entry(dev, &ucb->devs, dev_node) {
		if (dev->drv->resume)
		if (dev->drv->resume)
+1 −0
Original line number Original line Diff line number Diff line
@@ -26,6 +26,7 @@ struct mcp {
	dma_device_t	dma_telco_rd;
	dma_device_t	dma_telco_rd;
	dma_device_t	dma_telco_wr;
	dma_device_t	dma_telco_wr;
	struct device	attached_device;
	struct device	attached_device;
	int		gpio_base;
};
};


struct mcp_ops {
struct mcp_ops {
+3 −0
Original line number Original line Diff line number Diff line
@@ -11,6 +11,8 @@
#define UCB1200_H
#define UCB1200_H


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

#define UCB_IO_DATA	0x00
#define UCB_IO_DATA	0x00
#define UCB_IO_DIR	0x01
#define UCB_IO_DIR	0x01


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


struct ucb1x00_driver;
struct ucb1x00_driver;