Cleanups for MSM for 3.11

These are a handful of cleanups to the MSM tree.  The gpio cleanups
 get us closer to having proper pinmux and gpio support.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.19 (GNU/Linux)
 
 iQIcBAABAgAGBQJRu1dSAAoJEOa6n1xeVN+CbG4QAMxPKNDgBcX+UHRLMBh5YkbP
 ePoWz8QhQ/OWo3Oef6IBEwA3n2jfSF3hTYnXJI/LqRibL8yCDWKlSI6b52/vZsDg
 r2J4FMiHtBc0Wk+JGhKszdS+eLnljOljz49L5YEMCRglFVMveXqbKeTvbzfaGR6u
 SAJca3roEVo2Vgdf36CnYEHNxHrfK6yMzPVqiVgasPWnst10WguV+dhX9+REwT2p
 kp99U8wBEAp84nb2KzoVwKpzUpWWPcFWiaB1/EE6jB5+d3U0CLBWp+6E12m9tOTU
 L8Hx417zmwV/YvNfVb//SnTnBGYMybXDVlIzRQUuJimPm96SFw1Uw6+0+V+sAv3N
 T7WmyiyZ6UaDyQB1VCQNzIqEOq8qBacRaXH6kxk6T8UW8l08tSuSf/piiSw5wZLD
 6QJ1RFkjrcEulh0DDOcf6Fg34jVk3hjQFF86sBN+JTQfIQ1VBHDLSGuF+RjYk5LW
 gNN5xGuqHjDdbK/HNvMhIF8MN/B64Wm4PsOHRsN5RP9EXVIB5kEGUMwEEEa/jO8m
 rhWUPjFq7nE4BNNvrhKShjxtKJGi5OmYx5GYw189rJ5bzVQH68ZSIAGTh8TySpfB
 N/G82J+bGXz0xq8z81dKRsru+kdv2MkNL9mlJzYNbKhQP64ukD1XMmrWlH8DxtzY
 CPNWs8m5QCI4R1WiaP2W
 =9wS3
 -----END PGP SIGNATURE-----

Merge tag 'msm-cleanup-for-3.11' of git://git.kernel.org/pub/scm/linux/kernel/git/davidb/linux-msm into next/cleanup

From David Brown:
Cleanups for MSM for 3.11

These are a handful of cleanups to the MSM tree.  The gpio cleanups
get us closer to having proper pinmux and gpio support.

* tag 'msm-cleanup-for-3.11' of git://git.kernel.org/pub/scm/linux/kernel/git/davidb/linux-msm:
  mfd: ssbi: Use devm_* and simplify code
  gpio: msm: Add device tree and irqdomain support for gpio-msm-v2
  ARM: msm: Remove gpiomux-v2 and re-organize MSM_GPIOMUX configs
  msm: iomap: Remove unused bases and mappings
  msm: Remove unused file core.h
  ARM: msm: Remove init_irq declaration in machine description

Signed-off-by: Olof Johansson <olof@lixom.net>

Conflicts:
	arch/arm/boot/dts/msm8660-surf.dts
	arch/arm/boot/dts/msm8960-cdp.dts
This commit is contained in:
Olof Johansson 2013-06-14 18:26:26 -07:00
commit e45600107b
20 changed files with 203 additions and 292 deletions

View File

@ -0,0 +1,26 @@
MSM GPIO controller bindings
Required properties:
- compatible:
- "qcom,msm-gpio" for MSM controllers
- #gpio-cells : Should be two.
- first cell is the pin number
- second cell is used to specify optional parameters (unused)
- gpio-controller : Marks the device node as a GPIO controller.
- #interrupt-cells : Should be 2.
- interrupt-controller: Mark the device node as an interrupt controller
- interrupts : Specify the TLMM summary interrupt number
- ngpio : Specify the number of MSM GPIOs
Example:
msmgpio: gpio@fd510000 {
compatible = "qcom,msm-gpio";
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
reg = <0xfd510000 0x4000>;
interrupts = <0 208 0>;
ngpio = <150>;
};

View File

