summaryrefslogtreecommitdiff
path: root/cleopatre/linux-2.6.25.10-spc300/arch
diff options
context:
space:
mode:
authorsave2009-08-26 08:31:23 +0000
committersave2009-08-26 08:31:23 +0000
commit1a5638d81dd85334998ba17b6a5481b2b112ef74 (patch)
tree5ca9988a8e2e250b4e9c72394c913ed59e1b1b22 /cleopatre/linux-2.6.25.10-spc300/arch
parent272490c88233979bd259d7a11a5de462d3cf9bd3 (diff)
[CLEO][KERNEL]Added gpio interface for kernel part
- Forced using GENERIC_GPIO and LIBGPIO for our target - Corrected the ngpio field bug under libgpios library - Prepared gpio using with libgpio under init kernel part - Prepared menuconfig for spc300 gpios git-svn-id: svn+ssh://pessac/svn/cesar/trunk@5298 017c9cb6-072f-447c-8318-d5b54f68fe89
Diffstat (limited to 'cleopatre/linux-2.6.25.10-spc300/arch')
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/arch/arm/Kconfig2
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/board-arizona.c1
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300-devices.c153
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300-devices.h7
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300.c3
5 files changed, 151 insertions, 15 deletions
diff --git a/cleopatre/linux-2.6.25.10-spc300/arch/arm/Kconfig b/cleopatre/linux-2.6.25.10-spc300/arch/arm/Kconfig
index f5c01b744e..1340895469 100644
--- a/cleopatre/linux-2.6.25.10-spc300/arch/arm/Kconfig
+++ b/cleopatre/linux-2.6.25.10-spc300/arch/arm/Kconfig
@@ -215,6 +215,8 @@ config ARCH_SPC300
bool "SPiDCOM Technologies spc300 family"
select ARM_AMBA
select SPI_SPC300
+ select GENERIC_GPIO
+ select HAVE_GPIO_LIB
help
This enables support for SPiDCOM Technologies spc300 board.
diff --git a/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/board-arizona.c b/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/board-arizona.c
index 9a1d51627c..552ffa74bb 100644
--- a/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/board-arizona.c
+++ b/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/board-arizona.c
@@ -115,6 +115,7 @@ static void __init arizona_init(void)
spc300_add_device_spidevs(&flash_chip, &afe_chip);
spc300_add_device_spictrl();
spc300_add_device_ethernet();
+ spc300_add_device_gpio();
}
MACHINE_START(SPC300, "ARM SPC300 based board")
diff --git a/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300-devices.c b/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300-devices.c
index e6cfe78a06..fdb5376868 100644
--- a/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300-devices.c
+++ b/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300-devices.c
@@ -29,6 +29,7 @@
#include <asm/hardware.h>
#include <asm/io.h>
+#include <asm/gpio.h>
#include <asm/mach/arch.h>
#include <asm/arch/nvram.h>
@@ -200,10 +201,9 @@ static struct platform_device spc300_spictrl_device = {
/**
* GPIO Device Structure.
*/
-static struct spc300_gpio_config spc300_gpio_data = {
- .used = 0xFFFFFFFF, //by default all GPIOs are unusable
- .fixdir = 0xFFFFFFFF,
-};
+static char spc300_gpio_labels[MAX_INTERNAL_GPIOS][16];
+static struct gpio_chip spc300_gpio_chips[MAX_INTERNAL_GPIOS];
+#ifdef CONFIG_SPC300_GPIO_USER_MODE
static struct resource spc300_gpio_resource[] = {
[0] = {
.start = ARM_GPIO_BASE,
@@ -219,12 +219,10 @@ static struct resource spc300_gpio_resource[] = {
static struct platform_device spc300_gpio_device = {
.name = "spc300gpio",
.id = 0,
- .dev = {
- .platform_data = &spc300_gpio_data,
- },
.num_resources = ARRAY_SIZE(spc300_gpio_resource),
.resource = spc300_gpio_resource
};
+#endif
@@ -356,6 +354,123 @@ static struct platform_device spc300_pcm_device = {
};
+/**
+ * Set a gpio direction to input.
+ *
+ * \param chip gpio number chip.
+ * \param offset number offset for this chip (should be 0).
+ * \return error code.
+ */
+int spc300_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+ GPIO_SWPORTA_DDR_VA &= ~(1 << chip->base);
+ return (GPIO_SWPORTA_DDR_VA & (1<<chip->base)) ? -1 : 0;
+}
+/**
+ * Set a gpio direction to output.
+ *
+ * \param chip gpio number chip.
+ * \param offset number offset for this chip (should be 0).
+ * \param value initial value to set.
+ * \return error code.
+ */
+int spc300_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value)
+{
+ //Set initial value before setting direction
+ //to be sure that initial value is set when gpio is configured
+ //it's important for reset pin for example.
+ if(value)
+ GPIO_SWPORTA_DR_VA |= (1 << chip->base);
+ else
+ GPIO_SWPORTA_DR_VA &= ~(1 << chip->base);
+
+ GPIO_SWPORTA_DDR_VA |= (1 << chip->base);
+
+ //Check direction
+ if(!(GPIO_SWPORTA_DDR_VA & (1<<chip->base)))
+ return -1;
+ //check initial value
+ return ((GPIO_SWPORTA_DR_VA & (1 << chip->base)) > value) ? -1 : 0;
+}
+/**
+ * Get a gpio value.
+ *
+ * \param chip gpio number chip.
+ * \param offset number offset for this chip (should be 0).
+ * \return value of this gpio.
+ */
+int spc300_gpio_get_value(struct gpio_chip *chip, unsigned offset)
+{
+ return (GPIO_EXT_PORTA_VA & (1 << chip->base)) ? 1 : 0;
+}
+/**
+ * Set a gpio value.
+ *
+ * \param chip gpio number chip.
+ * \param offset number offset for this chip (should be 0).
+ * \param value value to set.
+ */
+void spc300_gpio_set_value(struct gpio_chip *chip, unsigned offset, int value)
+{
+ if(value)
+ GPIO_SWPORTA_DR_VA |= (1 << chip->base);
+ else
+ GPIO_SWPORTA_DR_VA &= ~(1 << chip->base);
+}
+
+/**
+ * Setup GPIO through libgpio.
+ *
+ * \param chip gpio chip structure.
+ * \param num gpio number.
+ */
+static void spc300_gpio_setup(struct gpio_chip *chip, int num)
+{
+ uint32_t gpio_config;
+
+ chip->can_sleep = 0;
+ chip->base = num;
+ chip->ngpio = 1;
+ chip->label = spc300_gpio_labels[num];
+ chip->get = NULL;
+ chip->set = NULL;
+ chip->direction_input = NULL;
+ chip->direction_output = NULL;
+
+ if(num < MIN_INTERNAL_GPIOS)
+ gpio_config = ((spc300_nvram.gpio_0_7_cfg >> (num*4)) & 0xF);
+ else
+ gpio_config = ((spc300_nvram.gpio_8_15_cfg >> ((num-MIN_INTERNAL_GPIOS)*4)) & 0xF);
+
+ //Check if gpio_config is ARM gpios
+ if(gpio_config == 0)
+ {
+ //check allowed direction
+ switch((spc300_nvram.gpio_allow_dir >> (num*2)) & 0x3)
+ {
+ case 3: //bi-directional
+ chip->get = &spc300_gpio_get_value;
+ chip->set = &spc300_gpio_set_value;
+ chip->direction_input = &spc300_gpio_direction_input;
+ chip->direction_output = &spc300_gpio_direction_output;
+ break;
+ case 2: //input
+ chip->get = &spc300_gpio_get_value;
+ chip->set = &spc300_gpio_set_value;
+ chip->direction_output = &spc300_gpio_direction_output;
+ break;
+ case 1: //output
+ chip->get = &spc300_gpio_get_value;
+ chip->direction_input = &spc300_gpio_direction_input;
+ break;
+ }
+ }
+
+ //Setup GPIO number
+ gpiochip_add(chip);
+}
+
+
/**
* Register UART 0 device.
@@ -440,9 +555,31 @@ void spc300_add_device_spictrl(void)
/**
* Register GPIO device.
*/
-void spc300_add_device_gpio(struct spc300_gpio_config *config)
+void spc300_add_device_gpio(void)
{
+ int i;
+
+ //TODO:use nvram defines
+
+ //Register allowed gpios through gpio_lib
+ for(i=0 ; i<MIN_INTERNAL_GPIOS ; i++)
+ {
+ spc300_gpio_setup(&spc300_gpio_chips[i], i);
+ }
+
+ /* SPC300 package 1 so nbgpios=MAX_INTERNAL_GPIOS */
+ if(((spc300_nvram.pkg_cfg & 0x000000F0)>>8) < 5)
+ {
+ for(i=MIN_INTERNAL_GPIOS ; i<MAX_INTERNAL_GPIOS ; i++)
+ {
+ spc300_gpio_setup(&spc300_gpio_chips[i], i);
+ }
+ }
+
+#ifdef CONFIG_SPC300_GPIO_USER_MODE
+ //Register gpio device driver for user_mode
platform_device_register(&spc300_gpio_device);
+#endif
}
/**
diff --git a/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300-devices.h b/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300-devices.h
index 4045179e20..ca8a8e257a 100644
--- a/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300-devices.h
+++ b/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300-devices.h
@@ -37,11 +37,6 @@ struct spc300_afe_spi_dev {
uint32_t spimode;
};
-struct spc300_gpio_config {
- uint32_t used;
- uint32_t fixdir;
-};
-
/**
* Register UART 0 device.
*/
@@ -60,7 +55,7 @@ void spc300_add_device_ethernet(void);
/**
* Register GPIO device.
*/
-void spc300_add_device_gpio(struct spc300_gpio_config *config);
+void spc300_add_device_gpio(void);
/**
* Register SPI Controller device.
diff --git a/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300.c b/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300.c
index 40622be73a..d6937e321f 100644
--- a/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300.c
+++ b/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300.c
@@ -69,7 +69,8 @@ static struct map_desc spc300_io_desc[] __initdata = {
{ IO_ADDRESS(ARM_ICTL_BASE) , __phys_to_pfn(ARM_ICTL_BASE) , SZ_1K , MT_DEVICE },
{ IO_ADDRESS(ARM_TIMER1_BASE) , __phys_to_pfn(ARM_TIMER1_BASE) , SZ_1K , MT_DEVICE },
{ IO_ADDRESS(ARM_UART1_BASE) , __phys_to_pfn(ARM_UART1_BASE) , SZ_1K , MT_DEVICE },
- { IO_ADDRESS(ARM_UART2_BASE) , __phys_to_pfn(ARM_UART2_BASE) , SZ_1K , MT_DEVICE }
+ { IO_ADDRESS(ARM_UART2_BASE) , __phys_to_pfn(ARM_UART2_BASE) , SZ_1K , MT_DEVICE },
+ { IO_ADDRESS(ARM_GPIO_BASE) , __phys_to_pfn(ARM_GPIO_BASE) , SZ_1K , MT_DEVICE }
};
static struct map_desc spc300_nvram_io_desc;
static struct map_desc spc300_plccode_io_desc;