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

Commit 7db6c82a authored by Ben Dooks's avatar Ben Dooks
Browse files

[ARM] S3C: Move common GPIO code from plat-s3c24xx



Move the common parts of the GPIO code into plat-s3c
for use with both the s3c24xx and s3c64xx systems.

Signed-off-by: default avatarBen Dooks <ben-linux@fluff.org>
parent efd3a8eb
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -86,6 +86,10 @@ enum s3c_gpio_number {
#define S3C64XX_GPP(_nr)	(S3C64XX_GPIO_P_START + (_nr))
#define S3C64XX_GPQ(_nr)	(S3C64XX_GPIO_Q_START + (_nr))

/* the end of the S3C64XX specific gpios */
#define S3C64XX_GPIO_END	(S3C64XX_GPQ(S3C64XX_GPIO_Q_NR) + 1)
#define S3C_GPIO_END		S3C64XX_GPIO_END

/* define the number of gpios we need to the one after the GPQ() range */
#define ARCH_NR_GPIOS	(S3C64XX_GPQ(S3C64XX_GPIO_Q_NR) + 1)

+1 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@ obj-y += init.o
obj-y				+= time.o
obj-y				+= clock.o
obj-y				+= pwm-clock.o
obj-y				+= gpio.o

# devices

+128 −0
Original line number Diff line number Diff line
/* linux/arch/arm/plat-s3c/gpio.c
 *
 * Copyright 2008 Simtec Electronics
 *	Ben Dooks <ben@simtec.co.uk>
 *	http://armlinux.simtec.co.uk/
 *
 * S3C series GPIO core
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
*/

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/gpio.h>

#include <plat/gpio-core.h>

/* Default routines for controlling GPIO, based on the original S3C24XX
 * GPIO functions which deal with the case where each gpio bank of the
 * chip is as following:
 *
 * base + 0x00: Control register, 2 bits per gpio
 *	        gpio n: 2 bits starting at (2*n)
 *		00 = input, 01 = output, others mean special-function
 * base + 0x04: Data register, 1 bit per gpio
 *		bit n: data bit n
*/

static int s3c_gpiolib_input(struct gpio_chip *chip, unsigned offset)
{
	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
	void __iomem *base = ourchip->base;
	unsigned long flags;
	unsigned long con;

	local_irq_save(flags);

	con = __raw_readl(base + 0x00);
	con &= ~(3 << (offset * 2));

	__raw_writel(con, base + 0x00);

	local_irq_restore(flags);
	return 0;
}

static int s3c_gpiolib_output(struct gpio_chip *chip,
			      unsigned offset, int value)
{
	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
	void __iomem *base = ourchip->base;
	unsigned long flags;
	unsigned long dat;
	unsigned long con;

	local_irq_save(flags);

	dat = __raw_readl(base + 0x04);
	dat &= ~(1 << offset);
	if (value)
		dat |= 1 << offset;
	__raw_writel(dat, base + 0x04);

	con = __raw_readl(base + 0x00);
	con &= ~(3 << (offset * 2));
	con |= 1 << (offset * 2);

	__raw_writel(con, base + 0x00);
	__raw_writel(dat, base + 0x04);

	local_irq_restore(flags);
	return 0;
}

static void s3c_gpiolib_set(struct gpio_chip *chip,
			    unsigned offset, int value)
{
	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
	void __iomem *base = ourchip->base;
	unsigned long flags;
	unsigned long dat;

	local_irq_save(flags);

	dat = __raw_readl(base + 0x04);
	dat &= ~(1 << offset);
	if (value)
		dat |= 1 << offset;
	__raw_writel(dat, base + 0x04);

	local_irq_restore(flags);
}

static int s3c_gpiolib_get(struct gpio_chip *chip, unsigned offset)
{
	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
	unsigned long val;

	val = __raw_readl(ourchip->base + 0x04);
	val >>= offset;
	val &= 1;

	return val;
}

__init void s3c_gpiolib_add(struct s3c_gpio_chip *chip)
{
	struct gpio_chip *gc = &chip->chip;

	BUG_ON(!chip->base);
	BUG_ON(!gc->label);
	BUG_ON(!gc->ngpio);

	if (!gc->direction_input)
		gc->direction_input = s3c_gpiolib_input;
	if (!gc->direction_output)
		gc->direction_output = s3c_gpiolib_output;
	if (!gc->set)
		gc->set = s3c_gpiolib_set;
	if (!gc->get)
		gc->get = s3c_gpiolib_get;

	/* gpiochip_add() prints own failure message on error. */
	gpiochip_add(gc);
}
+49 −0
Original line number Diff line number Diff line
/* linux/arch/arm/plat-s3c/include/plat/gpio-core.h
 *
 * Copyright 2008 Simtec Electronics
 *	http://armlinux.simtec.co.uk/
 *	Ben Dooks <ben@simtec.co.uk>
 *
 * S3C Platform - GPIO core
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
*/

/* Define the core gpiolib support functions that the s3c platforms may
 * need to extend or change depending on the hardware and the s3c chip
 * selected at build or found at run time.
 *
 * These definitions are not intended for driver inclusion, there is
 * nothing here that should not live outside the platform and core
 * specific code.
*/

/**
 * struct s3c_gpio_chip - wrapper for specific implementation of gpio
 * @chip: The chip structure to be exported via gpiolib.
 * @base: The base pointer to the gpio configuration registers.
 *
 * This wrapper provides the necessary information for the Samsung
 * specific gpios being registered with gpiolib.
 */
struct s3c_gpio_chip {
	struct gpio_chip	chip;
	void __iomem		*base;
};

static inline struct s3c_gpio_chip *to_s3c_gpio(struct gpio_chip *gpc)
{
	return container_of(gpc, struct s3c_gpio_chip, chip);
}

/** s3c_gpiolib_add() - add the s3c specific version of a gpio_chip.
 * @chip: The chip to register
 *
 * This is a wrapper to gpiochip_add() that takes our specific gpio chip
 * information and makes the necessary alterations for the platform and
 * notes the information for use with the configuration systems and any
 * other parts of the system.
 */
extern void s3c_gpiolib_add(struct s3c_gpio_chip *chip);
+5 −118
Original line number Diff line number Diff line
@@ -19,104 +19,12 @@
#include <linux/io.h>
#include <linux/gpio.h>

#include <plat/gpio-core.h>
#include <mach/hardware.h>
#include <asm/irq.h>

#include <mach/regs-gpio.h>

struct s3c24xx_gpio_chip {
	struct gpio_chip	chip;
	void __iomem		*base;
};

static inline struct s3c24xx_gpio_chip *to_s3c_chip(struct gpio_chip *gpc)
{
	return container_of(gpc, struct s3c24xx_gpio_chip, chip);
}

/* these routines are exported for use by other parts of the platform
 * and system support, but are not intended to be used directly by the
 * drivers themsevles.
 */

static int s3c24xx_gpiolib_input(struct gpio_chip *chip, unsigned offset)
{
	struct s3c24xx_gpio_chip *ourchip = to_s3c_chip(chip);
	void __iomem *base = ourchip->base;
	unsigned long flags;
	unsigned long con;

	local_irq_save(flags);

	con = __raw_readl(base + 0x00);
	con &= ~(3 << (offset * 2));
	con |= (S3C2410_GPIO_OUTPUT & 0xf) << (offset * 2);

	__raw_writel(con, base + 0x00);

	local_irq_restore(flags);
	return 0;
}

static int s3c24xx_gpiolib_output(struct gpio_chip *chip,
				  unsigned offset, int value)
{
	struct s3c24xx_gpio_chip *ourchip = to_s3c_chip(chip);
	void __iomem *base = ourchip->base;
	unsigned long flags;
	unsigned long dat;
	unsigned long con;

	local_irq_save(flags);

	dat = __raw_readl(base + 0x04);
	dat &= ~(1 << offset);
	if (value)
		dat |= 1 << offset;
	__raw_writel(dat, base + 0x04);

	con = __raw_readl(base + 0x00);
	con &= ~(3 << (offset * 2));
	con |= (S3C2410_GPIO_OUTPUT & 0xf) << (offset * 2);

	__raw_writel(con, base + 0x00);
	__raw_writel(dat, base + 0x04);

	local_irq_restore(flags);
	return 0;
}

static void s3c24xx_gpiolib_set(struct gpio_chip *chip,
				unsigned offset, int value)
{
	struct s3c24xx_gpio_chip *ourchip = to_s3c_chip(chip);
	void __iomem *base = ourchip->base;
	unsigned long flags;
	unsigned long dat;

	local_irq_save(flags);

	dat = __raw_readl(base + 0x04);
	dat &= ~(1 << offset);
	if (value)
		dat |= 1 << offset;
	__raw_writel(dat, base + 0x04);

	local_irq_restore(flags);
}

static int s3c24xx_gpiolib_get(struct gpio_chip *chip, unsigned offset)
{
	struct s3c24xx_gpio_chip *ourchip = to_s3c_chip(chip);
	unsigned long val;

	val = __raw_readl(ourchip->base + 0x04);
	val >>= offset;
	val &= 1;

	return val;
}

static int s3c24xx_gpiolib_banka_input(struct gpio_chip *chip, unsigned offset)
{
	return -EINVAL;
@@ -125,7 +33,7 @@ static int s3c24xx_gpiolib_banka_input(struct gpio_chip *chip, unsigned offset)
static int s3c24xx_gpiolib_banka_output(struct gpio_chip *chip,
					unsigned offset, int value)
{
	struct s3c24xx_gpio_chip *ourchip = to_s3c_chip(chip);
	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
	void __iomem *base = ourchip->base;
	unsigned long flags;
	unsigned long dat;
@@ -151,7 +59,7 @@ static int s3c24xx_gpiolib_banka_output(struct gpio_chip *chip,
	return 0;
}

static struct s3c24xx_gpio_chip gpios[] = {
static struct s3c_gpio_chip gpios[] = {
	[0] = {
		.base	= S3C24XX_GPIO_BASE(S3C2410_GPA0),
		.chip	= {
@@ -219,34 +127,13 @@ static struct s3c24xx_gpio_chip gpios[] = {
	},
};

static __init void s3c24xx_gpiolib_add(struct s3c24xx_gpio_chip *chip)
{
	struct gpio_chip *gc = &chip->chip;

	BUG_ON(!chip->base);
	BUG_ON(!gc->label);
	BUG_ON(!gc->ngpio);

	if (!gc->direction_input)
		gc->direction_input = s3c24xx_gpiolib_input;
	if (!gc->direction_output)
		gc->direction_output = s3c24xx_gpiolib_output;
	if (!gc->set)
		gc->set = s3c24xx_gpiolib_set;
	if (!gc->get)
		gc->get = s3c24xx_gpiolib_get;

	/* gpiochip_add() prints own failure message on error. */
	gpiochip_add(gc);
}

static __init int s3c24xx_gpiolib_init(void)
{
	struct s3c24xx_gpio_chip *chip = gpios;
	struct s3c_gpio_chip *chip = gpios;
	int gpn;

	for (gpn = 0; gpn < ARRAY_SIZE(gpios); gpn++, chip++)
		s3c24xx_gpiolib_add(chip);
		s3c_gpiolib_add(chip);

	return 0;
}