From 87c49e20579c933d531a376596875b8fd5dcb04f Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Mon, 10 Oct 2011 14:38:46 +0800 Subject: ARM: pxa: use chained interrupt for GPIO0 and GPIO1 GPIO0 and GPIO1 are linked to unique interrupt line in PXA series, others are linked to another interrupt line. All GPIO are linked to one interrupt line in MMP series. Since gpio driver is shared between PXA series and MMP series, define GPIO0 and GPIO1 as chained interrupt chip. So we can move out gpio code from irq.c to gpio-pxa.c. Signed-off-by: Haojian Zhuang Acked-by: Grant Likely --- drivers/gpio/gpio-pxa.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers') diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c index ee137712f9db..a4121bb50cf2 100644 --- a/drivers/gpio/gpio-pxa.c +++ b/drivers/gpio/gpio-pxa.c @@ -283,6 +283,20 @@ void __init pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn) __raw_writel(~0,c->regbase + GEDR_OFFSET); } +#ifdef CONFIG_ARCH_PXA + irq = gpio_to_irq(0); + irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip, + handle_edge_irq); + set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + irq_set_chained_handler(IRQ_GPIO0, pxa_gpio_demux_handler); + + irq = gpio_to_irq(1); + irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip, + handle_edge_irq); + set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + irq_set_chained_handler(IRQ_GPIO1, pxa_gpio_demux_handler); +#endif + for (irq = gpio_to_irq(start); irq <= gpio_to_irq(end); irq++) { irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip, handle_edge_irq); -- cgit v1.2.3-55-g7522 From 4929f5a8a99f64378659c5658621e45c90c2aaa9 Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Mon, 10 Oct 2011 16:03:51 +0800 Subject: ARM: pxa: rename gpio_to_irq and irq_to_gpio Avoid to define gpio_to_irq() and irq_to_gpio() for potential name confliction since multiple architecture will be built together. Signed-off-by: Haojian Zhuang --- arch/arm/mach-mmp/aspenite.c | 4 +- arch/arm/mach-mmp/flint.c | 4 +- arch/arm/mach-mmp/include/mach/gpio-pxa.h | 1 + arch/arm/mach-mmp/include/mach/gpio.h | 3 -- arch/arm/mach-mmp/include/mach/irqs.h | 1 + arch/arm/mach-mmp/tavorevb.c | 4 +- arch/arm/mach-mmp/teton_bga.c | 2 +- arch/arm/mach-pxa/capc7117.c | 12 ++--- arch/arm/mach-pxa/cm-x270.c | 2 +- arch/arm/mach-pxa/colibri-pxa270.c | 6 +-- arch/arm/mach-pxa/colibri-pxa300.c | 4 +- arch/arm/mach-pxa/colibri-pxa320.c | 4 +- arch/arm/mach-pxa/corgi.c | 2 +- arch/arm/mach-pxa/hx4700.c | 18 +++---- arch/arm/mach-pxa/icontrol.c | 8 +-- arch/arm/mach-pxa/include/mach/csb726.h | 4 +- arch/arm/mach-pxa/include/mach/gpio.h | 3 -- arch/arm/mach-pxa/littleton.c | 2 +- arch/arm/mach-pxa/magician.c | 8 +-- arch/arm/mach-pxa/mioa701.c | 8 +-- arch/arm/mach-pxa/mxm8x10.c | 4 +- arch/arm/mach-pxa/poodle.c | 2 +- arch/arm/mach-pxa/pxa25x.c | 2 +- arch/arm/mach-pxa/pxa27x.c | 2 +- arch/arm/mach-pxa/raumfeld.c | 8 +-- arch/arm/mach-pxa/saar.c | 6 +-- arch/arm/mach-pxa/saarb.c | 2 +- arch/arm/mach-pxa/spitz.c | 2 +- arch/arm/mach-pxa/stargate2.c | 4 +- arch/arm/mach-pxa/tavorevb.c | 4 +- arch/arm/mach-pxa/tavorevb3.c | 2 +- arch/arm/mach-pxa/tosa.c | 4 +- arch/arm/mach-pxa/viper.c | 12 ++--- arch/arm/mach-pxa/vpac270.c | 4 +- arch/arm/mach-pxa/z2.c | 2 +- arch/arm/mach-pxa/zeus.c | 20 +++---- arch/arm/mach-pxa/zylonite.c | 4 +- arch/arm/plat-pxa/include/plat/gpio-pxa.h | 1 + drivers/gpio/gpio-pxa.c | 89 +++++++++++++++++++++++++++++-- 39 files changed, 176 insertions(+), 98 deletions(-) (limited to 'drivers') diff --git a/arch/arm/mach-mmp/aspenite.c b/arch/arm/mach-mmp/aspenite.c index 06b5ad774604..fb7dfc157a5c 100644 --- a/arch/arm/mach-mmp/aspenite.c +++ b/arch/arm/mach-mmp/aspenite.c @@ -120,8 +120,8 @@ static struct resource smc91x_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = gpio_to_irq(27), - .end = gpio_to_irq(27), + .start = MMP_GPIO_TO_IRQ(27), + .end = MMP_GPIO_TO_IRQ(27), .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, } }; diff --git a/arch/arm/mach-mmp/flint.c b/arch/arm/mach-mmp/flint.c index c4fd806b15b4..a64c172082c4 100644 --- a/arch/arm/mach-mmp/flint.c +++ b/arch/arm/mach-mmp/flint.c @@ -87,8 +87,8 @@ static struct resource smc91x_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = gpio_to_irq(155), - .end = gpio_to_irq(155), + .start = MMP_GPIO_TO_IRQ(155), + .end = MMP_GPIO_TO_IRQ(155), .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, } }; diff --git a/arch/arm/mach-mmp/include/mach/gpio-pxa.h b/arch/arm/mach-mmp/include/mach/gpio-pxa.h index d14eeaf16322..a462d1ca214e 100644 --- a/arch/arm/mach-mmp/include/mach/gpio-pxa.h +++ b/arch/arm/mach-mmp/include/mach/gpio-pxa.h @@ -2,6 +2,7 @@ #define __ASM_MACH_GPIO_PXA_H #include +#include #include #define GPIO_REGS_VIRT (APB_VIRT_BASE + 0x19000) diff --git a/arch/arm/mach-mmp/include/mach/gpio.h b/arch/arm/mach-mmp/include/mach/gpio.h index 681262359d1c..32b684aacea8 100644 --- a/arch/arm/mach-mmp/include/mach/gpio.h +++ b/arch/arm/mach-mmp/include/mach/gpio.h @@ -3,9 +3,6 @@ #include -#define gpio_to_irq(gpio) (IRQ_GPIO_START + (gpio)) -#define irq_to_gpio(irq) ((irq) - IRQ_GPIO_START) - #define __gpio_is_inverted(gpio) (0) #define __gpio_is_occupied(gpio) (0) diff --git a/arch/arm/mach-mmp/include/mach/irqs.h b/arch/arm/mach-mmp/include/mach/irqs.h index a09d328e2ddd..ec95951f0983 100644 --- a/arch/arm/mach-mmp/include/mach/irqs.h +++ b/arch/arm/mach-mmp/include/mach/irqs.h @@ -221,6 +221,7 @@ #define IRQ_GPIO_START 128 #define IRQ_GPIO_NUM 192 #define IRQ_GPIO(x) (IRQ_GPIO_START + (x)) +#define MMP_GPIO_TO_IRQ(gpio) (IRQ_GPIO_START + (gpio)) #define IRQ_BOARD_START (IRQ_GPIO_START + IRQ_GPIO_NUM) diff --git a/arch/arm/mach-mmp/tavorevb.c b/arch/arm/mach-mmp/tavorevb.c index eb5be879fd8c..0afe3a39982f 100644 --- a/arch/arm/mach-mmp/tavorevb.c +++ b/arch/arm/mach-mmp/tavorevb.c @@ -71,8 +71,8 @@ static struct resource smc91x_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = gpio_to_irq(80), - .end = gpio_to_irq(80), + .start = MMP_GPIO_TO_IRQ(80), + .end = MMP_GPIO_TO_IRQ(80), .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, } }; diff --git a/arch/arm/mach-mmp/teton_bga.c b/arch/arm/mach-mmp/teton_bga.c index bbe4727b96cc..825a01cdcccd 100644 --- a/arch/arm/mach-mmp/teton_bga.c +++ b/arch/arm/mach-mmp/teton_bga.c @@ -66,7 +66,7 @@ static struct pxa27x_keypad_platform_data teton_bga_keypad_info __initdata = { static struct i2c_board_info teton_bga_i2c_info[] __initdata = { { I2C_BOARD_INFO("ds1337", 0x68), - .irq = gpio_to_irq(RTC_INT_GPIO) + .irq = MMP_GPIO_TO_IRQ(RTC_INT_GPIO) }, }; diff --git a/arch/arm/mach-pxa/capc7117.c b/arch/arm/mach-pxa/capc7117.c index 4efc16d39c79..5516317b9e64 100644 --- a/arch/arm/mach-pxa/capc7117.c +++ b/arch/arm/mach-pxa/capc7117.c @@ -50,8 +50,8 @@ static struct resource capc7117_ide_resources[] = { .flags = IORESOURCE_MEM }, [2] = { - .start = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO76)), - .end = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO76)), + .start = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO76)), + .end = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO76)), .flags = IORESOURCE_IRQ | IRQF_TRIGGER_RISING } }; @@ -80,7 +80,7 @@ static void __init capc7117_ide_init(void) static struct plat_serial8250_port ti16c752_platform_data[] = { [0] = { .mapbase = 0x14000000, - .irq = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO78)), + .irq = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO78)), .irqflags = IRQF_TRIGGER_RISING, .flags = TI16C752_FLAGS, .iotype = UPIO_MEM, @@ -89,7 +89,7 @@ static struct plat_serial8250_port ti16c752_platform_data[] = { }, [1] = { .mapbase = 0x14000040, - .irq = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO79)), + .irq = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO79)), .irqflags = IRQF_TRIGGER_RISING, .flags = TI16C752_FLAGS, .iotype = UPIO_MEM, @@ -98,7 +98,7 @@ static struct plat_serial8250_port ti16c752_platform_data[] = { }, [2] = { .mapbase = 0x14000080, - .irq = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO80)), + .irq = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO80)), .irqflags = IRQF_TRIGGER_RISING, .flags = TI16C752_FLAGS, .iotype = UPIO_MEM, @@ -107,7 +107,7 @@ static struct plat_serial8250_port ti16c752_platform_data[] = { }, [3] = { .mapbase = 0x140000c0, - .irq = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO81)), + .irq = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO81)), .irqflags = IRQF_TRIGGER_RISING, .flags = TI16C752_FLAGS, .iotype = UPIO_MEM, diff --git a/arch/arm/mach-pxa/cm-x270.c b/arch/arm/mach-pxa/cm-x270.c index 4ebcee5756b1..431ef56700c4 100644 --- a/arch/arm/mach-pxa/cm-x270.c +++ b/arch/arm/mach-pxa/cm-x270.c @@ -380,7 +380,7 @@ static struct spi_board_info cm_x270_spi_devices[] __initdata = { .modalias = "libertas_spi", .max_speed_hz = 13000000, .bus_num = 2, - .irq = gpio_to_irq(95), + .irq = PXA_GPIO_TO_IRQ(95), .chip_select = 0, .controller_data = &cm_x270_libertas_chip, .platform_data = &cm_x270_libertas_pdata, diff --git a/arch/arm/mach-pxa/colibri-pxa270.c b/arch/arm/mach-pxa/colibri-pxa270.c index 05bfa1b1c001..f0fe9a51dfcc 100644 --- a/arch/arm/mach-pxa/colibri-pxa270.c +++ b/arch/arm/mach-pxa/colibri-pxa270.c @@ -218,8 +218,8 @@ static struct resource colibri_pxa270_dm9000_resources[] = { .flags = IORESOURCE_MEM, }, { - .start = gpio_to_irq(GPIO114_COLIBRI_PXA270_ETH_IRQ), - .end = gpio_to_irq(GPIO114_COLIBRI_PXA270_ETH_IRQ), + .start = PXA_GPIO_TO_IRQ(GPIO114_COLIBRI_PXA270_ETH_IRQ), + .end = PXA_GPIO_TO_IRQ(GPIO114_COLIBRI_PXA270_ETH_IRQ), .flags = IORESOURCE_IRQ | IRQF_TRIGGER_RISING, }, }; @@ -249,7 +249,7 @@ static pxa2xx_audio_ops_t colibri_pxa270_ac97_pdata = { }; static struct ucb1400_pdata colibri_pxa270_ucb1400_pdata = { - .irq = gpio_to_irq(GPIO113_COLIBRI_PXA270_TS_IRQ), + .irq = PXA_GPIO_TO_IRQ(GPIO113_COLIBRI_PXA270_TS_IRQ), }; static struct platform_device colibri_pxa270_ucb1400_device = { diff --git a/arch/arm/mach-pxa/colibri-pxa300.c b/arch/arm/mach-pxa/colibri-pxa300.c index c825e8bf2db1..0a6222e20f9b 100644 --- a/arch/arm/mach-pxa/colibri-pxa300.c +++ b/arch/arm/mach-pxa/colibri-pxa300.c @@ -78,8 +78,8 @@ static struct resource colibri_asix_resource[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = gpio_to_irq(COLIBRI_ETH_IRQ_GPIO), - .end = gpio_to_irq(COLIBRI_ETH_IRQ_GPIO), + .start = PXA_GPIO_TO_IRQ(COLIBRI_ETH_IRQ_GPIO), + .end = PXA_GPIO_TO_IRQ(COLIBRI_ETH_IRQ_GPIO), .flags = IORESOURCE_IRQ | IRQF_TRIGGER_FALLING, } }; diff --git a/arch/arm/mach-pxa/colibri-pxa320.c b/arch/arm/mach-pxa/colibri-pxa320.c index 692e1ffc5586..8cbb2b43ed11 100644 --- a/arch/arm/mach-pxa/colibri-pxa320.c +++ b/arch/arm/mach-pxa/colibri-pxa320.c @@ -115,8 +115,8 @@ static struct resource colibri_asix_resource[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = gpio_to_irq(COLIBRI_ETH_IRQ_GPIO), - .end = gpio_to_irq(COLIBRI_ETH_IRQ_GPIO), + .start = PXA_GPIO_TO_IRQ(COLIBRI_ETH_IRQ_GPIO), + .end = PXA_GPIO_TO_IRQ(COLIBRI_ETH_IRQ_GPIO), .flags = IORESOURCE_IRQ | IRQF_TRIGGER_FALLING, } }; diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c index 549468d088b9..3812ba0ff50c 100644 --- a/arch/arm/mach-pxa/corgi.c +++ b/arch/arm/mach-pxa/corgi.c @@ -531,7 +531,7 @@ static struct spi_board_info corgi_spi_devices[] = { .chip_select = 0, .platform_data = &corgi_ads7846_info, .controller_data= &corgi_ads7846_chip, - .irq = gpio_to_irq(CORGI_GPIO_TP_INT), + .irq = PXA_GPIO_TO_IRQ(CORGI_GPIO_TP_INT), }, { .modalias = "corgi-lcd", .max_speed_hz = 50000, diff --git a/arch/arm/mach-pxa/hx4700.c b/arch/arm/mach-pxa/hx4700.c index 6f6368ece9bd..82e9976e5657 100644 --- a/arch/arm/mach-pxa/hx4700.c +++ b/arch/arm/mach-pxa/hx4700.c @@ -252,8 +252,8 @@ static struct resource asic3_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = gpio_to_irq(GPIO12_HX4700_ASIC3_IRQ), - .end = gpio_to_irq(GPIO12_HX4700_ASIC3_IRQ), + .start = PXA_GPIO_TO_IRQ(GPIO12_HX4700_ASIC3_IRQ), + .end = PXA_GPIO_TO_IRQ(GPIO12_HX4700_ASIC3_IRQ), .flags = IORESOURCE_IRQ, }, /* SD part */ @@ -263,8 +263,8 @@ static struct resource asic3_resources[] = { .flags = IORESOURCE_MEM, }, [3] = { - .start = gpio_to_irq(GPIO66_HX4700_ASIC3_nSDIO_IRQ), - .end = gpio_to_irq(GPIO66_HX4700_ASIC3_nSDIO_IRQ), + .start = PXA_GPIO_TO_IRQ(GPIO66_HX4700_ASIC3_nSDIO_IRQ), + .end = PXA_GPIO_TO_IRQ(GPIO66_HX4700_ASIC3_nSDIO_IRQ), .flags = IORESOURCE_IRQ, }, }; @@ -587,7 +587,7 @@ static struct spi_board_info tsc2046_board_info[] __initdata = { .modalias = "ads7846", .bus_num = 2, .max_speed_hz = 2600000, /* 100 kHz sample rate */ - .irq = gpio_to_irq(GPIO58_HX4700_TSC2046_nPENIRQ), + .irq = PXA_GPIO_TO_IRQ(GPIO58_HX4700_TSC2046_nPENIRQ), .platform_data = &tsc2046_info, .controller_data = &tsc2046_chip, }, @@ -635,15 +635,15 @@ static struct resource power_supply_resources[] = { .name = "ac", .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_LOWEDGE, - .start = gpio_to_irq(GPIOD9_nAC_IN), - .end = gpio_to_irq(GPIOD9_nAC_IN), + .start = PXA_GPIO_TO_IRQ(GPIOD9_nAC_IN), + .end = PXA_GPIO_TO_IRQ(GPIOD9_nAC_IN), }, [1] = { .name = "usb", .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_LOWEDGE, - .start = gpio_to_irq(GPIOD14_nUSBC_DETECT), - .end = gpio_to_irq(GPIOD14_nUSBC_DETECT), + .start = PXA_GPIO_TO_IRQ(GPIOD14_nUSBC_DETECT), + .end = PXA_GPIO_TO_IRQ(GPIOD14_nUSBC_DETECT), }, }; diff --git a/arch/arm/mach-pxa/icontrol.c b/arch/arm/mach-pxa/icontrol.c index f78d5db758da..33e81e87a9da 100644 --- a/arch/arm/mach-pxa/icontrol.c +++ b/arch/arm/mach-pxa/icontrol.c @@ -86,7 +86,7 @@ static struct spi_board_info mcp251x_board_info[] = { .chip_select = 0, .platform_data = &mcp251x_info, .controller_data = &mcp251x_chip_info1, - .irq = gpio_to_irq(ICONTROL_MCP251x_nIRQ1) + .irq = PXA_GPIO_TO_IRQ(ICONTROL_MCP251x_nIRQ1) }, { .modalias = "mcp2515", @@ -95,7 +95,7 @@ static struct spi_board_info mcp251x_board_info[] = { .chip_select = 1, .platform_data = &mcp251x_info, .controller_data = &mcp251x_chip_info2, - .irq = gpio_to_irq(ICONTROL_MCP251x_nIRQ2) + .irq = PXA_GPIO_TO_IRQ(ICONTROL_MCP251x_nIRQ2) }, { .modalias = "mcp2515", @@ -104,7 +104,7 @@ static struct spi_board_info mcp251x_board_info[] = { .chip_select = 0, .platform_data = &mcp251x_info, .controller_data = &mcp251x_chip_info3, - .irq = gpio_to_irq(ICONTROL_MCP251x_nIRQ3) + .irq = PXA_GPIO_TO_IRQ(ICONTROL_MCP251x_nIRQ3) }, { .modalias = "mcp2515", @@ -113,7 +113,7 @@ static struct spi_board_info mcp251x_board_info[] = { .chip_select = 1, .platform_data = &mcp251x_info, .controller_data = &mcp251x_chip_info4, - .irq = gpio_to_irq(ICONTROL_MCP251x_nIRQ4) + .irq = PXA_GPIO_TO_IRQ(ICONTROL_MCP251x_nIRQ4) } }; diff --git a/arch/arm/mach-pxa/include/mach/csb726.h b/arch/arm/mach-pxa/include/mach/csb726.h index 747ab1a71f2f..2628e7b72116 100644 --- a/arch/arm/mach-pxa/include/mach/csb726.h +++ b/arch/arm/mach-pxa/include/mach/csb726.h @@ -19,8 +19,8 @@ #define CSB726_FLASH_SIZE (64 * 1024 * 1024) #define CSB726_FLASH_uMON (8 * 1024 * 1024) -#define CSB726_IRQ_LAN gpio_to_irq(CSB726_GPIO_IRQ_LAN) -#define CSB726_IRQ_SM501 gpio_to_irq(CSB726_GPIO_IRQ_SM501) +#define CSB726_IRQ_LAN PXA_GPIO_TO_IRQ(CSB726_GPIO_IRQ_LAN) +#define CSB726_IRQ_SM501 PXA_GPIO_TO_IRQ(CSB726_GPIO_IRQ_SM501) #endif diff --git a/arch/arm/mach-pxa/include/mach/gpio.h b/arch/arm/mach-pxa/include/mach/gpio.h index 13b903907087..5cf0137e64d9 100644 --- a/arch/arm/mach-pxa/include/mach/gpio.h +++ b/arch/arm/mach-pxa/include/mach/gpio.h @@ -28,8 +28,5 @@ /* The defines for the driver are needed for the accelerated accessors */ #include "gpio-pxa.h" -#define gpio_to_irq(gpio) PXA_GPIO_TO_IRQ(gpio) -#define irq_to_gpio(irq) (irq - PXA_GPIO_TO_IRQ(0)) - #include #endif diff --git a/arch/arm/mach-pxa/littleton.c b/arch/arm/mach-pxa/littleton.c index 9cd235698771..27147f6ff7cb 100644 --- a/arch/arm/mach-pxa/littleton.c +++ b/arch/arm/mach-pxa/littleton.c @@ -395,7 +395,7 @@ static struct i2c_board_info littleton_i2c_info[] = { .type = "da9034", .addr = 0x34, .platform_data = &littleton_da9034_info, - .irq = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO18)), + .irq = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO18)), }, [1] = { .type = "max7320", diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c index 4b796c37af3e..e340ea084248 100644 --- a/arch/arm/mach-pxa/magician.c +++ b/arch/arm/mach-pxa/magician.c @@ -184,8 +184,8 @@ static struct resource egpio_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = gpio_to_irq(GPIO13_MAGICIAN_CPLD_IRQ), - .end = gpio_to_irq(GPIO13_MAGICIAN_CPLD_IRQ), + .start = PXA_GPIO_TO_IRQ(GPIO13_MAGICIAN_CPLD_IRQ), + .end = PXA_GPIO_TO_IRQ(GPIO13_MAGICIAN_CPLD_IRQ), .flags = IORESOURCE_IRQ, }, }; @@ -468,8 +468,8 @@ static struct resource pasic3_resources[] = { }, /* No IRQ handler in the PASIC3, DS1WM needs an external IRQ */ [1] = { - .start = gpio_to_irq(GPIO107_MAGICIAN_DS1WM_IRQ), - .end = gpio_to_irq(GPIO107_MAGICIAN_DS1WM_IRQ), + .start = PXA_GPIO_TO_IRQ(GPIO107_MAGICIAN_DS1WM_IRQ), + .end = PXA_GPIO_TO_IRQ(GPIO107_MAGICIAN_DS1WM_IRQ), .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, } }; diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c index b938fc2c316a..23f90c74c191 100644 --- a/arch/arm/mach-pxa/mioa701.c +++ b/arch/arm/mach-pxa/mioa701.c @@ -541,15 +541,15 @@ static struct pda_power_pdata power_pdata = { static struct resource power_resources[] = { [0] = { .name = "ac", - .start = gpio_to_irq(GPIO96_AC_DETECT), - .end = gpio_to_irq(GPIO96_AC_DETECT), + .start = PXA_GPIO_TO_IRQ(GPIO96_AC_DETECT), + .end = PXA_GPIO_TO_IRQ(GPIO96_AC_DETECT), .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_LOWEDGE, }, [1] = { .name = "usb", - .start = gpio_to_irq(GPIO13_nUSB_DETECT), - .end = gpio_to_irq(GPIO13_nUSB_DETECT), + .start = PXA_GPIO_TO_IRQ(GPIO13_nUSB_DETECT), + .end = PXA_GPIO_TO_IRQ(GPIO13_nUSB_DETECT), .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_LOWEDGE, }, diff --git a/arch/arm/mach-pxa/mxm8x10.c b/arch/arm/mach-pxa/mxm8x10.c index b5a8fd3fce04..a13a1e365851 100644 --- a/arch/arm/mach-pxa/mxm8x10.c +++ b/arch/arm/mach-pxa/mxm8x10.c @@ -416,8 +416,8 @@ static struct resource dm9k_resources[] = { .flags = IORESOURCE_MEM }, [2] = { - .start = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO9)), - .end = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO9)), + .start = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO9)), + .end = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO9)), .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE } }; diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c index 1e6d796829ac..8ee4b6cfa385 100644 --- a/arch/arm/mach-pxa/poodle.c +++ b/arch/arm/mach-pxa/poodle.c @@ -212,7 +212,7 @@ static struct spi_board_info poodle_spi_devices[] = { .bus_num = 1, .platform_data = &poodle_ads7846_info, .controller_data= &poodle_ads7846_chip, - .irq = gpio_to_irq(POODLE_GPIO_TP_INT), + .irq = PXA_GPIO_TO_IRQ(POODLE_GPIO_TP_INT), }, }; diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c index f05f9486b0cb..0f38cfce5c35 100644 --- a/arch/arm/mach-pxa/pxa25x.c +++ b/arch/arm/mach-pxa/pxa25x.c @@ -287,7 +287,7 @@ static inline void pxa25x_init_pm(void) {} static int pxa25x_set_wake(struct irq_data *d, unsigned int on) { - int gpio = irq_to_gpio(d->irq); + int gpio = pxa_irq_to_gpio(d->irq); uint32_t mask = 0; if (gpio >= 0 && gpio < 85) diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index bc5a98ebaa72..44563a0997bd 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c @@ -355,7 +355,7 @@ static inline void pxa27x_init_pm(void) {} */ static int pxa27x_set_wake(struct irq_data *d, unsigned int on) { - int gpio = irq_to_gpio(d->irq); + int gpio = pxa_irq_to_gpio(d->irq); uint32_t mask; if (gpio >= 0 && gpio < 128) diff --git a/arch/arm/mach-pxa/raumfeld.c b/arch/arm/mach-pxa/raumfeld.c index 6810cddec927..9c58e87f2b82 100644 --- a/arch/arm/mach-pxa/raumfeld.c +++ b/arch/arm/mach-pxa/raumfeld.c @@ -292,8 +292,8 @@ static struct resource smc91x_resources[] = { .flags = IORESOURCE_MEM, }, { - .start = gpio_to_irq(GPIO_ETH_IRQ), - .end = gpio_to_irq(GPIO_ETH_IRQ), + .start = PXA_GPIO_TO_IRQ(GPIO_ETH_IRQ), + .end = PXA_GPIO_TO_IRQ(GPIO_ETH_IRQ), .flags = IORESOURCE_IRQ | IRQF_TRIGGER_FALLING, } }; @@ -671,7 +671,7 @@ static struct lis3lv02d_platform_data lis3_pdata = { .chip_select = 1, \ .controller_data = (void *) GPIO_ACCEL_CS, \ .platform_data = &lis3_pdata, \ - .irq = gpio_to_irq(GPIO_ACCEL_IRQ), \ + .irq = PXA_GPIO_TO_IRQ(GPIO_ACCEL_IRQ), \ } #define SPI_DAC7512 \ @@ -955,7 +955,7 @@ static struct eeti_ts_platform_data eeti_ts_pdata = { static struct i2c_board_info raumfeld_controller_i2c_board_info __initdata = { .type = "eeti_ts", .addr = 0x0a, - .irq = gpio_to_irq(GPIO_TOUCH_IRQ), + .irq = PXA_GPIO_TO_IRQ(GPIO_TOUCH_IRQ), .platform_data = &eeti_ts_pdata, }; diff --git a/arch/arm/mach-pxa/saar.c b/arch/arm/mach-pxa/saar.c index fc2c1e05af9c..423ec899a8a8 100644 --- a/arch/arm/mach-pxa/saar.c +++ b/arch/arm/mach-pxa/saar.c @@ -96,8 +96,8 @@ static struct resource smc91x_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO97)), - .end = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO97)), + .start = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO97)), + .end = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO97)), .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, } }; @@ -502,7 +502,7 @@ static struct i2c_board_info saar_i2c_info[] = { .type = "da9034", .addr = 0x34, .platform_data = &saar_da9034_info, - .irq = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO83)), + .irq = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO83)), }, }; diff --git a/arch/arm/mach-pxa/saarb.c b/arch/arm/mach-pxa/saarb.c index 3e999e308a2d..d1cdd6a081ed 100644 --- a/arch/arm/mach-pxa/saarb.c +++ b/arch/arm/mach-pxa/saarb.c @@ -92,7 +92,7 @@ static struct i2c_board_info saarb_i2c_info[] = { .type = "88PM860x", .addr = 0x34, .platform_data = &saarb_pm8607_info, - .irq = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO83)), + .irq = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO83)), }, }; diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index 953a9195f9e5..1b39cec03cce 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c @@ -552,7 +552,7 @@ static struct spi_board_info spitz_spi_devices[] = { .chip_select = 0, .platform_data = &spitz_ads7846_info, .controller_data = &spitz_ads7846_chip, - .irq = gpio_to_irq(SPITZ_GPIO_TP_INT), + .irq = PXA_GPIO_TO_IRQ(SPITZ_GPIO_TP_INT), }, { .modalias = "corgi-lcd", .max_speed_hz = 50000, diff --git a/arch/arm/mach-pxa/stargate2.c b/arch/arm/mach-pxa/stargate2.c index bbf79d532d1e..940ca56b37f9 100644 --- a/arch/arm/mach-pxa/stargate2.c +++ b/arch/arm/mach-pxa/stargate2.c @@ -546,7 +546,7 @@ static struct i2c_board_info __initdata imote2_pwr_i2c_board_info[] = { .type = "da9030", .addr = 0x49, .platform_data = &imote2_da9030_pdata, - .irq = gpio_to_irq(1), + .irq = PXA_GPIO_TO_IRQ(1), }, }; @@ -913,7 +913,7 @@ static struct i2c_board_info __initdata stargate2_pwr_i2c_board_info[] = { .type = "da9030", .addr = 0x49, .platform_data = &stargate2_da9030_pdata, - .irq = gpio_to_irq(1), + .irq = PXA_GPIO_TO_IRQ(1), }, }; diff --git a/arch/arm/mach-pxa/tavorevb.c b/arch/arm/mach-pxa/tavorevb.c index ad47bb98f30d..43bdcb9761f2 100644 --- a/arch/arm/mach-pxa/tavorevb.c +++ b/arch/arm/mach-pxa/tavorevb.c @@ -85,8 +85,8 @@ static struct resource smc91x_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO47)), - .end = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO47)), + .start = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO47)), + .end = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO47)), .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, } }; diff --git a/arch/arm/mach-pxa/tavorevb3.c b/arch/arm/mach-pxa/tavorevb3.c index fd569167302a..46c60b3cbe79 100644 --- a/arch/arm/mach-pxa/tavorevb3.c +++ b/arch/arm/mach-pxa/tavorevb3.c @@ -101,7 +101,7 @@ static struct i2c_board_info evb3_i2c_info[] = { .type = "88PM860x", .addr = 0x34, .platform_data = &evb3_pm8607_info, - .irq = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO83)), + .irq = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO83)), }, }; diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index 402b0c96613b..1ddb9826448a 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c @@ -404,8 +404,8 @@ static struct pda_power_pdata tosa_power_data = { static struct resource tosa_power_resource[] = { { .name = "ac", - .start = gpio_to_irq(TOSA_GPIO_AC_IN), - .end = gpio_to_irq(TOSA_GPIO_AC_IN), + .start = PXA_GPIO_TO_IRQ(TOSA_GPIO_AC_IN), + .end = PXA_GPIO_TO_IRQ(TOSA_GPIO_AC_IN), .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_LOWEDGE, diff --git a/arch/arm/mach-pxa/viper.c b/arch/arm/mach-pxa/viper.c index 242ddae332d3..d9a653a77176 100644 --- a/arch/arm/mach-pxa/viper.c +++ b/arch/arm/mach-pxa/viper.c @@ -422,8 +422,8 @@ static struct resource smc91x_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = gpio_to_irq(VIPER_ETH_GPIO), - .end = gpio_to_irq(VIPER_ETH_GPIO), + .start = PXA_GPIO_TO_IRQ(VIPER_ETH_GPIO), + .end = PXA_GPIO_TO_IRQ(VIPER_ETH_GPIO), .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, }, [2] = { @@ -546,7 +546,7 @@ static struct plat_serial8250_port serial_platform_data[] = { /* External UARTs */ { .mapbase = VIPER_UARTA_PHYS, - .irq = gpio_to_irq(VIPER_UARTA_GPIO), + .irq = PXA_GPIO_TO_IRQ(VIPER_UARTA_GPIO), .irqflags = IRQF_TRIGGER_RISING, .uartclk = 1843200, .regshift = 1, @@ -556,7 +556,7 @@ static struct plat_serial8250_port serial_platform_data[] = { }, { .mapbase = VIPER_UARTB_PHYS, - .irq = gpio_to_irq(VIPER_UARTB_GPIO), + .irq = PXA_GPIO_TO_IRQ(VIPER_UARTB_GPIO), .irqflags = IRQF_TRIGGER_RISING, .uartclk = 1843200, .regshift = 1, @@ -596,8 +596,8 @@ static struct resource isp116x_resources[] = { .flags = IORESOURCE_MEM, }, [2] = { - .start = gpio_to_irq(VIPER_USB_GPIO), - .end = gpio_to_irq(VIPER_USB_GPIO), + .start = PXA_GPIO_TO_IRQ(VIPER_USB_GPIO), + .end = PXA_GPIO_TO_IRQ(VIPER_USB_GPIO), .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, }, }; diff --git a/arch/arm/mach-pxa/vpac270.c b/arch/arm/mach-pxa/vpac270.c index 585e4f443e15..bf2403c424bf 100644 --- a/arch/arm/mach-pxa/vpac270.c +++ b/arch/arm/mach-pxa/vpac270.c @@ -610,8 +610,8 @@ static struct resource vpac270_ide_resources[] = { .flags = IORESOURCE_DMA }, [3] = { /* IDE IRQ pin */ - .start = gpio_to_irq(GPIO36_VPAC270_IDE_IRQ), - .end = gpio_to_irq(GPIO36_VPAC270_IDE_IRQ), + .start = PXA_GPIO_TO_IRQ(GPIO36_VPAC270_IDE_IRQ), + .end = PXA_GPIO_TO_IRQ(GPIO36_VPAC270_IDE_IRQ), .flags = IORESOURCE_IRQ } }; diff --git a/arch/arm/mach-pxa/z2.c b/arch/arm/mach-pxa/z2.c index ead32c90fec1..424661833ce2 100644 --- a/arch/arm/mach-pxa/z2.c +++ b/arch/arm/mach-pxa/z2.c @@ -573,7 +573,7 @@ static struct spi_board_info spi_board_info[] __initdata = { .modalias = "libertas_spi", .platform_data = &z2_lbs_pdata, .controller_data = &z2_lbs_chip_info, - .irq = gpio_to_irq(GPIO36_ZIPITZ2_WIFI_IRQ), + .irq = PXA_GPIO_TO_IRQ(GPIO36_ZIPITZ2_WIFI_IRQ), .max_speed_hz = 13000000, .bus_num = 1, .chip_select = 0, diff --git a/arch/arm/mach-pxa/zeus.c b/arch/arm/mach-pxa/zeus.c index 498b83b089f3..68de9c17e4c5 100644 --- a/arch/arm/mach-pxa/zeus.c +++ b/arch/arm/mach-pxa/zeus.c @@ -233,7 +233,7 @@ static struct plat_serial8250_port serial_platform_data[] = { /* FIXME: Shared IRQs on COM1-COM4 will not work properly on v1i1 hardware. */ { /* COM1 */ .mapbase = 0x10000000, - .irq = gpio_to_irq(ZEUS_UARTA_GPIO), + .irq = PXA_GPIO_TO_IRQ(ZEUS_UARTA_GPIO), .irqflags = IRQF_TRIGGER_RISING, .uartclk = 14745600, .regshift = 1, @@ -242,7 +242,7 @@ static struct plat_serial8250_port serial_platform_data[] = { }, { /* COM2 */ .mapbase = 0x10800000, - .irq = gpio_to_irq(ZEUS_UARTB_GPIO), + .irq = PXA_GPIO_TO_IRQ(ZEUS_UARTB_GPIO), .irqflags = IRQF_TRIGGER_RISING, .uartclk = 14745600, .regshift = 1, @@ -251,7 +251,7 @@ static struct plat_serial8250_port serial_platform_data[] = { }, { /* COM3 */ .mapbase = 0x11000000, - .irq = gpio_to_irq(ZEUS_UARTC_GPIO), + .irq = PXA_GPIO_TO_IRQ(ZEUS_UARTC_GPIO), .irqflags = IRQF_TRIGGER_RISING, .uartclk = 14745600, .regshift = 1, @@ -260,7 +260,7 @@ static struct plat_serial8250_port serial_platform_data[] = { }, { /* COM4 */ .mapbase = 0x11800000, - .irq = gpio_to_irq(ZEUS_UARTD_GPIO), + .irq = PXA_GPIO_TO_IRQ(ZEUS_UARTD_GPIO), .irqflags = IRQF_TRIGGER_RISING, .uartclk = 14745600, .regshift = 1, @@ -321,8 +321,8 @@ static struct resource zeus_dm9k0_resource[] = { .flags = IORESOURCE_MEM }, [2] = { - .start = gpio_to_irq(ZEUS_ETH0_GPIO), - .end = gpio_to_irq(ZEUS_ETH0_GPIO), + .start = PXA_GPIO_TO_IRQ(ZEUS_ETH0_GPIO), + .end = PXA_GPIO_TO_IRQ(ZEUS_ETH0_GPIO), .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE, }, }; @@ -339,8 +339,8 @@ static struct resource zeus_dm9k1_resource[] = { .flags = IORESOURCE_MEM, }, [2] = { - .start = gpio_to_irq(ZEUS_ETH1_GPIO), - .end = gpio_to_irq(ZEUS_ETH1_GPIO), + .start = PXA_GPIO_TO_IRQ(ZEUS_ETH1_GPIO), + .end = PXA_GPIO_TO_IRQ(ZEUS_ETH1_GPIO), .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE, }, }; @@ -423,7 +423,7 @@ static struct spi_board_info zeus_spi_board_info[] = { [0] = { .modalias = "mcp2515", .platform_data = &zeus_mcp2515_pdata, - .irq = gpio_to_irq(ZEUS_CAN_GPIO), + .irq = PXA_GPIO_TO_IRQ(ZEUS_CAN_GPIO), .max_speed_hz = 1*1000*1000, .bus_num = 3, .mode = SPI_MODE_0, @@ -753,7 +753,7 @@ static struct i2c_board_info __initdata zeus_i2c_devices[] = { { I2C_BOARD_INFO("pca9535", 0x20), .platform_data = &zeus_pca953x_pdata[2], - .irq = gpio_to_irq(ZEUS_EXTGPIO_GPIO), + .irq = PXA_GPIO_TO_IRQ(ZEUS_EXTGPIO_GPIO), }, { I2C_BOARD_INFO("lm75a", 0x48) }, { I2C_BOARD_INFO("24c01", 0x50) }, diff --git a/arch/arm/mach-pxa/zylonite.c b/arch/arm/mach-pxa/zylonite.c index 31d496891891..2406fd2727ef 100644 --- a/arch/arm/mach-pxa/zylonite.c +++ b/arch/arm/mach-pxa/zylonite.c @@ -407,8 +407,8 @@ static void __init zylonite_init(void) * Note: We depend that the bootloader set * the correct value to MSC register for SMC91x. */ - smc91x_resources[1].start = gpio_to_irq(gpio_eth_irq); - smc91x_resources[1].end = gpio_to_irq(gpio_eth_irq); + smc91x_resources[1].start = PXA_GPIO_TO_IRQ(gpio_eth_irq); + smc91x_resources[1].end = PXA_GPIO_TO_IRQ(gpio_eth_irq); platform_device_register(&smc91x_device); pxa_set_ac97_info(NULL); diff --git a/arch/arm/plat-pxa/include/plat/gpio-pxa.h b/arch/arm/plat-pxa/include/plat/gpio-pxa.h index b6390beff323..15bf9be051e8 100644 --- a/arch/arm/plat-pxa/include/plat/gpio-pxa.h +++ b/arch/arm/plat-pxa/include/plat/gpio-pxa.h @@ -40,5 +40,6 @@ extern int pxa_last_gpio; typedef int (*set_wake_t)(struct irq_data *d, unsigned int on); extern void pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn); +extern int pxa_irq_to_gpio(int irq); #endif /* __PLAT_PXA_GPIO_H */ diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c index a4121bb50cf2..3e76c588f080 100644 --- a/drivers/gpio/gpio-pxa.c +++ b/drivers/gpio/gpio-pxa.c @@ -39,8 +39,19 @@ struct pxa_gpio_chip { #endif }; +enum { + PXA25X_GPIO = 0, + PXA26X_GPIO, + PXA27X_GPIO, + PXA3XX_GPIO, + PXA93X_GPIO, + MMP_GPIO = 0x10, + MMP2_GPIO, +}; + static DEFINE_SPINLOCK(gpio_lock); static struct pxa_gpio_chip *pxa_gpio_chips; +static int gpio_type; #define for_each_gpio_chip(i, c) \ for (i = 0, c = &pxa_gpio_chips[0]; i <= pxa_last_gpio; i += 32, c++) @@ -55,6 +66,75 @@ static inline struct pxa_gpio_chip *gpio_to_pxachip(unsigned gpio) return &pxa_gpio_chips[gpio_to_bank(gpio)]; } +static inline int gpio_is_pxa_type(int type) +{ + return (type & MMP_GPIO) == 0; +} + +static inline int gpio_is_mmp_type(int type) +{ + return (type & MMP_GPIO) != 0; +} + +#ifdef CONFIG_ARCH_PXA +static inline int __pxa_gpio_to_irq(int gpio) +{ + if (gpio_is_pxa_type(gpio_type)) + return PXA_GPIO_TO_IRQ(gpio); + return -1; +} + +static inline int __pxa_irq_to_gpio(int irq) +{ + if (gpio_is_pxa_type(gpio_type)) + return irq - PXA_GPIO_TO_IRQ(0); + return -1; +} +#else +static inline int __pxa_gpio_to_irq(int gpio) { return -1; } +static inline int __pxa_irq_to_gpio(int irq) { return -1; } +#endif + +#ifdef CONFIG_ARCH_MMP +static inline int __mmp_gpio_to_irq(int gpio) +{ + if (gpio_is_mmp_type(gpio_type)) + return MMP_GPIO_TO_IRQ(gpio); + return -1; +} + +static inline int __mmp_irq_to_gpio(int irq) +{ + if (gpio_is_mmp_type(gpio_type)) + return irq - MMP_GPIO_TO_IRQ(0); + return -1; +} +#else +static inline int __mmp_gpio_to_irq(int gpio) { return -1; } +static inline int __mmp_irq_to_gpio(int irq) { return -1; } +#endif + +static int pxa_gpio_to_irq(struct gpio_chip *chip, unsigned offset) +{ + int gpio, ret; + + gpio = chip->base + offset; + ret = __pxa_gpio_to_irq(gpio); + if (ret >= 0) + return ret; + return __mmp_gpio_to_irq(gpio); +} + +int pxa_irq_to_gpio(int irq) +{ + int ret; + + ret = __pxa_irq_to_gpio(irq); + if (ret >= 0) + return ret; + return __mmp_irq_to_gpio(irq); +} + static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset) { void __iomem *base = gpio_chip_base(chip); @@ -131,6 +211,7 @@ static int __init pxa_init_gpio_chip(int gpio_end) c->direction_output = pxa_gpio_direction_output; c->get = pxa_gpio_get; c->set = pxa_gpio_set; + c->to_irq = pxa_gpio_to_irq; /* number of GPIOs on last bank may be less than 32 */ c->ngpio = (gpio + 31 > gpio_end) ? (gpio_end - gpio + 1) : 32; @@ -158,7 +239,7 @@ static inline void update_edge_detect(struct pxa_gpio_chip *c) static int pxa_gpio_irq_type(struct irq_data *d, unsigned int type) { struct pxa_gpio_chip *c; - int gpio = irq_to_gpio(d->irq); + int gpio = pxa_irq_to_gpio(d->irq); unsigned long gpdr, mask = GPIO_bit(gpio); c = gpio_to_pxachip(gpio); @@ -229,7 +310,7 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc) static void pxa_ack_muxed_gpio(struct irq_data *d) { - int gpio = irq_to_gpio(d->irq); + int gpio = pxa_irq_to_gpio(d->irq); struct pxa_gpio_chip *c = gpio_to_pxachip(gpio); __raw_writel(GPIO_bit(gpio), c->regbase + GEDR_OFFSET); @@ -237,7 +318,7 @@ static void pxa_ack_muxed_gpio(struct irq_data *d) static void pxa_mask_muxed_gpio(struct irq_data *d) { - int gpio = irq_to_gpio(d->irq); + int gpio = pxa_irq_to_gpio(d->irq); struct pxa_gpio_chip *c = gpio_to_pxachip(gpio); uint32_t grer, gfer; @@ -251,7 +332,7 @@ static void pxa_mask_muxed_gpio(struct irq_data *d) static void pxa_unmask_muxed_gpio(struct irq_data *d) { - int gpio = irq_to_gpio(d->irq); + int gpio = pxa_irq_to_gpio(d->irq); struct pxa_gpio_chip *c = gpio_to_pxachip(gpio); c->irq_mask |= GPIO_bit(gpio); -- cgit v1.2.3-55-g7522 From 478e223cc39ee98f9f9f0c87cb971a2fe0ce8d12 Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Fri, 14 Oct 2011 16:44:07 +0800 Subject: ARM: pxa: recognize gpio number and type Use cpuid to recognize the gpio number and type. CPU_PXA26x is the special case since we can't identify it by cpuid. Signed-off-by: Haojian Zhuang --- drivers/gpio/gpio-pxa.c | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c index 3e76c588f080..aebc4e8b7fd1 100644 --- a/drivers/gpio/gpio-pxa.c +++ b/drivers/gpio/gpio-pxa.c @@ -347,12 +347,51 @@ static struct irq_chip pxa_muxed_gpio_chip = { .irq_set_type = pxa_gpio_irq_type, }; +static int pxa_gpio_nums(void) +{ + int count = 0; + +#ifdef CONFIG_ARCH_PXA + if (cpu_is_pxa25x()) { +#ifdef CONFIG_CPU_PXA26x + count = 89; + gpio_type = PXA26X_GPIO; +#elif defined(CONFIG_PXA25x) + count = 84; + gpio_type = PXA26X_GPIO; +#endif /* CONFIG_CPU_PXA26x */ + } else if (cpu_is_pxa27x()) { + count = 120; + gpio_type = PXA27X_GPIO; + } else if (cpu_is_pxa93x() || cpu_is_pxa95x()) { + count = 191; + gpio_type = PXA93X_GPIO; + } else if (cpu_is_pxa3xx()) { + count = 127; + gpio_type = PXA3XX_GPIO; + } +#endif /* CONFIG_ARCH_PXA */ + +#ifdef CONFIG_ARCH_MMP + if (cpu_is_pxa168() || cpu_is_pxa910()) { + count = 127; + gpio_type = MMP_GPIO; + } else if (cpu_is_mmp2()) { + count = 191; + gpio_type = MMP2_GPIO; + } +#endif /* CONFIG_ARCH_MMP */ + return count; +} + void __init pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn) { struct pxa_gpio_chip *c; int gpio, irq; - pxa_last_gpio = end; + pxa_last_gpio = pxa_gpio_nums(); + if (!pxa_last_gpio) + return; /* Initialize GPIO chips */ pxa_init_gpio_chip(end); -- cgit v1.2.3-55-g7522 From df664d20814f9b3c3020ced7088a328b477ecf8d Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Fri, 14 Oct 2011 17:24:03 +0800 Subject: ARM: pxa: use little endian read write in gpio driver Remove __raw_readl()/__raw_writel(). Use readl_relaxed()/writel_relaxed() instead. Signed-off-by: Haojian Zhuang --- drivers/gpio/gpio-pxa.c | 68 ++++++++++++++++++++++++------------------------- 1 file changed, 34 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c index aebc4e8b7fd1..31d2da4100cd 100644 --- a/drivers/gpio/gpio-pxa.c +++ b/drivers/gpio/gpio-pxa.c @@ -143,12 +143,12 @@ static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset) spin_lock_irqsave(&gpio_lock, flags); - value = __raw_readl(base + GPDR_OFFSET); + value = readl_relaxed(base + GPDR_OFFSET); if (__gpio_is_inverted(chip->base + offset)) value |= mask; else value &= ~mask; - __raw_writel(value, base + GPDR_OFFSET); + writel_relaxed(value, base + GPDR_OFFSET); spin_unlock_irqrestore(&gpio_lock, flags); return 0; @@ -161,16 +161,16 @@ static int pxa_gpio_direction_output(struct gpio_chip *chip, uint32_t tmp, mask = 1 << offset; unsigned long flags; - __raw_writel(mask, base + (value ? GPSR_OFFSET : GPCR_OFFSET)); + writel_relaxed(mask, base + (value ? GPSR_OFFSET : GPCR_OFFSET)); spin_lock_irqsave(&gpio_lock, flags); - tmp = __raw_readl(base + GPDR_OFFSET); + tmp = readl_relaxed(base + GPDR_OFFSET); if (__gpio_is_inverted(chip->base + offset)) tmp &= ~mask; else tmp |= mask; - __raw_writel(tmp, base + GPDR_OFFSET); + writel_relaxed(tmp, base + GPDR_OFFSET); spin_unlock_irqrestore(&gpio_lock, flags); return 0; @@ -178,12 +178,12 @@ static int pxa_gpio_direction_output(struct gpio_chip *chip, static int pxa_gpio_get(struct gpio_chip *chip, unsigned offset) { - return __raw_readl(gpio_chip_base(chip) + GPLR_OFFSET) & (1 << offset); + return readl_relaxed(gpio_chip_base(chip) + GPLR_OFFSET) & (1 << offset); } static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { - __raw_writel(1 << offset, gpio_chip_base(chip) + + writel_relaxed(1 << offset, gpio_chip_base(chip) + (value ? GPSR_OFFSET : GPCR_OFFSET)); } @@ -228,12 +228,12 @@ static inline void update_edge_detect(struct pxa_gpio_chip *c) { uint32_t grer, gfer; - grer = __raw_readl(c->regbase + GRER_OFFSET) & ~c->irq_mask; - gfer = __raw_readl(c->regbase + GFER_OFFSET) & ~c->irq_mask; + grer = readl_relaxed(c->regbase + GRER_OFFSET) & ~c->irq_mask; + gfer = readl_relaxed(c->regbase + GFER_OFFSET) & ~c->irq_mask; grer |= c->irq_edge_rise & c->irq_mask; gfer |= c->irq_edge_fall & c->irq_mask; - __raw_writel(grer, c->regbase + GRER_OFFSET); - __raw_writel(gfer, c->regbase + GFER_OFFSET); + writel_relaxed(grer, c->regbase + GRER_OFFSET); + writel_relaxed(gfer, c->regbase + GFER_OFFSET); } static int pxa_gpio_irq_type(struct irq_data *d, unsigned int type) @@ -257,12 +257,12 @@ static int pxa_gpio_irq_type(struct irq_data *d, unsigned int type) type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; } - gpdr = __raw_readl(c->regbase + GPDR_OFFSET); + gpdr = readl_relaxed(c->regbase + GPDR_OFFSET); if (__gpio_is_inverted(gpio)) - __raw_writel(gpdr | mask, c->regbase + GPDR_OFFSET); + writel_relaxed(gpdr | mask, c->regbase + GPDR_OFFSET); else - __raw_writel(gpdr & ~mask, c->regbase + GPDR_OFFSET); + writel_relaxed(gpdr & ~mask, c->regbase + GPDR_OFFSET); if (type & IRQ_TYPE_EDGE_RISING) c->irq_edge_rise |= mask; @@ -293,9 +293,9 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc) for_each_gpio_chip(gpio, c) { gpio_base = c->chip.base; - gedr = __raw_readl(c->regbase + GEDR_OFFSET); + gedr = readl_relaxed(c->regbase + GEDR_OFFSET); gedr = gedr & c->irq_mask; - __raw_writel(gedr, c->regbase + GEDR_OFFSET); + writel_relaxed(gedr, c->regbase + GEDR_OFFSET); n = find_first_bit(&gedr, BITS_PER_LONG); while (n < BITS_PER_LONG) { @@ -313,7 +313,7 @@ static void pxa_ack_muxed_gpio(struct irq_data *d) int gpio = pxa_irq_to_gpio(d->irq); struct pxa_gpio_chip *c = gpio_to_pxachip(gpio); - __raw_writel(GPIO_bit(gpio), c->regbase + GEDR_OFFSET); + writel_relaxed(GPIO_bit(gpio), c->regbase + GEDR_OFFSET); } static void pxa_mask_muxed_gpio(struct irq_data *d) @@ -324,10 +324,10 @@ static void pxa_mask_muxed_gpio(struct irq_data *d) c->irq_mask &= ~GPIO_bit(gpio); - grer = __raw_readl(c->regbase + GRER_OFFSET) & ~GPIO_bit(gpio); - gfer = __raw_readl(c->regbase + GFER_OFFSET) & ~GPIO_bit(gpio); - __raw_writel(grer, c->regbase + GRER_OFFSET); - __raw_writel(gfer, c->regbase + GFER_OFFSET); + grer = readl_relaxed(c->regbase + GRER_OFFSET) & ~GPIO_bit(gpio); + gfer = readl_relaxed(c->regbase + GFER_OFFSET) & ~GPIO_bit(gpio); + writel_relaxed(grer, c->regbase + GRER_OFFSET); + writel_relaxed(gfer, c->regbase + GFER_OFFSET); } static void pxa_unmask_muxed_gpio(struct irq_data *d) @@ -398,9 +398,9 @@ void __init pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn) /* clear all GPIO edge detects */ for_each_gpio_chip(gpio, c) { - __raw_writel(0, c->regbase + GFER_OFFSET); - __raw_writel(0, c->regbase + GRER_OFFSET); - __raw_writel(~0,c->regbase + GEDR_OFFSET); + writel_relaxed(0, c->regbase + GFER_OFFSET); + writel_relaxed(0, c->regbase + GRER_OFFSET); + writel_relaxed(~0,c->regbase + GEDR_OFFSET); } #ifdef CONFIG_ARCH_PXA @@ -435,13 +435,13 @@ static int pxa_gpio_suspend(void) int gpio; for_each_gpio_chip(gpio, c) { - c->saved_gplr = __raw_readl(c->regbase + GPLR_OFFSET); - c->saved_gpdr = __raw_readl(c->regbase + GPDR_OFFSET); - c->saved_grer = __raw_readl(c->regbase + GRER_OFFSET); - c->saved_gfer = __raw_readl(c->regbase + GFER_OFFSET); + c->saved_gplr = readl_relaxed(c->regbase + GPLR_OFFSET); + c->saved_gpdr = readl_relaxed(c->regbase + GPDR_OFFSET); + c->saved_grer = readl_relaxed(c->regbase + GRER_OFFSET); + c->saved_gfer = readl_relaxed(c->regbase + GFER_OFFSET); /* Clear GPIO transition detect bits */ - __raw_writel(0xffffffff, c->regbase + GEDR_OFFSET); + writel_relaxed(0xffffffff, c->regbase + GEDR_OFFSET); } return 0; } @@ -453,12 +453,12 @@ static void pxa_gpio_resume(void) for_each_gpio_chip(gpio, c) { /* restore level with set/clear */ - __raw_writel( c->saved_gplr, c->regbase + GPSR_OFFSET); - __raw_writel(~c->saved_gplr, c->regbase + GPCR_OFFSET); + writel_relaxed( c->saved_gplr, c->regbase + GPSR_OFFSET); + writel_relaxed(~c->saved_gplr, c->regbase + GPCR_OFFSET); - __raw_writel(c->saved_grer, c->regbase + GRER_OFFSET); - __raw_writel(c->saved_gfer, c->regbase + GFER_OFFSET); - __raw_writel(c->saved_gpdr, c->regbase + GPDR_OFFSET); + writel_relaxed(c->saved_grer, c->regbase + GRER_OFFSET); + writel_relaxed(c->saved_gfer, c->regbase + GFER_OFFSET); + writel_relaxed(c->saved_gpdr, c->regbase + GPDR_OFFSET); } } #else -- cgit v1.2.3-55-g7522 From 157d2644cb0c1e71a18baaffca56d2b1d0ebf10f Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Mon, 17 Oct 2011 20:37:52 +0800 Subject: ARM: pxa: change gpio to platform device Remove most gpio macros and change gpio driver to platform driver. Signed-off-by: Haojian Zhuang --- arch/arm/Kconfig | 2 + arch/arm/mach-mmp/aspenite.c | 1 + arch/arm/mach-mmp/avengers_lite.c | 1 + arch/arm/mach-mmp/brownstone.c | 1 + arch/arm/mach-mmp/flint.c | 1 + arch/arm/mach-mmp/gplugd.c | 1 + arch/arm/mach-mmp/include/mach/gpio.h | 3 +- arch/arm/mach-mmp/include/mach/mmp2.h | 2 + arch/arm/mach-mmp/include/mach/pxa168.h | 2 + arch/arm/mach-mmp/include/mach/pxa910.h | 2 + arch/arm/mach-mmp/mmp2.c | 28 ++++-- arch/arm/mach-mmp/pxa168.c | 29 +++++-- arch/arm/mach-mmp/pxa910.c | 29 +++++-- arch/arm/mach-mmp/tavorevb.c | 1 + arch/arm/mach-mmp/teton_bga.c | 1 + arch/arm/mach-mmp/ttc_dkb.c | 1 + arch/arm/mach-pxa/devices.c | 30 +++++++ arch/arm/mach-pxa/devices.h | 1 + arch/arm/mach-pxa/include/mach/gpio-pxa.h | 131 ---------------------------- arch/arm/mach-pxa/include/mach/gpio.h | 5 +- arch/arm/mach-pxa/include/mach/idp.h | 2 - arch/arm/mach-pxa/include/mach/littleton.h | 2 - arch/arm/mach-pxa/irq.c | 3 +- arch/arm/mach-pxa/mfp-pxa2xx.c | 6 +- arch/arm/mach-pxa/pxa25x.c | 3 +- arch/arm/mach-pxa/pxa27x.c | 3 +- arch/arm/mach-pxa/pxa3xx.c | 6 +- arch/arm/mach-pxa/pxa95x.c | 3 +- arch/arm/plat-pxa/include/plat/gpio-pxa.h | 45 ---------- drivers/gpio/Kconfig | 6 ++ drivers/gpio/Makefile | 2 +- drivers/gpio/gpio-pxa.c | 135 ++++++++++++++++++++++++++--- include/linux/gpio-pxa.h | 16 ++++ 33 files changed, 271 insertions(+), 233 deletions(-) delete mode 100644 arch/arm/mach-pxa/include/mach/gpio-pxa.h delete mode 100644 arch/arm/plat-pxa/include/plat/gpio-pxa.h create mode 100644 include/linux/gpio-pxa.h (limited to 'drivers') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 44789eff983f..57e16d4e14dc 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -591,6 +591,7 @@ config ARCH_MMP select ARCH_REQUIRE_GPIOLIB select CLKDEV_LOOKUP select GENERIC_CLOCKEVENTS + select GPIO_PXA select HAVE_SCHED_CLOCK select TICK_ONESHOT select PLAT_PXA @@ -673,6 +674,7 @@ config ARCH_PXA select CLKSRC_MMIO select ARCH_REQUIRE_GPIOLIB select GENERIC_CLOCKEVENTS + select GPIO_PXA select HAVE_SCHED_CLOCK select TICK_ONESHOT select PLAT_PXA diff --git a/arch/arm/mach-mmp/aspenite.c b/arch/arm/mach-mmp/aspenite.c index fb7dfc157a5c..edcbadad31c1 100644 --- a/arch/arm/mach-mmp/aspenite.c +++ b/arch/arm/mach-mmp/aspenite.c @@ -231,6 +231,7 @@ static void __init common_init(void) pxa168_add_nand(&aspenite_nand_info); pxa168_add_fb(&aspenite_lcd_info); pxa168_add_keypad(&aspenite_keypad_info); + platform_device_register(&pxa168_device_gpio); /* off-chip devices */ platform_device_register(&smc91x_device); diff --git a/arch/arm/mach-mmp/avengers_lite.c b/arch/arm/mach-mmp/avengers_lite.c index 39f0878d64a0..c5d53e0742e9 100644 --- a/arch/arm/mach-mmp/avengers_lite.c +++ b/arch/arm/mach-mmp/avengers_lite.c @@ -38,6 +38,7 @@ static void __init avengers_lite_init(void) /* on-chip devices */ pxa168_add_uart(2); + platform_device_register(&pxa168_device_gpio); } MACHINE_START(AVENGERS_LITE, "PXA168 Avengers lite Development Platform") diff --git a/arch/arm/mach-mmp/brownstone.c b/arch/arm/mach-mmp/brownstone.c index 983cfb15fbde..eb07565a06a3 100644 --- a/arch/arm/mach-mmp/brownstone.c +++ b/arch/arm/mach-mmp/brownstone.c @@ -202,6 +202,7 @@ static void __init brownstone_init(void) /* on-chip devices */ mmp2_add_uart(1); mmp2_add_uart(3); + platform_device_register(&mmp2_device_gpio); mmp2_add_twsi(1, NULL, ARRAY_AND_SIZE(brownstone_twsi1_info)); mmp2_add_sdhost(0, &mmp2_sdh_platdata_mmc0); /* SD/MMC */ mmp2_add_sdhost(2, &mmp2_sdh_platdata_mmc2); /* eMMC */ diff --git a/arch/arm/mach-mmp/flint.c b/arch/arm/mach-mmp/flint.c index a64c172082c4..c1f0aa88dd8a 100644 --- a/arch/arm/mach-mmp/flint.c +++ b/arch/arm/mach-mmp/flint.c @@ -110,6 +110,7 @@ static void __init flint_init(void) /* on-chip devices */ mmp2_add_uart(1); mmp2_add_uart(2); + platform_device_register(&mmp2_device_gpio); /* off-chip devices */ platform_device_register(&smc91x_device); diff --git a/arch/arm/mach-mmp/gplugd.c b/arch/arm/mach-mmp/gplugd.c index 69156568bc41..933420a7c3ba 100644 --- a/arch/arm/mach-mmp/gplugd.c +++ b/arch/arm/mach-mmp/gplugd.c @@ -184,6 +184,7 @@ static void __init gplugd_init(void) pxa168_add_uart(3); pxa168_add_ssp(0); pxa168_add_twsi(0, NULL, ARRAY_AND_SIZE(gplugd_i2c_board_info)); + platform_device_register(&pxa168_device_gpio); pxa168_add_eth(&gplugd_eth_platform_data); } diff --git a/arch/arm/mach-mmp/include/mach/gpio.h b/arch/arm/mach-mmp/include/mach/gpio.h index 904466d7eb95..13219ebf5128 100644 --- a/arch/arm/mach-mmp/include/mach/gpio.h +++ b/arch/arm/mach-mmp/include/mach/gpio.h @@ -3,7 +3,6 @@ #include -#define __gpio_is_inverted(gpio) (0) -#define __gpio_is_occupied(gpio) (0) +#include #endif /* __ASM_MACH_GPIO_H */ diff --git a/arch/arm/mach-mmp/include/mach/mmp2.h b/arch/arm/mach-mmp/include/mach/mmp2.h index 2f7b2d3c2b18..cba22fed2265 100644 --- a/arch/arm/mach-mmp/include/mach/mmp2.h +++ b/arch/arm/mach-mmp/include/mach/mmp2.h @@ -32,6 +32,8 @@ extern struct pxa_device_desc mmp2_device_sdh3; extern struct pxa_device_desc mmp2_device_asram; extern struct pxa_device_desc mmp2_device_isram; +extern struct platform_device mmp2_device_gpio; + static inline int mmp2_add_uart(int id) { struct pxa_device_desc *d = NULL; diff --git a/arch/arm/mach-mmp/include/mach/pxa168.h b/arch/arm/mach-mmp/include/mach/pxa168.h index 7fb568d2845b..f9286089da3a 100644 --- a/arch/arm/mach-mmp/include/mach/pxa168.h +++ b/arch/arm/mach-mmp/include/mach/pxa168.h @@ -42,6 +42,8 @@ struct pxa168_usb_pdata { /* pdata can be NULL */ int __init pxa168_add_usb_host(struct pxa168_usb_pdata *pdata); +extern struct platform_device pxa168_device_gpio; + static inline int pxa168_add_uart(int id) { struct pxa_device_desc *d = NULL; diff --git a/arch/arm/mach-mmp/include/mach/pxa910.h b/arch/arm/mach-mmp/include/mach/pxa910.h index 91be75591398..4de13abef7bb 100644 --- a/arch/arm/mach-mmp/include/mach/pxa910.h +++ b/arch/arm/mach-mmp/include/mach/pxa910.h @@ -21,6 +21,8 @@ extern struct pxa_device_desc pxa910_device_pwm3; extern struct pxa_device_desc pxa910_device_pwm4; extern struct pxa_device_desc pxa910_device_nand; +extern struct platform_device pxa910_device_gpio; + static inline int pxa910_add_uart(int id) { struct pxa_device_desc *d = NULL; diff --git a/arch/arm/mach-mmp/mmp2.c b/arch/arm/mach-mmp/mmp2.c index 5dd1d4a6aeb9..1ed222d3e22b 100644 --- a/arch/arm/mach-mmp/mmp2.c +++ b/arch/arm/mach-mmp/mmp2.c @@ -13,6 +13,7 @@ #include #include #include +#include #include @@ -24,7 +25,6 @@ #include #include #include -#include #include #include @@ -33,8 +33,6 @@ #define MFPR_VIRT_BASE (APB_VIRT_BASE + 0x1e000) -#define APMASK(i) (GPIO_REGS_VIRT + BANK_OFF(i) + 0x9c) - static struct mfp_addr_map mmp2_addr_map[] __initdata = { MFP_ADDR_X(GPIO0, GPIO58, 0x54), @@ -101,12 +99,6 @@ static void __init mmp2_init_gpio(void) /* enable GPIO clock */ __raw_writel(APBC_APBCLK | APBC_FNCLK, APBC_MMP2_GPIO); - - /* unmask GPIO edge detection for all 6 banks -- APMASKx */ - for (i = 0; i < 6; i++) - __raw_writel(0xffffffff, APMASK(i)); - - pxa_init_gpio(IRQ_MMP2_GPIO, 0, 167, NULL); } void __init mmp2_init_irq(void) @@ -230,3 +222,21 @@ MMP2_DEVICE(asram, "asram", -1, NONE, 0xe0000000, 0x4000); /* 0xd1000000 ~ 0xd101ffff is reserved for secure processor */ MMP2_DEVICE(isram, "isram", -1, NONE, 0xd1020000, 0x18000); +struct resource mmp2_resource_gpio[] = { + { + .start = 0xd4019000, + .end = 0xd4019fff, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_MMP2_GPIO, + .end = IRQ_MMP2_GPIO, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device mmp2_device_gpio = { + .name = "pxa-gpio", + .id = -1, + .num_resources = ARRAY_SIZE(mmp2_resource_gpio), + .resource = mmp2_resource_gpio, +}; diff --git a/arch/arm/mach-mmp/pxa168.c b/arch/arm/mach-mmp/pxa168.c index 76ca15c00e45..fefdfe59c07c 100644 --- a/arch/arm/mach-mmp/pxa168.c +++ b/arch/arm/mach-mmp/pxa168.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -20,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -43,20 +43,12 @@ static struct mfp_addr_map pxa168_mfp_addr_map[] __initdata = MFP_ADDR_END, }; -#define APMASK(i) (GPIO_REGS_VIRT + BANK_OFF(i) + 0x09c) - static void __init pxa168_init_gpio(void) { int i; /* enable GPIO clock */ __raw_writel(APBC_APBCLK | APBC_FNCLK, APBC_PXA168_GPIO); - - /* unmask GPIO edge detection for all 4 banks - APMASKx */ - for (i = 0; i < 4; i++) - __raw_writel(0xffffffff, APMASK(i)); - - pxa_init_gpio(IRQ_PXA168_GPIOX, 0, 127, NULL); } void __init pxa168_init_irq(void) @@ -174,6 +166,25 @@ PXA168_DEVICE(fb, "pxa168-fb", -1, LCD, 0xd420b000, 0x1c8); PXA168_DEVICE(keypad, "pxa27x-keypad", -1, KEYPAD, 0xd4012000, 0x4c); PXA168_DEVICE(eth, "pxa168-eth", -1, MFU, 0xc0800000, 0x0fff); +struct resource pxa168_resource_gpio[] = { + { + .start = 0xd4019000, + .end = 0xd4019fff, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_PXA168_GPIOX, + .end = IRQ_PXA168_GPIOX, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device pxa168_device_gpio = { + .name = "pxa-gpio", + .id = -1, + .num_resources = ARRAY_SIZE(pxa168_resource_gpio), + .resource = pxa168_resource_gpio, +}; + struct resource pxa168_usb_host_resources[] = { /* USB Host conroller register base */ [0] = { diff --git a/arch/arm/mach-mmp/pxa910.c b/arch/arm/mach-mmp/pxa910.c index 4ebbfbba39fc..7b992ced095c 100644 --- a/arch/arm/mach-mmp/pxa910.c +++ b/arch/arm/mach-mmp/pxa910.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -19,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -77,20 +77,12 @@ static struct mfp_addr_map pxa910_mfp_addr_map[] __initdata = MFP_ADDR_END, }; -#define APMASK(i) (GPIO_REGS_VIRT + BANK_OFF(i) + 0x09c) - static void __init pxa910_init_gpio(void) { int i; /* enable GPIO clock */ __raw_writel(APBC_APBCLK | APBC_FNCLK, APBC_PXA910_GPIO); - - /* unmask GPIO edge detection for all 4 banks - APMASKx */ - for (i = 0; i < 4; i++) - __raw_writel(0xffffffff, APMASK(i)); - - pxa_init_gpio(IRQ_PXA910_AP_GPIO, 0, 127, NULL); } void __init pxa910_init_irq(void) @@ -179,3 +171,22 @@ PXA910_DEVICE(pwm2, "pxa910-pwm", 1, NONE, 0xd401a400, 0x10); PXA910_DEVICE(pwm3, "pxa910-pwm", 2, NONE, 0xd401a800, 0x10); PXA910_DEVICE(pwm4, "pxa910-pwm", 3, NONE, 0xd401ac00, 0x10); PXA910_DEVICE(nand, "pxa3xx-nand", -1, NAND, 0xd4283000, 0x80, 97, 99); + +struct resource pxa910_resource_gpio[] = { + { + .start = 0xd4019000, + .end = 0xd4019fff, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_PXA910_AP_GPIO, + .end = IRQ_PXA910_AP_GPIO, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device pxa910_device_gpio = { + .name = "pxa-gpio", + .id = -1, + .num_resources = ARRAY_SIZE(pxa910_resource_gpio), + .resource = pxa910_resource_gpio, +}; diff --git a/arch/arm/mach-mmp/tavorevb.c b/arch/arm/mach-mmp/tavorevb.c index 331f5f358b59..bb2ddb72bca2 100644 --- a/arch/arm/mach-mmp/tavorevb.c +++ b/arch/arm/mach-mmp/tavorevb.c @@ -94,6 +94,7 @@ static void __init tavorevb_init(void) /* on-chip devices */ pxa910_add_uart(1); + platform_device_register(&pxa910_device_gpio); /* off-chip devices */ platform_device_register(&smc91x_device); diff --git a/arch/arm/mach-mmp/teton_bga.c b/arch/arm/mach-mmp/teton_bga.c index 825a01cdcccd..703de85b571c 100644 --- a/arch/arm/mach-mmp/teton_bga.c +++ b/arch/arm/mach-mmp/teton_bga.c @@ -78,6 +78,7 @@ static void __init teton_bga_init(void) pxa168_add_uart(1); pxa168_add_keypad(&teton_bga_keypad_info); pxa168_add_twsi(0, NULL, ARRAY_AND_SIZE(teton_bga_i2c_info)); + platform_device_register(&pxa168_device_gpio); } MACHINE_START(TETON_BGA, "PXA168-based Teton BGA Development Platform") diff --git a/arch/arm/mach-mmp/ttc_dkb.c b/arch/arm/mach-mmp/ttc_dkb.c index fac0d5d9d464..a80ed262df1c 100644 --- a/arch/arm/mach-mmp/ttc_dkb.c +++ b/arch/arm/mach-mmp/ttc_dkb.c @@ -123,6 +123,7 @@ static struct platform_device ttc_dkb_device_onenand = { }; static struct platform_device *ttc_dkb_devices[] = { + &pxa910_device_gpio, &ttc_dkb_device_onenand, }; diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c index 2e0425404de5..5bc13121eac5 100644 --- a/arch/arm/mach-pxa/devices.c +++ b/arch/arm/mach-pxa/devices.c @@ -1051,6 +1051,36 @@ struct platform_device pxa3xx_device_ssp4 = { }; #endif /* CONFIG_PXA3xx || CONFIG_PXA95x */ +struct resource pxa_resource_gpio[] = { + { + .start = 0x40e00000, + .end = 0x40e0ffff, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_GPIO0, + .end = IRQ_GPIO0, + .name = "gpio0", + .flags = IORESOURCE_IRQ, + }, { + .start = IRQ_GPIO1, + .end = IRQ_GPIO1, + .name = "gpio1", + .flags = IORESOURCE_IRQ, + }, { + .start = IRQ_GPIO_2_x, + .end = IRQ_GPIO_2_x, + .name = "gpio_mux", + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device pxa_device_gpio = { + .name = "pxa-gpio", + .id = -1, + .num_resources = ARRAY_SIZE(pxa_resource_gpio), + .resource = pxa_resource_gpio, +}; + /* pxa2xx-spi platform-device ID equals respective SSP platform-device ID + 1. * See comment in arch/arm/mach-pxa/ssp.c::ssp_probe() */ void __init pxa2xx_set_spi_info(unsigned id, struct pxa2xx_spi_master *info) diff --git a/arch/arm/mach-pxa/devices.h b/arch/arm/mach-pxa/devices.h index 2fd5a8b35757..1475db107254 100644 --- a/arch/arm/mach-pxa/devices.h +++ b/arch/arm/mach-pxa/devices.h @@ -16,6 +16,7 @@ extern struct platform_device pxa_device_ficp; extern struct platform_device sa1100_device_rtc; extern struct platform_device pxa_device_rtc; extern struct platform_device pxa_device_ac97; +extern struct platform_device pxa_device_gpio; extern struct platform_device pxa27x_device_i2c_power; extern struct platform_device pxa27x_device_ohci; diff --git a/arch/arm/mach-pxa/include/mach/gpio-pxa.h b/arch/arm/mach-pxa/include/mach/gpio-pxa.h deleted file mode 100644 index 134b3bc332cd..000000000000 --- a/arch/arm/mach-pxa/include/mach/gpio-pxa.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Written by Philipp Zabel - * - * 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 - * - */ -#ifndef __MACH_PXA_GPIO_PXA_H -#define __MACH_PXA_GPIO_PXA_H - -#include -#include - -#define GPIO_REGS_VIRT io_p2v(0x40E00000) - -#define BANK_OFF(n) (((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2)) -#define GPIO_REG(x) (*(volatile u32 *)(GPIO_REGS_VIRT + (x))) - -/* GPIO Pin Level Registers */ -#define GPLR0 GPIO_REG(BANK_OFF(0) + 0x00) -#define GPLR1 GPIO_REG(BANK_OFF(1) + 0x00) -#define GPLR2 GPIO_REG(BANK_OFF(2) + 0x00) -#define GPLR3 GPIO_REG(BANK_OFF(3) + 0x00) - -/* GPIO Pin Direction Registers */ -#define GPDR0 GPIO_REG(BANK_OFF(0) + 0x0c) -#define GPDR1 GPIO_REG(BANK_OFF(1) + 0x0c) -#define GPDR2 GPIO_REG(BANK_OFF(2) + 0x0c) -#define GPDR3 GPIO_REG(BANK_OFF(3) + 0x0c) - -/* GPIO Pin Output Set Registers */ -#define GPSR0 GPIO_REG(BANK_OFF(0) + 0x18) -#define GPSR1 GPIO_REG(BANK_OFF(1) + 0x18) -#define GPSR2 GPIO_REG(BANK_OFF(2) + 0x18) -#define GPSR3 GPIO_REG(BANK_OFF(3) + 0x18) - -/* GPIO Pin Output Clear Registers */ -#define GPCR0 GPIO_REG(BANK_OFF(0) + 0x24) -#define GPCR1 GPIO_REG(BANK_OFF(1) + 0x24) -#define GPCR2 GPIO_REG(BANK_OFF(2) + 0x24) -#define GPCR3 GPIO_REG(BANK_OFF(3) + 0x24) - -/* GPIO Rising Edge Detect Registers */ -#define GRER0 GPIO_REG(BANK_OFF(0) + 0x30) -#define GRER1 GPIO_REG(BANK_OFF(1) + 0x30) -#define GRER2 GPIO_REG(BANK_OFF(2) + 0x30) -#define GRER3 GPIO_REG(BANK_OFF(3) + 0x30) - -/* GPIO Falling Edge Detect Registers */ -#define GFER0 GPIO_REG(BANK_OFF(0) + 0x3c) -#define GFER1 GPIO_REG(BANK_OFF(1) + 0x3c) -#define GFER2 GPIO_REG(BANK_OFF(2) + 0x3c) -#define GFER3 GPIO_REG(BANK_OFF(3) + 0x3c) - -/* GPIO Edge Detect Status Registers */ -#define GEDR0 GPIO_REG(BANK_OFF(0) + 0x48) -#define GEDR1 GPIO_REG(BANK_OFF(1) + 0x48) -#define GEDR2 GPIO_REG(BANK_OFF(2) + 0x48) -#define GEDR3 GPIO_REG(BANK_OFF(3) + 0x48) - -/* GPIO Alternate Function Select Registers */ -#define GAFR0_L GPIO_REG(0x0054) -#define GAFR0_U GPIO_REG(0x0058) -#define GAFR1_L GPIO_REG(0x005C) -#define GAFR1_U GPIO_REG(0x0060) -#define GAFR2_L GPIO_REG(0x0064) -#define GAFR2_U GPIO_REG(0x0068) -#define GAFR3_L GPIO_REG(0x006C) -#define GAFR3_U GPIO_REG(0x0070) - -/* More handy macros. The argument is a literal GPIO number. */ - -#define GPIO_bit(x) (1 << ((x) & 0x1f)) - -#define GPLR(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x00) -#define GPDR(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x0c) -#define GPSR(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x18) -#define GPCR(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x24) -#define GRER(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x30) -#define GFER(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x3c) -#define GEDR(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x48) -#define GAFR(x) GPIO_REG(0x54 + (((x) & 0x70) >> 2)) - - -#define gpio_to_bank(gpio) ((gpio) >> 5) - -#ifdef CONFIG_CPU_PXA26x -/* GPIO86/87/88/89 on PXA26x have their direction bits in GPDR2 inverted, - * as well as their Alternate Function value being '1' for GPIO in GAFRx. - */ -static inline int __gpio_is_inverted(unsigned gpio) -{ - return cpu_is_pxa25x() && gpio > 85; -} -#else -static inline int __gpio_is_inverted(unsigned gpio) { return 0; } -#endif - -/* - * On PXA25x and PXA27x, GAFRx and GPDRx together decide the alternate - * function of a GPIO, and GPDRx cannot be altered once configured. It - * is attributed as "occupied" here (I know this terminology isn't - * accurate, you are welcome to propose a better one :-) - */ -static inline int __gpio_is_occupied(unsigned gpio) -{ - if (cpu_is_pxa27x() || cpu_is_pxa25x()) { - int af = (GAFR(gpio) >> ((gpio & 0xf) * 2)) & 0x3; - int dir = GPDR(gpio) & GPIO_bit(gpio); - - if (__gpio_is_inverted(gpio)) - return af != 1 || dir == 0; - else - return af != 0 || dir != 0; - } else - return GPDR(gpio) & GPIO_bit(gpio); -} - -#include -#endif /* __MACH_PXA_GPIO_PXA_H */ diff --git a/arch/arm/mach-pxa/include/mach/gpio.h b/arch/arm/mach-pxa/include/mach/gpio.h index 561cdbfd7ccf..0248e433bc98 100644 --- a/arch/arm/mach-pxa/include/mach/gpio.h +++ b/arch/arm/mach-pxa/include/mach/gpio.h @@ -25,7 +25,8 @@ #define __ASM_ARCH_PXA_GPIO_H #include -/* The defines for the driver are needed for the accelerated accessors */ -#include "gpio-pxa.h" + +#include +#include #endif diff --git a/arch/arm/mach-pxa/include/mach/idp.h b/arch/arm/mach-pxa/include/mach/idp.h index a7f912f5ea2f..22a96f87232b 100644 --- a/arch/arm/mach-pxa/include/mach/idp.h +++ b/arch/arm/mach-pxa/include/mach/idp.h @@ -131,8 +131,6 @@ #define PCC_VS2 (1 << 1) #define PCC_VS1 (1 << 0) -#define PCC_DETECT(x) (GPLR(7 + (x)) & GPIO_bit(7 + (x))) - /* A listing of interrupts used by external hardware devices */ #define TOUCH_PANEL_IRQ PXA_GPIO_TO_IRQ(5) diff --git a/arch/arm/mach-pxa/include/mach/littleton.h b/arch/arm/mach-pxa/include/mach/littleton.h index e20ac1b64b00..8066be54e9f5 100644 --- a/arch/arm/mach-pxa/include/mach/littleton.h +++ b/arch/arm/mach-pxa/include/mach/littleton.h @@ -1,8 +1,6 @@ #ifndef __ASM_ARCH_LITTLETON_H #define __ASM_ARCH_LITTLETON_H -#include - #define LITTLETON_ETH_PHYS 0x30000000 #define LITTLETON_GPIO_LCD_CS (17) diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c index 36c538f48fa6..5dae15ea6718 100644 --- a/arch/arm/mach-pxa/irq.c +++ b/arch/arm/mach-pxa/irq.c @@ -22,7 +22,6 @@ #include #include -#include #include "generic.h" @@ -122,7 +121,7 @@ asmlinkage void __exception_irq_entry ichp_handle_irq(struct pt_regs *regs) } while (1); } -void __init pxa_init_irq(int irq_nr, set_wake_t fn) +void __init pxa_init_irq(int irq_nr, int (*fn)(struct irq_data *, unsigned int)) { int irq, i, n; diff --git a/arch/arm/mach-pxa/mfp-pxa2xx.c b/arch/arm/mach-pxa/mfp-pxa2xx.c index 43a5f6861ca3..f14775536b83 100644 --- a/arch/arm/mach-pxa/mfp-pxa2xx.c +++ b/arch/arm/mach-pxa/mfp-pxa2xx.c @@ -13,6 +13,7 @@ * published by the Free Software Foundation. */ #include +#include #include #include #include @@ -20,7 +21,6 @@ #include #include -#include #include "generic.h" @@ -29,6 +29,10 @@ #define GAFR_L(x) __GAFR(0, x) #define GAFR_U(x) __GAFR(1, x) +#define BANK_OFF(n) (((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2)) +#define GPLR(x) __REG2(0x40E00000, BANK_OFF((x) >> 5)) +#define GPDR(x) __REG2(0x40E00000, BANK_OFF((x) >> 5) + 0x0c) + #define PWER_WE35 (1 << 24) struct gpio_desc { diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c index 0f38cfce5c35..91e4f6c03766 100644 --- a/arch/arm/mach-pxa/pxa25x.c +++ b/arch/arm/mach-pxa/pxa25x.c @@ -17,6 +17,7 @@ * need be. */ #include +#include #include #include #include @@ -312,14 +313,12 @@ set_pwer: void __init pxa25x_init_irq(void) { pxa_init_irq(32, pxa25x_set_wake); - pxa_init_gpio(IRQ_GPIO_2_x, 2, 84, pxa25x_set_wake); } #ifdef CONFIG_CPU_PXA26x void __init pxa26x_init_irq(void) { pxa_init_irq(32, pxa25x_set_wake); - pxa_init_gpio(IRQ_GPIO_2_x, 2, 89, pxa25x_set_wake); } #endif diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index 44563a0997bd..aed6cbcf3866 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c @@ -12,6 +12,7 @@ * published by the Free Software Foundation. */ #include +#include #include #include #include @@ -386,7 +387,6 @@ static int pxa27x_set_wake(struct irq_data *d, unsigned int on) void __init pxa27x_init_irq(void) { pxa_init_irq(34, pxa27x_set_wake); - pxa_init_gpio(IRQ_GPIO_2_x, 2, 120, pxa27x_set_wake); } static struct map_desc pxa27x_io_desc[] __initdata = { @@ -422,6 +422,7 @@ void __init pxa27x_set_i2c_power_info(struct i2c_pxa_platform_data *info) } static struct platform_device *devices[] __initdata = { + &pxa_device_gpio, &pxa27x_device_udc, &pxa_device_pmu, &pxa_device_i2s, diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c index 0737c59b88ae..06cfe348c709 100644 --- a/arch/arm/mach-pxa/pxa3xx.c +++ b/arch/arm/mach-pxa/pxa3xx.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -365,7 +364,8 @@ static struct irq_chip pxa_ext_wakeup_chip = { .irq_set_type = pxa_set_ext_wakeup_type, }; -static void __init pxa_init_ext_wakeup_irq(set_wake_t fn) +static void __init pxa_init_ext_wakeup_irq(int (*fn)(struct irq_data *, + unsigned int)) { int irq; @@ -388,7 +388,6 @@ void __init pxa3xx_init_irq(void) pxa_init_irq(56, pxa3xx_set_wake); pxa_init_ext_wakeup_irq(pxa3xx_set_wake); - pxa_init_gpio(IRQ_GPIO_2_x, 2, 127, NULL); } static struct map_desc pxa3xx_io_desc[] __initdata = { @@ -417,6 +416,7 @@ void __init pxa3xx_set_i2c_power_info(struct i2c_pxa_platform_data *info) } static struct platform_device *devices[] __initdata = { + &pxa_device_gpio, &pxa27x_device_udc, &pxa_device_pmu, &pxa_device_i2s, diff --git a/arch/arm/mach-pxa/pxa95x.c b/arch/arm/mach-pxa/pxa95x.c index 51371b39d2a3..0961093dd033 100644 --- a/arch/arm/mach-pxa/pxa95x.c +++ b/arch/arm/mach-pxa/pxa95x.c @@ -20,7 +20,6 @@ #include #include -#include #include #include #include @@ -235,7 +234,6 @@ static struct clk_lookup pxa95x_clkregs[] = { void __init pxa95x_init_irq(void) { pxa_init_irq(96, NULL); - pxa_init_gpio(IRQ_GPIO_2_x, 2, 127, NULL); } /* @@ -248,6 +246,7 @@ void __init pxa95x_set_i2c_power_info(struct i2c_pxa_platform_data *info) } static struct platform_device *devices[] __initdata = { + &pxa_device_gpio, &sa1100_device_rtc, &pxa_device_rtc, &pxa27x_device_ssp1, diff --git a/arch/arm/plat-pxa/include/plat/gpio-pxa.h b/arch/arm/plat-pxa/include/plat/gpio-pxa.h deleted file mode 100644 index 15bf9be051e8..000000000000 --- a/arch/arm/plat-pxa/include/plat/gpio-pxa.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef __PLAT_PXA_GPIO_H -#define __PLAT_PXA_GPIO_H - -struct irq_data; - -/* - * We handle the GPIOs by banks, each bank covers up to 32 GPIOs with - * one set of registers. The register offsets are organized below: - * - * GPLR GPDR GPSR GPCR GRER GFER GEDR - * BANK 0 - 0x0000 0x000C 0x0018 0x0024 0x0030 0x003C 0x0048 - * BANK 1 - 0x0004 0x0010 0x001C 0x0028 0x0034 0x0040 0x004C - * BANK 2 - 0x0008 0x0014 0x0020 0x002C 0x0038 0x0044 0x0050 - * - * BANK 3 - 0x0100 0x010C 0x0118 0x0124 0x0130 0x013C 0x0148 - * BANK 4 - 0x0104 0x0110 0x011C 0x0128 0x0134 0x0140 0x014C - * BANK 5 - 0x0108 0x0114 0x0120 0x012C 0x0138 0x0144 0x0150 - * - * NOTE: - * BANK 3 is only available on PXA27x and later processors. - * BANK 4 and 5 are only available on PXA935 - */ - -#define GPIO_BANK(n) (GPIO_REGS_VIRT + BANK_OFF(n)) - -#define GPLR_OFFSET 0x00 -#define GPDR_OFFSET 0x0C -#define GPSR_OFFSET 0x18 -#define GPCR_OFFSET 0x24 -#define GRER_OFFSET 0x30 -#define GFER_OFFSET 0x3C -#define GEDR_OFFSET 0x48 - -/* NOTE: some PXAs have fewer on-chip GPIOs (like PXA255, with 85). - * Those cases currently cause holes in the GPIO number space, the - * actual number of the last GPIO is recorded by 'pxa_last_gpio'. - */ -extern int pxa_last_gpio; - -typedef int (*set_wake_t)(struct irq_data *d, unsigned int on); - -extern void pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn); -extern int pxa_irq_to_gpio(int irq); - -#endif /* __PLAT_PXA_GPIO_H */ diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 8482a23887dc..aa0b94ff36d0 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -141,6 +141,12 @@ config GPIO_PL061 help Say yes here to support the PrimeCell PL061 GPIO device +config GPIO_PXA + bool "PXA GPIO support" + depends on ARCH_PXA || ARCH_MMP + help + Say yes here to support the PXA GPIO device + config GPIO_XILINX bool "Xilinx GPIO support" depends on PPC_OF || MICROBLAZE diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index dbcb0bcfd8da..5b2b9e26f49c 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -40,7 +40,7 @@ obj-$(CONFIG_GPIO_PCA953X) += gpio-pca953x.o obj-$(CONFIG_GPIO_PCF857X) += gpio-pcf857x.o obj-$(CONFIG_GPIO_PCH) += gpio-pch.o obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o -obj-$(CONFIG_PLAT_PXA) += gpio-pxa.o +obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o obj-$(CONFIG_PLAT_SAMSUNG) += gpio-samsung.o obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c index 31d2da4100cd..079f97fde2c7 100644 --- a/drivers/gpio/gpio-pxa.c +++ b/drivers/gpio/gpio-pxa.c @@ -12,13 +12,42 @@ * published by the Free Software Foundation. */ #include +#include #include #include #include +#include #include #include -#include +/* + * We handle the GPIOs by banks, each bank covers up to 32 GPIOs with + * one set of registers. The register offsets are organized below: + * + * GPLR GPDR GPSR GPCR GRER GFER GEDR + * BANK 0 - 0x0000 0x000C 0x0018 0x0024 0x0030 0x003C 0x0048 + * BANK 1 - 0x0004 0x0010 0x001C 0x0028 0x0034 0x0040 0x004C + * BANK 2 - 0x0008 0x0014 0x0020 0x002C 0x0038 0x0044 0x0050 + * + * BANK 3 - 0x0100 0x010C 0x0118 0x0124 0x0130 0x013C 0x0148 + * BANK 4 - 0x0104 0x0110 0x011C 0x0128 0x0134 0x0140 0x014C + * BANK 5 - 0x0108 0x0114 0x0120 0x012C 0x0138 0x0144 0x0150 + * + * NOTE: + * BANK 3 is only available on PXA27x and later processors. + * BANK 4 and 5 are only available on PXA935 + */ + +#define GPLR_OFFSET 0x00 +#define GPDR_OFFSET 0x0C +#define GPSR_OFFSET 0x18 +#define GPCR_OFFSET 0x24 +#define GRER_OFFSET 0x30 +#define GFER_OFFSET 0x3C +#define GEDR_OFFSET 0x48 +#define GAFR_OFFSET 0x54 + +#define BANK_OFF(n) (((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2)) int pxa_last_gpio; @@ -52,6 +81,7 @@ enum { static DEFINE_SPINLOCK(gpio_lock); static struct pxa_gpio_chip *pxa_gpio_chips; static int gpio_type; +static void __iomem *gpio_reg_base; #define for_each_gpio_chip(i, c) \ for (i = 0, c = &pxa_gpio_chips[0]; i <= pxa_last_gpio; i += 32, c++) @@ -76,6 +106,53 @@ static inline int gpio_is_mmp_type(int type) return (type & MMP_GPIO) != 0; } +/* GPIO86/87/88/89 on PXA26x have their direction bits in PXA_GPDR(2 inverted, + * as well as their Alternate Function value being '1' for GPIO in GAFRx. + */ +static inline int __gpio_is_inverted(int gpio) +{ + if ((gpio_type == PXA26X_GPIO) && (gpio > 85)) + return 1; + return 0; +} + +/* + * On PXA25x and PXA27x, GAFRx and GPDRx together decide the alternate + * function of a GPIO, and GPDRx cannot be altered once configured. It + * is attributed as "occupied" here (I know this terminology isn't + * accurate, you are welcome to propose a better one :-) + */ +static inline int __gpio_is_occupied(unsigned gpio) +{ + struct pxa_gpio_chip *pxachip; + void __iomem *base; + unsigned long gafr = 0, gpdr = 0; + int ret, af = 0, dir = 0; + + pxachip = gpio_to_pxachip(gpio); + base = gpio_chip_base(&pxachip->chip); + gpdr = readl_relaxed(base + GPDR_OFFSET); + + switch (gpio_type) { + case PXA25X_GPIO: + case PXA26X_GPIO: + case PXA27X_GPIO: + gafr = readl_relaxed(base + GAFR_OFFSET); + af = (gafr >> ((gpio & 0xf) * 2)) & 0x3; + dir = gpdr & GPIO_bit(gpio); + + if (__gpio_is_inverted(gpio)) + ret = (af != 1) || (dir == 0); + else + ret = (af != 0) || (dir != 0); + break; + default: + ret = gpdr & GPIO_bit(gpio); + break; + } + return ret; +} + #ifdef CONFIG_ARCH_PXA static inline int __pxa_gpio_to_irq(int gpio) { @@ -187,7 +264,7 @@ static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value) (value ? GPSR_OFFSET : GPCR_OFFSET)); } -static int __init pxa_init_gpio_chip(int gpio_end) +static int __devinit pxa_init_gpio_chip(int gpio_end) { int i, gpio, nbanks = gpio_to_bank(gpio_end) + 1; struct pxa_gpio_chip *chips; @@ -202,7 +279,7 @@ static int __init pxa_init_gpio_chip(int gpio_end) struct gpio_chip *c = &chips[i].chip; sprintf(chips[i].label, "gpio-%d", i); - chips[i].regbase = GPIO_BANK(i); + chips[i].regbase = gpio_reg_base + BANK_OFF(i); c->base = gpio; c->label = chips[i].label; @@ -384,17 +461,35 @@ static int pxa_gpio_nums(void) return count; } -void __init pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn) +static int __devinit pxa_gpio_probe(struct platform_device *pdev) { struct pxa_gpio_chip *c; + struct resource *res; int gpio, irq; + int irq0 = 0, irq1 = 0, irq_mux, gpio_offset = 0; pxa_last_gpio = pxa_gpio_nums(); if (!pxa_last_gpio) - return; + return -EINVAL; + + irq0 = platform_get_irq_byname(pdev, "gpio0"); + irq1 = platform_get_irq_byname(pdev, "gpio1"); + irq_mux = platform_get_irq_byname(pdev, "gpio_mux"); + if ((irq0 > 0 && irq1 <= 0) || (irq0 <= 0 && irq1 > 0) + || (irq_mux <= 0)) + return -EINVAL; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -EINVAL; + gpio_reg_base = ioremap(res->start, resource_size(res)); + if (!gpio_reg_base) + return -EINVAL; + + if (irq0 > 0) + gpio_offset = 2; /* Initialize GPIO chips */ - pxa_init_gpio_chip(end); + pxa_init_gpio_chip(pxa_last_gpio); /* clear all GPIO edge detects */ for_each_gpio_chip(gpio, c) { @@ -417,16 +512,29 @@ void __init pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn) irq_set_chained_handler(IRQ_GPIO1, pxa_gpio_demux_handler); #endif - for (irq = gpio_to_irq(start); irq <= gpio_to_irq(end); irq++) { + for (irq = gpio_to_irq(gpio_offset); + irq <= gpio_to_irq(pxa_last_gpio); irq++) { irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip, handle_edge_irq); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } - /* Install handler for GPIO>=2 edge detect interrupts */ - irq_set_chained_handler(mux_irq, pxa_gpio_demux_handler); - pxa_muxed_gpio_chip.irq_set_wake = fn; + irq_set_chained_handler(irq_mux, pxa_gpio_demux_handler); + return 0; +} + +static struct platform_driver pxa_gpio_driver = { + .probe = pxa_gpio_probe, + .driver = { + .name = "pxa-gpio", + }, +}; + +static int __init pxa_gpio_init(void) +{ + return platform_driver_register(&pxa_gpio_driver); } +postcore_initcall(pxa_gpio_init); #ifdef CONFIG_PM static int pxa_gpio_suspend(void) @@ -470,3 +578,10 @@ struct syscore_ops pxa_gpio_syscore_ops = { .suspend = pxa_gpio_suspend, .resume = pxa_gpio_resume, }; + +static int __init pxa_gpio_sysinit(void) +{ + register_syscore_ops(&pxa_gpio_syscore_ops); + return 0; +} +postcore_initcall(pxa_gpio_sysinit); diff --git a/include/linux/gpio-pxa.h b/include/linux/gpio-pxa.h new file mode 100644 index 000000000000..05071ee34c3f --- /dev/null +++ b/include/linux/gpio-pxa.h @@ -0,0 +1,16 @@ +#ifndef __GPIO_PXA_H +#define __GPIO_PXA_H + +#define GPIO_bit(x) (1 << ((x) & 0x1f)) + +#define gpio_to_bank(gpio) ((gpio) >> 5) + +/* NOTE: some PXAs have fewer on-chip GPIOs (like PXA255, with 85). + * Those cases currently cause holes in the GPIO number space, the + * actual number of the last GPIO is recorded by 'pxa_last_gpio'. + */ +extern int pxa_last_gpio; + +extern int pxa_irq_to_gpio(int irq); + +#endif /* __GPIO_PXA_H */ -- cgit v1.2.3-55-g7522 From be24168f144122b3730beab257fa058745d14cb4 Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Mon, 17 Oct 2011 21:07:15 +0800 Subject: ARM: mmp: clear gpio edge detect Append code to clear gpio edge detect in gpio-pxa driver. Signed-off-by: Haojian Zhuang --- drivers/gpio/gpio-pxa.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c index 079f97fde2c7..bfd755531f7a 100644 --- a/drivers/gpio/gpio-pxa.c +++ b/drivers/gpio/gpio-pxa.c @@ -46,6 +46,7 @@ #define GFER_OFFSET 0x3C #define GEDR_OFFSET 0x48 #define GAFR_OFFSET 0x54 +#define ED_MASK_OFFSET 0x9C /* GPIO edge detection for AP side */ #define BANK_OFF(n) (((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2)) @@ -496,6 +497,9 @@ static int __devinit pxa_gpio_probe(struct platform_device *pdev) writel_relaxed(0, c->regbase + GFER_OFFSET); writel_relaxed(0, c->regbase + GRER_OFFSET); writel_relaxed(~0,c->regbase + GEDR_OFFSET); + /* unmask GPIO edge detect for AP side */ + if (gpio_is_mmp_type(gpio_type)) + writel_relaxed(~0, c->regbase + ED_MASK_OFFSET); } #ifdef CONFIG_ARCH_PXA -- cgit v1.2.3-55-g7522 From 389eda15e0f41112d7c44213b3c4f8bd1c9398bc Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Mon, 17 Oct 2011 21:26:55 +0800 Subject: ARM: pxa: add clk support in gpio driver Support clk in gpio driver. There's no gpio clock in PXA25x and PXA27x. So use dummy clk instead. And move the gpio edge initialization into gpio driver for arch-mmp. Signed-off-by: Haojian Zhuang --- arch/arm/mach-mmp/mmp2.c | 11 ++--------- arch/arm/mach-mmp/pxa168.c | 11 ++--------- arch/arm/mach-mmp/pxa910.c | 11 ++--------- arch/arm/mach-pxa/pxa25x.c | 1 + arch/arm/mach-pxa/pxa27x.c | 1 + arch/arm/mach-pxa/pxa3xx.c | 2 ++ arch/arm/mach-pxa/pxa95x.c | 2 ++ drivers/gpio/gpio-pxa.c | 26 +++++++++++++++++++++++++- 8 files changed, 37 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/arch/arm/mach-mmp/mmp2.c b/arch/arm/mach-mmp/mmp2.c index 1ed222d3e22b..617c60a170a4 100644 --- a/arch/arm/mach-mmp/mmp2.c +++ b/arch/arm/mach-mmp/mmp2.c @@ -93,18 +93,9 @@ void mmp2_clear_pmic_int(void) __raw_writel(data, mfpr_pmic); } -static void __init mmp2_init_gpio(void) -{ - int i; - - /* enable GPIO clock */ - __raw_writel(APBC_APBCLK | APBC_FNCLK, APBC_MMP2_GPIO); -} - void __init mmp2_init_irq(void) { mmp2_init_icu(); - mmp2_init_gpio(); } static void sdhc_clk_enable(struct clk *clk) @@ -141,6 +132,7 @@ static APBC_CLK(twsi3, MMP2_TWSI3, 0, 26000000); static APBC_CLK(twsi4, MMP2_TWSI4, 0, 26000000); static APBC_CLK(twsi5, MMP2_TWSI5, 0, 26000000); static APBC_CLK(twsi6, MMP2_TWSI6, 0, 26000000); +static APBC_CLK(gpio, MMP2_GPIO, 0, 26000000); static APMU_CLK(nand, NAND, 0xbf, 100000000); static APMU_CLK_OPS(sdh0, SDH0, 0x1b, 200000000, &sdhc_clk_ops); @@ -160,6 +152,7 @@ static struct clk_lookup mmp2_clkregs[] = { INIT_CLKREG(&clk_twsi5, "pxa2xx-i2c.4", NULL), INIT_CLKREG(&clk_twsi6, "pxa2xx-i2c.5", NULL), INIT_CLKREG(&clk_nand, "pxa3xx-nand", NULL), + INIT_CLKREG(&clk_gpio, "pxa-gpio", NULL), INIT_CLKREG(&clk_sdh0, "sdhci-pxav3.0", "PXA-SDHCLK"), INIT_CLKREG(&clk_sdh1, "sdhci-pxav3.1", "PXA-SDHCLK"), INIT_CLKREG(&clk_sdh2, "sdhci-pxav3.2", "PXA-SDHCLK"), diff --git a/arch/arm/mach-mmp/pxa168.c b/arch/arm/mach-mmp/pxa168.c index fefdfe59c07c..84245035f351 100644 --- a/arch/arm/mach-mmp/pxa168.c +++ b/arch/arm/mach-mmp/pxa168.c @@ -43,18 +43,9 @@ static struct mfp_addr_map pxa168_mfp_addr_map[] __initdata = MFP_ADDR_END, }; -static void __init pxa168_init_gpio(void) -{ - int i; - - /* enable GPIO clock */ - __raw_writel(APBC_APBCLK | APBC_FNCLK, APBC_PXA168_GPIO); -} - void __init pxa168_init_irq(void) { icu_init_irq(); - pxa168_init_gpio(); } /* APB peripheral clocks */ @@ -72,6 +63,7 @@ static APBC_CLK(ssp2, PXA168_SSP2, 4, 0); static APBC_CLK(ssp3, PXA168_SSP3, 4, 0); static APBC_CLK(ssp4, PXA168_SSP4, 4, 0); static APBC_CLK(ssp5, PXA168_SSP5, 4, 0); +static APBC_CLK(gpio, PXA168_GPIO, 0, 13000000); static APBC_CLK(keypad, PXA168_KPC, 0, 32000); static APMU_CLK(nand, NAND, 0x19b, 156000000); @@ -97,6 +89,7 @@ static struct clk_lookup pxa168_clkregs[] = { INIT_CLKREG(&clk_ssp5, "pxa168-ssp.4", NULL), INIT_CLKREG(&clk_nand, "pxa3xx-nand", NULL), INIT_CLKREG(&clk_lcd, "pxa168-fb", NULL), + INIT_CLKREG(&clk_gpio, "pxa-gpio", NULL), INIT_CLKREG(&clk_keypad, "pxa27x-keypad", NULL), INIT_CLKREG(&clk_eth, "pxa168-eth", "MFUCLK"), INIT_CLKREG(&clk_usb, "pxa168-ehci", "PXA168-USBCLK"), diff --git a/arch/arm/mach-mmp/pxa910.c b/arch/arm/mach-mmp/pxa910.c index 7b992ced095c..3241a25784d0 100644 --- a/arch/arm/mach-mmp/pxa910.c +++ b/arch/arm/mach-mmp/pxa910.c @@ -77,18 +77,9 @@ static struct mfp_addr_map pxa910_mfp_addr_map[] __initdata = MFP_ADDR_END, }; -static void __init pxa910_init_gpio(void) -{ - int i; - - /* enable GPIO clock */ - __raw_writel(APBC_APBCLK | APBC_FNCLK, APBC_PXA910_GPIO); -} - void __init pxa910_init_irq(void) { icu_init_irq(); - pxa910_init_gpio(); } /* APB peripheral clocks */ @@ -100,6 +91,7 @@ static APBC_CLK(pwm1, PXA910_PWM1, 1, 13000000); static APBC_CLK(pwm2, PXA910_PWM2, 1, 13000000); static APBC_CLK(pwm3, PXA910_PWM3, 1, 13000000); static APBC_CLK(pwm4, PXA910_PWM4, 1, 13000000); +static APBC_CLK(gpio, PXA910_GPIO, 0, 13000000); static APMU_CLK(nand, NAND, 0x19b, 156000000); static APMU_CLK(u2o, USB, 0x1b, 480000000); @@ -115,6 +107,7 @@ static struct clk_lookup pxa910_clkregs[] = { INIT_CLKREG(&clk_pwm3, "pxa910-pwm.2", NULL), INIT_CLKREG(&clk_pwm4, "pxa910-pwm.3", NULL), INIT_CLKREG(&clk_nand, "pxa3xx-nand", NULL), + INIT_CLKREG(&clk_gpio, "pxa-gpio", NULL), INIT_CLKREG(&clk_u2o, "pxa-u2o", "U2OCLK"), }; diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c index 91e4f6c03766..8a775f631c55 100644 --- a/arch/arm/mach-pxa/pxa25x.c +++ b/arch/arm/mach-pxa/pxa25x.c @@ -209,6 +209,7 @@ static struct clk_lookup pxa25x_clkregs[] = { INIT_CLKREG(&clk_pxa25x_gpio11, NULL, "GPIO11_CLK"), INIT_CLKREG(&clk_pxa25x_gpio12, NULL, "GPIO12_CLK"), INIT_CLKREG(&clk_pxa25x_mem, "pxa2xx-pcmcia", NULL), + INIT_CLKREG(&clk_dummy, "pxa-gpio", NULL), }; static struct clk_lookup pxa25x_hwuart_clkreg = diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index aed6cbcf3866..6c49e66057e3 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c @@ -230,6 +230,7 @@ static struct clk_lookup pxa27x_clkregs[] = { INIT_CLKREG(&clk_pxa27x_im, NULL, "IMCLK"), INIT_CLKREG(&clk_pxa27x_memc, NULL, "MEMCLK"), INIT_CLKREG(&clk_pxa27x_mem, "pxa2xx-pcmcia", NULL), + INIT_CLKREG(&clk_dummy, "pxa-gpio", NULL), }; #ifdef CONFIG_PM diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c index 06cfe348c709..4f402afa6609 100644 --- a/arch/arm/mach-pxa/pxa3xx.c +++ b/arch/arm/mach-pxa/pxa3xx.c @@ -55,6 +55,7 @@ static DEFINE_PXA3_CKEN(pxa3xx_pwm0, PWM0, 13000000, 0); static DEFINE_PXA3_CKEN(pxa3xx_pwm1, PWM1, 13000000, 0); static DEFINE_PXA3_CKEN(pxa3xx_mmc1, MMC1, 19500000, 0); static DEFINE_PXA3_CKEN(pxa3xx_mmc2, MMC2, 19500000, 0); +static DEFINE_PXA3_CKEN(pxa3xx_gpio, GPIO, 13000000, 0); static DEFINE_CK(pxa3xx_lcd, LCD, &clk_pxa3xx_hsio_ops); static DEFINE_CK(pxa3xx_smemc, SMC, &clk_pxa3xx_smemc_ops); @@ -87,6 +88,7 @@ static struct clk_lookup pxa3xx_clkregs[] = { INIT_CLKREG(&clk_pxa3xx_mmc1, "pxa2xx-mci.0", NULL), INIT_CLKREG(&clk_pxa3xx_mmc2, "pxa2xx-mci.1", NULL), INIT_CLKREG(&clk_pxa3xx_smemc, "pxa2xx-pcmcia", NULL), + INIT_CLKREG(&clk_pxa3xx_gpio, "pxa-gpio", NULL), }; #ifdef CONFIG_PM diff --git a/arch/arm/mach-pxa/pxa95x.c b/arch/arm/mach-pxa/pxa95x.c index 0961093dd033..d082a583df78 100644 --- a/arch/arm/mach-pxa/pxa95x.c +++ b/arch/arm/mach-pxa/pxa95x.c @@ -211,6 +211,7 @@ static DEFINE_PXA3_CKEN(pxa95x_ssp3, SSP3, 13000000, 0); static DEFINE_PXA3_CKEN(pxa95x_ssp4, SSP4, 13000000, 0); static DEFINE_PXA3_CKEN(pxa95x_pwm0, PWM0, 13000000, 0); static DEFINE_PXA3_CKEN(pxa95x_pwm1, PWM1, 13000000, 0); +static DEFINE_PXA3_CKEN(pxa95x_gpio, GPIO, 13000000, 0); static struct clk_lookup pxa95x_clkregs[] = { INIT_CLKREG(&clk_pxa95x_pout, NULL, "CLK_POUT"), @@ -229,6 +230,7 @@ static struct clk_lookup pxa95x_clkregs[] = { INIT_CLKREG(&clk_pxa95x_ssp4, "pxa27x-ssp.3", NULL), INIT_CLKREG(&clk_pxa95x_pwm0, "pxa27x-pwm.0", NULL), INIT_CLKREG(&clk_pxa95x_pwm1, "pxa27x-pwm.1", NULL), + INIT_CLKREG(&clk_pxa95x_gpio, "pxa-gpio", NULL), }; void __init pxa95x_init_irq(void) diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c index bfd755531f7a..b2d3ee1d183a 100644 --- a/drivers/gpio/gpio-pxa.c +++ b/drivers/gpio/gpio-pxa.c @@ -11,6 +11,8 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ +#include +#include #include #include #include @@ -466,7 +468,8 @@ static int __devinit pxa_gpio_probe(struct platform_device *pdev) { struct pxa_gpio_chip *c; struct resource *res; - int gpio, irq; + struct clk *clk; + int gpio, irq, ret; int irq0 = 0, irq1 = 0, irq_mux, gpio_offset = 0; pxa_last_gpio = pxa_gpio_nums(); @@ -489,6 +492,27 @@ static int __devinit pxa_gpio_probe(struct platform_device *pdev) if (irq0 > 0) gpio_offset = 2; + clk = clk_get(&pdev->dev, NULL); + if (IS_ERR(clk)) { + dev_err(&pdev->dev, "Error %ld to get gpio clock\n", + PTR_ERR(clk)); + iounmap(gpio_reg_base); + return PTR_ERR(clk); + } + ret = clk_prepare(clk); + if (ret) { + clk_put(clk); + iounmap(gpio_reg_base); + return ret; + } + ret = clk_enable(clk); + if (ret) { + clk_unprepare(clk); + clk_put(clk); + iounmap(gpio_reg_base); + return ret; + } + /* Initialize GPIO chips */ pxa_init_gpio_chip(pxa_last_gpio); -- cgit v1.2.3-55-g7522 From 951c486f62490e032da0ad17e93270b0cfb6687f Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Mon, 14 Nov 2011 20:52:26 +0800 Subject: driver: pcmcia: replace IRQ_GPIO() with gpio_to_irq() Use common gpio_to_irq() to replace machine dependant macro IRQ_GPIO(). Signed-off-by: Haojian Zhuang --- drivers/pcmcia/pxa2xx_cm_x255.c | 16 ++++++++-------- drivers/pcmcia/pxa2xx_cm_x270.c | 9 ++++----- 2 files changed, 12 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/pcmcia/pxa2xx_cm_x255.c b/drivers/pcmcia/pxa2xx_cm_x255.c index 0b4f946cf13a..31ab6ddf52c9 100644 --- a/drivers/pcmcia/pxa2xx_cm_x255.c +++ b/drivers/pcmcia/pxa2xx_cm_x255.c @@ -16,8 +16,6 @@ #include #include -#include - #include "soc_common.h" #define GPIO_PCMCIA_SKTSEL (54) @@ -27,15 +25,15 @@ #define GPIO_PCMCIA_S1_RDYINT (8) #define GPIO_PCMCIA_RESET (9) -#define PCMCIA_S0_CD_VALID IRQ_GPIO(GPIO_PCMCIA_S0_CD_VALID) -#define PCMCIA_S1_CD_VALID IRQ_GPIO(GPIO_PCMCIA_S1_CD_VALID) -#define PCMCIA_S0_RDYINT IRQ_GPIO(GPIO_PCMCIA_S0_RDYINT) -#define PCMCIA_S1_RDYINT IRQ_GPIO(GPIO_PCMCIA_S1_RDYINT) +#define PCMCIA_S0_CD_VALID gpio_to_irq(GPIO_PCMCIA_S0_CD_VALID) +#define PCMCIA_S1_CD_VALID gpio_to_irq(GPIO_PCMCIA_S1_CD_VALID) +#define PCMCIA_S0_RDYINT gpio_to_irq(GPIO_PCMCIA_S0_RDYINT) +#define PCMCIA_S1_RDYINT gpio_to_irq(GPIO_PCMCIA_S1_RDYINT) static struct pcmcia_irqs irqs[] = { - { 0, PCMCIA_S0_CD_VALID, "PCMCIA0 CD" }, - { 1, PCMCIA_S1_CD_VALID, "PCMCIA1 CD" }, + { .sock = 0, .str = "PCMCIA0 CD" }, + { .sock = 1, .str = "PCMCIA1 CD" }, }; static int cmx255_pcmcia_hw_init(struct soc_pcmcia_socket *skt) @@ -46,6 +44,8 @@ static int cmx255_pcmcia_hw_init(struct soc_pcmcia_socket *skt) gpio_direction_output(GPIO_PCMCIA_RESET, 0); skt->socket.pci_irq = skt->nr == 0 ? PCMCIA_S0_RDYINT : PCMCIA_S1_RDYINT; + irqs[0].irq = PCMCIA_S0_CD_VALID; + irqs[1].irq = PCMCIA_S1_CD_VALID; ret = soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); if (!ret) gpio_free(GPIO_PCMCIA_RESET); diff --git a/drivers/pcmcia/pxa2xx_cm_x270.c b/drivers/pcmcia/pxa2xx_cm_x270.c index 923f315926ef..3dc7621a0767 100644 --- a/drivers/pcmcia/pxa2xx_cm_x270.c +++ b/drivers/pcmcia/pxa2xx_cm_x270.c @@ -16,20 +16,18 @@ #include #include -#include - #include "soc_common.h" #define GPIO_PCMCIA_S0_CD_VALID (84) #define GPIO_PCMCIA_S0_RDYINT (82) #define GPIO_PCMCIA_RESET (53) -#define PCMCIA_S0_CD_VALID IRQ_GPIO(GPIO_PCMCIA_S0_CD_VALID) -#define PCMCIA_S0_RDYINT IRQ_GPIO(GPIO_PCMCIA_S0_RDYINT) +#define PCMCIA_S0_CD_VALID gpio_to_irq(GPIO_PCMCIA_S0_CD_VALID) +#define PCMCIA_S0_RDYINT gpio_to_irq(GPIO_PCMCIA_S0_RDYINT) static struct pcmcia_irqs irqs[] = { - { 0, PCMCIA_S0_CD_VALID, "PCMCIA0 CD" }, + { .sock = 0, .str = "PCMCIA0 CD" }, }; static int cmx270_pcmcia_hw_init(struct soc_pcmcia_socket *skt) @@ -40,6 +38,7 @@ static int cmx270_pcmcia_hw_init(struct soc_pcmcia_socket *skt) gpio_direction_output(GPIO_PCMCIA_RESET, 0); skt->socket.pci_irq = PCMCIA_S0_RDYINT; + irqs[0].irq = PCMCIA_S0_CD_VALID; ret = soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); if (!ret) gpio_free(GPIO_PCMCIA_RESET); -- cgit v1.2.3-55-g7522 From f75ba50bdc2bcfab591bdf903312557033d0ac68 Mon Sep 17 00:00:00 2001 From: Jamie Iles Date: Tue, 8 Nov 2011 10:12:32 +0000 Subject: macb: initial support for Cadence GEM The Cadence GEM is based on the MACB Ethernet controller but has a few small changes with regards to register and bitfield placement. This patch detects the presence of a GEM by reading the module ID register and setting a flag appropriately. This handles the new HW address, USRIO and hash register base register locations in GEM. v3: - convert to macb_is_gem() inline rather than storing a boolean flag - handle rx_overrun stats for gem Acked-by: David S. Miller Acked-by: Nicolas Ferre Cc: Jean-Christophe PLAGNIOL-VILLARD Signed-off-by: Jamie Iles Tested-by: Jean-Christophe PLAGNIOL-VILLARD --- drivers/net/ethernet/Makefile | 2 +- drivers/net/ethernet/cadence/Kconfig | 16 +++++----- drivers/net/ethernet/cadence/macb.c | 43 ++++++++++++++----------- drivers/net/ethernet/cadence/macb.h | 61 ++++++++++++++++++++++++++++++++++++ 4 files changed, 95 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile index be5dde040261..94b7f287d6c5 100644 --- a/drivers/net/ethernet/Makefile +++ b/drivers/net/ethernet/Makefile @@ -10,7 +10,7 @@ obj-$(CONFIG_NET_VENDOR_ALTEON) += alteon/ obj-$(CONFIG_NET_VENDOR_AMD) += amd/ obj-$(CONFIG_NET_VENDOR_APPLE) += apple/ obj-$(CONFIG_NET_VENDOR_ATHEROS) += atheros/ -obj-$(CONFIG_NET_ATMEL) += cadence/ +obj-$(CONFIG_NET_CADENCE) += cadence/ obj-$(CONFIG_NET_BFIN) += adi/ obj-$(CONFIG_NET_VENDOR_BROADCOM) += broadcom/ obj-$(CONFIG_NET_VENDOR_BROCADE) += brocade/ diff --git a/drivers/net/ethernet/cadence/Kconfig b/drivers/net/ethernet/cadence/Kconfig index 98849a1fc749..a2e150059bc7 100644 --- a/drivers/net/ethernet/cadence/Kconfig +++ b/drivers/net/ethernet/cadence/Kconfig @@ -5,8 +5,8 @@ config HAVE_NET_MACB bool -config NET_ATMEL - bool "Atmel devices" +config NET_CADENCE + bool "Cadence devices" depends on HAVE_NET_MACB || (ARM && ARCH_AT91RM9200) ---help--- If you have a network (Ethernet) card belonging to this class, say Y. @@ -20,7 +20,7 @@ config NET_ATMEL the remaining Atmel network card questions. If you say Y, you will be asked for your specific card in the following questions. -if NET_ATMEL +if NET_CADENCE config ARM_AT91_ETHER tristate "AT91RM9200 Ethernet support" @@ -32,14 +32,16 @@ config ARM_AT91_ETHER ethernet support, then you should always answer Y to this. config MACB - tristate "Atmel MACB support" + tristate "Cadence MACB/GEM support" depends on HAVE_NET_MACB select PHYLIB ---help--- - The Atmel MACB ethernet interface is found on many AT32 and AT91 - parts. Say Y to include support for the MACB chip. + The Cadence MACB ethernet interface is found on many Atmel AT32 and + AT91 parts. This driver also supports the Cadence GEM (Gigabit + Ethernet MAC found in some ARM SoC devices). Note: the Gigabit mode + is not yet supported. Say Y to include support for the MACB/GEM chip. To compile this driver as a module, choose M here: the module will be called macb. -endif # NET_ATMEL +endif # NET_CADENCE diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index aa1d597091a8..4e61a8610d6a 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -1,5 +1,5 @@ /* - * Atmel MACB Ethernet Controller driver + * Cadence MACB/GEM Ethernet Controller driver * * Copyright (C) 2004-2006 Atmel Corporation * @@ -59,9 +59,9 @@ static void __macb_set_hwaddr(struct macb *bp) u16 top; bottom = cpu_to_le32(*((u32 *)bp->dev->dev_addr)); - macb_writel(bp, SA1B, bottom); + macb_or_gem_writel(bp, SA1B, bottom); top = cpu_to_le16(*((u16 *)(bp->dev->dev_addr + 4))); - macb_writel(bp, SA1T, top); + macb_or_gem_writel(bp, SA1T, top); } static void __init macb_get_hwaddr(struct macb *bp) @@ -70,8 +70,8 @@ static void __init macb_get_hwaddr(struct macb *bp) u16 top; u8 addr[6]; - bottom = macb_readl(bp, SA1B); - top = macb_readl(bp, SA1T); + bottom = macb_or_gem_readl(bp, SA1B); + top = macb_or_gem_readl(bp, SA1T); addr[0] = bottom & 0xff; addr[1] = (bottom >> 8) & 0xff; @@ -580,7 +580,10 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) if (status & MACB_BIT(ISR_ROVR)) { /* We missed at least one packet */ - bp->hw_stats.rx_overruns++; + if (macb_is_gem(bp)) + bp->hw_stats.gem.rx_overruns++; + else + bp->hw_stats.macb.rx_overruns++; } if (status & MACB_BIT(HRESP)) { @@ -902,8 +905,8 @@ static void macb_sethashtable(struct net_device *dev) mc_filter[bitnr >> 5] |= 1 << (bitnr & 31); } - macb_writel(bp, HRB, mc_filter[0]); - macb_writel(bp, HRT, mc_filter[1]); + macb_or_gem_writel(bp, HRB, mc_filter[0]); + macb_or_gem_writel(bp, HRT, mc_filter[1]); } /* @@ -925,8 +928,8 @@ static void macb_set_rx_mode(struct net_device *dev) if (dev->flags & IFF_ALLMULTI) { /* Enable all multicast mode */ - macb_writel(bp, HRB, -1); - macb_writel(bp, HRT, -1); + macb_or_gem_writel(bp, HRB, -1); + macb_or_gem_writel(bp, HRT, -1); cfg |= MACB_BIT(NCFGR_MTI); } else if (!netdev_mc_empty(dev)) { /* Enable specific multicasts */ @@ -934,8 +937,8 @@ static void macb_set_rx_mode(struct net_device *dev) cfg |= MACB_BIT(NCFGR_MTI); } else if (dev->flags & (~IFF_ALLMULTI)) { /* Disable all multicast mode */ - macb_writel(bp, HRB, 0); - macb_writel(bp, HRT, 0); + macb_or_gem_writel(bp, HRB, 0); + macb_or_gem_writel(bp, HRT, 0); cfg &= ~MACB_BIT(NCFGR_MTI); } @@ -1196,15 +1199,16 @@ static int __init macb_probe(struct platform_device *pdev) if (pdata && pdata->is_rmii) #if defined(CONFIG_ARCH_AT91) - macb_writel(bp, USRIO, (MACB_BIT(RMII) | MACB_BIT(CLKEN)) ); + macb_or_gem_writel(bp, USRIO, (MACB_BIT(RMII) | + MACB_BIT(CLKEN))); #else - macb_writel(bp, USRIO, 0); + macb_or_gem_writel(bp, USRIO, 0); #endif else #if defined(CONFIG_ARCH_AT91) - macb_writel(bp, USRIO, MACB_BIT(CLKEN)); + macb_or_gem_writel(bp, USRIO, MACB_BIT(CLKEN)); #else - macb_writel(bp, USRIO, MACB_BIT(MII)); + macb_or_gem_writel(bp, USRIO, MACB_BIT(MII)); #endif bp->tx_pending = DEF_TX_RING_PENDING; @@ -1221,8 +1225,9 @@ static int __init macb_probe(struct platform_device *pdev) platform_set_drvdata(pdev, dev); - netdev_info(dev, "Atmel MACB at 0x%08lx irq %d (%pM)\n", - dev->base_addr, dev->irq, dev->dev_addr); + netdev_info(dev, "Cadence %s at 0x%08lx irq %d (%pM)\n", + macb_is_gem(bp) ? "GEM" : "MACB", dev->base_addr, + dev->irq, dev->dev_addr); phydev = bp->phy_dev; netdev_info(dev, "attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n", @@ -1332,6 +1337,6 @@ module_init(macb_init); module_exit(macb_exit); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Atmel MACB Ethernet driver"); +MODULE_DESCRIPTION("Cadence MACB/GEM Ethernet driver"); MODULE_AUTHOR("Haavard Skinnemoen (Atmel)"); MODULE_ALIAS("platform:macb"); diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h index d3212f6db703..d50057c244b2 100644 --- a/drivers/net/ethernet/cadence/macb.h +++ b/drivers/net/ethernet/cadence/macb.h @@ -59,6 +59,15 @@ #define MACB_TPQ 0x00bc #define MACB_USRIO 0x00c0 #define MACB_WOL 0x00c4 +#define MACB_MID 0x00fc + +/* GEM register offsets. */ +#define GEM_NCFGR 0x0004 +#define GEM_USRIO 0x000c +#define GEM_HRB 0x0080 +#define GEM_HRT 0x0084 +#define GEM_SA1B 0x0088 +#define GEM_SA1T 0x008C /* Bitfields in NCR */ #define MACB_LB_OFFSET 0 @@ -228,6 +237,12 @@ #define MACB_WOL_MTI_OFFSET 19 #define MACB_WOL_MTI_SIZE 1 +/* Bitfields in MID */ +#define MACB_IDNUM_OFFSET 16 +#define MACB_IDNUM_SIZE 16 +#define MACB_REV_OFFSET 0 +#define MACB_REV_SIZE 16 + /* Constants for CLK */ #define MACB_CLK_DIV8 0 #define MACB_CLK_DIV16 1 @@ -254,11 +269,52 @@ << MACB_##name##_OFFSET)) \ | MACB_BF(name,value)) +#define GEM_BIT(name) \ + (1 << GEM_##name##_OFFSET) +#define GEM_BF(name, value) \ + (((value) & ((1 << GEM_##name##_SIZE) - 1)) \ + << GEM_##name##_OFFSET) +#define GEM_BFEXT(name, value)\ + (((value) >> GEM_##name##_OFFSET) \ + & ((1 << GEM_##name##_SIZE) - 1)) +#define GEM_BFINS(name, value, old) \ + (((old) & ~(((1 << GEM_##name##_SIZE) - 1) \ + << GEM_##name##_OFFSET)) \ + | GEM_BF(name, value)) + /* Register access macros */ #define macb_readl(port,reg) \ __raw_readl((port)->regs + MACB_##reg) #define macb_writel(port,reg,value) \ __raw_writel((value), (port)->regs + MACB_##reg) +#define gem_readl(port, reg) \ + __raw_readl((port)->regs + GEM_##reg) +#define gem_writel(port, reg, value) \ + __raw_writel((value), (port)->regs + GEM_##reg) + +/* + * Conditional GEM/MACB macros. These perform the operation to the correct + * register dependent on whether the device is a GEM or a MACB. For registers + * and bitfields that are common across both devices, use macb_{read,write}l + * to avoid the cost of the conditional. + */ +#define macb_or_gem_writel(__bp, __reg, __value) \ + ({ \ + if (macb_is_gem((__bp))) \ + gem_writel((__bp), __reg, __value); \ + else \ + macb_writel((__bp), __reg, __value); \ + }) + +#define macb_or_gem_readl(__bp, __reg) \ + ({ \ + u32 __v; \ + if (macb_is_gem((__bp))) \ + __v = gem_readl((__bp), __reg); \ + else \ + __v = macb_readl((__bp), __reg); \ + __v; \ + }) struct dma_desc { u32 addr; @@ -391,4 +447,9 @@ struct macb { unsigned int duplex; }; +static inline bool macb_is_gem(struct macb *bp) +{ + return MACB_BFEXT(IDNUM, macb_readl(bp, MID)) == 0x2; +} + #endif /* _MACB_H */ -- cgit v1.2.3-55-g7522 From 70c9f3d4372ffa90775603e9c4e055a26a9b83e1 Mon Sep 17 00:00:00 2001 From: Jamie Iles Date: Wed, 9 Mar 2011 16:22:54 +0000 Subject: macb: support higher rate GEM MDIO clock divisors GEM devices support larger clock divisors and have a different range of divisors. Program the MDIO clock divisors based on the device type. Signed-off-by: Jamie Iles Acked-by: David S. Miller Acked-by: Nicolas Ferre Tested-by: Jean-Christophe PLAGNIOL-VILLARD --- drivers/net/ethernet/cadence/macb.c | 55 +++++++++++++++++++++++++++++-------- drivers/net/ethernet/cadence/macb.h | 11 ++++++++ 2 files changed, 55 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index 4e61a8610d6a..c5c3eb450c1b 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -793,6 +793,48 @@ static void macb_reset_hw(struct macb *bp) macb_readl(bp, ISR); } +static u32 gem_mdc_clk_div(struct macb *bp) +{ + u32 config; + unsigned long pclk_hz = clk_get_rate(bp->pclk); + + if (pclk_hz <= 20000000) + config = GEM_BF(CLK, GEM_CLK_DIV8); + else if (pclk_hz <= 40000000) + config = GEM_BF(CLK, GEM_CLK_DIV16); + else if (pclk_hz <= 80000000) + config = GEM_BF(CLK, GEM_CLK_DIV32); + else if (pclk_hz <= 120000000) + config = GEM_BF(CLK, GEM_CLK_DIV48); + else if (pclk_hz <= 160000000) + config = GEM_BF(CLK, GEM_CLK_DIV64); + else + config = GEM_BF(CLK, GEM_CLK_DIV96); + + return config; +} + +static u32 macb_mdc_clk_div(struct macb *bp) +{ + u32 config; + unsigned long pclk_hz; + + if (macb_is_gem(bp)) + return gem_mdc_clk_div(bp); + + pclk_hz = clk_get_rate(bp->pclk); + if (pclk_hz <= 20000000) + config = MACB_BF(CLK, MACB_CLK_DIV8); + else if (pclk_hz <= 40000000) + config = MACB_BF(CLK, MACB_CLK_DIV16); + else if (pclk_hz <= 80000000) + config = MACB_BF(CLK, MACB_CLK_DIV32); + else + config = MACB_BF(CLK, MACB_CLK_DIV64); + + return config; +} + static void macb_init_hw(struct macb *bp) { u32 config; @@ -800,7 +842,7 @@ static void macb_init_hw(struct macb *bp) macb_reset_hw(bp); __macb_set_hwaddr(bp); - config = macb_readl(bp, NCFGR) & MACB_BF(CLK, -1L); + config = macb_mdc_clk_div(bp); config |= MACB_BIT(PAE); /* PAuse Enable */ config |= MACB_BIT(DRFCS); /* Discard Rx FCS */ config |= MACB_BIT(BIG); /* Receive oversized frames */ @@ -1119,7 +1161,6 @@ static int __init macb_probe(struct platform_device *pdev) struct net_device *dev; struct macb *bp; struct phy_device *phydev; - unsigned long pclk_hz; u32 config; int err = -ENXIO; @@ -1183,15 +1224,7 @@ static int __init macb_probe(struct platform_device *pdev) dev->base_addr = regs->start; /* Set MII management clock divider */ - pclk_hz = clk_get_rate(bp->pclk); - if (pclk_hz <= 20000000) - config = MACB_BF(CLK, MACB_CLK_DIV8); - else if (pclk_hz <= 40000000) - config = MACB_BF(CLK, MACB_CLK_DIV16); - else if (pclk_hz <= 80000000) - config = MACB_BF(CLK, MACB_CLK_DIV32); - else - config = MACB_BF(CLK, MACB_CLK_DIV64); + config = macb_mdc_clk_div(bp); macb_writel(bp, NCFGR, config); macb_get_hwaddr(bp); diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h index d50057c244b2..354ed8f77884 100644 --- a/drivers/net/ethernet/cadence/macb.h +++ b/drivers/net/ethernet/cadence/macb.h @@ -135,6 +135,9 @@ #define MACB_IRXFCS_OFFSET 19 #define MACB_IRXFCS_SIZE 1 +/* GEM specific NCFGR bitfields. */ +#define GEM_CLK_OFFSET 18 +#define GEM_CLK_SIZE 3 /* Bitfields in NSR */ #define MACB_NSR_LINK_OFFSET 0 #define MACB_NSR_LINK_SIZE 1 @@ -249,6 +252,14 @@ #define MACB_CLK_DIV32 2 #define MACB_CLK_DIV64 3 +/* GEM specific constants for CLK. */ +#define GEM_CLK_DIV8 0 +#define GEM_CLK_DIV16 1 +#define GEM_CLK_DIV32 2 +#define GEM_CLK_DIV48 3 +#define GEM_CLK_DIV64 4 +#define GEM_CLK_DIV96 5 + /* Constants for MAN register */ #define MACB_MAN_SOF 1 #define MACB_MAN_WRITE 1 -- cgit v1.2.3-55-g7522 From a494ed8e25759f05f5a419d675f198e4359ef6fc Mon Sep 17 00:00:00 2001 From: Jamie Iles Date: Wed, 9 Mar 2011 16:26:35 +0000 Subject: macb: support statistics for GEM devices GEM devices have a different number of statistics registers and they are at a different offset to MACB devices. Make the statistics collection method dependent on device type. Signed-off-by: Jamie Iles Acked-by: David S. Miller Acked-by: Nicolas Ferre Tested-by: Jean-Christophe PLAGNIOL-VILLARD --- drivers/net/ethernet/cadence/macb.c | 57 +++++++++++++++++++++++++++++++++++-- drivers/net/ethernet/cadence/macb.h | 54 ++++++++++++++++++++++++++++++++++- 2 files changed, 107 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index c5c3eb450c1b..6a7d3eae8cc7 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -285,8 +285,8 @@ err_out: static void macb_update_stats(struct macb *bp) { u32 __iomem *reg = bp->regs + MACB_PFR; - u32 *p = &bp->hw_stats.rx_pause_frames; - u32 *end = &bp->hw_stats.tx_pause_frames + 1; + u32 *p = &bp->hw_stats.macb.rx_pause_frames; + u32 *end = &bp->hw_stats.macb.tx_pause_frames + 1; WARN_ON((unsigned long)(end - p - 1) != (MACB_TPF - MACB_PFR) / 4); @@ -1042,11 +1042,62 @@ static int macb_close(struct net_device *dev) return 0; } +static void gem_update_stats(struct macb *bp) +{ + u32 __iomem *reg = bp->regs + GEM_OTX; + u32 *p = &bp->hw_stats.gem.tx_octets_31_0; + u32 *end = &bp->hw_stats.gem.rx_udp_checksum_errors + 1; + + for (; p < end; p++, reg++) + *p += __raw_readl(reg); +} + +static struct net_device_stats *gem_get_stats(struct macb *bp) +{ + struct gem_stats *hwstat = &bp->hw_stats.gem; + struct net_device_stats *nstat = &bp->stats; + + gem_update_stats(bp); + + nstat->rx_errors = (hwstat->rx_frame_check_sequence_errors + + hwstat->rx_alignment_errors + + hwstat->rx_resource_errors + + hwstat->rx_overruns + + hwstat->rx_oversize_frames + + hwstat->rx_jabbers + + hwstat->rx_undersized_frames + + hwstat->rx_length_field_frame_errors); + nstat->tx_errors = (hwstat->tx_late_collisions + + hwstat->tx_excessive_collisions + + hwstat->tx_underrun + + hwstat->tx_carrier_sense_errors); + nstat->multicast = hwstat->rx_multicast_frames; + nstat->collisions = (hwstat->tx_single_collision_frames + + hwstat->tx_multiple_collision_frames + + hwstat->tx_excessive_collisions); + nstat->rx_length_errors = (hwstat->rx_oversize_frames + + hwstat->rx_jabbers + + hwstat->rx_undersized_frames + + hwstat->rx_length_field_frame_errors); + nstat->rx_over_errors = hwstat->rx_resource_errors; + nstat->rx_crc_errors = hwstat->rx_frame_check_sequence_errors; + nstat->rx_frame_errors = hwstat->rx_alignment_errors; + nstat->rx_fifo_errors = hwstat->rx_overruns; + nstat->tx_aborted_errors = hwstat->tx_excessive_collisions; + nstat->tx_carrier_errors = hwstat->tx_carrier_sense_errors; + nstat->tx_fifo_errors = hwstat->tx_underrun; + + return nstat; +} + static struct net_device_stats *macb_get_stats(struct net_device *dev) { struct macb *bp = netdev_priv(dev); struct net_device_stats *nstat = &bp->stats; - struct macb_stats *hwstat = &bp->hw_stats; + struct macb_stats *hwstat = &bp->hw_stats.macb; + + if (macb_is_gem(bp)) + return gem_get_stats(bp); /* read stats from hardware */ macb_update_stats(bp); diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h index 354ed8f77884..1367b92edb3d 100644 --- a/drivers/net/ethernet/cadence/macb.h +++ b/drivers/net/ethernet/cadence/macb.h @@ -68,6 +68,7 @@ #define GEM_HRT 0x0084 #define GEM_SA1B 0x0088 #define GEM_SA1T 0x008C +#define GEM_OTX 0x0100 /* Bitfields in NCR */ #define MACB_LB_OFFSET 0 @@ -425,6 +426,54 @@ struct macb_stats { u32 tx_pause_frames; }; +struct gem_stats { + u32 tx_octets_31_0; + u32 tx_octets_47_32; + u32 tx_frames; + u32 tx_broadcast_frames; + u32 tx_multicast_frames; + u32 tx_pause_frames; + u32 tx_64_byte_frames; + u32 tx_65_127_byte_frames; + u32 tx_128_255_byte_frames; + u32 tx_256_511_byte_frames; + u32 tx_512_1023_byte_frames; + u32 tx_1024_1518_byte_frames; + u32 tx_greater_than_1518_byte_frames; + u32 tx_underrun; + u32 tx_single_collision_frames; + u32 tx_multiple_collision_frames; + u32 tx_excessive_collisions; + u32 tx_late_collisions; + u32 tx_deferred_frames; + u32 tx_carrier_sense_errors; + u32 rx_octets_31_0; + u32 rx_octets_47_32; + u32 rx_frames; + u32 rx_broadcast_frames; + u32 rx_multicast_frames; + u32 rx_pause_frames; + u32 rx_64_byte_frames; + u32 rx_65_127_byte_frames; + u32 rx_128_255_byte_frames; + u32 rx_256_511_byte_frames; + u32 rx_512_1023_byte_frames; + u32 rx_1024_1518_byte_frames; + u32 rx_greater_than_1518_byte_frames; + u32 rx_undersized_frames; + u32 rx_oversize_frames; + u32 rx_jabbers; + u32 rx_frame_check_sequence_errors; + u32 rx_length_field_frame_errors; + u32 rx_symbol_errors; + u32 rx_alignment_errors; + u32 rx_resource_errors; + u32 rx_overruns; + u32 rx_ip_header_checksum_errors; + u32 rx_tcp_checksum_errors; + u32 rx_udp_checksum_errors; +}; + struct macb { void __iomem *regs; @@ -443,7 +492,10 @@ struct macb { struct net_device *dev; struct napi_struct napi; struct net_device_stats stats; - struct macb_stats hw_stats; + union { + struct macb_stats macb; + struct gem_stats gem; + } hw_stats; dma_addr_t rx_ring_dma; dma_addr_t tx_ring_dma; -- cgit v1.2.3-55-g7522 From 757a03c6e004fbbdef872cb7ecdc940a891b8e6e Mon Sep 17 00:00:00 2001 From: Jamie Iles Date: Wed, 9 Mar 2011 16:29:59 +0000 Subject: macb: support DMA bus widths > 32 bits Some GEM implementations may support DMA bus widths up to 128 bits. We can get the maximum supported DMA bus width from the design configuration register so use that to program the device up. Signed-off-by: Jamie Iles Acked-by: David S. Miller Acked-by: Nicolas Ferre Tested-by: Jean-Christophe PLAGNIOL-VILLARD --- drivers/net/ethernet/cadence/macb.c | 23 +++++++++++++++++++++++ drivers/net/ethernet/cadence/macb.h | 19 +++++++++++++++++++ 2 files changed, 42 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index 6a7d3eae8cc7..38f1932013d1 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -835,6 +835,27 @@ static u32 macb_mdc_clk_div(struct macb *bp) return config; } +/* + * Get the DMA bus width field of the network configuration register that we + * should program. We find the width from decoding the design configuration + * register to find the maximum supported data bus width. + */ +static u32 macb_dbw(struct macb *bp) +{ + if (!macb_is_gem(bp)) + return 0; + + switch (GEM_BFEXT(DBWDEF, gem_readl(bp, DCFG1))) { + case 4: + return GEM_BF(DBW, GEM_DBW128); + case 2: + return GEM_BF(DBW, GEM_DBW64); + case 1: + default: + return GEM_BF(DBW, GEM_DBW32); + } +} + static void macb_init_hw(struct macb *bp) { u32 config; @@ -850,6 +871,7 @@ static void macb_init_hw(struct macb *bp) config |= MACB_BIT(CAF); /* Copy All Frames */ if (!(bp->dev->flags & IFF_BROADCAST)) config |= MACB_BIT(NBC); /* No BroadCast */ + config |= macb_dbw(bp); macb_writel(bp, NCFGR, config); /* Initialize TX and RX buffers */ @@ -1276,6 +1298,7 @@ static int __init macb_probe(struct platform_device *pdev) /* Set MII management clock divider */ config = macb_mdc_clk_div(bp); + config |= macb_dbw(bp); macb_writel(bp, NCFGR, config); macb_get_hwaddr(bp); diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h index 1367b92edb3d..71424aae9c50 100644 --- a/drivers/net/ethernet/cadence/macb.h +++ b/drivers/net/ethernet/cadence/macb.h @@ -69,6 +69,13 @@ #define GEM_SA1B 0x0088 #define GEM_SA1T 0x008C #define GEM_OTX 0x0100 +#define GEM_DCFG1 0x0280 +#define GEM_DCFG2 0x0284 +#define GEM_DCFG3 0x0288 +#define GEM_DCFG4 0x028c +#define GEM_DCFG5 0x0290 +#define GEM_DCFG6 0x0294 +#define GEM_DCFG7 0x0298 /* Bitfields in NCR */ #define MACB_LB_OFFSET 0 @@ -139,6 +146,14 @@ /* GEM specific NCFGR bitfields. */ #define GEM_CLK_OFFSET 18 #define GEM_CLK_SIZE 3 +#define GEM_DBW_OFFSET 21 +#define GEM_DBW_SIZE 2 + +/* Constants for data bus width. */ +#define GEM_DBW32 0 +#define GEM_DBW64 1 +#define GEM_DBW128 2 + /* Bitfields in NSR */ #define MACB_NSR_LINK_OFFSET 0 #define MACB_NSR_LINK_SIZE 1 @@ -247,6 +262,10 @@ #define MACB_REV_OFFSET 0 #define MACB_REV_SIZE 16 +/* Bitfields in DCFG1. */ +#define GEM_DBWDEF_OFFSET 25 +#define GEM_DBWDEF_SIZE 3 + /* Constants for CLK */ #define MACB_CLK_DIV8 0 #define MACB_CLK_DIV16 1 -- cgit v1.2.3-55-g7522 From 0116da4fcc1ae8a80d9002441e98768f2a6fa2fe Mon Sep 17 00:00:00 2001 From: Jamie Iles Date: Mon, 14 Mar 2011 17:38:30 +0000 Subject: macb: allow GEM to have configurable receive buffer size GEM has configurable receive buffer sizes so requires this to be programmed up. Any size < 2048 and a multiple of 64 bytes is permitted. Signed-off-by: Jamie Iles Acked-by: David S. Miller Acked-by: Nicolas Ferre Tested-by: Jean-Christophe PLAGNIOL-VILLARD --- drivers/net/ethernet/cadence/macb.c | 17 +++++++++++++++++ drivers/net/ethernet/cadence/macb.h | 5 +++++ 2 files changed, 22 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index 38f1932013d1..64d61461bdc7 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -856,6 +856,21 @@ static u32 macb_dbw(struct macb *bp) } } +/* + * Configure the receive DMA engine to use the correct receive buffer size. + * This is a configurable parameter for GEM. + */ +static void macb_configure_dma(struct macb *bp) +{ + u32 dmacfg; + + if (macb_is_gem(bp)) { + dmacfg = gem_readl(bp, DMACFG) & ~GEM_BF(RXBS, -1L); + dmacfg |= GEM_BF(RXBS, RX_BUFFER_SIZE / 64); + gem_writel(bp, DMACFG, dmacfg); + } +} + static void macb_init_hw(struct macb *bp) { u32 config; @@ -874,6 +889,8 @@ static void macb_init_hw(struct macb *bp) config |= macb_dbw(bp); macb_writel(bp, NCFGR, config); + macb_configure_dma(bp); + /* Initialize TX and RX buffers */ macb_writel(bp, RBQP, bp->rx_ring_dma); macb_writel(bp, TBQP, bp->tx_ring_dma); diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h index 71424aae9c50..193107884a5a 100644 --- a/drivers/net/ethernet/cadence/macb.h +++ b/drivers/net/ethernet/cadence/macb.h @@ -64,6 +64,7 @@ /* GEM register offsets. */ #define GEM_NCFGR 0x0004 #define GEM_USRIO 0x000c +#define GEM_DMACFG 0x0010 #define GEM_HRB 0x0080 #define GEM_HRT 0x0084 #define GEM_SA1B 0x0088 @@ -154,6 +155,10 @@ #define GEM_DBW64 1 #define GEM_DBW128 2 +/* Bitfields in DMACFG. */ +#define GEM_RXBS_OFFSET 16 +#define GEM_RXBS_SIZE 8 + /* Bitfields in NSR */ #define MACB_NSR_LINK_OFFSET 0 #define MACB_NSR_LINK_SIZE 1 -- cgit v1.2.3-55-g7522 From 31f9d4635bde3f03bc6dbac01d4c0fb0da9d06d7 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Tue, 22 Nov 2011 16:02:17 +0200 Subject: omap_hsmmc: consider MMC_PM_KEEP_POWER on suspend/resume When an mmc card has the MMC_PM_KEEP_POWER flag, it shouldn't be powered off on suspend (and thus doesn't have to be powered-on on resume) While on it, change the suspend flow a bit, to make it a bit easier to follow. Signed-off-by: Eliad Peller Acked-by: Chris Ball Signed-off-by: Tony Lindgren --- drivers/mmc/host/omap_hsmmc.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 101cd31c8220..6784fbbc337d 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -2176,13 +2176,7 @@ static int omap_hsmmc_suspend(struct device *dev) cancel_work_sync(&host->mmc_carddetect_work); ret = mmc_suspend_host(host->mmc); - if (ret == 0) { - omap_hsmmc_disable_irq(host); - OMAP_HSMMC_WRITE(host->base, HCTL, - OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP); - if (host->got_dbclk) - clk_disable(host->dbclk); - } else { + if (ret) { host->suspended = 0; if (host->pdata->resume) { ret = host->pdata->resume(&pdev->dev, @@ -2191,9 +2185,20 @@ static int omap_hsmmc_suspend(struct device *dev) dev_dbg(mmc_dev(host->mmc), "Unmask interrupt failed\n"); } + goto err; } - pm_runtime_put_sync(host->dev); + + if (!(host->mmc->pm_flags & MMC_PM_KEEP_POWER)) { + omap_hsmmc_disable_irq(host); + OMAP_HSMMC_WRITE(host->base, HCTL, + OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP); + } + if (host->got_dbclk) + clk_disable(host->dbclk); + } +err: + pm_runtime_put_sync(host->dev); return ret; } @@ -2213,7 +2218,8 @@ static int omap_hsmmc_resume(struct device *dev) if (host->got_dbclk) clk_enable(host->dbclk); - omap_hsmmc_conf_bus_power(host); + if (!(host->mmc->pm_flags & MMC_PM_KEEP_POWER)) + omap_hsmmc_conf_bus_power(host); if (host->pdata->resume) { ret = host->pdata->resume(&pdev->dev, host->slot_id); -- cgit v1.2.3-55-g7522 From 6fdc75de7d0554134890d33a0a6f5e18c7503c01 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Tue, 22 Nov 2011 16:02:18 +0200 Subject: ARM: OMAP: hsmmc: add pm_caps field Add pm_caps field to omap2_hsmmc_info and omap_mmc_slot_data structs, so we will be able to indicate mmc pm capabilities in the board file. Signed-off-by: Eliad Peller Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/hsmmc.c | 1 + arch/arm/mach-omap2/hsmmc.h | 1 + arch/arm/plat-omap/include/plat/mmc.h | 1 + drivers/mmc/host/omap_hsmmc.c | 2 ++ 4 files changed, 5 insertions(+) (limited to 'drivers') diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index f4a1020559a7..97dfedce084b 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -296,6 +296,7 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, mmc->slots[0].name = hc_name; mmc->nr_slots = 1; mmc->slots[0].caps = c->caps; + mmc->slots[0].pm_caps = c->pm_caps; mmc->slots[0].internal_clock = !c->ext_clock; mmc->dma_mask = 0xffffffff; if (cpu_is_omap44xx()) diff --git a/arch/arm/mach-omap2/hsmmc.h b/arch/arm/mach-omap2/hsmmc.h index f757e78d4d4f..c4409730c4bb 100644 --- a/arch/arm/mach-omap2/hsmmc.h +++ b/arch/arm/mach-omap2/hsmmc.h @@ -12,6 +12,7 @@ struct omap2_hsmmc_info { u8 mmc; /* controller 1/2/3 */ u32 caps; /* 4/8 wires and any additional host * capabilities OR'd (ref. linux/mmc/host.h) */ + u32 pm_caps; /* PM capabilities */ bool transceiver; /* MMC-2 option */ bool ext_clock; /* use external pin for input clock */ bool cover_only; /* No card detect - just cover switch */ diff --git a/arch/arm/plat-omap/include/plat/mmc.h b/arch/arm/plat-omap/include/plat/mmc.h index 94cf70afb236..f75946c3293d 100644 --- a/arch/arm/plat-omap/include/plat/mmc.h +++ b/arch/arm/plat-omap/include/plat/mmc.h @@ -96,6 +96,7 @@ struct omap_mmc_platform_data { */ u8 wires; /* Used for the MMC driver on omap1 and 2420 */ u32 caps; /* Used for the MMC driver on 2430 and later */ + u32 pm_caps; /* PM capabilities of the mmc */ /* * nomux means "standard" muxing is wrong on this board, and diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 6784fbbc337d..f0d792183b8e 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -1988,6 +1988,8 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) if (mmc_slot(host).nonremovable) mmc->caps |= MMC_CAP_NONREMOVABLE; + mmc->pm_caps = mmc_slot(host).pm_caps; + omap_hsmmc_conf_bus_power(host); /* Select DMA lines */ -- cgit v1.2.3-55-g7522 From a6d3a6622ee459eb44952246214d658b474ea8eb Mon Sep 17 00:00:00 2001 From: Keshava Munegowda Date: Tue, 11 Oct 2011 13:21:51 +0530 Subject: ARM: OMAP: USB: device name change for the clk names of usbhs device name usbhs clocks are changed from usbhs-omap.0 to usbhs_omap; this is because in the hwmod registration the device name is set as usbhs_omap; The redudant clock nodes are removed. Signed-off-by: Keshava Munegowda Reviewed-by: Partha Basak Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/clock3xxx_data.c | 26 ++++++++++++-------------- arch/arm/mach-omap2/clock44xx_data.c | 10 +++++----- drivers/mfd/omap-usb-host.c | 2 +- 3 files changed, 18 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c index 4e1b1a2f0537..9d59451446d9 100644 --- a/arch/arm/mach-omap2/clock3xxx_data.c +++ b/arch/arm/mach-omap2/clock3xxx_data.c @@ -3297,7 +3297,7 @@ static struct omap_clk omap3xxx_clks[] = { CLK(NULL, "cpefuse_fck", &cpefuse_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), CLK(NULL, "ts_fck", &ts_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), CLK(NULL, "usbtll_fck", &usbtll_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), - CLK("usbhs-omap.0", "usbtll_fck", &usbtll_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), + CLK("usbhs_omap", "usbtll_fck", &usbtll_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), CLK("omap-mcbsp.1", "prcm_fck", &core_96m_fck, CK_3XXX), CLK("omap-mcbsp.5", "prcm_fck", &core_96m_fck, CK_3XXX), CLK(NULL, "core_96m_fck", &core_96m_fck, CK_3XXX), @@ -3333,7 +3333,7 @@ static struct omap_clk omap3xxx_clks[] = { CLK(NULL, "pka_ick", &pka_ick, CK_34XX | CK_36XX), CLK(NULL, "core_l4_ick", &core_l4_ick, CK_3XXX), CLK(NULL, "usbtll_ick", &usbtll_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), - CLK("usbhs-omap.0", "usbtll_ick", &usbtll_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), + CLK("usbhs_omap", "usbtll_ick", &usbtll_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), CLK("omap_hsmmc.2", "ick", &mmchs3_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), CLK(NULL, "icr_ick", &icr_ick, CK_34XX | CK_36XX), CLK("omap-aes", "ick", &aes2_ick, CK_34XX | CK_36XX), @@ -3379,20 +3379,18 @@ static struct omap_clk omap3xxx_clks[] = { CLK(NULL, "cam_ick", &cam_ick, CK_34XX | CK_36XX), CLK(NULL, "csi2_96m_fck", &csi2_96m_fck, CK_34XX | CK_36XX), CLK(NULL, "usbhost_120m_fck", &usbhost_120m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), - CLK("usbhs-omap.0", "hs_fck", &usbhost_120m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), CLK(NULL, "usbhost_48m_fck", &usbhost_48m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), - CLK("usbhs-omap.0", "fs_fck", &usbhost_48m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), CLK(NULL, "usbhost_ick", &usbhost_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), - CLK("usbhs-omap.0", "usbhost_ick", &usbhost_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), - CLK("usbhs-omap.0", "utmi_p1_gfclk", &dummy_ck, CK_3XXX), - CLK("usbhs-omap.0", "utmi_p2_gfclk", &dummy_ck, CK_3XXX), - CLK("usbhs-omap.0", "xclk60mhsp1_ck", &dummy_ck, CK_3XXX), - CLK("usbhs-omap.0", "xclk60mhsp2_ck", &dummy_ck, CK_3XXX), - CLK("usbhs-omap.0", "usb_host_hs_utmi_p1_clk", &dummy_ck, CK_3XXX), - CLK("usbhs-omap.0", "usb_host_hs_utmi_p2_clk", &dummy_ck, CK_3XXX), - CLK("usbhs-omap.0", "usb_tll_hs_usb_ch0_clk", &dummy_ck, CK_3XXX), - CLK("usbhs-omap.0", "usb_tll_hs_usb_ch1_clk", &dummy_ck, CK_3XXX), - CLK("usbhs-omap.0", "init_60m_fclk", &dummy_ck, CK_3XXX), + CLK("usbhs_omap", "usbhost_ick", &usbhost_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), + CLK("usbhs_omap", "utmi_p1_gfclk", &dummy_ck, CK_3XXX), + CLK("usbhs_omap", "utmi_p2_gfclk", &dummy_ck, CK_3XXX), + CLK("usbhs_omap", "xclk60mhsp1_ck", &dummy_ck, CK_3XXX), + CLK("usbhs_omap", "xclk60mhsp2_ck", &dummy_ck, CK_3XXX), + CLK("usbhs_omap", "usb_host_hs_utmi_p1_clk", &dummy_ck, CK_3XXX), + CLK("usbhs_omap", "usb_host_hs_utmi_p2_clk", &dummy_ck, CK_3XXX), + CLK("usbhs_omap", "usb_tll_hs_usb_ch0_clk", &dummy_ck, CK_3XXX), + CLK("usbhs_omap", "usb_tll_hs_usb_ch1_clk", &dummy_ck, CK_3XXX), + CLK("usbhs_omap", "init_60m_fclk", &dummy_ck, CK_3XXX), CLK(NULL, "usim_fck", &usim_fck, CK_3430ES2PLUS | CK_36XX), CLK(NULL, "gpt1_fck", &gpt1_fck, CK_3XXX), CLK(NULL, "wkup_32k_fck", &wkup_32k_fck, CK_3XXX), diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c index 0798a802497a..c8a1b2740778 100644 --- a/arch/arm/mach-omap2/clock44xx_data.c +++ b/arch/arm/mach-omap2/clock44xx_data.c @@ -3295,7 +3295,7 @@ static struct omap_clk omap44xx_clks[] = { CLK(NULL, "uart2_fck", &uart2_fck, CK_443X), CLK(NULL, "uart3_fck", &uart3_fck, CK_443X), CLK(NULL, "uart4_fck", &uart4_fck, CK_443X), - CLK("usbhs-omap.0", "fs_fck", &usb_host_fs_fck, CK_443X), + CLK("usbhs_omap", "fs_fck", &usb_host_fs_fck, CK_443X), CLK(NULL, "utmi_p1_gfclk", &utmi_p1_gfclk, CK_443X), CLK(NULL, "usb_host_hs_utmi_p1_clk", &usb_host_hs_utmi_p1_clk, CK_443X), CLK(NULL, "utmi_p2_gfclk", &utmi_p2_gfclk, CK_443X), @@ -3306,7 +3306,7 @@ static struct omap_clk omap44xx_clks[] = { CLK(NULL, "usb_host_hs_hsic60m_p2_clk", &usb_host_hs_hsic60m_p2_clk, CK_443X), CLK(NULL, "usb_host_hs_hsic480m_p2_clk", &usb_host_hs_hsic480m_p2_clk, CK_443X), CLK(NULL, "usb_host_hs_func48mclk", &usb_host_hs_func48mclk, CK_443X), - CLK("usbhs-omap.0", "hs_fck", &usb_host_hs_fck, CK_443X), + CLK("usbhs_omap", "hs_fck", &usb_host_hs_fck, CK_443X), CLK(NULL, "otg_60m_gfclk", &otg_60m_gfclk, CK_443X), CLK(NULL, "usb_otg_hs_xclk", &usb_otg_hs_xclk, CK_443X), CLK("musb-omap2430", "ick", &usb_otg_hs_ick, CK_443X), @@ -3314,7 +3314,7 @@ static struct omap_clk omap44xx_clks[] = { CLK(NULL, "usb_tll_hs_usb_ch2_clk", &usb_tll_hs_usb_ch2_clk, CK_443X), CLK(NULL, "usb_tll_hs_usb_ch0_clk", &usb_tll_hs_usb_ch0_clk, CK_443X), CLK(NULL, "usb_tll_hs_usb_ch1_clk", &usb_tll_hs_usb_ch1_clk, CK_443X), - CLK("usbhs-omap.0", "usbtll_ick", &usb_tll_hs_ick, CK_443X), + CLK("usbhs_omap", "usbtll_ick", &usb_tll_hs_ick, CK_443X), CLK(NULL, "usim_ck", &usim_ck, CK_443X), CLK(NULL, "usim_fclk", &usim_fclk, CK_443X), CLK(NULL, "usim_fck", &usim_fck, CK_443X), @@ -3374,8 +3374,8 @@ static struct omap_clk omap44xx_clks[] = { CLK(NULL, "uart2_ick", &dummy_ck, CK_443X), CLK(NULL, "uart3_ick", &dummy_ck, CK_443X), CLK(NULL, "uart4_ick", &dummy_ck, CK_443X), - CLK("usbhs-omap.0", "usbhost_ick", &dummy_ck, CK_443X), - CLK("usbhs-omap.0", "usbtll_fck", &dummy_ck, CK_443X), + CLK("usbhs_omap", "usbhost_ick", &dummy_ck, CK_443X), + CLK("usbhs_omap", "usbtll_fck", &dummy_ck, CK_443X), CLK("omap_wdt", "ick", &dummy_ck, CK_443X), CLK("omap_timer.1", "32k_ck", &sys_32k_ck, CK_443X), CLK("omap_timer.2", "32k_ck", &sys_32k_ck, CK_443X), diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c index 86e14583a082..806242ebe65a 100644 --- a/drivers/mfd/omap-usb-host.c +++ b/drivers/mfd/omap-usb-host.c @@ -28,7 +28,7 @@ #include #include -#define USBHS_DRIVER_NAME "usbhs-omap" +#define USBHS_DRIVER_NAME "usbhs_omap" #define OMAP_EHCI_DEVICE "ehci-omap" #define OMAP_OHCI_DEVICE "ohci-omap3" -- cgit v1.2.3-55-g7522 From 6c984b066d84bb6e8f5a739ffb1dc4858df017a3 Mon Sep 17 00:00:00 2001 From: Keshava Munegowda Date: Tue, 11 Oct 2011 13:22:11 +0530 Subject: ARM: OMAP: USBHOST: Replace usbhs core driver APIs by Runtime pm APIs The ehci and ohci drivers does not use the APIs of the usbhs core driver; the runtime pm APIs are used for clock enable/disable. Since usbhs is parent platform device of the ehci and ohci devices, the runtime apis indirectly uses the usb hs core device as input parameter to for clock functions. Signed-off-by: Keshava Munegowda Reviewed-by: Kevin Hilman Reviewed-by: Partha Basak Acked-by: Felipe Balbi Acked-by: Alan Stern Signed-off-by: Paul Walmsley --- arch/arm/plat-omap/include/plat/usb.h | 3 --- drivers/usb/host/ehci-omap.c | 17 +++++++---------- drivers/usb/host/ohci-omap3.c | 18 +++++++----------- 3 files changed, 14 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/arch/arm/plat-omap/include/plat/usb.h b/arch/arm/plat-omap/include/plat/usb.h index 17d3c939775c..2b66dc266bcf 100644 --- a/arch/arm/plat-omap/include/plat/usb.h +++ b/arch/arm/plat-omap/include/plat/usb.h @@ -100,9 +100,6 @@ extern void usb_musb_init(struct omap_musb_board_data *board_data); extern void usbhs_init(const struct usbhs_omap_board_data *pdata); -extern int omap_usbhs_enable(struct device *dev); -extern void omap_usbhs_disable(struct device *dev); - extern int omap4430_phy_power(struct device *dev, int ID, int on); extern int omap4430_phy_set_clk(struct device *dev, int on); extern int omap4430_phy_init(struct device *dev); diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index e39b0297bad1..568cefbd63a2 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c @@ -41,6 +41,7 @@ #include #include #include +#include /* EHCI Register Set */ #define EHCI_INSNREG04 (0xA0) @@ -190,11 +191,8 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) } } - ret = omap_usbhs_enable(dev); - if (ret) { - dev_err(dev, "failed to start usbhs with err %d\n", ret); - goto err_enable; - } + pm_runtime_enable(dev); + pm_runtime_get_sync(dev); /* * An undocumented "feature" in the OMAP3 EHCI controller, @@ -240,11 +238,8 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) return 0; err_add_hcd: - omap_usbhs_disable(dev); - -err_enable: disable_put_regulator(pdata); - usb_put_hcd(hcd); + pm_runtime_put_sync(dev); err_io: iounmap(regs); @@ -266,10 +261,12 @@ static int ehci_hcd_omap_remove(struct platform_device *pdev) struct usb_hcd *hcd = dev_get_drvdata(dev); usb_remove_hcd(hcd); - omap_usbhs_disable(dev); disable_put_regulator(dev->platform_data); iounmap(hcd->regs); usb_put_hcd(hcd); + pm_runtime_put_sync(dev); + pm_runtime_disable(dev); + return 0; } diff --git a/drivers/usb/host/ohci-omap3.c b/drivers/usb/host/ohci-omap3.c index 516ebc4d6cc2..1b8133b6e451 100644 --- a/drivers/usb/host/ohci-omap3.c +++ b/drivers/usb/host/ohci-omap3.c @@ -31,6 +31,7 @@ #include #include +#include /*-------------------------------------------------------------------------*/ @@ -134,7 +135,7 @@ static int __devinit ohci_hcd_omap3_probe(struct platform_device *pdev) int irq; if (usb_disabled()) - goto err_end; + return -ENODEV; if (!dev->parent) { dev_err(dev, "Missing parent device\n"); @@ -172,11 +173,8 @@ static int __devinit ohci_hcd_omap3_probe(struct platform_device *pdev) hcd->rsrc_len = resource_size(res); hcd->regs = regs; - ret = omap_usbhs_enable(dev); - if (ret) { - dev_dbg(dev, "failed to start ohci\n"); - goto err_end; - } + pm_runtime_enable(dev); + pm_runtime_get_sync(dev); ohci_hcd_init(hcd_to_ohci(hcd)); @@ -189,9 +187,7 @@ static int __devinit ohci_hcd_omap3_probe(struct platform_device *pdev) return 0; err_add_hcd: - omap_usbhs_disable(dev); - -err_end: + pm_runtime_put_sync(dev); usb_put_hcd(hcd); err_io: @@ -220,9 +216,9 @@ static int __devexit ohci_hcd_omap3_remove(struct platform_device *pdev) iounmap(hcd->regs); usb_remove_hcd(hcd); - omap_usbhs_disable(dev); + pm_runtime_put_sync(dev); + pm_runtime_disable(dev); usb_put_hcd(hcd); - return 0; } -- cgit v1.2.3-55-g7522 From 1e7fe1a9253f3b66dc4013e40bd5d72415af0835 Mon Sep 17 00:00:00 2001 From: Keshava Munegowda Date: Tue, 11 Oct 2011 13:23:29 +0530 Subject: MFD: OMAP: USB: Runtime PM support The usbhs core driver does not enable/disable the interface and functional clocks directly, These clocks are handled by runtime pm, hence instead of the clock enable/disable, the runtime pm APIS are used. however,the optional clocks and port clocks are handled by the usbhs core. Dependency: This patch is dependent on this series: [PATCH 0/5 v13 or latest version] omap: usb: host: Runtime PM preparation for EHCI and OHCI drivers. Validation performed: The global suspend/resume of EHCI and OHCI is validated on OMAP3430 sdp board with this patch combined with the series: [PATCH 0/5 v13 or latest version] omap: usb: host: Runtime PM preparation for EHCI and OHCI drivers. Signed-off-by: Keshava Munegowda Reviewed-by: Kevin Hilman Reviewed-by: Partha Basak Acked-by: Felipe Balbi Acked-by: Samuel Ortiz Signed-off-by: Paul Walmsley --- drivers/mfd/omap-usb-host.c | 753 ++++++++++++++++++-------------------------- 1 file changed, 303 insertions(+), 450 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c index 806242ebe65a..3f565ef3e149 100644 --- a/drivers/mfd/omap-usb-host.c +++ b/drivers/mfd/omap-usb-host.c @@ -27,6 +27,7 @@ #include #include #include +#include #define USBHS_DRIVER_NAME "usbhs_omap" #define OMAP_EHCI_DEVICE "ehci-omap" @@ -147,9 +148,6 @@ struct usbhs_hcd_omap { - struct clk *usbhost_ick; - struct clk *usbhost_hs_fck; - struct clk *usbhost_fs_fck; struct clk *xclk60mhsp1_ck; struct clk *xclk60mhsp2_ck; struct clk *utmi_p1_fck; @@ -159,8 +157,7 @@ struct usbhs_hcd_omap { struct clk *usbhost_p2_fck; struct clk *usbtll_p2_fck; struct clk *init_60m_fclk; - struct clk *usbtll_fck; - struct clk *usbtll_ick; + struct clk *ehci_logic_fck; void __iomem *uhh_base; void __iomem *tll_base; @@ -169,7 +166,6 @@ struct usbhs_hcd_omap { u32 usbhs_rev; spinlock_t lock; - int count; }; /*-------------------------------------------------------------------------*/ @@ -319,269 +315,6 @@ err_end: return ret; } -/** - * usbhs_omap_probe - initialize TI-based HCDs - * - * Allocates basic resources for this USB host controller. - */ -static int __devinit usbhs_omap_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct usbhs_omap_platform_data *pdata = dev->platform_data; - struct usbhs_hcd_omap *omap; - struct resource *res; - int ret = 0; - int i; - - if (!pdata) { - dev_err(dev, "Missing platform data\n"); - ret = -ENOMEM; - goto end_probe; - } - - omap = kzalloc(sizeof(*omap), GFP_KERNEL); - if (!omap) { - dev_err(dev, "Memory allocation failed\n"); - ret = -ENOMEM; - goto end_probe; - } - - spin_lock_init(&omap->lock); - - for (i = 0; i < OMAP3_HS_USB_PORTS; i++) - omap->platdata.port_mode[i] = pdata->port_mode[i]; - - omap->platdata.ehci_data = pdata->ehci_data; - omap->platdata.ohci_data = pdata->ohci_data; - - omap->usbhost_ick = clk_get(dev, "usbhost_ick"); - if (IS_ERR(omap->usbhost_ick)) { - ret = PTR_ERR(omap->usbhost_ick); - dev_err(dev, "usbhost_ick failed error:%d\n", ret); - goto err_end; - } - - omap->usbhost_hs_fck = clk_get(dev, "hs_fck"); - if (IS_ERR(omap->usbhost_hs_fck)) { - ret = PTR_ERR(omap->usbhost_hs_fck); - dev_err(dev, "usbhost_hs_fck failed error:%d\n", ret); - goto err_usbhost_ick; - } - - omap->usbhost_fs_fck = clk_get(dev, "fs_fck"); - if (IS_ERR(omap->usbhost_fs_fck)) { - ret = PTR_ERR(omap->usbhost_fs_fck); - dev_err(dev, "usbhost_fs_fck failed error:%d\n", ret); - goto err_usbhost_hs_fck; - } - - omap->usbtll_fck = clk_get(dev, "usbtll_fck"); - if (IS_ERR(omap->usbtll_fck)) { - ret = PTR_ERR(omap->usbtll_fck); - dev_err(dev, "usbtll_fck failed error:%d\n", ret); - goto err_usbhost_fs_fck; - } - - omap->usbtll_ick = clk_get(dev, "usbtll_ick"); - if (IS_ERR(omap->usbtll_ick)) { - ret = PTR_ERR(omap->usbtll_ick); - dev_err(dev, "usbtll_ick failed error:%d\n", ret); - goto err_usbtll_fck; - } - - omap->utmi_p1_fck = clk_get(dev, "utmi_p1_gfclk"); - if (IS_ERR(omap->utmi_p1_fck)) { - ret = PTR_ERR(omap->utmi_p1_fck); - dev_err(dev, "utmi_p1_gfclk failed error:%d\n", ret); - goto err_usbtll_ick; - } - - omap->xclk60mhsp1_ck = clk_get(dev, "xclk60mhsp1_ck"); - if (IS_ERR(omap->xclk60mhsp1_ck)) { - ret = PTR_ERR(omap->xclk60mhsp1_ck); - dev_err(dev, "xclk60mhsp1_ck failed error:%d\n", ret); - goto err_utmi_p1_fck; - } - - omap->utmi_p2_fck = clk_get(dev, "utmi_p2_gfclk"); - if (IS_ERR(omap->utmi_p2_fck)) { - ret = PTR_ERR(omap->utmi_p2_fck); - dev_err(dev, "utmi_p2_gfclk failed error:%d\n", ret); - goto err_xclk60mhsp1_ck; - } - - omap->xclk60mhsp2_ck = clk_get(dev, "xclk60mhsp2_ck"); - if (IS_ERR(omap->xclk60mhsp2_ck)) { - ret = PTR_ERR(omap->xclk60mhsp2_ck); - dev_err(dev, "xclk60mhsp2_ck failed error:%d\n", ret); - goto err_utmi_p2_fck; - } - - omap->usbhost_p1_fck = clk_get(dev, "usb_host_hs_utmi_p1_clk"); - if (IS_ERR(omap->usbhost_p1_fck)) { - ret = PTR_ERR(omap->usbhost_p1_fck); - dev_err(dev, "usbhost_p1_fck failed error:%d\n", ret); - goto err_xclk60mhsp2_ck; - } - - omap->usbtll_p1_fck = clk_get(dev, "usb_tll_hs_usb_ch0_clk"); - if (IS_ERR(omap->usbtll_p1_fck)) { - ret = PTR_ERR(omap->usbtll_p1_fck); - dev_err(dev, "usbtll_p1_fck failed error:%d\n", ret); - goto err_usbhost_p1_fck; - } - - omap->usbhost_p2_fck = clk_get(dev, "usb_host_hs_utmi_p2_clk"); - if (IS_ERR(omap->usbhost_p2_fck)) { - ret = PTR_ERR(omap->usbhost_p2_fck); - dev_err(dev, "usbhost_p2_fck failed error:%d\n", ret); - goto err_usbtll_p1_fck; - } - - omap->usbtll_p2_fck = clk_get(dev, "usb_tll_hs_usb_ch1_clk"); - if (IS_ERR(omap->usbtll_p2_fck)) { - ret = PTR_ERR(omap->usbtll_p2_fck); - dev_err(dev, "usbtll_p2_fck failed error:%d\n", ret); - goto err_usbhost_p2_fck; - } - - omap->init_60m_fclk = clk_get(dev, "init_60m_fclk"); - if (IS_ERR(omap->init_60m_fclk)) { - ret = PTR_ERR(omap->init_60m_fclk); - dev_err(dev, "init_60m_fclk failed error:%d\n", ret); - goto err_usbtll_p2_fck; - } - - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "uhh"); - if (!res) { - dev_err(dev, "UHH EHCI get resource failed\n"); - ret = -ENODEV; - goto err_init_60m_fclk; - } - - omap->uhh_base = ioremap(res->start, resource_size(res)); - if (!omap->uhh_base) { - dev_err(dev, "UHH ioremap failed\n"); - ret = -ENOMEM; - goto err_init_60m_fclk; - } - - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tll"); - if (!res) { - dev_err(dev, "UHH EHCI get resource failed\n"); - ret = -ENODEV; - goto err_tll; - } - - omap->tll_base = ioremap(res->start, resource_size(res)); - if (!omap->tll_base) { - dev_err(dev, "TLL ioremap failed\n"); - ret = -ENOMEM; - goto err_tll; - } - - platform_set_drvdata(pdev, omap); - - ret = omap_usbhs_alloc_children(pdev); - if (ret) { - dev_err(dev, "omap_usbhs_alloc_children failed\n"); - goto err_alloc; - } - - goto end_probe; - -err_alloc: - iounmap(omap->tll_base); - -err_tll: - iounmap(omap->uhh_base); - -err_init_60m_fclk: - clk_put(omap->init_60m_fclk); - -err_usbtll_p2_fck: - clk_put(omap->usbtll_p2_fck); - -err_usbhost_p2_fck: - clk_put(omap->usbhost_p2_fck); - -err_usbtll_p1_fck: - clk_put(omap->usbtll_p1_fck); - -err_usbhost_p1_fck: - clk_put(omap->usbhost_p1_fck); - -err_xclk60mhsp2_ck: - clk_put(omap->xclk60mhsp2_ck); - -err_utmi_p2_fck: - clk_put(omap->utmi_p2_fck); - -err_xclk60mhsp1_ck: - clk_put(omap->xclk60mhsp1_ck); - -err_utmi_p1_fck: - clk_put(omap->utmi_p1_fck); - -err_usbtll_ick: - clk_put(omap->usbtll_ick); - -err_usbtll_fck: - clk_put(omap->usbtll_fck); - -err_usbhost_fs_fck: - clk_put(omap->usbhost_fs_fck); - -err_usbhost_hs_fck: - clk_put(omap->usbhost_hs_fck); - -err_usbhost_ick: - clk_put(omap->usbhost_ick); - -err_end: - kfree(omap); - -end_probe: - return ret; -} - -/** - * usbhs_omap_remove - shutdown processing for UHH & TLL HCDs - * @pdev: USB Host Controller being removed - * - * Reverses the effect of usbhs_omap_probe(). - */ -static int __devexit usbhs_omap_remove(struct platform_device *pdev) -{ - struct usbhs_hcd_omap *omap = platform_get_drvdata(pdev); - - if (omap->count != 0) { - dev_err(&pdev->dev, - "Either EHCI or OHCI is still using usbhs core\n"); - return -EBUSY; - } - - iounmap(omap->tll_base); - iounmap(omap->uhh_base); - clk_put(omap->init_60m_fclk); - clk_put(omap->usbtll_p2_fck); - clk_put(omap->usbhost_p2_fck); - clk_put(omap->usbtll_p1_fck); - clk_put(omap->usbhost_p1_fck); - clk_put(omap->xclk60mhsp2_ck); - clk_put(omap->utmi_p2_fck); - clk_put(omap->xclk60mhsp1_ck); - clk_put(omap->utmi_p1_fck); - clk_put(omap->usbtll_ick); - clk_put(omap->usbtll_fck); - clk_put(omap->usbhost_fs_fck); - clk_put(omap->usbhost_hs_fck); - clk_put(omap->usbhost_ick); - kfree(omap); - - return 0; -} - static bool is_ohci_port(enum usbhs_omap_port_mode pmode) { switch (pmode) { @@ -689,30 +422,85 @@ static void usbhs_omap_tll_init(struct device *dev, u8 tll_channel_count) } } -static int usbhs_enable(struct device *dev) +static int usbhs_runtime_resume(struct device *dev) { struct usbhs_hcd_omap *omap = dev_get_drvdata(dev); struct usbhs_omap_platform_data *pdata = &omap->platdata; - unsigned long flags = 0; - int ret = 0; - unsigned long timeout; - unsigned reg; + unsigned long flags; + + dev_dbg(dev, "usbhs_runtime_resume\n"); - dev_dbg(dev, "starting TI HSUSB Controller\n"); if (!pdata) { dev_dbg(dev, "missing platform_data\n"); return -ENODEV; } spin_lock_irqsave(&omap->lock, flags); - if (omap->count > 0) - goto end_count; - clk_enable(omap->usbhost_ick); - clk_enable(omap->usbhost_hs_fck); - clk_enable(omap->usbhost_fs_fck); - clk_enable(omap->usbtll_fck); - clk_enable(omap->usbtll_ick); + if (omap->ehci_logic_fck && !IS_ERR(omap->ehci_logic_fck)) + clk_enable(omap->ehci_logic_fck); + + if (is_ehci_tll_mode(pdata->port_mode[0])) { + clk_enable(omap->usbhost_p1_fck); + clk_enable(omap->usbtll_p1_fck); + } + if (is_ehci_tll_mode(pdata->port_mode[1])) { + clk_enable(omap->usbhost_p2_fck); + clk_enable(omap->usbtll_p2_fck); + } + clk_enable(omap->utmi_p1_fck); + clk_enable(omap->utmi_p2_fck); + + spin_unlock_irqrestore(&omap->lock, flags); + + return 0; +} + +static int usbhs_runtime_suspend(struct device *dev) +{ + struct usbhs_hcd_omap *omap = dev_get_drvdata(dev); + struct usbhs_omap_platform_data *pdata = &omap->platdata; + unsigned long flags; + + dev_dbg(dev, "usbhs_runtime_suspend\n"); + + if (!pdata) { + dev_dbg(dev, "missing platform_data\n"); + return -ENODEV; + } + + spin_lock_irqsave(&omap->lock, flags); + + if (is_ehci_tll_mode(pdata->port_mode[0])) { + clk_disable(omap->usbhost_p1_fck); + clk_disable(omap->usbtll_p1_fck); + } + if (is_ehci_tll_mode(pdata->port_mode[1])) { + clk_disable(omap->usbhost_p2_fck); + clk_disable(omap->usbtll_p2_fck); + } + clk_disable(omap->utmi_p2_fck); + clk_disable(omap->utmi_p1_fck); + + if (omap->ehci_logic_fck && !IS_ERR(omap->ehci_logic_fck)) + clk_disable(omap->ehci_logic_fck); + + spin_unlock_irqrestore(&omap->lock, flags); + + return 0; +} + +static void omap_usbhs_init(struct device *dev) +{ + struct usbhs_hcd_omap *omap = dev_get_drvdata(dev); + struct usbhs_omap_platform_data *pdata = &omap->platdata; + unsigned long flags; + unsigned reg; + + dev_dbg(dev, "starting TI HSUSB Controller\n"); + + pm_runtime_get_sync(dev); + spin_lock_irqsave(&omap->lock, flags); if (pdata->ehci_data->phy_reset) { if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) { @@ -736,50 +524,6 @@ static int usbhs_enable(struct device *dev) omap->usbhs_rev = usbhs_read(omap->uhh_base, OMAP_UHH_REVISION); dev_dbg(dev, "OMAP UHH_REVISION 0x%x\n", omap->usbhs_rev); - /* perform TLL soft reset, and wait until reset is complete */ - usbhs_write(omap->tll_base, OMAP_USBTLL_SYSCONFIG, - OMAP_USBTLL_SYSCONFIG_SOFTRESET); - - /* Wait for TLL reset to complete */ - timeout = jiffies + msecs_to_jiffies(1000); - while (!(usbhs_read(omap->tll_base, OMAP_USBTLL_SYSSTATUS) - & OMAP_USBTLL_SYSSTATUS_RESETDONE)) { - cpu_relax(); - - if (time_after(jiffies, timeout)) { - dev_dbg(dev, "operation timed out\n"); - ret = -EINVAL; - goto err_tll; - } - } - - dev_dbg(dev, "TLL RESET DONE\n"); - - /* (1<<3) = no idle mode only for initial debugging */ - usbhs_write(omap->tll_base, OMAP_USBTLL_SYSCONFIG, - OMAP_USBTLL_SYSCONFIG_ENAWAKEUP | - OMAP_USBTLL_SYSCONFIG_SIDLEMODE | - OMAP_USBTLL_SYSCONFIG_AUTOIDLE); - - /* Put UHH in NoIdle/NoStandby mode */ - reg = usbhs_read(omap->uhh_base, OMAP_UHH_SYSCONFIG); - if (is_omap_usbhs_rev1(omap)) { - reg |= (OMAP_UHH_SYSCONFIG_ENAWAKEUP - | OMAP_UHH_SYSCONFIG_SIDLEMODE - | OMAP_UHH_SYSCONFIG_CACTIVITY - | OMAP_UHH_SYSCONFIG_MIDLEMODE); - reg &= ~OMAP_UHH_SYSCONFIG_AUTOIDLE; - - - } else if (is_omap_usbhs_rev2(omap)) { - reg &= ~OMAP4_UHH_SYSCONFIG_IDLEMODE_CLEAR; - reg |= OMAP4_UHH_SYSCONFIG_NOIDLE; - reg &= ~OMAP4_UHH_SYSCONFIG_STDBYMODE_CLEAR; - reg |= OMAP4_UHH_SYSCONFIG_NOSTDBY; - } - - usbhs_write(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg); - reg = usbhs_read(omap->uhh_base, OMAP_UHH_HOSTCONFIG); /* setup ULPI bypass and burst configurations */ reg |= (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN @@ -825,49 +569,6 @@ static int usbhs_enable(struct device *dev) reg &= ~OMAP4_P1_MODE_CLEAR; reg &= ~OMAP4_P2_MODE_CLEAR; - if (is_ehci_phy_mode(pdata->port_mode[0])) { - ret = clk_set_parent(omap->utmi_p1_fck, - omap->xclk60mhsp1_ck); - if (ret != 0) { - dev_err(dev, "xclk60mhsp1_ck set parent" - "failed error:%d\n", ret); - goto err_tll; - } - } else if (is_ehci_tll_mode(pdata->port_mode[0])) { - ret = clk_set_parent(omap->utmi_p1_fck, - omap->init_60m_fclk); - if (ret != 0) { - dev_err(dev, "init_60m_fclk set parent" - "failed error:%d\n", ret); - goto err_tll; - } - clk_enable(omap->usbhost_p1_fck); - clk_enable(omap->usbtll_p1_fck); - } - - if (is_ehci_phy_mode(pdata->port_mode[1])) { - ret = clk_set_parent(omap->utmi_p2_fck, - omap->xclk60mhsp2_ck); - if (ret != 0) { - dev_err(dev, "xclk60mhsp1_ck set parent" - "failed error:%d\n", ret); - goto err_tll; - } - } else if (is_ehci_tll_mode(pdata->port_mode[1])) { - ret = clk_set_parent(omap->utmi_p2_fck, - omap->init_60m_fclk); - if (ret != 0) { - dev_err(dev, "init_60m_fclk set parent" - "failed error:%d\n", ret); - goto err_tll; - } - clk_enable(omap->usbhost_p2_fck); - clk_enable(omap->usbtll_p2_fck); - } - - clk_enable(omap->utmi_p1_fck); - clk_enable(omap->utmi_p2_fck); - if (is_ehci_tll_mode(pdata->port_mode[0]) || (is_ohci_port(pdata->port_mode[0]))) reg |= OMAP4_P1_MODE_TLL; @@ -913,12 +614,15 @@ static int usbhs_enable(struct device *dev) (pdata->ehci_data->reset_gpio_port[1], 1); } -end_count: - omap->count++; spin_unlock_irqrestore(&omap->lock, flags); - return 0; + pm_runtime_put_sync(dev); +} + +static void omap_usbhs_deinit(struct device *dev) +{ + struct usbhs_hcd_omap *omap = dev_get_drvdata(dev); + struct usbhs_omap_platform_data *pdata = &omap->platdata; -err_tll: if (pdata->ehci_data->phy_reset) { if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) gpio_free(pdata->ehci_data->reset_gpio_port[0]); @@ -926,123 +630,272 @@ err_tll: if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1])) gpio_free(pdata->ehci_data->reset_gpio_port[1]); } - - clk_disable(omap->usbtll_ick); - clk_disable(omap->usbtll_fck); - clk_disable(omap->usbhost_fs_fck); - clk_disable(omap->usbhost_hs_fck); - clk_disable(omap->usbhost_ick); - spin_unlock_irqrestore(&omap->lock, flags); - return ret; } -static void usbhs_disable(struct device *dev) + +/** + * usbhs_omap_probe - initialize TI-based HCDs + * + * Allocates basic resources for this USB host controller. + */ +static int __devinit usbhs_omap_probe(struct platform_device *pdev) { - struct usbhs_hcd_omap *omap = dev_get_drvdata(dev); - struct usbhs_omap_platform_data *pdata = &omap->platdata; - unsigned long flags = 0; - unsigned long timeout; + struct device *dev = &pdev->dev; + struct usbhs_omap_platform_data *pdata = dev->platform_data; + struct usbhs_hcd_omap *omap; + struct resource *res; + int ret = 0; + int i; - dev_dbg(dev, "stopping TI HSUSB Controller\n"); + if (!pdata) { + dev_err(dev, "Missing platform data\n"); + ret = -ENOMEM; + goto end_probe; + } - spin_lock_irqsave(&omap->lock, flags); + omap = kzalloc(sizeof(*omap), GFP_KERNEL); + if (!omap) { + dev_err(dev, "Memory allocation failed\n"); + ret = -ENOMEM; + goto end_probe; + } - if (omap->count == 0) - goto end_disble; + spin_lock_init(&omap->lock); - omap->count--; + for (i = 0; i < OMAP3_HS_USB_PORTS; i++) + omap->platdata.port_mode[i] = pdata->port_mode[i]; + + omap->platdata.ehci_data = pdata->ehci_data; + omap->platdata.ohci_data = pdata->ohci_data; - if (omap->count != 0) - goto end_disble; + pm_runtime_enable(dev); - /* Reset OMAP modules for insmod/rmmod to work */ - usbhs_write(omap->uhh_base, OMAP_UHH_SYSCONFIG, - is_omap_usbhs_rev2(omap) ? - OMAP4_UHH_SYSCONFIG_SOFTRESET : - OMAP_UHH_SYSCONFIG_SOFTRESET); - timeout = jiffies + msecs_to_jiffies(100); - while (!(usbhs_read(omap->uhh_base, OMAP_UHH_SYSSTATUS) - & (1 << 0))) { - cpu_relax(); + for (i = 0; i < OMAP3_HS_USB_PORTS; i++) + if (is_ehci_phy_mode(i) || is_ehci_tll_mode(i) || + is_ehci_hsic_mode(i)) { + omap->ehci_logic_fck = clk_get(dev, "ehci_logic_fck"); + if (IS_ERR(omap->ehci_logic_fck)) { + ret = PTR_ERR(omap->ehci_logic_fck); + dev_warn(dev, "ehci_logic_fck failed:%d\n", + ret); + } + break; + } - if (time_after(jiffies, timeout)) - dev_dbg(dev, "operation timed out\n"); + omap->utmi_p1_fck = clk_get(dev, "utmi_p1_gfclk"); + if (IS_ERR(omap->utmi_p1_fck)) { + ret = PTR_ERR(omap->utmi_p1_fck); + dev_err(dev, "utmi_p1_gfclk failed error:%d\n", ret); + goto err_end; } - while (!(usbhs_read(omap->uhh_base, OMAP_UHH_SYSSTATUS) - & (1 << 1))) { - cpu_relax(); + omap->xclk60mhsp1_ck = clk_get(dev, "xclk60mhsp1_ck"); + if (IS_ERR(omap->xclk60mhsp1_ck)) { + ret = PTR_ERR(omap->xclk60mhsp1_ck); + dev_err(dev, "xclk60mhsp1_ck failed error:%d\n", ret); + goto err_utmi_p1_fck; + } - if (time_after(jiffies, timeout)) - dev_dbg(dev, "operation timed out\n"); + omap->utmi_p2_fck = clk_get(dev, "utmi_p2_gfclk"); + if (IS_ERR(omap->utmi_p2_fck)) { + ret = PTR_ERR(omap->utmi_p2_fck); + dev_err(dev, "utmi_p2_gfclk failed error:%d\n", ret); + goto err_xclk60mhsp1_ck; } - while (!(usbhs_read(omap->uhh_base, OMAP_UHH_SYSSTATUS) - & (1 << 2))) { - cpu_relax(); + omap->xclk60mhsp2_ck = clk_get(dev, "xclk60mhsp2_ck"); + if (IS_ERR(omap->xclk60mhsp2_ck)) { + ret = PTR_ERR(omap->xclk60mhsp2_ck); + dev_err(dev, "xclk60mhsp2_ck failed error:%d\n", ret); + goto err_utmi_p2_fck; + } - if (time_after(jiffies, timeout)) - dev_dbg(dev, "operation timed out\n"); + omap->usbhost_p1_fck = clk_get(dev, "usb_host_hs_utmi_p1_clk"); + if (IS_ERR(omap->usbhost_p1_fck)) { + ret = PTR_ERR(omap->usbhost_p1_fck); + dev_err(dev, "usbhost_p1_fck failed error:%d\n", ret); + goto err_xclk60mhsp2_ck; } - usbhs_write(omap->tll_base, OMAP_USBTLL_SYSCONFIG, (1 << 1)); + omap->usbtll_p1_fck = clk_get(dev, "usb_tll_hs_usb_ch0_clk"); + if (IS_ERR(omap->usbtll_p1_fck)) { + ret = PTR_ERR(omap->usbtll_p1_fck); + dev_err(dev, "usbtll_p1_fck failed error:%d\n", ret); + goto err_usbhost_p1_fck; + } - while (!(usbhs_read(omap->tll_base, OMAP_USBTLL_SYSSTATUS) - & (1 << 0))) { - cpu_relax(); + omap->usbhost_p2_fck = clk_get(dev, "usb_host_hs_utmi_p2_clk"); + if (IS_ERR(omap->usbhost_p2_fck)) { + ret = PTR_ERR(omap->usbhost_p2_fck); + dev_err(dev, "usbhost_p2_fck failed error:%d\n", ret); + goto err_usbtll_p1_fck; + } - if (time_after(jiffies, timeout)) - dev_dbg(dev, "operation timed out\n"); + omap->usbtll_p2_fck = clk_get(dev, "usb_tll_hs_usb_ch1_clk"); + if (IS_ERR(omap->usbtll_p2_fck)) { + ret = PTR_ERR(omap->usbtll_p2_fck); + dev_err(dev, "usbtll_p2_fck failed error:%d\n", ret); + goto err_usbhost_p2_fck; } - if (is_omap_usbhs_rev2(omap)) { - if (is_ehci_tll_mode(pdata->port_mode[0])) - clk_disable(omap->usbtll_p1_fck); - if (is_ehci_tll_mode(pdata->port_mode[1])) - clk_disable(omap->usbtll_p2_fck); - clk_disable(omap->utmi_p2_fck); - clk_disable(omap->utmi_p1_fck); + omap->init_60m_fclk = clk_get(dev, "init_60m_fclk"); + if (IS_ERR(omap->init_60m_fclk)) { + ret = PTR_ERR(omap->init_60m_fclk); + dev_err(dev, "init_60m_fclk failed error:%d\n", ret); + goto err_usbtll_p2_fck; } - clk_disable(omap->usbtll_ick); - clk_disable(omap->usbtll_fck); - clk_disable(omap->usbhost_fs_fck); - clk_disable(omap->usbhost_hs_fck); - clk_disable(omap->usbhost_ick); + if (is_ehci_phy_mode(pdata->port_mode[0])) { + /* for OMAP3 , the clk set paretn fails */ + ret = clk_set_parent(omap->utmi_p1_fck, + omap->xclk60mhsp1_ck); + if (ret != 0) + dev_err(dev, "xclk60mhsp1_ck set parent" + "failed error:%d\n", ret); + } else if (is_ehci_tll_mode(pdata->port_mode[0])) { + ret = clk_set_parent(omap->utmi_p1_fck, + omap->init_60m_fclk); + if (ret != 0) + dev_err(dev, "init_60m_fclk set parent" + "failed error:%d\n", ret); + } - /* The gpio_free migh sleep; so unlock the spinlock */ - spin_unlock_irqrestore(&omap->lock, flags); + if (is_ehci_phy_mode(pdata->port_mode[1])) { + ret = clk_set_parent(omap->utmi_p2_fck, + omap->xclk60mhsp2_ck); + if (ret != 0) + dev_err(dev, "xclk60mhsp2_ck set parent" + "failed error:%d\n", ret); + } else if (is_ehci_tll_mode(pdata->port_mode[1])) { + ret = clk_set_parent(omap->utmi_p2_fck, + omap->init_60m_fclk); + if (ret != 0) + dev_err(dev, "init_60m_fclk set parent" + "failed error:%d\n", ret); + } - if (pdata->ehci_data->phy_reset) { - if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) - gpio_free(pdata->ehci_data->reset_gpio_port[0]); + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "uhh"); + if (!res) { + dev_err(dev, "UHH EHCI get resource failed\n"); + ret = -ENODEV; + goto err_init_60m_fclk; + } - if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1])) - gpio_free(pdata->ehci_data->reset_gpio_port[1]); + omap->uhh_base = ioremap(res->start, resource_size(res)); + if (!omap->uhh_base) { + dev_err(dev, "UHH ioremap failed\n"); + ret = -ENOMEM; + goto err_init_60m_fclk; } - return; -end_disble: - spin_unlock_irqrestore(&omap->lock, flags); -} + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tll"); + if (!res) { + dev_err(dev, "UHH EHCI get resource failed\n"); + ret = -ENODEV; + goto err_tll; + } -int omap_usbhs_enable(struct device *dev) -{ - return usbhs_enable(dev->parent); + omap->tll_base = ioremap(res->start, resource_size(res)); + if (!omap->tll_base) { + dev_err(dev, "TLL ioremap failed\n"); + ret = -ENOMEM; + goto err_tll; + } + + platform_set_drvdata(pdev, omap); + + ret = omap_usbhs_alloc_children(pdev); + if (ret) { + dev_err(dev, "omap_usbhs_alloc_children failed\n"); + goto err_alloc; + } + + omap_usbhs_init(dev); + + goto end_probe; + +err_alloc: + iounmap(omap->tll_base); + +err_tll: + iounmap(omap->uhh_base); + +err_init_60m_fclk: + clk_put(omap->init_60m_fclk); + +err_usbtll_p2_fck: + clk_put(omap->usbtll_p2_fck); + +err_usbhost_p2_fck: + clk_put(omap->usbhost_p2_fck); + +err_usbtll_p1_fck: + clk_put(omap->usbtll_p1_fck); + +err_usbhost_p1_fck: + clk_put(omap->usbhost_p1_fck); + +err_xclk60mhsp2_ck: + clk_put(omap->xclk60mhsp2_ck); + +err_utmi_p2_fck: + clk_put(omap->utmi_p2_fck); + +err_xclk60mhsp1_ck: + clk_put(omap->xclk60mhsp1_ck); + +err_utmi_p1_fck: + clk_put(omap->utmi_p1_fck); + +err_end: + clk_put(omap->ehci_logic_fck); + pm_runtime_disable(dev); + kfree(omap); + +end_probe: + return ret; } -EXPORT_SYMBOL_GPL(omap_usbhs_enable); -void omap_usbhs_disable(struct device *dev) +/** + * usbhs_omap_remove - shutdown processing for UHH & TLL HCDs + * @pdev: USB Host Controller being removed + * + * Reverses the effect of usbhs_omap_probe(). + */ +static int __devexit usbhs_omap_remove(struct platform_device *pdev) { - usbhs_disable(dev->parent); + struct usbhs_hcd_omap *omap = platform_get_drvdata(pdev); + + omap_usbhs_deinit(&pdev->dev); + iounmap(omap->tll_base); + iounmap(omap->uhh_base); + clk_put(omap->init_60m_fclk); + clk_put(omap->usbtll_p2_fck); + clk_put(omap->usbhost_p2_fck); + clk_put(omap->usbtll_p1_fck); + clk_put(omap->usbhost_p1_fck); + clk_put(omap->xclk60mhsp2_ck); + clk_put(omap->utmi_p2_fck); + clk_put(omap->xclk60mhsp1_ck); + clk_put(omap->utmi_p1_fck); + clk_put(omap->ehci_logic_fck); + pm_runtime_disable(&pdev->dev); + kfree(omap); + + return 0; } -EXPORT_SYMBOL_GPL(omap_usbhs_disable); + +static const struct dev_pm_ops usbhsomap_dev_pm_ops = { + .runtime_suspend = usbhs_runtime_suspend, + .runtime_resume = usbhs_runtime_resume, +}; static struct platform_driver usbhs_omap_driver = { .driver = { .name = (char *)usbhs_driver_name, .owner = THIS_MODULE, + .pm = &usbhsomap_dev_pm_ops, }, .remove = __exit_p(usbhs_omap_remove), }; -- cgit v1.2.3-55-g7522 From fb97a8466522f8f35ab886f7af8eefefa0a4905e Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Fri, 18 Nov 2011 15:29:25 +0100 Subject: net/macb: add DT support for Cadence macb/gem driver Allow the device tree to provide the mac address and the phy mode. Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD [nicolas.ferre@atmel.com: change "compatible" node property, doc and DT hwaddr] Signed-off-by: Nicolas Ferre [jamie@jamieiles.com: add "gem" compatibility strings and doc] Acked-by: Jamie Iles Acked-by: David S. Miller --- Documentation/devicetree/bindings/net/macb.txt | 25 +++++++++ drivers/net/ethernet/cadence/macb.c | 73 +++++++++++++++++++++++--- drivers/net/ethernet/cadence/macb.h | 2 + 3 files changed, 92 insertions(+), 8 deletions(-) create mode 100644 Documentation/devicetree/bindings/net/macb.txt (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/net/macb.txt b/Documentation/devicetree/bindings/net/macb.txt new file mode 100644 index 000000000000..44afa0e5057d --- /dev/null +++ b/Documentation/devicetree/bindings/net/macb.txt @@ -0,0 +1,25 @@ +* Cadence MACB/GEM Ethernet controller + +Required properties: +- compatible: Should be "cdns,[-]{macb|gem}" + Use "cdns,at91sam9260-macb" Atmel at91sam9260 and at91sam9263 SoCs. + Use "cdns,at32ap7000-macb" for other 10/100 usage or use the generic form: "cdns,macb". + Use "cnds,pc302-gem" for Picochip picoXcell pc302 and later devices based on + the Cadence GEM, or the generic form: "cdns,gem". +- reg: Address and length of the register set for the device +- interrupts: Should contain macb interrupt +- phy-mode: String, operation mode of the PHY interface. + Supported values are: "mii", "rmii", "gmii", "rgmii". + +Optional properties: +- local-mac-address: 6 bytes, mac address + +Examples: + + macb0: ethernet@fffc4000 { + compatible = "cdns,at32ap7000-macb"; + reg = <0xfffc4000 0x4000>; + interrupts = <21>; + phy-mode = "rmii"; + local-mac-address = [3a 0e 03 04 05 06]; + }; diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index 64d61461bdc7..baf1a0d88d8a 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include "macb.h" @@ -191,7 +193,6 @@ static int macb_mii_probe(struct net_device *dev) { struct macb *bp = netdev_priv(dev); struct phy_device *phydev; - struct macb_platform_data *pdata; int ret; phydev = phy_find_first(bp->mii_bus); @@ -200,14 +201,11 @@ static int macb_mii_probe(struct net_device *dev) return -1; } - pdata = bp->pdev->dev.platform_data; /* TODO : add pin_irq */ /* attach the mac to the phy */ ret = phy_connect_direct(dev, phydev, &macb_handle_link_change, 0, - pdata && pdata->is_rmii ? - PHY_INTERFACE_MODE_RMII : - PHY_INTERFACE_MODE_MII); + bp->phy_interface); if (ret) { netdev_err(dev, "Could not attach to PHY\n"); return ret; @@ -1244,6 +1242,52 @@ static const struct net_device_ops macb_netdev_ops = { #endif }; +#if defined(CONFIG_OF) +static const struct of_device_id macb_dt_ids[] = { + { .compatible = "cdns,at32ap7000-macb" }, + { .compatible = "cdns,at91sam9260-macb" }, + { .compatible = "cdns,macb" }, + { .compatible = "cdns,pc302-gem" }, + { .compatible = "cdns,gem" }, + { /* sentinel */ } +}; + +MODULE_DEVICE_TABLE(of, macb_dt_ids); + +static int __devinit macb_get_phy_mode_dt(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + + if (np) + return of_get_phy_mode(np); + + return -ENODEV; +} + +static int __devinit macb_get_hwaddr_dt(struct macb *bp) +{ + struct device_node *np = bp->pdev->dev.of_node; + if (np) { + const char *mac = of_get_mac_address(np); + if (mac) { + memcpy(bp->dev->dev_addr, mac, ETH_ALEN); + return 0; + } + } + + return -ENODEV; +} +#else +static int __devinit macb_get_phy_mode_dt(struct platform_device *pdev) +{ + return -ENODEV; +} +static int __devinit macb_get_hwaddr_dt(struct macb *bp) +{ + return -ENODEV; +} +#endif + static int __init macb_probe(struct platform_device *pdev) { struct macb_platform_data *pdata; @@ -1318,10 +1362,22 @@ static int __init macb_probe(struct platform_device *pdev) config |= macb_dbw(bp); macb_writel(bp, NCFGR, config); - macb_get_hwaddr(bp); - pdata = pdev->dev.platform_data; + err = macb_get_hwaddr_dt(bp); + if (err < 0) + macb_get_hwaddr(bp); + + err = macb_get_phy_mode_dt(pdev); + if (err < 0) { + pdata = pdev->dev.platform_data; + if (pdata && pdata->is_rmii) + bp->phy_interface = PHY_INTERFACE_MODE_RMII; + else + bp->phy_interface = PHY_INTERFACE_MODE_MII; + } else { + bp->phy_interface = err; + } - if (pdata && pdata->is_rmii) + if (bp->phy_interface == PHY_INTERFACE_MODE_RMII) #if defined(CONFIG_ARCH_AT91) macb_or_gem_writel(bp, USRIO, (MACB_BIT(RMII) | MACB_BIT(CLKEN))); @@ -1444,6 +1500,7 @@ static struct platform_driver macb_driver = { .driver = { .name = "macb", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(macb_dt_ids), }, }; diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h index 193107884a5a..335e288f5314 100644 --- a/drivers/net/ethernet/cadence/macb.h +++ b/drivers/net/ethernet/cadence/macb.h @@ -532,6 +532,8 @@ struct macb { unsigned int link; unsigned int speed; unsigned int duplex; + + phy_interface_t phy_interface; }; static inline bool macb_is_gem(struct macb *bp) -- cgit v1.2.3-55-g7522 From 2839038bb1a72ed7ef3c39521e0ca981c9cb1534 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Thu, 24 Nov 2011 22:21:14 +0100 Subject: net/at91_ether: use gpio_is_valid for phy IRQ line Use the generic gpiolib gpio_is_valid() function to test if the phy IRQ line GPIO is actually provided. For non-connected or non-existing phy IRQ lines, -EINVAL value is used for phy_irq_pin field of struct at91_eth_data. Signed-off-by: Nicolas Ferre Acked-by: Jean-Christophe PLAGNIOL-VILLARD Acked-by: David S. Miller --- drivers/net/ethernet/cadence/at91_ether.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/cadence/at91_ether.c b/drivers/net/ethernet/cadence/at91_ether.c index dfeb46cb3f74..1a5b6efa0120 100644 --- a/drivers/net/ethernet/cadence/at91_ether.c +++ b/drivers/net/ethernet/cadence/at91_ether.c @@ -256,8 +256,7 @@ static void enable_phyirq(struct net_device *dev) unsigned int dsintr, irq_number; int status; - irq_number = lp->board_data.phy_irq_pin; - if (!irq_number) { + if (!gpio_is_valid(lp->board_data.phy_irq_pin)) { /* * PHY doesn't have an IRQ pin (RTL8201, DP83847, AC101L), * or board does not have it connected. @@ -266,6 +265,7 @@ static void enable_phyirq(struct net_device *dev) return; } + irq_number = lp->board_data.phy_irq_pin; status = request_irq(irq_number, at91ether_phy_interrupt, 0, dev->name, dev); if (status) { printk(KERN_ERR "at91_ether: PHY IRQ %d request failed - status %d!\n", irq_number, status); @@ -320,8 +320,7 @@ static void disable_phyirq(struct net_device *dev) unsigned int dsintr; unsigned int irq_number; - irq_number = lp->board_data.phy_irq_pin; - if (!irq_number) { + if (!gpio_is_valid(lp->board_data.phy_irq_pin)) { del_timer_sync(&lp->check_timer); return; } @@ -366,6 +365,7 @@ static void disable_phyirq(struct net_device *dev) disable_mdi(); spin_unlock_irq(&lp->lock); + irq_number = lp->board_data.phy_irq_pin; free_irq(irq_number, dev); /* Free interrupt handler */ } @@ -1078,7 +1078,7 @@ static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_add netif_carrier_off(dev); /* will be enabled in open() */ /* If board has no PHY IRQ, use a timer to poll the PHY */ - if (!lp->board_data.phy_irq_pin) { + if (!gpio_is_valid(lp->board_data.phy_irq_pin)) { init_timer(&lp->check_timer); lp->check_timer.data = (unsigned long)dev; lp->check_timer.function = at91ether_check_link; @@ -1170,7 +1170,8 @@ static int __devexit at91ether_remove(struct platform_device *pdev) struct net_device *dev = platform_get_drvdata(pdev); struct at91_private *lp = netdev_priv(dev); - if (lp->board_data.phy_irq_pin >= 32) + if (gpio_is_valid(lp->board_data.phy_irq_pin) && + lp->board_data.phy_irq_pin >= 32) gpio_free(lp->board_data.phy_irq_pin); unregister_netdev(dev); @@ -1189,11 +1190,12 @@ static int at91ether_suspend(struct platform_device *pdev, pm_message_t mesg) { struct net_device *net_dev = platform_get_drvdata(pdev); struct at91_private *lp = netdev_priv(net_dev); - int phy_irq = lp->board_data.phy_irq_pin; if (netif_running(net_dev)) { - if (phy_irq) + if (gpio_is_valid(lp->board_data.phy_irq_pin)) { + int phy_irq = lp->board_data.phy_irq_pin; disable_irq(phy_irq); + } netif_stop_queue(net_dev); netif_device_detach(net_dev); @@ -1207,7 +1209,6 @@ static int at91ether_resume(struct platform_device *pdev) { struct net_device *net_dev = platform_get_drvdata(pdev); struct at91_private *lp = netdev_priv(net_dev); - int phy_irq = lp->board_data.phy_irq_pin; if (netif_running(net_dev)) { clk_enable(lp->ether_clk); @@ -1215,8 +1216,10 @@ static int at91ether_resume(struct platform_device *pdev) netif_device_attach(net_dev); netif_start_queue(net_dev); - if (phy_irq) + if (gpio_is_valid(lp->board_data.phy_irq_pin)) { + int phy_irq = lp->board_data.phy_irq_pin; enable_irq(phy_irq); + } } return 0; } -- cgit v1.2.3-55-g7522 From 92891da11a3f913b50a685c3facff6a5891a45ba Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Sat, 17 Dec 2011 23:29:29 -0700 Subject: i2c: tegra: Add __devinit/exit to probe/remove This fixes some section mismatch build warnings. Signed-off-by: Stephen Warren Signed-off-by: Olof Johansson --- drivers/i2c/busses/i2c-tegra.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 46b6500c5478..e8560ed3d3c8 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -558,7 +558,7 @@ static const struct i2c_algorithm tegra_i2c_algo = { .functionality = tegra_i2c_func, }; -static int tegra_i2c_probe(struct platform_device *pdev) +static int __devinit tegra_i2c_probe(struct platform_device *pdev) { struct tegra_i2c_dev *i2c_dev; struct tegra_i2c_platform_data *pdata = pdev->dev.platform_data; @@ -690,7 +690,7 @@ err_iounmap: return ret; } -static int tegra_i2c_remove(struct platform_device *pdev) +static int __devexit tegra_i2c_remove(struct platform_device *pdev) { struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev); i2c_del_adapter(&i2c_dev->adapter); -- cgit v1.2.3-55-g7522 From 68fb669554a7def658873afdb9460f9a6289d6d9 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Sat, 17 Dec 2011 23:29:30 -0700 Subject: i2c: tegra: Support DVC controller in device tree One of the Tegra I2C blocks is inside the DVC (Digital Voltage Controller) block. This block is identical to the rest of the I2C blocks, except that it only supports master mode, it has registers moved around, and it needs some extra init to get it into I2C mode. The register moves are handled by i2c_readl and i2c_writel This patch adds a new compatible value for controllers of this "DVC" type; I figured that this approach was reasonable, as opposed to adding an is-dvc property under the existing compatible value, since the HW truly is different. v2: Call of_device_is_compatible() to determine is_dvc, instead of storing the flag in tegra_i2c_of_match[]'s .data field. Signed-off-by: Stephen Warren Signed-off-by: Olof Johansson --- drivers/i2c/busses/i2c-tegra.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index e8560ed3d3c8..6381604696d3 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -636,7 +636,10 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev) i2c_dev->bus_clk_rate = be32_to_cpup(prop); } - if (pdev->id == 3) + if (pdev->dev.of_node) + i2c_dev->is_dvc = of_device_is_compatible(pdev->dev.of_node, + "nvidia,tegra20-i2c-dvc"); + else if (pdev->id == 3) i2c_dev->is_dvc = 1; init_completion(&i2c_dev->msg_complete); @@ -742,6 +745,7 @@ static int tegra_i2c_resume(struct platform_device *pdev) /* Match table for of_platform binding */ static const struct of_device_id tegra_i2c_of_match[] __devinitconst = { { .compatible = "nvidia,tegra20-i2c", }, + { .compatible = "nvidia,tegra20-i2c-dvc", }, {}, }; MODULE_DEVICE_TABLE(of, tegra_i2c_of_match); -- cgit v1.2.3-55-g7522 From b17471f5d121a53be1ccf6e0b0599441e56b468c Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Tue, 20 Dec 2011 13:13:07 -0800 Subject: net: macb: fix build break with !CONFIG_OF This fixes the build of the macb driver that was broken by the DT changes: drivers/net/ethernet/cadence/macb.c:1503: error: implicit declaration of function 'of_match_ptr' drivers/net/ethernet/cadence/macb.c:1503: error: 'macb_dt_ids' undeclared here (not in a function) drivers/net/ethernet/cadence/macb.c:1503: error: initializer element is not constant drivers/net/ethernet/cadence/macb.c:1503: error: (near initialization for 'macb_driver.driver.of_match_table') Signed-off-by: Olof Johansson Acked-by: Nicolas Ferre --- drivers/net/ethernet/cadence/macb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index baf1a0d88d8a..f3d5c65d99cf 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include -- cgit v1.2.3-55-g7522 From 62194244cf871aec73b5854077f1c527416ccd7b Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Fri, 23 Dec 2011 11:20:54 +0900 Subject: USB: Add Samsung Exynos OHCI diver This patch adds USB OHCI driver for Samsung EXYNOS SoCs. Signed-off-by: Jingoo Han Acked-by: Greg Kroah-Hartman Signed-off-by: Kukjin Kim --- drivers/usb/Kconfig | 1 + drivers/usb/host/Kconfig | 6 + drivers/usb/host/ohci-exynos.c | 274 +++++++++++++++++++++++++++++++++++++++++ drivers/usb/host/ohci-hcd.c | 5 + 4 files changed, 286 insertions(+) create mode 100644 drivers/usb/host/ohci-exynos.c (limited to 'drivers') diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 791f11bed606..75823a1abeb6 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -48,6 +48,7 @@ config USB_ARCH_HAS_OHCI default y if ARCH_DAVINCI_DA8XX default y if ARCH_CNS3XXX default y if PLAT_SPEAR + default y if ARCH_EXYNOS # PPC: default y if STB03xxx default y if PPC_MPC52xx diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 060e0e2b1ae6..eea85dc16826 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -371,6 +371,12 @@ config USB_OHCI_SH Enables support for the on-chip OHCI controller on the SuperH. If you use the PCI OHCI controller, this option is not necessary. +config USB_OHCI_EXYNOS + boolean "OHCI support for Samsung EXYNOS SoC Series" + depends on USB_OHCI_HCD && ARCH_EXYNOS + help + Enable support for the Samsung Exynos SOC's on-chip OHCI controller. + config USB_CNS3XXX_OHCI bool "Cavium CNS3XXX OHCI Module" depends on USB_OHCI_HCD && ARCH_CNS3XXX diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c new file mode 100644 index 000000000000..55aa35aa3d7b --- /dev/null +++ b/drivers/usb/host/ohci-exynos.c @@ -0,0 +1,274 @@ +/* + * SAMSUNG EXYNOS USB HOST OHCI Controller + * + * Copyright (C) 2011 Samsung Electronics Co.Ltd + * Author: Jingoo Han + * + * 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. + * + */ + +#include +#include +#include +#include + +struct exynos_ohci_hcd { + struct device *dev; + struct usb_hcd *hcd; + struct clk *clk; +}; + +static int ohci_exynos_start(struct usb_hcd *hcd) +{ + struct ohci_hcd *ohci = hcd_to_ohci(hcd); + int ret; + + ohci_dbg(ohci, "ohci_exynos_start, ohci:%p", ohci); + + ret = ohci_init(ohci); + if (ret < 0) + return ret; + + ret = ohci_run(ohci); + if (ret < 0) { + err("can't start %s", hcd->self.bus_name); + ohci_stop(hcd); + return ret; + } + + return 0; +} + +static const struct hc_driver exynos_ohci_hc_driver = { + .description = hcd_name, + .product_desc = "EXYNOS OHCI Host Controller", + .hcd_priv_size = sizeof(struct ohci_hcd), + + .irq = ohci_irq, + .flags = HCD_MEMORY|HCD_USB11, + + .start = ohci_exynos_start, + .stop = ohci_stop, + .shutdown = ohci_shutdown, + + .get_frame_number = ohci_get_frame, + + .urb_enqueue = ohci_urb_enqueue, + .urb_dequeue = ohci_urb_dequeue, + .endpoint_disable = ohci_endpoint_disable, + + .hub_status_data = ohci_hub_status_data, + .hub_control = ohci_hub_control, +#ifdef CONFIG_PM + .bus_suspend = ohci_bus_suspend, + .bus_resume = ohci_bus_resume, +#endif + .start_port_reset = ohci_start_port_reset, +}; + +static int __devinit exynos_ohci_probe(struct platform_device *pdev) +{ + struct exynos4_ohci_platdata *pdata; + struct exynos_ohci_hcd *exynos_ohci; + struct usb_hcd *hcd; + struct ohci_hcd *ohci; + struct resource *res; + int irq; + int err; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "No platform data defined\n"); + return -EINVAL; + } + + exynos_ohci = kzalloc(sizeof(struct exynos_ohci_hcd), GFP_KERNEL); + if (!exynos_ohci) + return -ENOMEM; + + exynos_ohci->dev = &pdev->dev; + + hcd = usb_create_hcd(&exynos_ohci_hc_driver, &pdev->dev, + dev_name(&pdev->dev)); + if (!hcd) { + dev_err(&pdev->dev, "Unable to create HCD\n"); + err = -ENOMEM; + goto fail_hcd; + } + + exynos_ohci->hcd = hcd; + exynos_ohci->clk = clk_get(&pdev->dev, "usbhost"); + + if (IS_ERR(exynos_ohci->clk)) { + dev_err(&pdev->dev, "Failed to get usbhost clock\n"); + err = PTR_ERR(exynos_ohci->clk); + goto fail_clk; + } + + err = clk_enable(exynos_ohci->clk); + if (err) + goto fail_clken; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "Failed to get I/O memory\n"); + err = -ENXIO; + goto fail_io; + } + + hcd->rsrc_start = res->start; + hcd->rsrc_len = resource_size(res); + hcd->regs = ioremap(res->start, resource_size(res)); + if (!hcd->regs) { + dev_err(&pdev->dev, "Failed to remap I/O memory\n"); + err = -ENOMEM; + goto fail_io; + } + + irq = platform_get_irq(pdev, 0); + if (!irq) { + dev_err(&pdev->dev, "Failed to get IRQ\n"); + err = -ENODEV; + goto fail; + } + + if (pdata->phy_init) + pdata->phy_init(pdev, S5P_USB_PHY_HOST); + + ohci = hcd_to_ohci(hcd); + ohci_hcd_init(ohci); + + err = usb_add_hcd(hcd, irq, IRQF_SHARED); + if (err) { + dev_err(&pdev->dev, "Failed to add USB HCD\n"); + goto fail; + } + + platform_set_drvdata(pdev, exynos_ohci); + + return 0; + +fail: + iounmap(hcd->regs); +fail_io: + clk_disable(exynos_ohci->clk); +fail_clken: + clk_put(exynos_ohci->clk); +fail_clk: + usb_put_hcd(hcd); +fail_hcd: + kfree(exynos_ohci); + return err; +} + +static int __devexit exynos_ohci_remove(struct platform_device *pdev) +{ + struct exynos4_ohci_platdata *pdata = pdev->dev.platform_data; + struct exynos_ohci_hcd *exynos_ohci = platform_get_drvdata(pdev); + struct usb_hcd *hcd = exynos_ohci->hcd; + + usb_remove_hcd(hcd); + + if (pdata && pdata->phy_exit) + pdata->phy_exit(pdev, S5P_USB_PHY_HOST); + + iounmap(hcd->regs); + + clk_disable(exynos_ohci->clk); + clk_put(exynos_ohci->clk); + + usb_put_hcd(hcd); + kfree(exynos_ohci); + + return 0; +} + +static void exynos_ohci_shutdown(struct platform_device *pdev) +{ + struct exynos_ohci_hcd *exynos_ohci = platform_get_drvdata(pdev); + struct usb_hcd *hcd = exynos_ohci->hcd; + + if (hcd->driver->shutdown) + hcd->driver->shutdown(hcd); +} + +#ifdef CONFIG_PM +static int exynos_ohci_suspend(struct device *dev) +{ + struct exynos_ohci_hcd *exynos_ohci = dev_get_drvdata(dev); + struct usb_hcd *hcd = exynos_ohci->hcd; + struct ohci_hcd *ohci = hcd_to_ohci(hcd); + struct platform_device *pdev = to_platform_device(dev); + struct exynos4_ohci_platdata *pdata = pdev->dev.platform_data; + unsigned long flags; + int rc = 0; + + /* + * Root hub was already suspended. Disable irq emission and + * mark HW unaccessible, bail out if RH has been resumed. Use + * the spinlock to properly synchronize with possible pending + * RH suspend or resume activity. + * + * This is still racy as hcd->state is manipulated outside of + * any locks =P But that will be a different fix. + */ + spin_lock_irqsave(&ohci->lock, flags); + if (hcd->state != HC_STATE_SUSPENDED && hcd->state != HC_STATE_HALT) { + rc = -EINVAL; + goto fail; + } + + clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + + if (pdata && pdata->phy_exit) + pdata->phy_exit(pdev, S5P_USB_PHY_HOST); +fail: + spin_unlock_irqrestore(&ohci->lock, flags); + + return rc; +} + +static int exynos_ohci_resume(struct device *dev) +{ + struct exynos_ohci_hcd *exynos_ohci = dev_get_drvdata(dev); + struct usb_hcd *hcd = exynos_ohci->hcd; + struct platform_device *pdev = to_platform_device(dev); + struct exynos4_ohci_platdata *pdata = pdev->dev.platform_data; + + if (pdata && pdata->phy_init) + pdata->phy_init(pdev, S5P_USB_PHY_HOST); + + /* Mark hardware accessible again as we are out of D3 state by now */ + set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + + ohci_finish_controller_resume(hcd); + + return 0; +} +#else +#define exynos_ohci_suspend NULL +#define exynos_ohci_resume NULL +#endif + +static const struct dev_pm_ops exynos_ohci_pm_ops = { + .suspend = exynos_ohci_suspend, + .resume = exynos_ohci_resume, +}; + +static struct platform_driver exynos_ohci_driver = { + .probe = exynos_ohci_probe, + .remove = __devexit_p(exynos_ohci_remove), + .shutdown = exynos_ohci_shutdown, + .driver = { + .name = "exynos-ohci", + .owner = THIS_MODULE, + .pm = &exynos_ohci_pm_ops, + } +}; + +MODULE_ALIAS("platform:exynos-ohci"); +MODULE_AUTHOR("Jingoo Han "); diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index b2639191549e..a1006ff79384 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1005,6 +1005,11 @@ MODULE_LICENSE ("GPL"); #define PLATFORM_DRIVER ohci_hcd_s3c2410_driver #endif +#ifdef CONFIG_USB_OHCI_EXYNOS +#include "ohci-exynos.c" +#define PLATFORM_DRIVER exynos_ohci_driver +#endif + #ifdef CONFIG_USB_OHCI_HCD_OMAP1 #include "ohci-omap.c" #define OMAP1_PLATFORM_DRIVER ohci_hcd_omap_driver -- cgit v1.2.3-55-g7522 From 34641de2ef118b9c78a842fb75e6d3cc49c1de31 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 5 Dec 2011 19:06:06 +0800 Subject: pcmcia: pxa: replace IRQ_GPIO() with gpio_to_irq() Since commit 6384fd "ARM: pxa: rename IRQ_GPIO to PXA_GPIO_TO_IRQ", I got buid errors due to implicit declaration of function 'IRQ_GPIO'. Use common gpio_to_irq() to replace machine dependant macro IRQ_GPIO(). Cc: Marek Vasut Cc: Ian Molton Cc: Jonathan Cameron Cc: Zhuang Cc: Eric Miao Cc: Russell King Signed-off-by: Axel Lin Acked-by: Haojian Zhuang Acked-by: Eric Miao Acked-by: Marek Vasut Signed-off-by: Arnd Bergmann --- drivers/pcmcia/pxa2xx_e740.c | 11 +++++++---- drivers/pcmcia/pxa2xx_palmld.c | 2 +- drivers/pcmcia/pxa2xx_palmtc.c | 2 +- drivers/pcmcia/pxa2xx_stargate2.c | 6 ++++-- drivers/pcmcia/pxa2xx_trizeps4.c | 5 +++-- drivers/pcmcia/pxa2xx_vpac270.c | 4 ++-- 6 files changed, 18 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/pcmcia/pxa2xx_e740.c b/drivers/pcmcia/pxa2xx_e740.c index 8bfbd4dca131..17cd2ce7428f 100644 --- a/drivers/pcmcia/pxa2xx_e740.c +++ b/drivers/pcmcia/pxa2xx_e740.c @@ -26,20 +26,23 @@ static struct pcmcia_irqs cd_irqs[] = { { .sock = 0, - .irq = IRQ_GPIO(GPIO_E740_PCMCIA_CD0), .str = "CF card detect" }, { .sock = 1, - .irq = IRQ_GPIO(GPIO_E740_PCMCIA_CD1), .str = "Wifi switch" }, }; static int e740_pcmcia_hw_init(struct soc_pcmcia_socket *skt) { - skt->socket.pci_irq = skt->nr == 0 ? IRQ_GPIO(GPIO_E740_PCMCIA_RDY0) : - IRQ_GPIO(GPIO_E740_PCMCIA_RDY1); + if (skt->nr == 0) + skt->socket.pci_irq = gpio_to_irq(GPIO_E740_PCMCIA_RDY0); + else + skt->socket.pci_irq = gpio_to_irq(GPIO_E740_PCMCIA_RDY1); + + cd_irqs[0].irq = gpio_to_irq(GPIO_E740_PCMCIA_CD0); + cd_irqs[1].irq = gpio_to_irq(GPIO_E740_PCMCIA_CD1); return soc_pcmcia_request_irqs(skt, &cd_irqs[skt->nr], 1); } diff --git a/drivers/pcmcia/pxa2xx_palmld.c b/drivers/pcmcia/pxa2xx_palmld.c index d589ad1dcd4c..6a8e011a8c13 100644 --- a/drivers/pcmcia/pxa2xx_palmld.c +++ b/drivers/pcmcia/pxa2xx_palmld.c @@ -33,7 +33,7 @@ static int palmld_pcmcia_hw_init(struct soc_pcmcia_socket *skt) ret = gpio_request_array(palmld_pcmcia_gpios, ARRAY_SIZE(palmld_pcmcia_gpios)); - skt->socket.pci_irq = IRQ_GPIO(GPIO_NR_PALMLD_PCMCIA_READY); + skt->socket.pci_irq = gpio_to_irq(GPIO_NR_PALMLD_PCMCIA_READY); return ret; } diff --git a/drivers/pcmcia/pxa2xx_palmtc.c b/drivers/pcmcia/pxa2xx_palmtc.c index 9c6a04b2f71b..9e38de769ba3 100644 --- a/drivers/pcmcia/pxa2xx_palmtc.c +++ b/drivers/pcmcia/pxa2xx_palmtc.c @@ -37,7 +37,7 @@ static int palmtc_pcmcia_hw_init(struct soc_pcmcia_socket *skt) ret = gpio_request_array(palmtc_pcmcia_gpios, ARRAY_SIZE(palmtc_pcmcia_gpios)); - skt->socket.pci_irq = IRQ_GPIO(GPIO_NR_PALMTC_PCMCIA_READY); + skt->socket.pci_irq = gpio_to_irq(GPIO_NR_PALMTC_PCMCIA_READY); return ret; } diff --git a/drivers/pcmcia/pxa2xx_stargate2.c b/drivers/pcmcia/pxa2xx_stargate2.c index 939622251dfb..6c2366b74a35 100644 --- a/drivers/pcmcia/pxa2xx_stargate2.c +++ b/drivers/pcmcia/pxa2xx_stargate2.c @@ -34,7 +34,7 @@ #define SG2_S0_GPIO_READY 81 static struct pcmcia_irqs irqs[] = { - { 0, IRQ_GPIO(SG2_S0_GPIO_DETECT), "PCMCIA0 CD" }, + {.sock = 0, .str = "PCMCIA0 CD" }, }; static struct gpio sg2_pcmcia_gpios[] = { @@ -44,7 +44,9 @@ static struct gpio sg2_pcmcia_gpios[] = { static int sg2_pcmcia_hw_init(struct soc_pcmcia_socket *skt) { - skt->socket.pci_irq = IRQ_GPIO(SG2_S0_GPIO_READY); + skt->socket.pci_irq = gpio_to_irq(SG2_S0_GPIO_READY); + irqs[0].irq = gpio_to_irq(SG2_S0_GPIO_DETECT); + return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); } diff --git a/drivers/pcmcia/pxa2xx_trizeps4.c b/drivers/pcmcia/pxa2xx_trizeps4.c index 57ddb969d888..7c33f898135a 100644 --- a/drivers/pcmcia/pxa2xx_trizeps4.c +++ b/drivers/pcmcia/pxa2xx_trizeps4.c @@ -30,7 +30,7 @@ extern void board_pcmcia_power(int power); static struct pcmcia_irqs irqs[] = { - { 0, IRQ_GPIO(GPIO_PCD), "cs0_cd" } + { .sock = 0, .str = "cs0_cd" } /* on other baseboards we can have more inputs */ }; @@ -53,7 +53,8 @@ static int trizeps_pcmcia_hw_init(struct soc_pcmcia_socket *skt) gpio_free(GPIO_PRDY); return -EINVAL; } - skt->socket.pci_irq = IRQ_GPIO(GPIO_PRDY); + skt->socket.pci_irq = gpio_to_irq(GPIO_PRDY); + irqs[0].irq = gpio_to_irq(GPIO_PCD); break; default: break; diff --git a/drivers/pcmcia/pxa2xx_vpac270.c b/drivers/pcmcia/pxa2xx_vpac270.c index 66ab92cf3105..61b17d235dbe 100644 --- a/drivers/pcmcia/pxa2xx_vpac270.c +++ b/drivers/pcmcia/pxa2xx_vpac270.c @@ -38,12 +38,10 @@ static struct gpio vpac270_cf_gpios[] = { static struct pcmcia_irqs cd_irqs[] = { { .sock = 0, - .irq = IRQ_GPIO(GPIO84_VPAC270_PCMCIA_CD), .str = "PCMCIA CD" }, { .sock = 1, - .irq = IRQ_GPIO(GPIO17_VPAC270_CF_CD), .str = "CF CD" }, }; @@ -57,6 +55,7 @@ static int vpac270_pcmcia_hw_init(struct soc_pcmcia_socket *skt) ARRAY_SIZE(vpac270_pcmcia_gpios)); skt->socket.pci_irq = gpio_to_irq(GPIO35_VPAC270_PCMCIA_RDY); + cd_irqs[0].irq = gpio_to_irq(GPIO84_VPAC270_PCMCIA_CD); if (!ret) ret = soc_pcmcia_request_irqs(skt, &cd_irqs[0], 1); @@ -65,6 +64,7 @@ static int vpac270_pcmcia_hw_init(struct soc_pcmcia_socket *skt) ARRAY_SIZE(vpac270_cf_gpios)); skt->socket.pci_irq = gpio_to_irq(GPIO12_VPAC270_CF_RDY); + cd_irqs[1].irq = gpio_to_irq(GPIO17_VPAC270_CF_CD); if (!ret) ret = soc_pcmcia_request_irqs(skt, &cd_irqs[1], 1); -- cgit v1.2.3-55-g7522 From b5d798cc7a221aec50baf496c482280f1b809143 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 5 Dec 2011 19:13:12 +0800 Subject: Input: zylonite-wm97xx - replace IRQ_GPIO() with gpio_to_irq() Since commit 6384fd "ARM: pxa: rename IRQ_GPIO to PXA_GPIO_TO_IRQ", I got below buid errors due to implicit declaration of function 'IRQ_GPIO'. Use common gpio_to_irq() to replace machine dependant macro IRQ_GPIO(). CC drivers/input/touchscreen/zylonite-wm97xx.o drivers/input/touchscreen/zylonite-wm97xx.c: In function 'zylonite_wm97xx_probe': drivers/input/touchscreen/zylonite-wm97xx.c:195: error: implicit declaration of function 'IRQ_GPIO' make[3]: *** [drivers/input/touchscreen/zylonite-wm97xx.o] Error 1 make[2]: *** [drivers/input/touchscreen] Error 2 make[1]: *** [drivers/input] Error 2 make: *** [drivers] Error 2 Cc: Mark Brown Cc: Haojian Zhuang Signed-off-by: Axel Lin Signed-off-by: Arnd Bergmann --- drivers/input/touchscreen/zylonite-wm97xx.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/zylonite-wm97xx.c b/drivers/input/touchscreen/zylonite-wm97xx.c index f6328c0cded6..0a707bbbbea6 100644 --- a/drivers/input/touchscreen/zylonite-wm97xx.c +++ b/drivers/input/touchscreen/zylonite-wm97xx.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -192,8 +193,8 @@ static int zylonite_wm97xx_probe(struct platform_device *pdev) else gpio_touch_irq = mfp_to_gpio(MFP_PIN_GPIO26); - wm->pen_irq = IRQ_GPIO(gpio_touch_irq); - irq_set_irq_type(IRQ_GPIO(gpio_touch_irq), IRQ_TYPE_EDGE_BOTH); + wm->pen_irq = gpio_to_irq(gpio_touch_irq); + irq_set_irq_type(wm->pen_irq, IRQ_TYPE_EDGE_BOTH); wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN, WM97XX_GPIO_POL_HIGH, -- cgit v1.2.3-55-g7522 From 9d2d94385327f98ea69c183bb6c1d27cac49abf0 Mon Sep 17 00:00:00 2001 From: Jett.Zhou Date: Wed, 30 Nov 2011 14:29:44 +0800 Subject: RTC: sa1100: Clean out ost register These registers are used in old ioctl of UIE and PIE, now they are emulated by rtc generic code of hrtimer, so it can be removed. Signed-off-by: Jett.Zhou Acked-by: Haojian Zhuang Signed-off-by: Arnd Bergmann --- drivers/rtc/rtc-sa1100.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c index 0b40bb88a884..6f22c1fdff66 100644 --- a/drivers/rtc/rtc-sa1100.c +++ b/drivers/rtc/rtc-sa1100.c @@ -36,7 +36,6 @@ #ifdef CONFIG_ARCH_PXA #include -#include #endif #define RTC_DEF_DIVIDER (32768 - 1) @@ -188,8 +187,6 @@ static void sa1100_rtc_release(struct device *dev) { spin_lock_irq(&sa1100_rtc_lock); RTSR = 0; - OIER &= ~OIER_E1; - OSSR = OSSR_M1; spin_unlock_irq(&sa1100_rtc_lock); free_irq(IRQ_RTCAlrm, dev); -- cgit v1.2.3-55-g7522 From 42874759d7494648e42e6e0465fc9c4f3752bba4 Mon Sep 17 00:00:00 2001 From: Jett.Zhou Date: Wed, 30 Nov 2011 12:26:22 +0800 Subject: RTC: sa1100: remove redundant code of setting alarm In rtc generic interface of setting alarm, it will check the alarm time value valid or not, so rtc_periodic_alarm is redundant, remove it. Signed-off-by: Jett.Zhou Acked-by: Haojian Zhuang Signed-off-by: Arnd Bergmann --- drivers/rtc/rtc-sa1100.c | 53 +++++++++++------------------------------------- 1 file changed, 12 insertions(+), 41 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c index 6f22c1fdff66..d268cf11b367 100644 --- a/drivers/rtc/rtc-sa1100.c +++ b/drivers/rtc/rtc-sa1100.c @@ -45,16 +45,6 @@ static const unsigned long RTC_FREQ = 1024; static struct rtc_time rtc_alarm; static DEFINE_SPINLOCK(sa1100_rtc_lock); -static inline int rtc_periodic_alarm(struct rtc_time *tm) -{ - return (tm->tm_year == -1) || - ((unsigned)tm->tm_mon >= 12) || - ((unsigned)(tm->tm_mday - 1) >= 31) || - ((unsigned)tm->tm_hour > 23) || - ((unsigned)tm->tm_min > 59) || - ((unsigned)tm->tm_sec > 59); -} - /* * Calculate the next alarm time given the requested alarm time mask * and the current time. @@ -82,27 +72,6 @@ static void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now, } } -static int rtc_update_alarm(struct rtc_time *alrm) -{ - struct rtc_time alarm_tm, now_tm; - unsigned long now, time; - int ret; - - do { - now = RCNR; - rtc_time_to_tm(now, &now_tm); - rtc_next_alarm_time(&alarm_tm, &now_tm, alrm); - ret = rtc_tm_to_time(&alarm_tm, &time); - if (ret != 0) - break; - - RTSR = RTSR & (RTSR_HZE|RTSR_ALE|RTSR_AL); - RTAR = time; - } while (now != RCNR); - - return ret; -} - static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id) { struct platform_device *pdev = to_platform_device(dev_id); @@ -146,9 +115,6 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id) rtc_update_irq(rtc, 1, events); - if (rtsr & RTSR_AL && rtc_periodic_alarm(&rtc_alarm)) - rtc_update_alarm(&rtc_alarm); - spin_unlock(&sa1100_rtc_lock); return IRQ_HANDLED; @@ -234,16 +200,21 @@ static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) { + struct rtc_time now_tm, alarm_tm; int ret; spin_lock_irq(&sa1100_rtc_lock); - ret = rtc_update_alarm(&alrm->time); - if (ret == 0) { - if (alrm->enabled) - RTSR |= RTSR_ALE; - else - RTSR &= ~RTSR_ALE; - } + + now = RCNR; + rtc_time_to_tm(now, &now_tm); + rtc_next_alarm_time(&alarm_tm, &now_tm, alrm->time); + rtc_tm_to_time(&alarm_tm, &time); + RTAR = time; + if (alrm->enabled) + RTSR |= RTSR_ALE; + else + RTSR &= ~RTSR_ALE; + spin_unlock_irq(&sa1100_rtc_lock); return ret; -- cgit v1.2.3-55-g7522 From 7cea00657dd4daef66ad95e976d5d67ed94cb97e Mon Sep 17 00:00:00 2001 From: Jett.Zhou Date: Wed, 30 Nov 2011 12:26:23 +0800 Subject: RTC: sa1100: support sa1100, pxa and mmp soc families Since the regmap of rtc on sa1100, pxa and mmp Marvell soc families are almost the same, so re-arch the rtc-sa1100 to support them. Signed-off-by: Jett.Zhou Acked-by: Arnd Bergmann Acked-by: Haojian Zhuang Acked-by: Robert Jarzmik Signed-off-by: Arnd Bergmann --- arch/arm/mach-pxa/devices.c | 20 ++++ arch/arm/mach-sa1100/generic.c | 20 ++++ drivers/rtc/Kconfig | 2 +- drivers/rtc/rtc-sa1100.c | 256 ++++++++++++++++++++++++++++------------- 4 files changed, 218 insertions(+), 80 deletions(-) (limited to 'drivers') diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c index 2e0425404de5..8b134c3b457f 100644 --- a/arch/arm/mach-pxa/devices.c +++ b/arch/arm/mach-pxa/devices.c @@ -415,9 +415,29 @@ static struct resource pxa_rtc_resources[] = { }, }; +static struct resource sa1100_rtc_resources[] = { + [0] = { + .start = 0x40900000, + .end = 0x409000ff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_RTC1Hz, + .end = IRQ_RTC1Hz, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = IRQ_RTCAlrm, + .end = IRQ_RTCAlrm, + .flags = IORESOURCE_IRQ, + }, +}; + struct platform_device sa1100_device_rtc = { .name = "sa1100-rtc", .id = -1, + .num_resources = ARRAY_SIZE(sa1100_rtc_resources), + .resource = sa1100_rtc_resources, }; struct platform_device pxa_device_rtc = { diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c index 5fa5ae1f39e1..3eff179d4fd7 100644 --- a/arch/arm/mach-sa1100/generic.c +++ b/arch/arm/mach-sa1100/generic.c @@ -334,9 +334,29 @@ void sa11x0_register_irda(struct irda_platform_data *irda) sa11x0_register_device(&sa11x0ir_device, irda); } +static struct resource sa11x0rtc_resources[] = { + [0] = { + .start = 0x90010000, + .end = 0x900100ff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_RTC1Hz, + .end = IRQ_RTC1Hz, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = IRQ_RTCAlrm, + .end = IRQ_RTCAlrm, + .flags = IORESOURCE_IRQ, + }, +}; + static struct platform_device sa11x0rtc_device = { .name = "sa1100-rtc", .id = -1, + .resource = sa11x0rtc_resources, + .num_resources = ARRAY_SIZE(sa11x0rtc_resources), }; static struct platform_device *sa11x0_devices[] __initdata = { diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 53eb4e55b289..877cf6fdcf24 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -774,7 +774,7 @@ config RTC_DRV_EP93XX config RTC_DRV_SA1100 tristate "SA11x0/PXA2xx" - depends on ARCH_SA1100 || ARCH_PXA + depends on ARCH_SA1100 || ARCH_PXA || ARCH_MMP help If you say Y here you will get access to the real time clock built into your SA11x0 or PXA2xx CPU. diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c index d268cf11b367..fc1ffe97fca1 100644 --- a/drivers/rtc/rtc-sa1100.c +++ b/drivers/rtc/rtc-sa1100.c @@ -27,24 +27,42 @@ #include #include #include -#include #include -#include +#include +#include +#include #include #include -#ifdef CONFIG_ARCH_PXA -#include -#endif - #define RTC_DEF_DIVIDER (32768 - 1) #define RTC_DEF_TRIM 0 - -static const unsigned long RTC_FREQ = 1024; -static struct rtc_time rtc_alarm; -static DEFINE_SPINLOCK(sa1100_rtc_lock); - +#define RTC_FREQ 1024 + +#define RCNR 0x00 /* RTC Count Register */ +#define RTAR 0x04 /* RTC Alarm Register */ +#define RTSR 0x08 /* RTC Status Register */ +#define RTTR 0x0c /* RTC Timer Trim Register */ + +#define RTSR_HZE (1 << 3) /* HZ interrupt enable */ +#define RTSR_ALE (1 << 2) /* RTC alarm interrupt enable */ +#define RTSR_HZ (1 << 1) /* HZ rising-edge detected */ +#define RTSR_AL (1 << 0) /* RTC alarm detected */ + +#define rtc_readl(sa1100_rtc, reg) \ + readl_relaxed((sa1100_rtc)->base + (reg)) +#define rtc_writel(sa1100_rtc, reg, value) \ + writel_relaxed((value), (sa1100_rtc)->base + (reg)) + +struct sa1100_rtc { + struct resource *ress; + void __iomem *base; + struct clk *clk; + int irq_1Hz; + int irq_Alrm; + struct rtc_device *rtc; + spinlock_t lock; /* Protects this structure */ +}; /* * Calculate the next alarm time given the requested alarm time mask * and the current time. @@ -75,22 +93,23 @@ static void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now, static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id) { struct platform_device *pdev = to_platform_device(dev_id); - struct rtc_device *rtc = platform_get_drvdata(pdev); + struct sa1100_rtc *sa1100_rtc = platform_get_drvdata(pdev); unsigned int rtsr; unsigned long events = 0; - spin_lock(&sa1100_rtc_lock); + spin_lock(&sa1100_rtc->lock); - rtsr = RTSR; /* clear interrupt sources */ - RTSR = 0; + rtsr = rtc_readl(sa1100_rtc, RTSR); + rtc_writel(sa1100_rtc, RTSR, 0); + /* Fix for a nasty initialization problem the in SA11xx RTSR register. * See also the comments in sa1100_rtc_probe(). */ if (rtsr & (RTSR_ALE | RTSR_HZE)) { /* This is the original code, before there was the if test * above. This code does not clear interrupts that were not * enabled. */ - RTSR = (RTSR_AL | RTSR_HZ) & (rtsr >> 2); + rtc_writel(sa1100_rtc, RTSR, (RTSR_AL | RTSR_HZ) & (rtsr >> 2)); } else { /* For some reason, it is possible to enter this routine * without interruptions enabled, it has been tested with @@ -99,13 +118,13 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id) * This situation leads to an infinite "loop" of interrupt * routine calling and as a result the processor seems to * lock on its first call to open(). */ - RTSR = RTSR_AL | RTSR_HZ; + rtc_writel(sa1100_rtc, RTSR, (RTSR_AL | RTSR_HZ)); } /* clear alarm interrupt if it has occurred */ if (rtsr & RTSR_AL) rtsr &= ~RTSR_ALE; - RTSR = rtsr & (RTSR_ALE | RTSR_HZE); + rtc_writel(sa1100_rtc, RTSR, rtsr & (RTSR_ALE | RTSR_HZE)); /* update irq data & counter */ if (rtsr & RTSR_AL) @@ -113,86 +132,100 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id) if (rtsr & RTSR_HZ) events |= RTC_UF | RTC_IRQF; - rtc_update_irq(rtc, 1, events); + rtc_update_irq(sa1100_rtc->rtc, 1, events); - spin_unlock(&sa1100_rtc_lock); + spin_unlock(&sa1100_rtc->lock); return IRQ_HANDLED; } static int sa1100_rtc_open(struct device *dev) { + struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev); int ret; - struct platform_device *plat_dev = to_platform_device(dev); - struct rtc_device *rtc = platform_get_drvdata(plat_dev); - ret = request_irq(IRQ_RTC1Hz, sa1100_rtc_interrupt, IRQF_DISABLED, - "rtc 1Hz", dev); + ret = request_irq(sa1100_rtc->irq_1Hz, sa1100_rtc_interrupt, + IRQF_DISABLED, "rtc 1Hz", dev); if (ret) { - dev_err(dev, "IRQ %d already in use.\n", IRQ_RTC1Hz); + dev_err(dev, "IRQ %d already in use.\n", sa1100_rtc->irq_1Hz); goto fail_ui; } - ret = request_irq(IRQ_RTCAlrm, sa1100_rtc_interrupt, IRQF_DISABLED, - "rtc Alrm", dev); + ret = request_irq(sa1100_rtc->irq_Alrm, sa1100_rtc_interrupt, + IRQF_DISABLED, "rtc Alrm", dev); if (ret) { - dev_err(dev, "IRQ %d already in use.\n", IRQ_RTCAlrm); + dev_err(dev, "IRQ %d already in use.\n", sa1100_rtc->irq_Alrm); goto fail_ai; } - rtc->max_user_freq = RTC_FREQ; - rtc_irq_set_freq(rtc, NULL, RTC_FREQ); + sa1100_rtc->rtc->max_user_freq = RTC_FREQ; + rtc_irq_set_freq(sa1100_rtc->rtc, NULL, RTC_FREQ); return 0; fail_ai: - free_irq(IRQ_RTC1Hz, dev); + free_irq(sa1100_rtc->irq_1Hz, dev); fail_ui: return ret; } static void sa1100_rtc_release(struct device *dev) { - spin_lock_irq(&sa1100_rtc_lock); - RTSR = 0; - spin_unlock_irq(&sa1100_rtc_lock); + struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev); - free_irq(IRQ_RTCAlrm, dev); - free_irq(IRQ_RTC1Hz, dev); + spin_lock_irq(&sa1100_rtc->lock); + rtc_writel(sa1100_rtc, RTSR, 0); + spin_unlock_irq(&sa1100_rtc->lock); + + free_irq(sa1100_rtc->irq_Alrm, dev); + free_irq(sa1100_rtc->irq_1Hz, dev); } static int sa1100_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) { - spin_lock_irq(&sa1100_rtc_lock); + struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev); + unsigned int rtsr; + + spin_lock_irq(&sa1100_rtc->lock); + + rtsr = rtc_readl(sa1100_rtc, RTSR); if (enabled) - RTSR |= RTSR_ALE; + rtsr |= RTSR_ALE; else - RTSR &= ~RTSR_ALE; - spin_unlock_irq(&sa1100_rtc_lock); + rtsr &= ~RTSR_ALE; + rtc_writel(sa1100_rtc, RTSR, rtsr); + + spin_unlock_irq(&sa1100_rtc->lock); return 0; } static int sa1100_rtc_read_time(struct device *dev, struct rtc_time *tm) { - rtc_time_to_tm(RCNR, tm); + struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev); + + rtc_time_to_tm(rtc_readl(sa1100_rtc, RCNR), tm); return 0; } static int sa1100_rtc_set_time(struct device *dev, struct rtc_time *tm) { + struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev); unsigned long time; int ret; ret = rtc_tm_to_time(tm, &time); if (ret == 0) - RCNR = time; + rtc_writel(sa1100_rtc, RCNR, time); return ret; } static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) { - u32 rtsr; + struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev); + unsigned long time; + unsigned int rtsr; - memcpy(&alrm->time, &rtc_alarm, sizeof(struct rtc_time)); - rtsr = RTSR; + time = rtc_readl(sa1100_rtc, RCNR); + rtc_time_to_tm(time, &alrm->time); + rtsr = rtc_readl(sa1100_rtc, RTSR); alrm->enabled = (rtsr & RTSR_ALE) ? 1 : 0; alrm->pending = (rtsr & RTSR_AL) ? 1 : 0; return 0; @@ -200,31 +233,39 @@ static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) { + struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev); struct rtc_time now_tm, alarm_tm; - int ret; + unsigned long time, alarm; + unsigned int rtsr; + + spin_lock_irq(&sa1100_rtc->lock); - spin_lock_irq(&sa1100_rtc_lock); + time = rtc_readl(sa1100_rtc, RCNR); + rtc_time_to_tm(time, &now_tm); + rtc_next_alarm_time(&alarm_tm, &now_tm, &alrm->time); + rtc_tm_to_time(&alarm_tm, &alarm); + rtc_writel(sa1100_rtc, RTAR, alarm); - now = RCNR; - rtc_time_to_tm(now, &now_tm); - rtc_next_alarm_time(&alarm_tm, &now_tm, alrm->time); - rtc_tm_to_time(&alarm_tm, &time); - RTAR = time; + rtsr = rtc_readl(sa1100_rtc, RTSR); if (alrm->enabled) - RTSR |= RTSR_ALE; + rtsr |= RTSR_ALE; else - RTSR &= ~RTSR_ALE; + rtsr &= ~RTSR_ALE; + rtc_writel(sa1100_rtc, RTSR, rtsr); - spin_unlock_irq(&sa1100_rtc_lock); + spin_unlock_irq(&sa1100_rtc->lock); - return ret; + return 0; } static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq) { - seq_printf(seq, "trim/divider\t\t: 0x%08x\n", (u32) RTTR); - seq_printf(seq, "RTSR\t\t\t: 0x%08x\n", (u32)RTSR); + struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev); + seq_printf(seq, "trim/divider\t\t: 0x%08x\n", + rtc_readl(sa1100_rtc, RTTR)); + seq_printf(seq, "RTSR\t\t\t: 0x%08x\n", + rtc_readl(sa1100_rtc, RTSR)); return 0; } @@ -241,7 +282,51 @@ static const struct rtc_class_ops sa1100_rtc_ops = { static int sa1100_rtc_probe(struct platform_device *pdev) { - struct rtc_device *rtc; + struct sa1100_rtc *sa1100_rtc; + unsigned int rttr; + int ret; + + sa1100_rtc = kzalloc(sizeof(struct sa1100_rtc), GFP_KERNEL); + if (!sa1100_rtc) + return -ENOMEM; + + spin_lock_init(&sa1100_rtc->lock); + platform_set_drvdata(pdev, sa1100_rtc); + + ret = -ENXIO; + sa1100_rtc->ress = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!sa1100_rtc->ress) { + dev_err(&pdev->dev, "No I/O memory resource defined\n"); + goto err_ress; + } + + sa1100_rtc->irq_1Hz = platform_get_irq(pdev, 0); + if (sa1100_rtc->irq_1Hz < 0) { + dev_err(&pdev->dev, "No 1Hz IRQ resource defined\n"); + goto err_ress; + } + sa1100_rtc->irq_Alrm = platform_get_irq(pdev, 1); + if (sa1100_rtc->irq_Alrm < 0) { + dev_err(&pdev->dev, "No alarm IRQ resource defined\n"); + goto err_ress; + } + + ret = -ENOMEM; + sa1100_rtc->base = ioremap(sa1100_rtc->ress->start, + resource_size(sa1100_rtc->ress)); + if (!sa1100_rtc->base) { + dev_err(&pdev->dev, "Unable to map pxa RTC I/O memory\n"); + goto err_map; + } + + sa1100_rtc->clk = clk_get(&pdev->dev, NULL); + if (IS_ERR(sa1100_rtc->clk)) { + dev_err(&pdev->dev, "failed to find rtc clock source\n"); + ret = PTR_ERR(sa1100_rtc->clk); + goto err_clk; + } + clk_prepare(sa1100_rtc->clk); + clk_enable(sa1100_rtc->clk); /* * According to the manual we should be able to let RTTR be zero @@ -250,24 +335,24 @@ static int sa1100_rtc_probe(struct platform_device *pdev) * If the clock divider is uninitialized then reset it to the * default value to get the 1Hz clock. */ - if (RTTR == 0) { - RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16); - dev_warn(&pdev->dev, "warning: " - "initializing default clock divider/trim value\n"); + if (rtc_readl(sa1100_rtc, RTTR) == 0) { + rttr = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16); + rtc_writel(sa1100_rtc, RTTR, rttr); + dev_warn(&pdev->dev, "warning: initializing default clock" + " divider/trim value\n"); /* The current RTC value probably doesn't make sense either */ - RCNR = 0; + rtc_writel(sa1100_rtc, RCNR, 0); } device_init_wakeup(&pdev->dev, 1); - rtc = rtc_device_register(pdev->name, &pdev->dev, &sa1100_rtc_ops, - THIS_MODULE); - - if (IS_ERR(rtc)) - return PTR_ERR(rtc); - - platform_set_drvdata(pdev, rtc); - + sa1100_rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, + &sa1100_rtc_ops, THIS_MODULE); + if (IS_ERR(sa1100_rtc->rtc)) { + dev_err(&pdev->dev, "Failed to register RTC device -> %d\n", + ret); + goto err_rtc_reg; + } /* Fix for a nasty initialization problem the in SA11xx RTSR register. * See also the comments in sa1100_rtc_interrupt(). * @@ -290,33 +375,46 @@ static int sa1100_rtc_probe(struct platform_device *pdev) * * Notice that clearing bit 1 and 0 is accomplished by writting ONES to * the corresponding bits in RTSR. */ - RTSR = RTSR_AL | RTSR_HZ; + rtc_writel(sa1100_rtc, RTSR, (RTSR_AL | RTSR_HZ)); return 0; + +err_rtc_reg: +err_clk: + iounmap(sa1100_rtc->base); +err_ress: +err_map: + kfree(sa1100_rtc); + return ret; } static int sa1100_rtc_remove(struct platform_device *pdev) { - struct rtc_device *rtc = platform_get_drvdata(pdev); - - if (rtc) - rtc_device_unregister(rtc); + struct sa1100_rtc *sa1100_rtc = platform_get_drvdata(pdev); + rtc_device_unregister(sa1100_rtc->rtc); + clk_disable(sa1100_rtc->clk); + clk_unprepare(sa1100_rtc->clk); + iounmap(sa1100_rtc->base); return 0; } #ifdef CONFIG_PM static int sa1100_rtc_suspend(struct device *dev) { + struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev); + if (device_may_wakeup(dev)) - enable_irq_wake(IRQ_RTCAlrm); + enable_irq_wake(sa1100_rtc->irq_Alrm); return 0; } static int sa1100_rtc_resume(struct device *dev) { + struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev); + if (device_may_wakeup(dev)) - disable_irq_wake(IRQ_RTCAlrm); + disable_irq_wake(sa1100_rtc->irq_Alrm); return 0; } -- cgit v1.2.3-55-g7522