mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
gpio: msm: Make msmgpio a platform device
The gpio driver was not a true platform driver and hence wasn't supported by device tree. This patch fixes that for non-DT targets by making sure the device gets added early on during board init. For DT-targets, adding the gpio-controller property for the device makes sure the msmgpio device gets probed. This change is done for all TLMM_v2 targets (msm8660 and future) TLMM_V1 targets remain unaffected. Change-Id: I8a55ab1e2af0366b3e6893b334ba2396d2a83190 Signed-off-by: Rohit Vaswani <rvaswani@codeaurora.org>
This commit is contained in:
parent
e72230cc4c
commit
cbb676c98c
13 changed files with 148 additions and 71 deletions
39
Documentation/devicetree/bindings/gpio/gpio-msm.txt
Normal file
39
Documentation/devicetree/bindings/gpio/gpio-msm.txt
Normal file
|
@ -0,0 +1,39 @@
|
|||
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
|
||||
|
||||
Example:
|
||||
|
||||
msmgpio: gpio@fd510000 {
|
||||
compatible = "qcom,msm-gpio";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
reg = <0xfd510000 0x4000>;
|
||||
};
|
||||
|
||||
To specify gpios for a device:
|
||||
|
||||
device1@f991f000 {
|
||||
compatible = "qcom,msm-device-v1";
|
||||
reg = <0xf991f000 0x1000>;
|
||||
gpios = <&msmgpio 45 0>;
|
||||
cs-gpios = <&msmgpio 46 0>;
|
||||
};
|
||||
|
||||
45, 46 - gpio numbers.
|
||||
The driver for device1 can call of_get_gpio() to extract the
|
||||
gpio45. In order to extract gpio46, the driver needs to call
|
||||
of_get_named_gpio with "cs-gpios" as the name parameter.
|
||||
Please refer to the file: include/linux/of_gpio.h for the
|
||||
complete list of APIs the driver can use to extract gpio
|
||||
information from the device tree.
|
|
@ -33,10 +33,11 @@
|
|||
|
||||
msmgpio: gpio@fd510000 {
|
||||
compatible = "qcom,msm-gpio";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
reg = <0xfd510000 0x4000>;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
timer {
|
||||
|
|
|
@ -37,6 +37,8 @@
|
|||
|
||||
msmgpio: gpio@fd510000 {
|
||||
compatible = "qcom,msm-gpio";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
reg = <0xfd510000 0x4000>;
|
||||
|
|
|
@ -2913,6 +2913,7 @@ static void enable_avc_i2c_bus(void)
|
|||
static void __init apq8064_common_init(void)
|
||||
{
|
||||
u32 platform_version;
|
||||
platform_device_register(&msm_gpio_device);
|
||||
msm_tsens_early_init(&apq_tsens_pdata);
|
||||
msm_thermal_init(&msm_thermal_pdata);
|
||||
if (socinfo_init() < 0)
|
||||
|
|
|
@ -2572,6 +2572,7 @@ static void __init msm8930_cdp_init(void)
|
|||
if (meminfo_init(SYS_MEMORY, SZ_256M) < 0)
|
||||
pr_err("meminfo_init() failed!\n");
|
||||
|
||||
platform_device_register(&msm_gpio_device);
|
||||
msm_tsens_early_init(&msm_tsens_pdata);
|
||||
msm_thermal_init(&msm_thermal_pdata);
|
||||
BUG_ON(msm_rpm_init(&msm8930_rpm_data));
|
||||
|
|
|
@ -3082,6 +3082,7 @@ static void __init msm8960_cdp_init(void)
|
|||
if (meminfo_init(SYS_MEMORY, SZ_256M) < 0)
|
||||
pr_err("meminfo_init() failed!\n");
|
||||
|
||||
platform_device_register(&msm_gpio_device);
|
||||
msm_tsens_early_init(&msm_tsens_pdata);
|
||||
msm_thermal_init(&msm_thermal_pdata);
|
||||
BUG_ON(msm_rpm_init(&msm8960_rpm_data));
|
||||
|
|
|
@ -976,6 +976,7 @@ static void __init msm9615_common_init(void)
|
|||
msm_android_usb_hsic_device.dev.platform_data;
|
||||
|
||||
msm9615_device_init();
|
||||
platform_device_register(&msm_gpio_device);
|
||||
msm9615_init_gpiomux();
|
||||
msm9615_i2c_init();
|
||||
regulator_suppress_info_printing();
|
||||
|
|
|
@ -10213,6 +10213,7 @@ static void __init msm8x60_init(struct msm_board_data *board_data)
|
|||
#endif
|
||||
pmic_reset_irq = PM8058_IRQ_BASE + PM8058_RESOUT_IRQ;
|
||||
|
||||
platform_device_register(&msm_gpio_device);
|
||||
/*
|
||||
* Initialize RPM first as other drivers and devices may need
|
||||
* it for their initialization.
|
||||
|
|
|
@ -4017,6 +4017,11 @@ static struct resource sglte_resources[] = {
|
|||
},
|
||||
};
|
||||
|
||||
struct platform_device msm_gpio_device = {
|
||||
.name = "msmgpio",
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
struct platform_device mdm_sglte_device = {
|
||||
.name = "mdm2_modem",
|
||||
.id = -1,
|
||||
|
|
|
@ -1372,6 +1372,10 @@ struct platform_device msm_android_usb_hsic_device = {
|
|||
},
|
||||
};
|
||||
|
||||
struct platform_device msm_gpio_device = {
|
||||
.name = "msmgpio",
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
void __init msm9615_device_init(void)
|
||||
{
|
||||
|
@ -1382,7 +1386,6 @@ void __init msm9615_device_init(void)
|
|||
msm_rpmrs_levels[0].latency_us;
|
||||
msm_android_usb_hsic_pdata.swfi_latency =
|
||||
msm_rpmrs_levels[0].latency_us;
|
||||
|
||||
}
|
||||
|
||||
#define MSM_SHARED_RAM_PHYS 0x40000000
|
||||
|
|
|
@ -100,6 +100,11 @@
|
|||
#define MSM_UART9DM_PHYS (MSM_GSBI9_PHYS + 0x40000)
|
||||
#define INT_UART9DM_IRQ GSBI9_UARTDM_IRQ
|
||||
|
||||
struct platform_device msm_gpio_device = {
|
||||
.name = "msmgpio",
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
static void charm_ap2mdm_kpdpwr_on(void)
|
||||
{
|
||||
gpio_direction_output(AP2MDM_PMIC_RESET_N, 0);
|
||||
|
|
|
@ -436,3 +436,5 @@ extern struct platform_device msm8930_device_acpuclk;
|
|||
extern struct platform_device msm8930aa_device_acpuclk;
|
||||
extern struct platform_device msm8960_device_acpuclk;
|
||||
extern struct platform_device msm9615_device_acpuclk;
|
||||
|
||||
extern struct platform_device msm_gpio_device;
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <linux/irqdomain.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <asm/mach/irq.h>
|
||||
|
||||
|
@ -402,59 +403,6 @@ static struct irq_chip msm_gpio_irq_chip = {
|
|||
.irq_disable = msm_gpio_irq_disable,
|
||||
};
|
||||
|
||||
/*
|
||||
* This lock class tells lockdep that GPIO irqs are in a different
|
||||
* category than their parent, so it won't report false recursion.
|
||||
*/
|
||||
static struct lock_class_key msm_gpio_lock_class;
|
||||
|
||||
/* TODO: This should be a real platform_driver */
|
||||
static int __devinit msm_gpio_probe(void)
|
||||
{
|
||||
int ret;
|
||||
#ifndef CONFIG_OF
|
||||
int irq, i;
|
||||
#endif
|
||||
|
||||
spin_lock_init(&tlmm_lock);
|
||||
bitmap_zero(msm_gpio.enabled_irqs, NR_MSM_GPIOS);
|
||||
bitmap_zero(msm_gpio.wake_irqs, NR_MSM_GPIOS);
|
||||
bitmap_zero(msm_gpio.dual_edge_irqs, NR_MSM_GPIOS);
|
||||
ret = gpiochip_add(&msm_gpio.gpio_chip);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
#ifndef CONFIG_OF
|
||||
for (i = 0; i < msm_gpio.gpio_chip.ngpio; ++i) {
|
||||
irq = msm_gpio_to_irq(&msm_gpio.gpio_chip, i);
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
ret = request_irq(TLMM_MSM_SUMMARY_IRQ, msm_summary_irq_handler,
|
||||
IRQF_TRIGGER_HIGH, "msmgpio", NULL);
|
||||
if (ret) {
|
||||
pr_err("Request_irq failed for TLMM_MSM_SUMMARY_IRQ - %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit msm_gpio_remove(void)
|
||||
{
|
||||
int ret = gpiochip_remove(&msm_gpio.gpio_chip);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
irq_set_handler(TLMM_MSM_SUMMARY_IRQ, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int msm_gpio_suspend(void)
|
||||
{
|
||||
|
@ -518,22 +466,6 @@ static struct syscore_ops msm_gpio_syscore_ops = {
|
|||
.resume = msm_gpio_resume,
|
||||
};
|
||||
|
||||
static int __init msm_gpio_init(void)
|
||||
{
|
||||
msm_gpio_probe();
|
||||
register_syscore_ops(&msm_gpio_syscore_ops);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit msm_gpio_exit(void)
|
||||
{
|
||||
unregister_syscore_ops(&msm_gpio_syscore_ops);
|
||||
msm_gpio_remove();
|
||||
}
|
||||
|
||||
postcore_initcall(msm_gpio_init);
|
||||
module_exit(msm_gpio_exit);
|
||||
|
||||
static void msm_tlmm_set_field(const struct tlmm_field_cfg *configs,
|
||||
unsigned id, unsigned width, unsigned val)
|
||||
{
|
||||
|
@ -594,6 +526,89 @@ int msm_gpio_install_direct_irq(unsigned gpio, unsigned irq,
|
|||
}
|
||||
EXPORT_SYMBOL(msm_gpio_install_direct_irq);
|
||||
|
||||
/*
|
||||
* This lock class tells lockdep that GPIO irqs are in a different
|
||||
* category than their parent, so it won't report false recursion.
|
||||
*/
|
||||
static struct lock_class_key msm_gpio_lock_class;
|
||||
|
||||
static int __devinit msm_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
#ifndef CONFIG_OF
|
||||
int irq, i;
|
||||
#endif
|
||||
msm_gpio.gpio_chip.dev = &pdev->dev;
|
||||
spin_lock_init(&tlmm_lock);
|
||||
bitmap_zero(msm_gpio.enabled_irqs, NR_MSM_GPIOS);
|
||||
bitmap_zero(msm_gpio.wake_irqs, NR_MSM_GPIOS);
|
||||
bitmap_zero(msm_gpio.dual_edge_irqs, NR_MSM_GPIOS);
|
||||
ret = gpiochip_add(&msm_gpio.gpio_chip);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
#ifndef CONFIG_OF
|
||||
for (i = 0; i < msm_gpio.gpio_chip.ngpio; ++i) {
|
||||
irq = msm_gpio_to_irq(&msm_gpio.gpio_chip, i);
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
ret = request_irq(TLMM_MSM_SUMMARY_IRQ, msm_summary_irq_handler,
|
||||
IRQF_TRIGGER_HIGH, "msmgpio", NULL);
|
||||
if (ret) {
|
||||
pr_err("Request_irq failed for TLMM_MSM_SUMMARY_IRQ - %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
register_syscore_ops(&msm_gpio_syscore_ops);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static struct of_device_id msm_gpio_of_match[] __devinitdata = {
|
||||
{.compatible = "qcom,msm-gpio", },
|
||||
{ },
|
||||
};
|
||||
#endif
|
||||
|
||||
static int __devexit msm_gpio_remove(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
unregister_syscore_ops(&msm_gpio_syscore_ops);
|
||||
ret = gpiochip_remove(&msm_gpio.gpio_chip);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
irq_set_handler(TLMM_MSM_SUMMARY_IRQ, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver msm_gpio_driver = {
|
||||
.probe = msm_gpio_probe,
|
||||
.remove = __devexit_p(msm_gpio_remove),
|
||||
.driver = {
|
||||
.name = "msmgpio",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(msm_gpio_of_match),
|
||||
},
|
||||
};
|
||||
|
||||
static void __exit msm_gpio_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&msm_gpio_driver);
|
||||
}
|
||||
module_exit(msm_gpio_exit);
|
||||
|
||||
static int __init msm_gpio_init(void)
|
||||
{
|
||||
return platform_driver_register(&msm_gpio_driver);
|
||||
}
|
||||
postcore_initcall(msm_gpio_init);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static int msm_gpio_irq_domain_xlate(struct irq_domain *d,
|
||||
struct device_node *controller,
|
||||
|
|
Loading…
Reference in a new issue