diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-02 05:46:13 +0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-02 05:46:13 +0400 |
commit | 8f446a7a069e0af0639385f67c78ee2279bca04c (patch) | |
tree | 580cf495616b36ca0af0826afa87c430cdc1e7cb /arch/arm/mach-integrator | |
parent | 84be4ae2c038e2b03d650cbf2a7cfd9e8d6e9e51 (diff) | |
parent | 04ef037c926ddb31088c976538e29eada4fd1490 (diff) | |
download | linux-8f446a7a069e0af0639385f67c78ee2279bca04c.tar.xz |
Merge tag 'drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM soc driver specific changes from Olof Johansson:
- A long-coming conversion of various platforms to a common LED
infrastructure
- AT91 is moved over to use the newer MCI driver for MMC
- Pincontrol conversions for samsung platforms
- DT bindings for gscaler on samsung
- i2c driver fixes for tegra, acked by i2c maintainer
Fix up conflicts as per Olof.
* tag 'drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (48 commits)
drivers: bus: omap_l3: use resources instead of hardcoded irqs
pinctrl: exynos: Fix wakeup IRQ domain registration check
pinctrl: samsung: Uninline samsung_pinctrl_get_soc_data
pinctrl: exynos: Correct the detection of wakeup-eint node
pinctrl: exynos: Mark exynos_irq_demux_eint as inline
pinctrl: exynos: Handle only unmasked wakeup interrupts
pinctrl: exynos: Fix typos in gpio/wkup _irq_mask
pinctrl: exynos: Set pin function to EINT in irq_set_type of GPIO EINTa
drivers: bus: Move the OMAP interconnect driver to drivers/bus/
i2c: tegra: dynamically control fast clk
i2c: tegra: I2_M_NOSTART functionality not supported in Tegra20
ARM: tegra: clock: remove unused clock entry for i2c
ARM: tegra: clock: add connection name in i2c clock entry
i2c: tegra: pass proper name for getting clock
ARM: tegra: clock: add i2c fast clock entry in clock table
ARM: EXYNOS: Adds G-Scaler device from Device Tree
ARM: EXYNOS: Add clock support for G-Scaler
ARM: EXYNOS: Enable pinctrl driver support for EXYNOS4 device tree enabled platform
ARM: dts: Add pinctrl node entries for SAMSUNG EXYNOS4210 SoC
ARM: EXYNOS: skip wakeup interrupt setup if pinctrl driver is used
...
Diffstat (limited to 'arch/arm/mach-integrator')
-rw-r--r-- | arch/arm/mach-integrator/Makefile | 3 | ||||
-rw-r--r-- | arch/arm/mach-integrator/core.c | 3 | ||||
-rw-r--r-- | arch/arm/mach-integrator/include/mach/cm.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-integrator/leds.c | 161 |
4 files changed, 101 insertions, 68 deletions
diff --git a/arch/arm/mach-integrator/Makefile b/arch/arm/mach-integrator/Makefile index ebeef966e1f5..5521d18bf19a 100644 --- a/arch/arm/mach-integrator/Makefile +++ b/arch/arm/mach-integrator/Makefile @@ -4,11 +4,10 @@ # Object file lists. -obj-y := core.o lm.o +obj-y := core.o lm.o leds.o obj-$(CONFIG_ARCH_INTEGRATOR_AP) += integrator_ap.o obj-$(CONFIG_ARCH_INTEGRATOR_CP) += integrator_cp.o -obj-$(CONFIG_LEDS) += leds.o obj-$(CONFIG_PCI) += pci_v3.o pci.o obj-$(CONFIG_CPU_FREQ_INTEGRATOR) += cpu.o obj-$(CONFIG_INTEGRATOR_IMPD1) += impd1.o diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c index a432d4325f89..dad3cb74ed31 100644 --- a/arch/arm/mach-integrator/core.c +++ b/arch/arm/mach-integrator/core.c @@ -28,7 +28,6 @@ #include <mach/cm.h> #include <mach/irqs.h> -#include <asm/leds.h> #include <asm/mach-types.h> #include <asm/mach/time.h> #include <asm/pgtable.h> @@ -128,8 +127,6 @@ static struct amba_pl010_data integrator_uart_data = { .set_mctrl = integrator_uart_set_mctrl, }; -#define CM_CTRL IO_ADDRESS(INTEGRATOR_HDR_CTRL) - static DEFINE_RAW_SPINLOCK(cm_lock); /** diff --git a/arch/arm/mach-integrator/include/mach/cm.h b/arch/arm/mach-integrator/include/mach/cm.h index 445d57adb043..1a78692e32a4 100644 --- a/arch/arm/mach-integrator/include/mach/cm.h +++ b/arch/arm/mach-integrator/include/mach/cm.h @@ -3,6 +3,8 @@ */ void cm_control(u32, u32); +#define CM_CTRL IO_ADDRESS(INTEGRATOR_HDR_CTRL) + #define CM_CTRL_LED (1 << 0) #define CM_CTRL_nMBDET (1 << 1) #define CM_CTRL_REMAP (1 << 2) diff --git a/arch/arm/mach-integrator/leds.c b/arch/arm/mach-integrator/leds.c index 466defa97842..7a7f6d3273bf 100644 --- a/arch/arm/mach-integrator/leds.c +++ b/arch/arm/mach-integrator/leds.c @@ -1,90 +1,125 @@ /* - * linux/arch/arm/mach-integrator/leds.c + * Driver for the 4 user LEDs found on the Integrator AP/CP baseboard + * Based on Versatile and RealView machine LED code * - * Integrator/AP and Integrator/CP LED control routines - * - * Copyright (C) 1999 ARM Limited - * Copyright (C) 2000 Deep Blue Solutions Ltd - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * License terms: GNU General Public License (GPL) version 2 + * Author: Bryan Wu <bryan.wu@canonical.com> */ #include <linux/kernel.h> #include <linux/init.h> -#include <linux/smp.h> -#include <linux/spinlock.h> #include <linux/io.h> +#include <linux/slab.h> +#include <linux/leds.h> +#include <mach/cm.h> #include <mach/hardware.h> #include <mach/platform.h> -#include <asm/leds.h> -#include <asm/mach-types.h> -#include <mach/cm.h> -static int saved_leds; +#if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS) + +#define ALPHA_REG __io_address(INTEGRATOR_DBG_BASE) +#define LEDREG (__io_address(INTEGRATOR_DBG_BASE) + INTEGRATOR_DBG_LEDS_OFFSET) -static void integrator_leds_event(led_event_t ledevt) +struct integrator_led { + struct led_classdev cdev; + u8 mask; +}; + +/* + * The triggers lines up below will only be used if the + * LED triggers are compiled in. + */ +static const struct { + const char *name; + const char *trigger; +} integrator_leds[] = { + { "integrator:green0", "heartbeat", }, + { "integrator:yellow", }, + { "integrator:red", }, + { "integrator:green1", }, + { "integrator:core_module", "cpu0", }, +}; + +static void integrator_led_set(struct led_classdev *cdev, + enum led_brightness b) { - unsigned long flags; - const unsigned int dbg_base = IO_ADDRESS(INTEGRATOR_DBG_BASE); - unsigned int update_alpha_leds; + struct integrator_led *led = container_of(cdev, + struct integrator_led, cdev); + u32 reg = __raw_readl(LEDREG); - // yup, change the LEDs - local_irq_save(flags); - update_alpha_leds = 0; + if (b != LED_OFF) + reg |= led->mask; + else + reg &= ~led->mask; - switch(ledevt) { - case led_idle_start: - cm_control(CM_CTRL_LED, 0); - break; + while (__raw_readl(ALPHA_REG) & 1) + cpu_relax(); - case led_idle_end: - cm_control(CM_CTRL_LED, CM_CTRL_LED); - break; + __raw_writel(reg, LEDREG); +} - case led_timer: - saved_leds ^= GREEN_LED; - update_alpha_leds = 1; - break; +static enum led_brightness integrator_led_get(struct led_classdev *cdev) +{ + struct integrator_led *led = container_of(cdev, + struct integrator_led, cdev); + u32 reg = __raw_readl(LEDREG); - case led_red_on: - saved_leds |= RED_LED; - update_alpha_leds = 1; - break; + return (reg & led->mask) ? LED_FULL : LED_OFF; +} - case led_red_off: - saved_leds &= ~RED_LED; - update_alpha_leds = 1; - break; +static void cm_led_set(struct led_classdev *cdev, + enum led_brightness b) +{ + if (b != LED_OFF) + cm_control(CM_CTRL_LED, CM_CTRL_LED); + else + cm_control(CM_CTRL_LED, 0); +} - default: - break; - } +static enum led_brightness cm_led_get(struct led_classdev *cdev) +{ + u32 reg = readl(CM_CTRL); - if (update_alpha_leds) { - while (__raw_readl(dbg_base + INTEGRATOR_DBG_ALPHA_OFFSET) & 1); - __raw_writel(saved_leds, dbg_base + INTEGRATOR_DBG_LEDS_OFFSET); - } - local_irq_restore(flags); + return (reg & CM_CTRL_LED) ? LED_FULL : LED_OFF; } -static int __init leds_init(void) +static int __init integrator_leds_init(void) { - if (machine_is_integrator() || machine_is_cintegrator()) - leds_event = integrator_leds_event; + int i; + + for (i = 0; i < ARRAY_SIZE(integrator_leds); i++) { + struct integrator_led *led; + + led = kzalloc(sizeof(*led), GFP_KERNEL); + if (!led) + break; + + + led->cdev.name = integrator_leds[i].name; + + if (i == 4) { /* Setting for LED in core module */ + led->cdev.brightness_set = cm_led_set; + led->cdev.brightness_get = cm_led_get; + } else { + led->cdev.brightness_set = integrator_led_set; + led->cdev.brightness_get = integrator_led_get; + } + + led->cdev.default_trigger = integrator_leds[i].trigger; + led->mask = BIT(i); + + if (led_classdev_register(NULL, &led->cdev) < 0) { + kfree(led); + break; + } + } return 0; } -core_initcall(leds_init); +/* + * Since we may have triggers on any subsystem, defer registration + * until after subsystem_init. + */ +fs_initcall(integrator_leds_init); +#endif |