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

Commit 44173fb2 authored by Yoichi Yuasa's avatar Yoichi Yuasa Committed by Ralf Baechle
Browse files

[MIPS] Separate platform_device registration for VR41xx GPIO

parent a74b4605
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -2,4 +2,4 @@
# Makefile for common code of the NEC VR4100 series.
#

obj-y	+= bcu.o cmu.o icu.o init.o irq.o pmu.o siu.o type.o
obj-y	+= bcu.o cmu.o giu.o icu.o init.o irq.o pmu.o siu.o type.o
+122 −0
Original line number Diff line number Diff line
/*
 *  NEC VR4100 series GIU platform device.
 *
 *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/platform_device.h>

#include <asm/cpu.h>
#include <asm/vr41xx/giu.h>
#include <asm/vr41xx/irq.h>

static struct resource giu_50pins_pullupdown_resource[] __initdata = {
	{
		.start	= 0x0b000100,
		.end	= 0x0b00011f,
		.flags	= IORESOURCE_MEM,
	},
	{
		.start	= 0x0b0002e0,
		.end	= 0x0b0002e3,
		.flags	= IORESOURCE_MEM,
	},
	{
		.start	= GIUINT_IRQ,
		.end	= GIUINT_IRQ,
		.flags	= IORESOURCE_IRQ,
	},
};

static struct resource giu_36pins_resource[] __initdata = {
	{
		.start	= 0x0f000140,
		.end	= 0x0f00015f,
		.flags	= IORESOURCE_MEM,
	},
	{
		.start	= GIUINT_IRQ,
		.end	= GIUINT_IRQ,
		.flags	= IORESOURCE_IRQ,
	},
};

static struct resource giu_48pins_resource[] __initdata = {
	{
		.start	= 0x0f000140,
		.end	= 0x0f000167,
		.flags	= IORESOURCE_MEM,
	},
	{
		.start	= GIUINT_IRQ,
		.end	= GIUINT_IRQ,
		.flags	= IORESOURCE_IRQ,
	},
};

static int __init vr41xx_giu_add(void)
{
	struct platform_device *pdev;
	struct resource *res;
	unsigned int num;
	int retval;

	pdev = platform_device_alloc("GIU", -1);
	if (!pdev)
		return -ENOMEM;

	switch (current_cpu_data.cputype) {
	case CPU_VR4111:
	case CPU_VR4121:
		pdev->id = GPIO_50PINS_PULLUPDOWN;
		res = giu_50pins_pullupdown_resource;
		num = ARRAY_SIZE(giu_50pins_pullupdown_resource);
		break;
	case CPU_VR4122:
	case CPU_VR4131:
		pdev->id = GPIO_36PINS;
		res = giu_36pins_resource;
		num = ARRAY_SIZE(giu_36pins_resource);
		break;
	case CPU_VR4133:
		pdev->id = GPIO_48PINS_EDGE_SELECT;
		res = giu_48pins_resource;
		num = ARRAY_SIZE(giu_48pins_resource);
		break;
	default:
		retval = -ENODEV;
		goto err_free_device;
	}

	retval = platform_device_add_resources(pdev, res, num);
	if (retval)
		goto err_free_device;

	retval = platform_device_add(pdev);
	if (retval)
		goto err_free_device;

	return 0;

err_free_device:
	platform_device_put(pdev);

	return retval;
}
device_initcall(vr41xx_giu_add);
+34 −98
Original line number Diff line number Diff line
@@ -19,18 +19,17 @@
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
#include <linux/platform_device.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
#include <linux/types.h>

#include <asm/cpu.h>
#include <asm/io.h>
#include <asm/vr41xx/giu.h>
#include <asm/vr41xx/irq.h>
@@ -44,18 +43,6 @@ static int major; /* default is dynamic major device number */
module_param(major, int, 0);
MODULE_PARM_DESC(major, "Major device number");

#define GIU_TYPE1_START		0x0b000100UL
#define GIU_TYPE1_SIZE		0x20UL

#define GIU_TYPE2_START		0x0f000140UL
#define GIU_TYPE2_SIZE		0x20UL