@ -26,6 +26,17 @@
cpu-offset = <0x40000>; cpu-offset = <0x40000>;
}; };
msmgpio: gpio@800000 {
compatible = "qcom,msm-gpio";
reg = <0x00800000 0x1000>;
gpio-controller;
#gpio-cells = <2>;
ngpio = <173>;
interrupts = <0 32 0x4>;
interrupt-controller;
#interrupt-cells = <2>;
};
serial@19c40000 { serial@19c40000 {
compatible = "qcom,msm-hsuart", "qcom,msm-uart"; compatible = "qcom,msm-hsuart", "qcom,msm-uart";
reg = <0x19c40000 0x1000>, reg = <0x19c40000 0x1000>,

View File

@ -26,7 +26,18 @@
cpu-offset = <0x80000>; cpu-offset = <0x80000>;
}; };
serial@16440000 { msmgpio: gpio@fd510000 {
compatible = "qcom,msm-gpio";
gpio-controller;
#gpio-cells = <2>;
ngpio = <150>;
interrupts = <0 32 0x4>;
interrupt-controller;
#interrupt-cells = <2>;
reg = <0xfd510000 0x4000>;
};
serial@19440000 {
compatible = "qcom,msm-hsuart", "qcom,msm-uart"; compatible = "qcom,msm-hsuart", "qcom,msm-uart";
reg = <0x16440000 0x1000>, reg = <0x16440000 0x1000>,
<0x16400000 0x1000>; <0x16400000 0x1000>;

View File

@ -48,9 +48,7 @@ config ARCH_MSM8X60
select CPU_V7 select CPU_V7
select GPIO_MSM_V2 select GPIO_MSM_V2
select HAVE_SMP select HAVE_SMP
select MSM_GPIOMUX
select MSM_SCM if SMP select MSM_SCM if SMP
select MSM_V2_TLMM
select USE_OF select USE_OF
config ARCH_MSM8960 config ARCH_MSM8960
@ -58,9 +56,8 @@ config ARCH_MSM8960
select ARM_GIC select ARM_GIC
select CPU_V7 select CPU_V7
select HAVE_SMP select HAVE_SMP
select MSM_GPIOMUX select GPIO_MSM_V2
select MSM_SCM if SMP select MSM_SCM if SMP
select MSM_V2_TLMM
select USE_OF select USE_OF
config MSM_HAS_DEBUG_UART_HS config MSM_HAS_DEBUG_UART_HS
@ -124,10 +121,10 @@ config MSM_SMD
bool bool
config MSM_GPIOMUX config MSM_GPIOMUX
bool depends on !(ARCH_MSM8X60 || ARCH_MSM8960)
bool "MSM V1 TLMM GPIOMUX architecture"
config MSM_V2_TLMM help
bool Support for MSM V1 TLMM GPIOMUX architecture.
config MSM_SCM config MSM_SCM
bool bool

View File

@ -27,7 +27,5 @@ obj-$(CONFIG_ARCH_MSM7X30) += board-msm7x30.o devices-msm7x30.o
obj-$(CONFIG_ARCH_QSD8X50) += board-qsd8x50.o devices-qsd8x50.o obj-$(CONFIG_ARCH_QSD8X50) += board-qsd8x50.o devices-qsd8x50.o
obj-$(CONFIG_ARCH_MSM8X60) += board-dt-8660.o obj-$(CONFIG_ARCH_MSM8X60) += board-dt-8660.o
obj-$(CONFIG_ARCH_MSM8960) += board-dt-8960.o obj-$(CONFIG_ARCH_MSM8960) += board-dt-8960.o
obj-$(CONFIG_MSM_GPIOMUX) += gpiomux.o
obj-$(CONFIG_ARCH_MSM7X30) += gpiomux-v1.o gpiomux.o obj-$(CONFIG_ARCH_QSD8X50) += gpiomux-8x50.o
obj-$(CONFIG_ARCH_QSD8X50) += gpiomux-8x50.o gpiomux-v1.o gpiomux.o
obj-$(CONFIG_ARCH_MSM8X60) += gpiomux-8x60.o gpiomux-v2.o gpiomux.o

View File

@ -11,7 +11,6 @@
*/ */
#include <linux/init.h> #include <linux/init.h>
#include <linux/irqchip.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
@ -44,7 +43,6 @@ static const char *msm8x60_fluid_match[] __initdata = {
DT_MACHINE_START(MSM_DT, "Qualcomm MSM (Flattened Device Tree)") DT_MACHINE_START(MSM_DT, "Qualcomm MSM (Flattened Device Tree)")
.smp = smp_ops(msm_smp_ops), .smp = smp_ops(msm_smp_ops),
.map_io = msm_map_msm8x60_io, .map_io = msm_map_msm8x60_io,
.init_irq = irqchip_init,
.init_machine = msm8x60_dt_init, .init_machine = msm8x60_dt_init,
.init_late = msm8x60_init_late, .init_late = msm8x60_init_late,
.init_time = msm_dt_timer_init, .init_time = msm_dt_timer_init,

View File

@ -11,7 +11,6 @@
*/ */
#include <linux/init.h> #include <linux/init.h>
#include <linux/irqchip.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
@ -31,7 +30,6 @@ static const char * const msm8960_dt_match[] __initconst = {
DT_MACHINE_START(MSM8960_DT, "Qualcomm MSM (Flattened Device Tree)") DT_MACHINE_START(MSM8960_DT, "Qualcomm MSM (Flattened Device Tree)")
.smp = smp_ops(msm_smp_ops), .smp = smp_ops(msm_smp_ops),
.map_io = msm_map_msm8960_io, .map_io = msm_map_msm8960_io,
.init_irq = irqchip_init,
.init_time = msm_dt_timer_init, .init_time = msm_dt_timer_init,
.init_machine = msm_dt_init, .init_machine = msm_dt_init,
.dt_compat = msm8960_dt_match, .dt_compat = msm8960_dt_match,

View File

@ -1,2 +0,0 @@
extern struct smp_operations msm_smp_ops;
extern void msm_cpu_die(unsigned int cpu);

View File

@ -1,19 +0,0 @@
/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* 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 "gpiomux.h"
struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = {};

View File

@ -1,25 +0,0 @@
/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* 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/io.h>
#include <mach/msm_iomap.h>
#include "gpiomux.h"
void __msm_gpiomux_write(unsigned gpio, gpiomux_config_t val)
{
writel(val & ~GPIOMUX_CTL_MASK,
MSM_TLMM_BASE + 0x1000 + (0x10 * gpio));
}

View File

@ -1,61 +0,0 @@
/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* 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.
*/
#ifndef __ARCH_ARM_MACH_MSM_GPIOMUX_V2_H
#define __ARCH_ARM_MACH_MSM_GPIOMUX_V2_H
#define GPIOMUX_NGPIOS 173
typedef u16 gpiomux_config_t;
enum {
GPIOMUX_DRV_2MA = 0UL << 6,
GPIOMUX_DRV_4MA = 1UL << 6,
GPIOMUX_DRV_6MA = 2UL << 6,
GPIOMUX_DRV_8MA = 3UL << 6,
GPIOMUX_DRV_10MA = 4UL << 6,
GPIOMUX_DRV_12MA = 5UL << 6,
GPIOMUX_DRV_14MA = 6UL << 6,
GPIOMUX_DRV_16MA = 7UL << 6,
};
enum {
GPIOMUX_FUNC_GPIO = 0UL << 2,
GPIOMUX_FUNC_1 = 1UL << 2,
GPIOMUX_FUNC_2 = 2UL << 2,
GPIOMUX_FUNC_3 = 3UL << 2,
GPIOMUX_FUNC_4 = 4UL << 2,
GPIOMUX_FUNC_5 = 5UL << 2,
GPIOMUX_FUNC_6 = 6UL << 2,
GPIOMUX_FUNC_7 = 7UL << 2,
GPIOMUX_FUNC_8 = 8UL << 2,
GPIOMUX_FUNC_9 = 9UL << 2,
GPIOMUX_FUNC_A = 10UL << 2,
GPIOMUX_FUNC_B = 11UL << 2,
GPIOMUX_FUNC_C = 12UL << 2,
GPIOMUX_FUNC_D = 13UL << 2,
GPIOMUX_FUNC_E = 14UL << 2,
GPIOMUX_FUNC_F = 15UL << 2,
};
enum {
GPIOMUX_PULL_NONE = 0UL,
GPIOMUX_PULL_DOWN = 1UL,
GPIOMUX_PULL_KEEPER = 2UL,
GPIOMUX_PULL_UP = 3UL,
};
#endif

View File

@ -17,9 +17,24 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include "gpiomux.h" #include "gpiomux.h"
#include "proc_comm.h"
static DEFINE_SPINLOCK(gpiomux_lock); static DEFINE_SPINLOCK(gpiomux_lock);
static void __msm_gpiomux_write(unsigned gpio, gpiomux_config_t val)
{
unsigned tlmm_config = (val & ~GPIOMUX_CTL_MASK) |
((gpio & 0x3ff) << 4);
unsigned tlmm_disable = 0;
int rc;
rc = msm_proc_comm(PCOM_RPC_GPIO_TLMM_CONFIG_EX,
&tlmm_config, &tlmm_disable);
if (rc)
pr_err("%s: unexpected proc_comm failure %d: %08x %08x\n",
__func__, rc, tlmm_config, tlmm_disable);
}
int msm_gpiomux_write(unsigned gpio, int msm_gpiomux_write(unsigned gpio,
gpiomux_config_t active, gpiomux_config_t active,
gpiomux_config_t suspended) gpiomux_config_t suspended)

View File

@ -20,12 +20,7 @@
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <mach/msm_gpiomux.h> #include <mach/msm_gpiomux.h>
#if defined(CONFIG_MSM_V2_TLMM)
#include "gpiomux-v2.h"
#else
#include "gpiomux-v1.h" #include "gpiomux-v1.h"
#endif
/** /**
* struct msm_gpiomux_config: gpiomux settings for one gpio line. * struct msm_gpiomux_config: gpiomux settings for one gpio line.

View File

@ -32,13 +32,6 @@
* *
*/ */
#define MSM8960_QGIC_DIST_PHYS 0x02000000
#define MSM8960_QGIC_DIST_SIZE SZ_4K
#define MSM8960_QGIC_CPU_PHYS 0x02002000
#define MSM8960_QGIC_CPU_SIZE SZ_4K
#define MSM8960_TMR_PHYS 0x0200A000 #define MSM8960_TMR_PHYS 0x0200A000
#define MSM8960_TMR_SIZE SZ_4K #define MSM8960_TMR_SIZE SZ_4K

View File

@ -35,12 +35,6 @@
* *
*/ */
#define MSM8X60_QGIC_DIST_PHYS 0x02080000
#define MSM8X60_QGIC_DIST_SIZE SZ_4K
#define MSM8X60_QGIC_CPU_PHYS 0x02081000
#define MSM8X60_QGIC_CPU_SIZE SZ_4K
#define MSM_TLMM_BASE IOMEM(0xF0004000) #define MSM_TLMM_BASE IOMEM(0xF0004000)
#define MSM_TLMM_PHYS 0x00800000 #define MSM_TLMM_PHYS 0x00800000
#define MSM_TLMM_SIZE SZ_16K #define MSM_TLMM_SIZE SZ_16K

View File

@ -62,8 +62,6 @@
/* Virtual addresses shared across all MSM targets. */ /* Virtual addresses shared across all MSM targets. */
#define MSM_CSR_BASE IOMEM(0xE0001000) #define MSM_CSR_BASE IOMEM(0xE0001000)
#define MSM_QGIC_DIST_BASE IOMEM(0xF0000000)
#define MSM_QGIC_CPU_BASE IOMEM(0xF0001000)
#define MSM_TMR_BASE IOMEM(0xF0200000) #define MSM_TMR_BASE IOMEM(0xF0200000)
#define MSM_TMR0_BASE IOMEM(0xF0201000) #define MSM_TMR0_BASE IOMEM(0xF0201000)
#define MSM_GPIO1_BASE IOMEM(0xE0003000) #define MSM_GPIO1_BASE IOMEM(0xE0003000)

View File

@ -107,8 +107,6 @@ void __init msm_map_qsd8x50_io(void)
#ifdef CONFIG_ARCH_MSM8X60 #ifdef CONFIG_ARCH_MSM8X60
static struct map_desc msm8x60_io_desc[] __initdata = { static struct map_desc msm8x60_io_desc[] __initdata = {
MSM_CHIP_DEVICE(QGIC_DIST, MSM8X60),
MSM_CHIP_DEVICE(QGIC_CPU, MSM8X60),
MSM_CHIP_DEVICE(TMR, MSM8X60), MSM_CHIP_DEVICE(TMR, MSM8X60),
MSM_CHIP_DEVICE(TMR0, MSM8X60), MSM_CHIP_DEVICE(TMR0, MSM8X60),
#ifdef CONFIG_DEBUG_MSM8660_UART #ifdef CONFIG_DEBUG_MSM8660_UART
@ -124,8 +122,6 @@ void __init msm_map_msm8x60_io(void)
#ifdef CONFIG_ARCH_MSM8960 #ifdef CONFIG_ARCH_MSM8960
static struct map_desc msm8960_io_desc[] __initdata = { static struct map_desc msm8960_io_desc[] __initdata = {
MSM_CHIP_DEVICE(QGIC_DIST, MSM8960),
MSM_CHIP_DEVICE(QGIC_CPU, MSM8960),
MSM_CHIP_DEVICE(TMR, MSM8960), MSM_CHIP_DEVICE(TMR, MSM8960),
MSM_CHIP_DEVICE(TMR0, MSM8960), MSM_CHIP_DEVICE(TMR0, MSM8960),
#ifdef CONFIG_DEBUG_MSM8960_UART #ifdef CONFIG_DEBUG_MSM8960_UART

View File

@ -165,7 +165,7 @@ config GPIO_MSM_V1
config GPIO_MSM_V2 config GPIO_MSM_V2
tristate "Qualcomm MSM GPIO v2" tristate "Qualcomm MSM GPIO v2"
depends on GPIOLIB && ARCH_MSM depends on GPIOLIB && OF && ARCH_MSM
help help
Say yes here to support the GPIO interface on ARM v7 based Say yes here to support the GPIO interface on ARM v7 based
Qualcomm MSM chips. Most of the pins on the MSM can be Qualcomm MSM chips. Most of the pins on the MSM can be

View File

@ -19,18 +19,21 @@
#include <linux/bitmap.h> #include <linux/bitmap.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/err.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/irqchip/chained_irq.h> #include <linux/irqchip/chained_irq.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of_address.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/slab.h>
#include <mach/msm_gpiomux.h> #define MAX_NR_GPIO 300
#include <mach/msm_iomap.h>
/* Bits of interest in the GPIO_IN_OUT register. /* Bits of interest in the GPIO_IN_OUT register.
*/ */
@ -77,13 +80,6 @@ enum {
TARGET_PROC_NONE = 7, TARGET_PROC_NONE = 7,
}; };
#define GPIO_INTR_CFG_SU(gpio) (MSM_TLMM_BASE + 0x0400 + (0x04 * (gpio)))
#define GPIO_CONFIG(gpio) (MSM_TLMM_BASE + 0x1000 + (0x10 * (gpio)))
#define GPIO_IN_OUT(gpio) (MSM_TLMM_BASE + 0x1004 + (0x10 * (gpio)))
#define GPIO_INTR_CFG(gpio) (MSM_TLMM_BASE + 0x1008 + (0x10 * (gpio)))
#define GPIO_INTR_STATUS(gpio) (MSM_TLMM_BASE + 0x100c + (0x10 * (gpio)))
/** /**
* struct msm_gpio_dev: the MSM8660 SoC GPIO device structure * struct msm_gpio_dev: the MSM8660 SoC GPIO device structure
* *
@ -102,11 +98,27 @@ enum {
*/ */
struct msm_gpio_dev { struct msm_gpio_dev {
struct gpio_chip gpio_chip; struct gpio_chip gpio_chip;
DECLARE_BITMAP(enabled_irqs, NR_GPIO_IRQS); DECLARE_BITMAP(enabled_irqs, MAX_NR_GPIO);
DECLARE_BITMAP(wake_irqs, NR_GPIO_IRQS); DECLARE_BITMAP(wake_irqs, MAX_NR_GPIO);
DECLARE_BITMAP(dual_edge_irqs, NR_GPIO_IRQS); DECLARE_BITMAP(dual_edge_irqs, MAX_NR_GPIO);
struct irq_domain *domain;
unsigned int summary_irq;
void __iomem *msm_tlmm_base;
}; };
struct msm_gpio_dev msm_gpio;
#define GPIO_INTR_CFG_SU(gpio) (msm_gpio.msm_tlmm_base + 0x0400 + \
(0x04 * (gpio)))
#define GPIO_CONFIG(gpio) (msm_gpio.msm_tlmm_base + 0x1000 + \
(0x10 * (gpio)))
#define GPIO_IN_OUT(gpio) (msm_gpio.msm_tlmm_base + 0x1004 + \
(0x10 * (gpio)))
#define GPIO_INTR_CFG(gpio) (msm_gpio.msm_tlmm_base + 0x1008 + \
(0x10 * (gpio)))
#define GPIO_INTR_STATUS(gpio) (msm_gpio.msm_tlmm_base + 0x100c + \
(0x10 * (gpio)))
static DEFINE_SPINLOCK(tlmm_lock); static DEFINE_SPINLOCK(tlmm_lock);
static inline struct msm_gpio_dev *to_msm_gpio_dev(struct gpio_chip *chip) static inline struct msm_gpio_dev *to_msm_gpio_dev(struct gpio_chip *chip)
@ -159,37 +171,29 @@ static int msm_gpio_direction_output(struct gpio_chip *chip,
static int msm_gpio_request(struct gpio_chip *chip, unsigned offset) static int msm_gpio_request(struct gpio_chip *chip, unsigned offset)
{ {
return msm_gpiomux_get(chip->base + offset); return 0;
} }
static void msm_gpio_free(struct gpio_chip *chip, unsigned offset) static void msm_gpio_free(struct gpio_chip *chip, unsigned offset)
{ {
msm_gpiomux_put(chip->base + offset); return;
} }
static int msm_gpio_to_irq(struct gpio_chip *chip, unsigned offset) static int msm_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{ {
return MSM_GPIO_TO_INT(chip->base + offset); struct msm_gpio_dev *g_dev = to_msm_gpio_dev(chip);
struct irq_domain *domain = g_dev->domain;
return irq_create_mapping(domain, offset);
} }
static inline int msm_irq_to_gpio(struct gpio_chip *chip, unsigned irq) static inline int msm_irq_to_gpio(struct gpio_chip *chip, unsigned irq)
{ {
return irq - MSM_GPIO_TO_INT(chip->base); struct irq_data *irq_data = irq_get_irq_data(irq);
return irq_data->hwirq;
} }
static struct msm_gpio_dev msm_gpio = {
.gpio_chip = {
.base = 0,
.ngpio = NR_GPIO_IRQS,
.direction_input = msm_gpio_direction_input,
.direction_output = msm_gpio_direction_output,
.get = msm_gpio_get,
.set = msm_gpio_set,
.to_irq = msm_gpio_to_irq,
.request = msm_gpio_request,
.free = msm_gpio_free,
},
};
/* For dual-edge interrupts in software, since the hardware has no /* For dual-edge interrupts in software, since the hardware has no
* such support: * such support:
@ -227,9 +231,9 @@ static void msm_gpio_update_dual_edge_pos(unsigned gpio)
if (intstat || val == val2) if (intstat || val == val2)
return; return;
} while (loop_limit-- > 0); } while (loop_limit-- > 0);
pr_err("dual-edge irq failed to stabilize, " pr_err("%s: dual-edge irq failed to stabilize, "
"interrupts dropped. %#08x != %#08x\n", "interrupts dropped. %#08x != %#08x\n",
val, val2); __func__, val, val2);
} }
static void msm_gpio_irq_ack(struct irq_data *d) static void msm_gpio_irq_ack(struct irq_data *d)
@ -316,10 +320,10 @@ static void msm_summary_irq_handler(unsigned int irq, struct irq_desc *desc)
chained_irq_enter(chip, desc); chained_irq_enter(chip, desc);
for_each_set_bit(i, msm_gpio.enabled_irqs, NR_GPIO_IRQS) { for_each_set_bit(i, msm_gpio.enabled_irqs, MAX_NR_GPIO) {
if (readl(GPIO_INTR_STATUS(i)) & BIT(INTR_STATUS)) if (readl(GPIO_INTR_STATUS(i)) & BIT(INTR_STATUS))
generic_handle_irq(msm_gpio_to_irq(&msm_gpio.gpio_chip, generic_handle_irq(irq_find_mapping(msm_gpio.domain,
i)); i));
} }
chained_irq_exit(chip, desc); chained_irq_exit(chip, desc);
@ -330,13 +334,13 @@ static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq); int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq);
if (on) { if (on) {
if (bitmap_empty(msm_gpio.wake_irqs, NR_GPIO_IRQS)) if (bitmap_empty(msm_gpio.wake_irqs, MAX_NR_GPIO))
irq_set_irq_wake(TLMM_SCSS_SUMMARY_IRQ, 1); irq_set_irq_wake(msm_gpio.summary_irq, 1);
set_bit(gpio, msm_gpio.wake_irqs); set_bit(gpio, msm_gpio.wake_irqs);
} else { } else {
clear_bit(gpio, msm_gpio.wake_irqs); clear_bit(gpio, msm_gpio.wake_irqs);
if (bitmap_empty(msm_gpio.wake_irqs, NR_GPIO_IRQS)) if (bitmap_empty(msm_gpio.wake_irqs, MAX_NR_GPIO))
irq_set_irq_wake(TLMM_SCSS_SUMMARY_IRQ, 0); irq_set_irq_wake(msm_gpio.summary_irq, 0);
} }
return 0; return 0;
@ -351,30 +355,86 @@ static struct irq_chip msm_gpio_irq_chip = {
.irq_set_wake = msm_gpio_irq_set_wake, .irq_set_wake = msm_gpio_irq_set_wake,
}; };
static int msm_gpio_probe(struct platform_device *dev) static struct lock_class_key msm_gpio_lock_class;
static int msm_gpio_irq_domain_map(struct irq_domain *d, unsigned int irq,
irq_hw_number_t hwirq)
{ {
int i, irq, ret; irq_set_lockdep_class(irq, &msm_gpio_lock_class);
irq_set_chip_and_handler(irq, &msm_gpio_irq_chip,
handle_level_irq);
set_irq_flags(irq, IRQF_VALID);
bitmap_zero(msm_gpio.enabled_irqs, NR_GPIO_IRQS);
bitmap_zero(msm_gpio.wake_irqs, NR_GPIO_IRQS);
bitmap_zero(msm_gpio.dual_edge_irqs, NR_GPIO_IRQS);
msm_gpio.gpio_chip.label = dev->name;
ret = gpiochip_add(&msm_gpio.gpio_chip);
if (ret < 0)
return ret;
for (i = 0; i < msm_gpio.gpio_chip.ngpio; ++i) {
irq = msm_gpio_to_irq(&msm_gpio.gpio_chip, i);
irq_set_chip_and_handler(irq, &msm_gpio_irq_chip,
handle_level_irq);
set_irq_flags(irq, IRQF_VALID);
}
irq_set_chained_handler(TLMM_SCSS_SUMMARY_IRQ,
msm_summary_irq_handler);
return 0; return 0;
} }
static const struct irq_domain_ops msm_gpio_irq_domain_ops = {
.xlate = irq_domain_xlate_twocell,
.map = msm_gpio_irq_domain_map,
};
static int msm_gpio_probe(struct platform_device *pdev)
{
int ret, ngpio;
struct resource *res;
if (!of_property_read_u32(pdev->dev.of_node, "ngpio", &ngpio)) {
dev_err(&pdev->dev, "%s: ngpio property missing\n", __func__);
return -EINVAL;
}
if (ngpio > MAX_NR_GPIO)
WARN(1, "ngpio exceeds the MAX_NR_GPIO. Increase MAX_NR_GPIO\n");
bitmap_zero(msm_gpio.enabled_irqs, MAX_NR_GPIO);
bitmap_zero(msm_gpio.wake_irqs, MAX_NR_GPIO);
bitmap_zero(msm_gpio.dual_edge_irqs, MAX_NR_GPIO);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
msm_gpio.msm_tlmm_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(msm_gpio.msm_tlmm_base))
return PTR_ERR(msm_gpio.msm_tlmm_base);
msm_gpio.gpio_chip.ngpio = ngpio;
msm_gpio.gpio_chip.label = pdev->name;
msm_gpio.gpio_chip.dev = &pdev->dev;
msm_gpio.gpio_chip.base = 0;
msm_gpio.gpio_chip.direction_input = msm_gpio_direction_input;
msm_gpio.gpio_chip.direction_output = msm_gpio_direction_output;
msm_gpio.gpio_chip.get = msm_gpio_get;
msm_gpio.gpio_chip.set = msm_gpio_set;
msm_gpio.gpio_chip.to_irq = msm_gpio_to_irq;
msm_gpio.gpio_chip.request = msm_gpio_request;
msm_gpio.gpio_chip.free = msm_gpio_free;
ret = gpiochip_add(&msm_gpio.gpio_chip);
if (ret < 0) {
dev_err(&pdev->dev, "gpiochip_add failed with error %d\n", ret);
return ret;
}
msm_gpio.summary_irq = platform_get_irq(pdev, 0);
if (msm_gpio.summary_irq < 0) {
dev_err(&pdev->dev, "No Summary irq defined for msmgpio\n");
return msm_gpio.summary_irq;
}
msm_gpio.domain = irq_domain_add_linear(pdev->dev.of_node, ngpio,
&msm_gpio_irq_domain_ops,
&msm_gpio);
if (!msm_gpio.domain)
return -ENODEV;
irq_set_chained_handler(msm_gpio.summary_irq, msm_summary_irq_handler);
return 0;
}
static struct of_device_id msm_gpio_of_match[] = {
{ .compatible = "qcom,msm-gpio", },
{ },
};
static int msm_gpio_remove(struct platform_device *dev) static int msm_gpio_remove(struct platform_device *dev)
{ {
int ret = gpiochip_remove(&msm_gpio.gpio_chip); int ret = gpiochip_remove(&msm_gpio.gpio_chip);
@ -382,7 +442,7 @@ static int msm_gpio_remove(struct platform_device *dev)
if (ret < 0) if (ret < 0)
return ret; return ret;
irq_set_handler(TLMM_SCSS_SUMMARY_IRQ, NULL); irq_set_handler(msm_gpio.summary_irq, NULL);
return 0; return 0;
} }
@ -393,36 +453,11 @@ static struct platform_driver msm_gpio_driver = {
.driver = { .driver = {
.name = "msmgpio", .name = "msmgpio",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.of_match_table = msm_gpio_of_match,
}, },
}; };
static struct platform_device msm_device_gpio = { module_platform_driver(msm_gpio_driver)
.name = "msmgpio",
.id = -1,
};
static int __init msm_gpio_init(void)
{
int rc;
rc = platform_driver_register(&msm_gpio_driver);
if (!rc) {
rc = platform_device_register(&msm_device_gpio);
if (rc)
platform_driver_unregister(&msm_gpio_driver);
}
return rc;
}
static void __exit msm_gpio_exit(void)
{
platform_device_unregister(&msm_device_gpio);
platform_driver_unregister(&msm_gpio_driver);
}
postcore_initcall(msm_gpio_init);
module_exit(msm_gpio_exit);
MODULE_AUTHOR("Gregory Bean <gbean@codeaurora.org>"); MODULE_AUTHOR("Gregory Bean <gbean@codeaurora.org>");
MODULE_DESCRIPTION("Driver for Qualcomm MSM TLMMv2 SoC GPIOs"); MODULE_DESCRIPTION("Driver for Qualcomm MSM TLMMv2 SoC GPIOs");

View File

@ -268,35 +268,23 @@ static int ssbi_probe(struct platform_device *pdev)
struct device_node *np = pdev->dev.of_node; struct device_node *np = pdev->dev.of_node;
struct resource *mem_res; struct resource *mem_res;
struct ssbi *ssbi; struct ssbi *ssbi;
int ret = 0;
const char *type; const char *type;
ssbi = kzalloc(sizeof(struct ssbi), GFP_KERNEL); ssbi = devm_kzalloc(&pdev->dev, sizeof(*ssbi), GFP_KERNEL);
if (!ssbi) { if (!ssbi)
pr_err("can not allocate ssbi_data\n");
return -ENOMEM; return -ENOMEM;
}
mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!mem_res) { ssbi->base = devm_ioremap_resource(&pdev->dev, mem_res);
pr_err("missing mem resource\n"); if (IS_ERR(ssbi->base))
ret = -EINVAL; return PTR_ERR(ssbi->base);
goto err_get_mem_res;
}
ssbi->base = ioremap(mem_res->start, resource_size(mem_res));
if (!ssbi->base) {
pr_err("ioremap of 0x%p failed\n", (void *)mem_res->start);
ret = -EINVAL;
goto err_ioremap;
}
platform_set_drvdata(pdev, ssbi); platform_set_drvdata(pdev, ssbi);
type = of_get_property(np, "qcom,controller-type", NULL); type = of_get_property(np, "qcom,controller-type", NULL);
if (type == NULL) { if (type == NULL) {
pr_err("Missing qcom,controller-type property\n"); dev_err(&pdev->dev, "Missing qcom,controller-type property\n");
ret = -EINVAL; return -EINVAL;
goto err_ssbi_controller;
} }
dev_info(&pdev->dev, "SSBI controller type: '%s'\n", type); dev_info(&pdev->dev, "SSBI controller type: '%s'\n", type);
if (strcmp(type, "ssbi") == 0) if (strcmp(type, "ssbi") == 0)
@ -306,9 +294,8 @@ static int ssbi_probe(struct platform_device *pdev)
else if (strcmp(type, "pmic-arbiter") == 0) else if (strcmp(type, "pmic-arbiter") == 0)
ssbi->controller_type = MSM_SBI_CTRL_PMIC_ARBITER; ssbi->controller_type = MSM_SBI_CTRL_PMIC_ARBITER;
else { else {
pr_err("Unknown qcom,controller-type\n"); dev_err(&pdev->dev, "Unknown qcom,controller-type\n");
ret = -EINVAL; return -EINVAL;
goto err_ssbi_controller;
} }
if (ssbi->controller_type == MSM_SBI_CTRL_PMIC_ARBITER) { if (ssbi->controller_type == MSM_SBI_CTRL_PMIC_ARBITER) {
@ -321,29 +308,7 @@ static int ssbi_probe(struct platform_device *pdev)
spin_lock_init(&ssbi->lock); spin_lock_init(&ssbi->lock);
ret = of_platform_populate(np, NULL, NULL, &pdev->dev); return of_platform_populate(np, NULL, NULL, &pdev->dev);
if (ret)
goto err_ssbi_controller;
return 0;
err_ssbi_controller:
platform_set_drvdata(pdev, NULL);
iounmap(ssbi->base);
err_ioremap:
err_get_mem_res:
kfree(ssbi);
return ret;
}
static int ssbi_remove(struct platform_device *pdev)
{
struct ssbi *ssbi = platform_get_drvdata(pdev);
platform_set_drvdata(pdev, NULL);
iounmap(ssbi->base);
kfree(ssbi);
return 0;
} }
static struct of_device_id ssbi_match_table[] = { static struct of_device_id ssbi_match_table[] = {
@ -354,25 +319,13 @@ MODULE_DEVICE_TABLE(of, ssbi_match_table);
static struct platform_driver ssbi_driver = { static struct platform_driver ssbi_driver = {
.probe = ssbi_probe, .probe = ssbi_probe,
.remove = ssbi_remove,
.driver = { .driver = {
.name = "ssbi", .name = "ssbi",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.of_match_table = ssbi_match_table, .of_match_table = ssbi_match_table,
}, },
}; };
module_platform_driver(ssbi_driver);
static int __init ssbi_init(void)
{
return platform_driver_register(&ssbi_driver);
}
module_init(ssbi_init);
static void __exit ssbi_exit(void)
{
platform_driver_unregister(&ssbi_driver);
}
module_exit(ssbi_exit)
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_VERSION("1.0"); MODULE_VERSION("1.0");