diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-26 22:56:38 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-26 22:56:38 +0200 |
commit | f948ad0787de7b393c325803014fd7d5f1b501b1 (patch) | |
tree | d5ac20ec61151809b8e365a137099a3f93562692 /drivers/gpio/gpio-mxc.c | |
parent | Merge branch 'stable' of git://git.kernel.org/pub/scm/linux/kernel/git/cmetca... (diff) | |
parent | gpio: of_get_named_gpio_flags() return -EPROBE_DEFER if GPIO not yet available (diff) | |
download | linux-f948ad0787de7b393c325803014fd7d5f1b501b1.tar.xz linux-f948ad0787de7b393c325803014fd7d5f1b501b1.zip |
Merge tag 'gpio-for-v3.6' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio
Pull GPIO changes from Linus Walleij:
- New driver for AMD-8111 southbridge GPIOs
- New driver for Wolfson Micro Arizona devices
- Propagate device tree parse errors
- Probe deferral finalizations - all expected calls to GPIO will now
hopefully request deferral where apropriate
- Misc updates to TCA6424, WM8994, LPC32xx, PCF857x, Samsung MXC, OMAP
and PCA953X drivers.
Fix up gpio_idx conflicts in drivers/gpio/gpio-mxc.c
* tag 'gpio-for-v3.6' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio:
gpio: of_get_named_gpio_flags() return -EPROBE_DEFER if GPIO not yet available
gpiolib: Defer failed gpio requests by default
MAINTAINERS: add entry OMAP GPIO driver
gpio/pca953x: increase variables size to support 24 bit of data
GPIO: PCA953X: Increase size of invert variable to support 24 bit
gpio/omap: move bank->dbck initialization to omap_gpio_mod_init()
gpio/mxc: use the edge_sel feature if available
gpio: propagate of_parse_phandle_with_args errors
gpio: samsung: add flags specifier to device-tree binding
gpiolib: Add support for Wolfson Microelectronics Arizona class devices
gpio: gpio-lpc32xx: Add gpio_to_irq mapping
gpio: pcf857x: share 8/16 bit access functions
gpio: LPC32xx: Driver cleanup
MAINTAINERS: Add Wolfson gpiolib drivers to the Wolfson entry
gpiolib: wm8994: Convert to devm_kzalloc()
gpiolib: wm8994: Use irq_domain mappings for gpios
gpio: add a driver for GPIO pins found on AMD-8111 south bridge chips
gpio/tca6424: merge I2C transactions, remove cast
gpio/of: fix a typo of comment message
Diffstat (limited to 'drivers/gpio/gpio-mxc.c')
-rw-r--r-- | drivers/gpio/gpio-mxc.c | 71 |
1 files changed, 57 insertions, 14 deletions
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index 04691d3abe60..4db460b6ecf7 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c @@ -37,7 +37,8 @@ enum mxc_gpio_hwtype { IMX1_GPIO, /* runs on i.mx1 */ IMX21_GPIO, /* runs on i.mx21 and i.mx27 */ - IMX31_GPIO, /* runs on all other i.mx */ + IMX31_GPIO, /* runs on i.mx31 */ + IMX35_GPIO, /* runs on all other i.mx */ }; /* device type dependent stuff */ @@ -49,6 +50,7 @@ struct mxc_gpio_hwdata { unsigned icr2_reg; unsigned imr_reg; unsigned isr_reg; + int edge_sel_reg; unsigned low_level; unsigned high_level; unsigned rise_edge; @@ -73,6 +75,7 @@ static struct mxc_gpio_hwdata imx1_imx21_gpio_hwdata = { .icr2_reg = 0x2c, .imr_reg = 0x30, .isr_reg = 0x34, + .edge_sel_reg = -EINVAL, .low_level = 0x03, .high_level = 0x02, .rise_edge = 0x00, @@ -87,6 +90,22 @@ static struct mxc_gpio_hwdata imx31_gpio_hwdata = { .icr2_reg = 0x10, .imr_reg = 0x14, .isr_reg = 0x18, + .edge_sel_reg = -EINVAL, + .low_level = 0x00, + .high_level = 0x01, + .rise_edge = 0x02, + .fall_edge = 0x03, +}; + +static struct mxc_gpio_hwdata imx35_gpio_hwdata = { + .dr_reg = 0x00, + .gdir_reg = 0x04, + .psr_reg = 0x08, + .icr1_reg = 0x0c, + .icr2_reg = 0x10, + .imr_reg = 0x14, + .isr_reg = 0x18, + .edge_sel_reg = 0x1c, .low_level = 0x00, .high_level = 0x01, .rise_edge = 0x02, @@ -103,12 +122,13 @@ static struct mxc_gpio_hwdata *mxc_gpio_hwdata; #define GPIO_ICR2 (mxc_gpio_hwdata->icr2_reg) #define GPIO_IMR (mxc_gpio_hwdata->imr_reg) #define GPIO_ISR (mxc_gpio_hwdata->isr_reg) +#define GPIO_EDGE_SEL (mxc_gpio_hwdata->edge_sel_reg) #define GPIO_INT_LOW_LEV (mxc_gpio_hwdata->low_level) #define GPIO_INT_HIGH_LEV (mxc_gpio_hwdata->high_level) #define GPIO_INT_RISE_EDGE (mxc_gpio_hwdata->rise_edge) #define GPIO_INT_FALL_EDGE (mxc_gpio_hwdata->fall_edge) -#define GPIO_INT_NONE 0x4 +#define GPIO_INT_BOTH_EDGES 0x4 static struct platform_device_id mxc_gpio_devtype[] = { { @@ -121,6 +141,9 @@ static struct platform_device_id mxc_gpio_devtype[] = { .name = "imx31-gpio", .driver_data = IMX31_GPIO, }, { + .name = "imx35-gpio", + .driver_data = IMX35_GPIO, + }, { /* sentinel */ } }; @@ -129,6 +152,7 @@ static const struct of_device_id mxc_gpio_dt_ids[] = { { .compatible = "fsl,imx1-gpio", .data = &mxc_gpio_devtype[IMX1_GPIO], }, { .compatible = "fsl,imx21-gpio", .data = &mxc_gpio_devtype[IMX21_GPIO], }, { .compatible = "fsl,imx31-gpio", .data = &mxc_gpio_devtype[IMX31_GPIO], }, + { .compatible = "fsl,imx35-gpio", .data = &mxc_gpio_devtype[IMX35_GPIO], }, { /* sentinel */ } }; @@ -160,15 +184,19 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type) edge = GPIO_INT_FALL_EDGE; break; case IRQ_TYPE_EDGE_BOTH: - val = gpio_get_value(gpio); - if (val) { - edge = GPIO_INT_LOW_LEV; - pr_debug("mxc: set GPIO %d to low trigger\n", gpio); + if (GPIO_EDGE_SEL >= 0) { + edge = GPIO_INT_BOTH_EDGES; } else { - edge = GPIO_INT_HIGH_LEV; - pr_debug("mxc: set GPIO %d to high trigger\n", gpio); + val = gpio_get_value(gpio); + if (val) { + edge = GPIO_INT_LOW_LEV; + pr_debug("mxc: set GPIO %d to low trigger\n", gpio); + } else { + edge = GPIO_INT_HIGH_LEV; + pr_debug("mxc: set GPIO %d to high trigger\n", gpio); + } + port->both_edges |= 1 << gpio_idx; } - port->both_edges |= 1 << gpio_idx; break; case IRQ_TYPE_LEVEL_LOW: edge = GPIO_INT_LOW_LEV; @@ -180,10 +208,23 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type) return -EINVAL; } - reg += GPIO_ICR1 + ((gpio_idx & 0x10) >> 2); /* ICR1 or ICR2 */ - bit = gpio_idx & 0xf; - val = readl(reg) & ~(0x3 << (bit << 1)); - writel(val | (edge << (bit << 1)), reg); + if (GPIO_EDGE_SEL >= 0) { + val = readl(port->base + GPIO_EDGE_SEL); + if (edge == GPIO_INT_BOTH_EDGES) + writel(val | (1 << gpio_idx), + port->base + GPIO_EDGE_SEL); + else + writel(val & ~(1 << gpio_idx), + port->base + GPIO_EDGE_SEL); + } + + if (edge != GPIO_INT_BOTH_EDGES) { + reg += GPIO_ICR1 + ((gpio_idx & 0x10) >> 2); /* lower or upper register */ + bit = gpio_idx & 0xf; + val = readl(reg) & ~(0x3 << (bit << 1)); + writel(val | (edge << (bit << 1)), reg); + } + writel(1 << gpio_idx, port->base + GPIO_ISR); return 0; @@ -335,7 +376,9 @@ static void __devinit mxc_gpio_get_hw(struct platform_device *pdev) return; } - if (hwtype == IMX31_GPIO) + if (hwtype == IMX35_GPIO) + mxc_gpio_hwdata = &imx35_gpio_hwdata; + else if (hwtype == IMX31_GPIO) mxc_gpio_hwdata = &imx31_gpio_hwdata; else mxc_gpio_hwdata = &imx1_imx21_gpio_hwdata; |