#define GIU_TYPE3_START		0x0f000140UL
#define GIU_TYPE3_SIZE		0x28UL

#define GIU_PULLUPDOWN_START	0x0b0002e0UL
#define GIU_PULLUPDOWN_SIZE	0x04UL

#define GIUIOSELL	0x00
#define GIUIOSELH	0x02
#define GIUPIODL	0x04
@@ -89,8 +76,6 @@ MODULE_PARM_DESC(major, "Major device number");
#define GPIO_HAS_INTERRUPT_EDGE_SELECT	0x0100

static spinlock_t giu_lock;
static struct resource *giu_resource1;
static struct resource *giu_resource2;
static unsigned long giu_flags;
static unsigned int giu_nr_pins;

@@ -234,7 +219,7 @@ void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_
				giu_set(GIUINTHTSELL, mask);
			else
				giu_clear(GIUINTHTSELL, mask);
			if (current_cpu_data.cputype == CPU_VR4133) {
			if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) {
				switch (trigger) {
				case IRQ_TRIGGER_EDGE_FALLING:
					giu_set(GIUFEDGEINHL, mask);
@@ -269,7 +254,7 @@ void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_
				giu_set(GIUINTHTSELH, mask);
			else
				giu_clear(GIUINTHTSELH, mask);
			if (current_cpu_data.cputype == CPU_VR4133) {
			if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) {
				switch (trigger) {
				case IRQ_TRIGGER_EDGE_FALLING:
					giu_set(GIUFEDGEINHH, mask);
@@ -298,7 +283,6 @@ void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_
		giu_write(GIUINTSTATH, mask);
	}
}

EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger);

void vr41xx_set_irq_level(unsigned int pin, irq_level_t level)
@@ -321,7 +305,6 @@ void vr41xx_set_irq_level(unsigned int pin, irq_level_t level)
		giu_write(GIUINTSTATH, mask);
	}
}

EXPORT_SYMBOL_GPL(vr41xx_set_irq_level);

gpio_data_t vr41xx_gpio_get_pin(unsigned int pin)
@@ -350,7 +333,6 @@ gpio_data_t vr41xx_gpio_get_pin(unsigned int pin)

	return GPIO_DATA_LOW;
}

EXPORT_SYMBOL_GPL(vr41xx_gpio_get_pin);

int vr41xx_gpio_set_pin(unsigned int pin, gpio_data_t data)
@@ -388,7 +370,6 @@ int vr41xx_gpio_set_pin(unsigned int pin, gpio_data_t data)

	return 0;
}

EXPORT_SYMBOL_GPL(vr41xx_gpio_set_pin);

int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir)
@@ -438,7 +419,6 @@ int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir)

	return 0;
}

EXPORT_SYMBOL_GPL(vr41xx_gpio_set_direction);

int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull)
@@ -477,7 +457,6 @@ int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull)

	return 0;
}

EXPORT_SYMBOL_GPL(vr41xx_gpio_pullupdown);

