diff options
author | Uwe Kleine-König <uwe@kleine-koenig.org> | 2013-02-13 09:43:35 +0100 |
---|---|---|
committer | Uwe Kleine-König <uwe@kleine-koenig.org> | 2013-02-13 09:43:35 +0100 |
commit | efb50d0291e1a12975ad60f868dc04b0fe095297 (patch) | |
tree | 50785d06650863d79de4ca30b7446a0dda97af97 | |
parent | b01df9c847571abd1e79c5db81b0109eb6bdeb3b (diff) | |
download | OSELAS.BSP-EnergyMicro-Gecko-efb50d0291e1a12975ad60f868dc04b0fe095297.tar.gz OSELAS.BSP-EnergyMicro-Gecko-efb50d0291e1a12975ad60f868dc04b0fe095297.tar.xz |
platform-energymicro-efm32gg-dk3750: update kernel
- implement gpio driver
- correct spelling of "Energy Micro"
- minor cleanups
14 files changed, 549 insertions, 59 deletions
diff --git a/kernelconfig-3.8-rc5 b/kernelconfig-3.8-rc5 index 4ff9aa5..47eddcd 100644 --- a/kernelconfig-3.8-rc5 +++ b/kernelconfig-3.8-rc5 @@ -4,6 +4,7 @@ # CONFIG_ARM=y CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y CONFIG_NO_IOPORT=y CONFIG_STACKTRACE_SUPPORT=y CONFIG_HAVE_LATENCYTOP_SUPPORT=y @@ -552,6 +553,7 @@ CONFIG_EEPROM_93CX6=y # # Texas Instruments shared transport line discipline # +# CONFIG_TI_ST is not set # # Altera FPGA firmware download module @@ -666,6 +668,7 @@ CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_TIMBERDALE is not set # CONFIG_SERIAL_ALTERA_JTAGUART is not set # CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_IFX6X60 is not set # CONFIG_SERIAL_XILINX_PS_UART is not set CONFIG_SERIAL_EFM32_UART=y CONFIG_SERIAL_EFM32_UART_CONSOLE=y @@ -688,6 +691,8 @@ CONFIG_SPI_MASTER=y # CONFIG_SPI_ALTERA is not set CONFIG_SPI_BITBANG=y CONFIG_SPI_EFM32=y +# CONFIG_SPI_GPIO is not set +# CONFIG_SPI_OC_TINY is not set # CONFIG_SPI_PXA2XX_PCI is not set # CONFIG_SPI_XILINX is not set # CONFIG_SPI_DESIGNWARE is not set @@ -718,6 +723,47 @@ CONFIG_SPI_EFM32=y # # CONFIG_PTP_1588_CLOCK_PCH is not set CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +CONFIG_OF_GPIO=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO drivers: +# +# CONFIG_GPIO_GENERIC_PLATFORM is not set +CONFIG_GPIO_EFM32=y +# CONFIG_GPIO_EM is not set +# CONFIG_GPIO_TS5500 is not set + +# +# I2C GPIO expanders: +# + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_GPIO_MC33880 is not set +# CONFIG_GPIO_74X164 is not set + +# +# AC97 GPIO expanders: +# + +# +# MODULbus GPIO expanders: +# + +# +# USB GPIO expanders: +# # CONFIG_W1 is not set # CONFIG_POWER_SUPPLY is not set # CONFIG_POWER_AVS is not set @@ -733,6 +779,7 @@ CONFIG_HWMON=y CONFIG_SENSORS_EFM32_ADC=y # CONFIG_SENSORS_F71805F is not set # CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_GPIO_FAN is not set # CONFIG_SENSORS_IT87 is not set # CONFIG_SENSORS_LM70 is not set # CONFIG_SENSORS_MAX1111 is not set @@ -740,6 +787,7 @@ CONFIG_SENSORS_EFM32_ADC=y # CONFIG_SENSORS_NTC_THERMISTOR is not set # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_SHT15 is not set # CONFIG_SENSORS_SMSC47M1 is not set # CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_SCH56XX_COMMON is not set @@ -767,8 +815,11 @@ CONFIG_BCMA_POSSIBLE=y # CONFIG_MFD_CORE=y # CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set # CONFIG_MFD_TI_AM335X_TSCADC is not set +# CONFIG_HTC_EGPIO is not set # CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TPS65912_SPI is not set # CONFIG_MFD_STMPE is not set # CONFIG_MFD_TMIO is not set # CONFIG_MFD_T7L66XB is not set @@ -991,6 +1042,11 @@ CONFIG_HAVE_ARCH_KGDB=y CONFIG_ARM_UNWIND=y # CONFIG_DEBUG_USER is not set # CONFIG_DEBUG_LL is not set +# CONFIG_DEBUG_EFM32_USART1 is not set +# CONFIG_DEBUG_EFM32_UART1 is not set +# CONFIG_DEBUG_LL_UART_NONE is not set +# CONFIG_DEBUG_ICEDCC is not set +# CONFIG_DEBUG_SEMIHOSTING is not set CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" # diff --git a/patches/linux-3.8-rc5/0009-Cortex-M3-Add-base-support-for-Cortex-M3.patch b/patches/linux-3.8-rc5/0009-Cortex-M3-Add-base-support-for-Cortex-M3.patch index edd02e3..4af73cc 100644 --- a/patches/linux-3.8-rc5/0009-Cortex-M3-Add-base-support-for-Cortex-M3.patch +++ b/patches/linux-3.8-rc5/0009-Cortex-M3-Add-base-support-for-Cortex-M3.patch @@ -27,6 +27,7 @@ id:1358413196-5609-3-git-send-email-u.kleine-koenig@pengutronix.de: - rebase - use more named constants - add comment about setmode being empty + - add more (yet unused) v7m register defines --- arch/arm/include/asm/assembler.h | 17 +++- arch/arm/include/asm/cputype.h | 12 ++- @@ -37,7 +38,7 @@ id:1358413196-5609-3-git-send-email-u.kleine-koenig@pengutronix.de: arch/arm/include/asm/processor.h | 7 ++ arch/arm/include/asm/ptrace.h | 8 ++ arch/arm/include/asm/system_info.h | 1 + - arch/arm/include/asm/v7m.h | 11 +++ + arch/arm/include/asm/v7m.h | 14 ++++ arch/arm/include/uapi/asm/ptrace.h | 36 ++++++-- arch/arm/kernel/asm-offsets.c | 3 + arch/arm/kernel/head-nommu.S | 10 ++- @@ -45,7 +46,7 @@ id:1358413196-5609-3-git-send-email-u.kleine-koenig@pengutronix.de: arch/arm/kernel/traps.c | 2 + arch/arm/mm/nommu.c | 2 + arch/arm/mm/proc-v7m.S | 162 ++++++++++++++++++++++++++++++++++++ - 17 files changed, 331 insertions(+), 21 deletions(-) + 17 files changed, 334 insertions(+), 21 deletions(-) create mode 100644 arch/arm/include/asm/v7m.h create mode 100644 arch/arm/mm/proc-v7m.S @@ -322,16 +323,19 @@ index dfd386d..720ea03 100644 diff --git a/arch/arm/include/asm/v7m.h b/arch/arm/include/asm/v7m.h new file mode 100644 -index 0000000..350c18f +index 0000000..94b77ca --- /dev/null +++ b/arch/arm/include/asm/v7m.h -@@ -0,0 +1,11 @@ +@@ -0,0 +1,14 @@ +/* + * Common defines for v7m cpus + */ +#define V7M_SCS_CPUID IOMEM(0xe000ed00) +#define V7M_SCS_VTOR IOMEM(0xe000ed08) + ++#define V7M_SCS_SCR IOMEM(0xe000ed10) ++#define V7M_SCS_SCR_SLEEPDEEP (1 << 2) ++ +#define V7M_SCS_CCR IOMEM(0xe000ed14) +#define V7M_SCS_CCR_STKALIGN (1 << 9) + diff --git a/patches/linux-3.8-rc5/0015-ARM-new-platform-for-Energy-Micro-s-EFM32-Cortex-M3-.patch b/patches/linux-3.8-rc5/0015-ARM-new-platform-for-Energy-Micro-s-EFM32-Cortex-M3-.patch index 7cbce6e..15a4318 100644 --- a/patches/linux-3.8-rc5/0015-ARM-new-platform-for-Energy-Micro-s-EFM32-Cortex-M3-.patch +++ b/patches/linux-3.8-rc5/0015-ARM-new-platform-for-Energy-Micro-s-EFM32-Cortex-M3-.patch @@ -10,7 +10,7 @@ Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> arch/arm/Kconfig | 13 +- arch/arm/Kconfig.debug | 16 +++ arch/arm/Makefile | 1 + - arch/arm/boot/dts/efm32gg-dk3750.dts | 76 +++++++++++ + arch/arm/boot/dts/efm32gg-dk3750.dts | 87 ++++++++++++ arch/arm/mach-efm32/Makefile | 3 + arch/arm/mach-efm32/Makefile.boot | 1 + arch/arm/mach-efm32/clk.c | 38 ++++++ @@ -24,7 +24,7 @@ Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> arch/arm/mach-efm32/include/mach/system.h | 18 +++ arch/arm/mach-efm32/include/mach/timex.h | 7 + arch/arm/mach-efm32/time.c | 170 ++++++++++++++++++++++++ - 17 files changed, 469 insertions(+), 1 deletion(-) + 17 files changed, 480 insertions(+), 1 deletion(-) create mode 100644 arch/arm/boot/dts/efm32gg-dk3750.dts create mode 100644 arch/arm/mach-efm32/Makefile create mode 100644 arch/arm/mach-efm32/Makefile.boot @@ -41,7 +41,7 @@ Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> create mode 100644 arch/arm/mach-efm32/time.c diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig -index 9d09a41..029f074 100644 +index 9d09a41..cb2a9f7 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -418,6 +418,17 @@ config ARCH_EBSA110 @@ -49,7 +49,7 @@ index 9d09a41..029f074 100644 parallel port. +config ARCH_EFM32 -+ bool "EnergyMicro Cortex M3 Platform" ++ bool "Energy Micro Cortex M3 Platform" + depends on !MMU + select ARM_NVIC + select CLKSRC_MMIO @@ -112,10 +112,10 @@ index 69a5955..374e25a 100644 machine-$(CONFIG_ARCH_H720X) += h720x diff --git a/arch/arm/boot/dts/efm32gg-dk3750.dts b/arch/arm/boot/dts/efm32gg-dk3750.dts new file mode 100644 -index 0000000..22e058f +index 0000000..19fcc80 --- /dev/null +++ b/arch/arm/boot/dts/efm32gg-dk3750.dts -@@ -0,0 +1,76 @@ +@@ -0,0 +1,87 @@ +/dts-v1/; +/include/ "skeleton.dtsi" + @@ -156,6 +156,17 @@ index 0000000..22e058f + status = "ok"; + }; + ++ gpio: gpio@0x40006000 { ++ compatible = "efm32,gpio"; ++ reg = <0x40006000 0x1000>; ++ interrupts = <1 11>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ status = "ok"; ++ }; ++ + spi@0x4000c400 { /* USART1 */ + #address-cells = <1>; + #size-cells = <0>; @@ -185,10 +196,10 @@ index 0000000..22e058f + boardfpga: boardfpga@0x80000000 { + compatible = "efm32board"; + reg = <0x80000000 0x400>; -+ /* this is a lie, gpio_even = 1 */ -+ interrupts = <1>; ++ irq-gpios = <&gpio 64 1>; + interrupt-controller; + #interrupt-cells = <1>; ++ status = "ok"; + }; + }; +}; diff --git a/patches/linux-3.8-rc5/0016-ARM-efm32-add-support-for-non-dt-builds-and-add-more.patch b/patches/linux-3.8-rc5/0016-ARM-efm32-add-support-for-non-dt-builds-and-add-more.patch index a947a64..98ea864 100644 --- a/patches/linux-3.8-rc5/0016-ARM-efm32-add-support-for-non-dt-builds-and-add-more.patch +++ b/patches/linux-3.8-rc5/0016-ARM-efm32-add-support-for-non-dt-builds-and-add-more.patch @@ -40,7 +40,7 @@ Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> create mode 100644 arch/arm/mach-efm32/machines/efm32gg_dk3750.c diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig -index 029f074..46a8762 100644 +index cb2a9f7..3e764dc 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1041,6 +1041,8 @@ source "arch/arm/mach-davinci/Kconfig" diff --git a/patches/linux-3.8-rc5/0017-gpio-new-driver-for-Energy-Micro-s-GPIO-component.patch b/patches/linux-3.8-rc5/0017-gpio-new-driver-for-Energy-Micro-s-GPIO-component.patch new file mode 100644 index 0000000..a473a91 --- /dev/null +++ b/patches/linux-3.8-rc5/0017-gpio-new-driver-for-Energy-Micro-s-GPIO-component.patch @@ -0,0 +1,386 @@ +From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= <u.kleine-koenig@pengutronix.de> +Date: Tue, 12 Feb 2013 23:31:27 +0100 +Subject: [PATCH] gpio: new driver for Energy Micro's GPIO component + +--- + arch/arm/Kconfig | 1 + + drivers/gpio/Kconfig | 4 + + drivers/gpio/Makefile | 1 + + drivers/gpio/gpio-efm32.c | 329 +++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 335 insertions(+) + create mode 100644 drivers/gpio/gpio-efm32.c + +diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig +index 3e764dc..7833c0a 100644 +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -421,6 +421,7 @@ config ARCH_EBSA110 + config ARCH_EFM32 + bool "Energy Micro Cortex M3 Platform" + depends on !MMU ++ select ARCH_REQUIRE_GPIOLIB + select ARM_NVIC + select CLKSRC_MMIO + select CPU_V7M +diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig +index 682de75..4712e1c 100644 +--- a/drivers/gpio/Kconfig ++++ b/drivers/gpio/Kconfig +@@ -122,6 +122,10 @@ config GPIO_IT8761E + help + Say yes here to support GPIO functionality of IT8761E super I/O chip. + ++config GPIO_EFM32 ++ tristate "Energy Micro EFM32 GPIO support" ++ depends on ARCH_EFM32 ++ + config GPIO_EM + tristate "Emma Mobile GPIO" + depends on ARM +diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile +index c5aebd0..fc53fd5 100644 +--- a/drivers/gpio/Makefile ++++ b/drivers/gpio/Makefile +@@ -22,6 +22,7 @@ obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o + obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o + obj-$(CONFIG_GPIO_DA9055) += gpio-da9055.o + obj-$(CONFIG_ARCH_DAVINCI) += gpio-davinci.o ++obj-$(CONFIG_GPIO_EFM32) += gpio-efm32.o + obj-$(CONFIG_GPIO_EM) += gpio-em.o + obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o + obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o +diff --git a/drivers/gpio/gpio-efm32.c b/drivers/gpio/gpio-efm32.c +new file mode 100644 +index 0000000..648a154 +--- /dev/null ++++ b/drivers/gpio/gpio-efm32.c +@@ -0,0 +1,329 @@ ++#include <linux/platform_device.h> ++#include <linux/device.h> ++#include <linux/of.h> ++#include <linux/of_device.h> ++#include <linux/of_address.h> ++#include <linux/irqdomain.h> ++#include <linux/interrupt.h> ++#include <linux/gfp.h> ++#include <linux/module.h> ++#include <linux/irq.h> ++ ++#include <asm/gpio.h> ++#include <asm/io.h> ++ ++#define DRIVER_NAME "efm32-gpio" ++ ++#define GPIO_Px_MODEL(p) (0x024 * (p) + 0x004) ++#define GPIO_Px_MODEH(p) (0x024 * (p) + 0x008) ++#define GPIO_Px_DOUT(p) (0x024 * (p) + 0x00c) ++#define GPIO_Px_DOUTSET(p) (0x024 * (p) + 0x010) ++#define GPIO_Px_DOUTCLR(p) (0x024 * (p) + 0x014) ++#define GPIO_Px_DIN(p) (0x024 * (p) + 0x01c) ++#define GPIO_EXTIPSELL 0x100 ++#define GPIO_EXTIPSELH 0x104 ++#define GPIO_IEN 0x110 ++#define GPIO_IF 0x114 ++#define GPIO_IFC 0x11c ++ ++struct efm32_gpio_ddata { ++ void __iomem *base; ++ spinlock_t lock; ++ unsigned int irq_even, irq_odd; ++ struct irq_domain *irq_domain; ++ struct gpio_chip chip; ++ unsigned assigned_irqpins; ++}; ++ ++#define to_ddata(chip) container_of(chip, struct efm32_gpio_ddata, chip) ++ ++static unsigned efm32_gpio_get_mode(struct efm32_gpio_ddata *ddata, ++ unsigned pin, unsigned port) ++{ ++ return (readl(ddata->base + (pin < 8 ? GPIO_Px_MODEL(port) : GPIO_Px_MODEH(port))) >> (4 * (pin & 7))) & 0xf; ++ ++} ++static int efm32_gpio_direction_input(struct gpio_chip *chip, unsigned offset) ++{ ++ struct efm32_gpio_ddata *ddata = to_ddata(chip); ++ unsigned pin = offset % 16; ++ unsigned port = offset / 16; ++ unsigned mode = efm32_gpio_get_mode(ddata, pin, port); ++ ++ /* ++ * XXX: don't reconfigure, needs to be resolved in combination with a ++ * pinmux driver ++ */ ++ if (mode > 0 && mode < 4) ++ return 0; ++ else ++ return -EIO; ++} ++ ++static int efm32_gpio_get(struct gpio_chip *chip, unsigned offset) ++{ ++ struct efm32_gpio_ddata *ddata = to_ddata(chip); ++ unsigned pin = offset % 16; ++ unsigned port = offset / 16; ++ ++ /* XXX use bitband to simplify? */ ++ return readl(ddata->base + GPIO_Px_DIN(port)) & (1 << pin); ++} ++ ++static int efm32_gpio_direction_output(struct gpio_chip *chip, ++ unsigned offset, int value) ++{ ++ struct efm32_gpio_ddata *ddata = to_ddata(chip); ++ unsigned pin = offset % 16; ++ unsigned port = offset / 16; ++ unsigned mode = efm32_gpio_get_mode(ddata, pin, port); ++ ++ /* ++ * XXX: don't reconfigure, needs to be resolved in combination with a ++ * pinmux driver ++ */ ++ if (mode >= 4) ++ return 0; ++ else ++ return -EIO; ++} ++ ++static void efm32_gpio_set(struct gpio_chip *chip, ++ unsigned offset, int value) ++{ ++ struct efm32_gpio_ddata *ddata = to_ddata(chip); ++ unsigned pin = offset % 16; ++ unsigned port = offset / 16; ++ ++ writel(1 << pin, ddata->base + ++ (value ? GPIO_Px_DOUTSET(port) : GPIO_Px_DOUTCLR(port))); ++} ++ ++static int efm32_gpio_to_irq(struct gpio_chip *chip, unsigned offset) ++{ ++ struct efm32_gpio_ddata *ddata = to_ddata(chip); ++ unsigned pin = offset % 16; ++ unsigned port = offset / 16; ++ unsigned extipsel_offset = pin < 8 ? GPIO_EXTIPSELL : GPIO_EXTIPSELH; ++ unsigned extipsel; ++ unsigned extipsel_shift = (pin % 8) * 4; ++ ++ spin_lock(&ddata->lock); ++ ++ extipsel = readl(ddata->base + extipsel_offset); ++ ++ if (ddata->assigned_irqpins & (1 << pin)) { ++ if (((extipsel >> extipsel_shift) & 0x7) != port) { ++ spin_unlock(&ddata->lock); ++ return -EBUSY; ++ } ++ } ++ ++ extipsel &= ~(0x7 << extipsel_shift); ++ extipsel |= port << extipsel_shift; ++ ddata->assigned_irqpins |= 1 << pin; ++ writel(extipsel, ddata->base + extipsel_offset); ++ ++ spin_unlock(&ddata->lock); ++ ++ return irq_create_mapping(ddata->irq_domain, offset % 16); ++} ++ ++static irqreturn_t efm32_gpio_handler(struct efm32_gpio_ddata *ddata, unsigned mask) ++{ ++ unsigned flag, init_flag; ++ irqreturn_t ret = IRQ_NONE; ++ ++ init_flag = flag = readl(ddata->base + GPIO_IF) & mask; ++ ++ while (flag) { ++ int line = __fls(flag); ++ ++ writel(1 << line, ddata->base + GPIO_IFC); ++ if (generic_handle_irq(irq_create_mapping(ddata->irq_domain, line))) ++ ret = IRQ_HANDLED; ++ ++ flag &= ~(1 << line); ++ } ++ return ret; ++} ++ ++static irqreturn_t efm32_gpio_handler_even(int irq, void *data) ++{ ++ struct efm32_gpio_ddata *ddata = data; ++ return efm32_gpio_handler(ddata, 0x55555555U); ++} ++ ++static irqreturn_t efm32_gpio_handler_odd(int irq, void *data) ++{ ++ struct efm32_gpio_ddata *ddata = data; ++ return efm32_gpio_handler(ddata, 0xaaaaaaaaU); ++} ++ ++static void efm32_gpio_irq_ack(struct irq_data *data) ++{ ++ struct efm32_gpio_ddata *ddata = irq_get_chip_data(data->irq); ++ writel(1 << data->hwirq, ddata->base + GPIO_IFC); ++} ++ ++static void efm32_gpio_irq_mask(struct irq_data *data) ++{ ++ struct efm32_gpio_ddata *ddata = irq_get_chip_data(data->irq); ++ unsigned ien; ++ ++ spin_lock(&ddata->lock); ++ ien = readl(ddata->base + GPIO_IEN); ++ ien &= ~(1 << data->hwirq); ++ writel(ien, ddata->base + GPIO_IEN); ++ spin_unlock(&ddata->lock); ++} ++ ++static void efm32_gpio_irq_unmask(struct irq_data *data) ++{ ++ struct efm32_gpio_ddata *ddata = irq_get_chip_data(data->irq); ++ unsigned ien; ++ ++ spin_lock(&ddata->lock); ++ ien = readl(ddata->base + GPIO_IEN); ++ ien |= 1 << data->hwirq; ++ writel(ien, ddata->base + GPIO_IEN); ++ spin_unlock(&ddata->lock); ++} ++ ++static struct irq_chip efm32_gpio_irqchip = { ++ .irq_ack = efm32_gpio_irq_ack, ++ .irq_mask = efm32_gpio_irq_mask, ++ .irq_unmask = efm32_gpio_irq_unmask, ++}; ++ ++static int efm32_gpio_irq_map(struct irq_domain *d, unsigned int virq, ++ irq_hw_number_t hw) ++{ ++ struct efm32_gpio_ddata *ddata = d->host_data; ++ ++ irq_set_chip_data(virq, ddata); ++ irq_set_chip_and_handler(virq, &efm32_gpio_irqchip, handle_edge_irq); ++ ++ set_irq_flags(virq, IRQF_VALID | IRQF_PROBE); ++ ++ return 0; ++} ++ ++static const struct irq_domain_ops efm32_gpio_irq_domain_ops = { ++ .map = efm32_gpio_irq_map, ++}; ++ ++static int efm32_gpio_probe(struct platform_device *pdev) ++{ ++ struct efm32_gpio_ddata *ddata; ++ struct resource *res; ++ int ret = -ENOMEM; ++ int irq_even, irq_odd; ++ ++ ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL); ++ if (!ddata) { ++ dev_err(&pdev->dev, "cannot allocate driver data"); ++ return -ENOMEM; ++ } ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ dev_err(&pdev->dev, "can't get device resources\n"); ++ return -ENOENT; ++ } ++ ++ irq_even = platform_get_irq(pdev, 0); ++ irq_odd = platform_get_irq(pdev, 1); ++ if (irq_even <= 0 || irq_odd <= 0) { ++ dev_err(&pdev->dev, "can't get irq numbers (%d, %d)\n", ++ irq_even, irq_odd); ++ return -ENOENT; ++ } ++ ddata->irq_even = irq_even; ++ ddata->irq_odd = irq_odd; ++ ++ ddata->base = devm_request_and_ioremap(&pdev->dev, res); ++ if (!ddata->base) { ++ dev_err(&pdev->dev, ++ "cannot request and ioremap register set\n"); ++ return -EADDRNOTAVAIL; ++ } ++ ++ spin_lock_init(&ddata->lock); ++ ++ /* disable and clear irqs */ ++ writel(0, ddata->base + GPIO_IEN); ++ writel(0xffff, ddata->base + GPIO_IFC); ++ ++ ddata->irq_domain = irq_domain_add_linear(pdev->dev.of_node, ++ 16, &efm32_gpio_irq_domain_ops, ddata); ++ if (!ddata->irq_domain) { ++ dev_err(&pdev->dev, "failed to add irq_domain\n"); ++ goto err_add_irq_domain; ++ } ++ ++ ddata->chip.label = DRIVER_NAME; ++ ddata->chip.dev = &pdev->dev; ++ ddata->chip.owner = THIS_MODULE; ++ ++ //ddata->chip.get_direction ++ ddata->chip.direction_input = efm32_gpio_direction_input; ++ ddata->chip.get = efm32_gpio_get; ++ ddata->chip.direction_output = efm32_gpio_direction_output; ++ ddata->chip.set = efm32_gpio_set; ++ ddata->chip.to_irq = efm32_gpio_to_irq; ++ ddata->chip.base = -1; ++ ddata->chip.ngpio = 96; ++ ddata->chip.can_sleep = 0; ++ ++ ret = request_irq(ddata->irq_even, efm32_gpio_handler_even, ++ 0, DRIVER_NAME, ddata); ++ if (ret) ++ goto err_request_even_irq; ++ ++ ret = request_irq(ddata->irq_odd, efm32_gpio_handler_odd, ++ 0, DRIVER_NAME, ddata); ++ if (ret) ++ goto err_request_odd_irq; ++ ++ ret = gpiochip_add(&ddata->chip); ++ if (ret) { ++ free_irq(ddata->irq_odd, ddata); ++err_request_odd_irq: ++ ++ free_irq(ddata->irq_even, ddata); ++err_request_even_irq: ++ ++ irq_domain_remove(ddata->irq_domain); ++ } ++ ++err_add_irq_domain: ++ return ret; ++} ++ ++static const struct of_device_id efm32_gpio_dt_ids[] = { ++ { ++ .compatible = "efm32,gpio", ++ }, { ++ /* sentinel */ ++ } ++}; ++MODULE_DEVICE_TABLE(of, efm32_gpio_dt_ids); ++ ++static struct platform_driver efm32_gpio_driver = { ++ .probe = efm32_gpio_probe, ++ ++ .driver = { ++ .name = DRIVER_NAME, ++ .owner = THIS_MODULE, ++ .of_match_table = efm32_gpio_dt_ids, ++ }, ++}; ++ ++static int __init efm32_gpio_init(void) ++{ ++ return platform_driver_register(&efm32_gpio_driver); ++} ++postcore_initcall(efm32_gpio_init); ++ ++MODULE_LICENSE("GPL v2"); diff --git a/patches/linux-3.8-rc5/0017-efm-board-controller-driver.patch b/patches/linux-3.8-rc5/0018-efm-board-controller-driver.patch index b2b784d..ab4f929 100644 --- a/patches/linux-3.8-rc5/0017-efm-board-controller-driver.patch +++ b/patches/linux-3.8-rc5/0018-efm-board-controller-driver.patch @@ -3,10 +3,10 @@ Date: Thu, 7 Feb 2013 09:45:30 +0100 Subject: [PATCH] efm board controller driver --- - drivers/mfd/Kconfig | 4 ++ + drivers/mfd/Kconfig | 4 + drivers/mfd/Makefile | 1 + - drivers/mfd/efm32board.c | 166 ++++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 171 insertions(+) + drivers/mfd/efm32board.c | 192 ++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 197 insertions(+) create mode 100644 drivers/mfd/efm32board.c diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig @@ -35,14 +35,16 @@ index 8b977f8..cb0556f 100644 +obj-$(CONFIG_MFD_EFM32BOARD) += efm32board.o diff --git a/drivers/mfd/efm32board.c b/drivers/mfd/efm32board.c new file mode 100644 -index 0000000..1e1cf35 +index 0000000..fc87ac2 --- /dev/null +++ b/drivers/mfd/efm32board.c -@@ -0,0 +1,166 @@ +@@ -0,0 +1,192 @@ +#include <linux/platform_device.h> +#include <linux/irq.h> ++#include <linux/interrupt.h> +#include <linux/irqdomain.h> +#include <linux/export.h> ++#include <linux/of_gpio.h> +#include <asm/io.h> + +#define DRIVER_NAME "efm32board" @@ -63,7 +65,7 @@ index 0000000..1e1cf35 + struct efm32board_ddata *ddata = irq_get_chip_data(data->irq); + unsigned short val; + -+ /* XXX: lock */ ++ /* XXX: locking */ + val = readw(ddata->base + INTFLAG); + val &= ~(1 << data->hwirq); + writew(val, ddata->base + INTFLAG); @@ -74,10 +76,12 @@ index 0000000..1e1cf35 + struct efm32board_ddata *ddata = irq_get_chip_data(data->irq); + unsigned short val; + -+ /* XXX: lock */ -+ val = readw(ddata->base + INTEN); -+ val &= ~(1 << data->hwirq); -+ writew(val, ddata->base + INTEN); ++ if (data->hwirq != 2) { ++ /* XXX: locking */ ++ val = readw(ddata->base + INTEN); ++ val &= ~(1 << data->hwirq); ++ writew(val, ddata->base + INTEN); ++ } +} + +static void efm32board_irq_unmask(struct irq_data *data) @@ -85,19 +89,17 @@ index 0000000..1e1cf35 + struct efm32board_ddata *ddata = irq_get_chip_data(data->irq); + unsigned short val; + -+ /* XXX: lock */ ++ /* XXX: locking */ + val = readw(ddata->base + INTEN); + val |= 1 << data->hwirq; + writew(val, ddata->base + INTEN); +} + -+static void efm32board_handler(unsigned int irq, struct irq_desc *desc) ++static irqreturn_t efm32board_handler(unsigned int irq, void *data) +{ + unsigned short val; -+ struct efm32board_ddata *ddata = irq_get_handler_data(irq); -+ -+ /* ack gpio irq. XXX: this should go into a gpio driver */ -+ writel(1, (void __iomem *)0x4000611c); ++ struct efm32board_ddata *ddata = data; ++ irqreturn_t ret = IRQ_NONE; + + val = readw(ddata->base + INTFLAG); + /* ack BC irq */ @@ -106,9 +108,11 @@ index 0000000..1e1cf35 + while (val) { + int line = __fls(val); + -+ generic_handle_irq(irq_create_mapping(ddata->domain, line)); ++ if (!generic_handle_irq(irq_create_mapping(ddata->domain, line))) ++ ret = IRQ_HANDLED; + val &= ~(1 << line); + } ++ return ret; +} + +int efm32board_irqdomain_map(struct irq_domain *d, unsigned int virq, @@ -132,7 +136,7 @@ index 0000000..1e1cf35 +static int efm32board_probe(struct platform_device *pdev) +{ + struct resource *res; -+ int irq; ++ int irq, gpio, ret; + struct efm32board_ddata *ddata; + unsigned short val; + @@ -148,10 +152,28 @@ index 0000000..1e1cf35 + return -ENOENT; + } + -+ irq = platform_get_irq(pdev, 0); ++ gpio = of_get_named_gpio_flags(pdev->dev.of_node, "irq-gpios", 0, NULL); ++ if (gpio < 0) { ++ dev_err(&pdev->dev, "can't get irq gpio\n"); ++ return gpio; ++ } ++ ++ ret = gpio_request(gpio, DRIVER_NAME); ++ if (ret) { ++ dev_err(&pdev->dev, "cannot request irq gpio\n"); ++ return ret; ++ } ++ ++ ret = gpio_direction_input(gpio); ++ if (ret) { ++ dev_err(&pdev->dev, "cannot configure irq gpio as input\n"); ++ return ret; ++ } ++ ++ irq = gpio_to_irq(gpio); + if (irq <= 0) { + dev_err(&pdev->dev, "can't get irq number\n"); -+ return -ENOENT; ++ return irq < 0 ? irq : -ENOENT; + } + ddata->irq = irq; + @@ -179,16 +201,20 @@ index 0000000..1e1cf35 + ddata->chip.irq_mask = efm32board_irq_mask; + ddata->chip.irq_unmask = efm32board_irq_unmask; + -+ irq_set_handler_data(irq, ddata); -+ irq_set_chained_handler(irq, efm32board_handler); ++ ret = request_irq(irq, efm32board_handler, 0, DRIVER_NAME, ddata); ++ if (ret) ++ goto err_request_irq; + + ddata->domain = irq_domain_add_simple(pdev->dev.of_node, 5, 0, + &efm32board_irqdomain_ops, ddata); + if (!ddata->domain) { ++ ret = -ENOMEM; + dev_err(&pdev->dev, "cannot create irq domain\n"); -+ return -ENOMEM; ++ ++ free_irq(irq, ddata); + } -+ return 0; ++err_request_irq: ++ return ret; +} + +static const struct of_device_id efm32board_dt_ids[] = { diff --git a/patches/linux-3.8-rc5/0018-ARM-v7m-add-trivial-suspend-support.patch b/patches/linux-3.8-rc5/0019-ARM-v7m-add-trivial-suspend-support.patch index deb16a9..fb1236b 100644 --- a/patches/linux-3.8-rc5/0018-ARM-v7m-add-trivial-suspend-support.patch +++ b/patches/linux-3.8-rc5/0019-ARM-v7m-add-trivial-suspend-support.patch @@ -13,10 +13,10 @@ Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig -index 46a8762..09eb7f5 100644 +index 7833c0a..2ef2bf1 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig -@@ -2315,7 +2315,7 @@ source "kernel/power/Kconfig" +@@ -2316,7 +2316,7 @@ source "kernel/power/Kconfig" config ARCH_SUSPEND_POSSIBLE depends on !ARCH_S5PC100 depends on CPU_ARM920T || CPU_ARM926T || CPU_SA1100 || \ diff --git a/patches/linux-3.8-rc5/0019-ARM-efm32-add-trivial-suspend-support.patch b/patches/linux-3.8-rc5/0020-ARM-efm32-add-trivial-suspend-support.patch index 7f2ba23..82715f7 100644 --- a/patches/linux-3.8-rc5/0019-ARM-efm32-add-trivial-suspend-support.patch +++ b/patches/linux-3.8-rc5/0020-ARM-efm32-add-trivial-suspend-support.patch @@ -8,8 +8,8 @@ Content-Transfer-Encoding: 8bit Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> --- arch/arm/mach-efm32/Makefile | 1 + - arch/arm/mach-efm32/pm.c | 40 ++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 41 insertions(+) + arch/arm/mach-efm32/pm.c | 46 ++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 47 insertions(+) create mode 100644 arch/arm/mach-efm32/pm.c diff --git a/arch/arm/mach-efm32/Makefile b/arch/arm/mach-efm32/Makefile @@ -25,30 +25,36 @@ index ba4d6ee..0f593e7 100644 obj-$(CONFIG_EFM32_NONDT) += machines/ devices/ diff --git a/arch/arm/mach-efm32/pm.c b/arch/arm/mach-efm32/pm.c new file mode 100644 -index 0000000..de03941 +index 0000000..4c80906 --- /dev/null +++ b/arch/arm/mach-efm32/pm.c -@@ -0,0 +1,40 @@ +@@ -0,0 +1,46 @@ +#include <linux/init.h> +#include <linux/suspend.h> + +#include <asm/io.h> ++#include <asm/v7m.h> + +#include "cmu.h" + -+static inline void v7m_write_scr(u32 val) -+{ -+ writel(val, (u32 __iomem *)0xe000ed10); -+} -+ +static int efm32_suspend_enter(suspend_state_t state) +{ + u32 cmu_status = readl(CMU_STATUS); + -+ v7m_write_scr(0x4); ++ /* ++ * setting SLEEPDEEP makes the efm32 enter EM2 or EM3 (iff both ++ * LFACLK and LFBCLK are off). ++ */ ++ writel(V7M_SCS_SCR_SLEEPDEEP, V7M_SCS_SCR); ++ + cpu_do_idle(); -+ v7m_write_scr(0x0); + ++ writel(0, V7M_SCS_SCR); ++ ++ /* ++ * deep sleep disables the HF oscilator, reenable it if it was on ++ * before. ++ */ + if (cmu_status & CMU_STATUS_HFXOSEL) { + writel(CMU_OSCENCMD_HFXOEN, CMU_OSCENCMD); + writel(CMU_CMD_HFCLKSEL_HFXO, CMU_CMD); diff --git a/patches/linux-3.8-rc5/0020-HACK-ARM-allow-a-bootloader-to-be-embedded-and-do-it.patch b/patches/linux-3.8-rc5/0021-HACK-ARM-allow-a-bootloader-to-be-embedded-and-do-it.patch index f2d0929..f2d0929 100644 --- a/patches/linux-3.8-rc5/0020-HACK-ARM-allow-a-bootloader-to-be-embedded-and-do-it.patch +++ b/patches/linux-3.8-rc5/0021-HACK-ARM-allow-a-bootloader-to-be-embedded-and-do-it.patch diff --git a/patches/linux-3.8-rc5/0021-HACK-don-t-reserve-memory-for-device-tree-if-it-s-be.patch b/patches/linux-3.8-rc5/0022-HACK-don-t-reserve-memory-for-device-tree-if-it-s-be.patch index b7f5680..b7f5680 100644 --- a/patches/linux-3.8-rc5/0021-HACK-don-t-reserve-memory-for-device-tree-if-it-s-be.patch +++ b/patches/linux-3.8-rc5/0022-HACK-don-t-reserve-memory-for-device-tree-if-it-s-be.patch diff --git a/patches/linux-3.8-rc5/0022-HACK-make-stack-dumps-provoked-by-BUG-a-bit-more-hel.patch b/patches/linux-3.8-rc5/0023-HACK-make-stack-dumps-provoked-by-BUG-a-bit-more-hel.patch index b99bcec..b99bcec 100644 --- a/patches/linux-3.8-rc5/0022-HACK-make-stack-dumps-provoked-by-BUG-a-bit-more-hel.patch +++ b/patches/linux-3.8-rc5/0023-HACK-make-stack-dumps-provoked-by-BUG-a-bit-more-hel.patch diff --git a/patches/linux-3.8-rc5/0023-HACK-ARM-increase-TASK_SIZE-for-MMU.patch b/patches/linux-3.8-rc5/0024-HACK-ARM-increase-TASK_SIZE-for-MMU.patch index cdd8d29..cdd8d29 100644 --- a/patches/linux-3.8-rc5/0023-HACK-ARM-increase-TASK_SIZE-for-MMU.patch +++ b/patches/linux-3.8-rc5/0024-HACK-ARM-increase-TASK_SIZE-for-MMU.patch diff --git a/patches/linux-3.8-rc5/0024-HACK-work-around-for-big-images.patch b/patches/linux-3.8-rc5/0025-HACK-work-around-for-big-images.patch index 06691a1..06691a1 100644 --- a/patches/linux-3.8-rc5/0024-HACK-work-around-for-big-images.patch +++ b/patches/linux-3.8-rc5/0025-HACK-work-around-for-big-images.patch diff --git a/patches/linux-3.8-rc5/series b/patches/linux-3.8-rc5/series index ba6a57b..b8be078 100644 --- a/patches/linux-3.8-rc5/series +++ b/patches/linux-3.8-rc5/series @@ -16,12 +16,13 @@ 0014-Cortex-M3-Allow-the-building-of-Cortex-M3-kernel-por.patch 0015-ARM-new-platform-for-Energy-Micro-s-EFM32-Cortex-M3-.patch 0016-ARM-efm32-add-support-for-non-dt-builds-and-add-more.patch -0017-efm-board-controller-driver.patch -0018-ARM-v7m-add-trivial-suspend-support.patch -0019-ARM-efm32-add-trivial-suspend-support.patch -0020-HACK-ARM-allow-a-bootloader-to-be-embedded-and-do-it.patch -0021-HACK-don-t-reserve-memory-for-device-tree-if-it-s-be.patch -0022-HACK-make-stack-dumps-provoked-by-BUG-a-bit-more-hel.patch -0023-HACK-ARM-increase-TASK_SIZE-for-MMU.patch -0024-HACK-work-around-for-big-images.patch -# 1659ab9769424059b871ff1ae1310d18 - git-ptx-patches magic +0017-gpio-new-driver-for-Energy-Micro-s-GPIO-component.patch +0018-efm-board-controller-driver.patch +0019-ARM-v7m-add-trivial-suspend-support.patch +0020-ARM-efm32-add-trivial-suspend-support.patch +0021-HACK-ARM-allow-a-bootloader-to-be-embedded-and-do-it.patch +0022-HACK-don-t-reserve-memory-for-device-tree-if-it-s-be.patch +0023-HACK-make-stack-dumps-provoked-by-BUG-a-bit-more-hel.patch +0024-HACK-ARM-increase-TASK_SIZE-for-MMU.patch +0025-HACK-work-around-for-big-images.patch +# 135b678da0c40f665a17effb4fc8dfd5 - git-ptx-patches magic |