static ssize_t gpio_read(struct file *file, char __user *buf, size_t len,
@@ -596,61 +575,40 @@ static const struct file_operations gpio_fops = {

static int __devinit giu_probe(struct platform_device *dev)
{
	unsigned long start, size, flags = 0;
	unsigned int nr_pins = 0, trigger, i, pin;
	struct resource *res1, *res2 = NULL;
	void *base;
	struct resource *res;
	unsigned int trigger, i, pin;
	struct irq_chip *chip;
	int retval;

	switch (current_cpu_data.cputype) {
	case CPU_VR4111:
	case CPU_VR4121:
		start = GIU_TYPE1_START;
		size = GIU_TYPE1_SIZE;
		flags = GPIO_HAS_PULLUPDOWN_IO;
		nr_pins = 50;
	int irq, retval;

	switch (dev->id) {
	case GPIO_50PINS_PULLUPDOWN:
		giu_flags = GPIO_HAS_PULLUPDOWN_IO;
		giu_nr_pins = 50;
		break;
	case CPU_VR4122:
	case CPU_VR4131:
		start = GIU_TYPE2_START;
		size = GIU_TYPE2_SIZE;
		nr_pins = 36;
	case GPIO_36PINS:
		giu_nr_pins = 36;
		break;
	case CPU_VR4133:
		start = GIU_TYPE3_START;
		size = GIU_TYPE3_SIZE;
		flags = GPIO_HAS_INTERRUPT_EDGE_SELECT;
		nr_pins = 48;
	case GPIO_48PINS_EDGE_SELECT:
		giu_flags = GPIO_HAS_INTERRUPT_EDGE_SELECT;
		giu_nr_pins = 48;
		break;
	default:
		printk(KERN_ERR "GIU: unknown ID %d\n", dev->id);
		return -ENODEV;
	}

	res1 = request_mem_region(start, size, "GIU");
	if (res1 == NULL)
	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
	if (!res)
		return -EBUSY;

	base = ioremap(start, size);
	if (base == NULL) {
		release_resource(res1);
	giu_base = ioremap(res->start, res->end - res->start + 1);
	if (!giu_base)
		return -ENOMEM;
	}

	if (flags & GPIO_HAS_PULLUPDOWN_IO) {
		res2 = request_mem_region(GIU_PULLUPDOWN_START, GIU_PULLUPDOWN_SIZE, "GIU");
		if (res2 == NULL) {
			iounmap(base);
			release_resource(res1);
			return -EBUSY;
		}
	}

	retval = register_chrdev(major, "GIU", &gpio_fops);
	if (retval < 0) {
		iounmap(base);
		release_resource(res1);
		release_resource(res2);
		iounmap(giu_base);
		giu_base = NULL;
		return retval;
	}

@@ -660,11 +618,6 @@ static int __devinit giu_probe(struct platform_device *dev)
	}

	spin_lock_init(&giu_lock);
	giu_base = base;
	giu_resource1 = res1;
	giu_resource2 = res2;
	giu_flags = flags;
	giu_nr_pins = nr_pins;

	giu_write(GIUINTENL, 0);
	giu_write(GIUINTENH, 0);
@@ -685,22 +638,23 @@ static int __devinit giu_probe(struct platform_device *dev)

	}

	return cascade_irq(GIUINT_IRQ, giu_get_irq);
	irq = platform_get_irq(dev, 0);
	if (irq < 0 || irq >= NR_IRQS)
		return -EBUSY;

	return cascade_irq(irq, giu_get_irq);
}

static int __devexit giu_remove(struct platform_device *dev)
{
	if (giu_base) {
		iounmap(giu_base);

	release_resource(giu_resource1);
	if (giu_flags & GPIO_HAS_PULLUPDOWN_IO)
		release_resource(giu_resource2);
		giu_base = NULL;
	}

	return 0;
}

static struct platform_device *giu_platform_device;

static struct platform_driver giu_device_driver = {
	.probe		= giu_probe,
	.remove		= __devexit_p(giu_remove),
@@ -712,30 +666,12 @@ static struct platform_driver giu_device_driver = {

static int __init vr41xx_giu_init(void)
{
	int retval;

	giu_platform_device = platform_device_alloc("GIU", -1);
	if (!giu_platform_device)
		return -ENOMEM;

	retval = platform_device_add(giu_platform_device);
	if (retval < 0) {
		platform_device_put(giu_platform_device);
		return retval;
	}

	retval = platform_driver_register(&giu_device_driver);
	if (retval < 0)
		platform_device_unregister(giu_platform_device);

	return retval;
	return platform_driver_register(&giu_device_driver);
}

static void __exit vr41xx_giu_exit(void)
{
	platform_driver_unregister(&giu_device_driver);

	platform_device_unregister(giu_platform_device);
}

module_init(vr41xx_giu_init);
+9 −0
Original line number Diff line number Diff line
@@ -20,6 +20,15 @@
#ifndef __NEC_VR41XX_GIU_H
#define __NEC_VR41XX_GIU_H

/*
 * NEC VR4100 series GIU platform device IDs.
 */
enum {
	GPIO_50PINS_PULLUPDOWN,
	GPIO_36PINS,
	GPIO_48PINS_EDGE_SELECT,
};

typedef enum {
	IRQ_TRIGGER_LEVEL,
	IRQ_TRIGGER_EDGE,