diff options
| -rw-r--r-- | arch/arm/mach-pxa/Kconfig | 7 | ||||
| -rw-r--r-- | arch/arm/mach-pxa/Makefile | 5 | ||||
| -rw-r--r-- | arch/arm/mach-pxa/corgi_ssp.c | 2 | ||||
| -rw-r--r-- | arch/arm/mach-pxa/ssp.c | 128 | ||||
| -rw-r--r-- | include/asm-arm/arch-pxa/ssp.h | 8 |
5 files changed, 58 insertions, 92 deletions
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index b380a438e68f..e201aa9765b9 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig | |||
| @@ -60,6 +60,7 @@ config MACH_CORGI | |||
| 60 | bool "Enable Sharp SL-C700 (Corgi) Support" | 60 | bool "Enable Sharp SL-C700 (Corgi) Support" |
| 61 | depends PXA_SHARPSL_25x | 61 | depends PXA_SHARPSL_25x |
| 62 | select PXA_SHARP_C7xx | 62 | select PXA_SHARP_C7xx |
| 63 | select PXA_SSP | ||
| 63 | 64 | ||
| 64 | config MACH_SHEPHERD | 65 | config MACH_SHEPHERD |
| 65 | bool "Enable Sharp SL-C750 (Shepherd) Support" | 66 | bool "Enable Sharp SL-C750 (Shepherd) Support" |
| @@ -102,12 +103,18 @@ config IWMMXT | |||
| 102 | 103 | ||
| 103 | config PXA_SHARP_C7xx | 104 | config PXA_SHARP_C7xx |
| 104 | bool | 105 | bool |
| 106 | select PXA_SSP | ||
| 105 | help | 107 | help |
| 106 | Enable support for all Sharp C7xx models | 108 | Enable support for all Sharp C7xx models |
| 107 | 109 | ||
| 108 | config PXA_SHARP_Cxx00 | 110 | config PXA_SHARP_Cxx00 |
| 109 | bool | 111 | bool |
| 112 | select PXA_SSP | ||
| 110 | help | 113 | help |
| 111 | Enable common support for Sharp Cxx00 models | 114 | Enable common support for Sharp Cxx00 models |
| 112 | 115 | ||
| 116 | config PXA_SSP | ||
| 117 | tristate | ||
| 118 | help | ||
| 119 | Enable support for PXA2xx SSP ports | ||
| 113 | endif | 120 | endif |
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index 8bc72d07cea8..d210bd5032ce 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile | |||
| @@ -11,8 +11,8 @@ obj-$(CONFIG_PXA27x) += pxa27x.o | |||
| 11 | obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o | 11 | obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o |
| 12 | obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o | 12 | obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o |
| 13 | obj-$(CONFIG_ARCH_PXA_IDP) += idp.o | 13 | obj-$(CONFIG_ARCH_PXA_IDP) += idp.o |
| 14 | obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o corgi_ssp.o corgi_lcd.o ssp.o | 14 | obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o corgi_ssp.o corgi_lcd.o |
| 15 | obj-$(CONFIG_PXA_SHARP_Cxx00) += spitz.o corgi_ssp.o corgi_lcd.o ssp.o | 15 | obj-$(CONFIG_PXA_SHARP_Cxx00) += spitz.o corgi_ssp.o corgi_lcd.o |
| 16 | obj-$(CONFIG_MACH_POODLE) += poodle.o | 16 | obj-$(CONFIG_MACH_POODLE) += poodle.o |
| 17 | obj-$(CONFIG_MACH_TOSA) += tosa.o | 17 | obj-$(CONFIG_MACH_TOSA) += tosa.o |
| 18 | 18 | ||
| @@ -26,6 +26,7 @@ obj-$(CONFIG_LEDS) += $(led-y) | |||
| 26 | 26 | ||
| 27 | # Misc features | 27 | # Misc features |
| 28 | obj-$(CONFIG_PM) += pm.o sleep.o | 28 | obj-$(CONFIG_PM) += pm.o sleep.o |
| 29 | obj-$(CONFIG_PXA_SSP) += ssp.o | ||
| 29 | 30 | ||
| 30 | ifeq ($(CONFIG_PXA27x),y) | 31 | ifeq ($(CONFIG_PXA27x),y) |
| 31 | obj-$(CONFIG_PM) += standby.o | 32 | obj-$(CONFIG_PM) += standby.o |
diff --git a/arch/arm/mach-pxa/corgi_ssp.c b/arch/arm/mach-pxa/corgi_ssp.c index 591e5f32dbec..bdf10cfa9440 100644 --- a/arch/arm/mach-pxa/corgi_ssp.c +++ b/arch/arm/mach-pxa/corgi_ssp.c | |||
| @@ -203,7 +203,7 @@ static int __init corgi_ssp_probe(struct device *dev) | |||
| 203 | GPDR(ssp_machinfo->cs_ads7846) |= GPIO_bit(ssp_machinfo->cs_ads7846); /* output */ | 203 | GPDR(ssp_machinfo->cs_ads7846) |= GPIO_bit(ssp_machinfo->cs_ads7846); /* output */ |
| 204 | GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); /* High - Disable ADS7846*/ | 204 | GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); /* High - Disable ADS7846*/ |
| 205 | 205 | ||
| 206 | ret = ssp_init(&corgi_ssp_dev,ssp_machinfo->port); | 206 | ret = ssp_init(&corgi_ssp_dev, ssp_machinfo->port, 0); |
| 207 | 207 | ||
| 208 | if (ret) | 208 | if (ret) |
| 209 | printk(KERN_ERR "Unable to register SSP handler!\n"); | 209 | printk(KERN_ERR "Unable to register SSP handler!\n"); |
diff --git a/arch/arm/mach-pxa/ssp.c b/arch/arm/mach-pxa/ssp.c index 4d826c021315..a68b30eff4d2 100644 --- a/arch/arm/mach-pxa/ssp.c +++ b/arch/arm/mach-pxa/ssp.c | |||
| @@ -19,6 +19,8 @@ | |||
| 19 | * 22nd Aug 2003 Initial version. | 19 | * 22nd Aug 2003 Initial version. |
| 20 | * 20th Dec 2004 Added ssp_config for changing port config without | 20 | * 20th Dec 2004 Added ssp_config for changing port config without |
| 21 | * closing the port. | 21 | * closing the port. |
| 22 | * 4th Aug 2005 Added option to disable irq handler registration and | ||
| 23 | * cleaned up irq and clock detection. | ||
| 22 | */ | 24 | */ |
| 23 | 25 | ||
| 24 | #include <linux/module.h> | 26 | #include <linux/module.h> |
| @@ -37,6 +39,26 @@ | |||
| 37 | 39 | ||
| 38 | #define PXA_SSP_PORTS 3 | 40 | #define PXA_SSP_PORTS 3 |
| 39 | 41 | ||
| 42 | struct ssp_info_ { | ||
| 43 | int irq; | ||
| 44 | u32 clock; | ||
| 45 | }; | ||
| 46 | |||
| 47 | /* | ||
| 48 | * SSP port clock and IRQ settings | ||
| 49 | */ | ||
| 50 | static const struct ssp_info_ ssp_info[PXA_SSP_PORTS] = { | ||
| 51 | #if defined (CONFIG_PXA27x) | ||
| 52 | {IRQ_SSP, CKEN23_SSP1}, | ||
| 53 | {IRQ_SSP2, CKEN3_SSP2}, | ||
| 54 | {IRQ_SSP3, CKEN4_SSP3}, | ||
| 55 | #else | ||
| 56 | {IRQ_SSP, CKEN3_SSP}, | ||
| 57 | {IRQ_NSSP, CKEN9_NSSP}, | ||
| 58 | {IRQ_ASSP, CKEN10_ASSP}, | ||
| 59 | #endif | ||
| 60 | }; | ||
| 61 | |||
| 40 | static DECLARE_MUTEX(sem); | 62 | static DECLARE_MUTEX(sem); |
| 41 | static int use_count[PXA_SSP_PORTS] = {0, 0, 0}; | 63 | static int use_count[PXA_SSP_PORTS] = {0, 0, 0}; |
| 42 | 64 | ||
| @@ -210,9 +232,9 @@ int ssp_config(struct ssp_dev *dev, u32 mode, u32 flags, u32 psp_flags, u32 spee | |||
| 210 | * %-EBUSY if the resources are already in use | 232 | * %-EBUSY if the resources are already in use |
| 211 | * %0 on success | 233 | * %0 on success |
| 212 | */ | 234 | */ |
| 213 | int ssp_init(struct ssp_dev *dev, u32 port) | 235 | int ssp_init(struct ssp_dev *dev, u32 port, u32 init_flags) |
| 214 | { | 236 | { |
| 215 | int ret, irq; | 237 | int ret; |
| 216 | 238 | ||
| 217 | if (port > PXA_SSP_PORTS || port == 0) | 239 | if (port > PXA_SSP_PORTS || port == 0) |
| 218 | return -ENODEV; | 240 | return -ENODEV; |
| @@ -229,61 +251,20 @@ int ssp_init(struct ssp_dev *dev, u32 port) | |||
| 229 | up(&sem); | 251 | up(&sem); |
| 230 | return -EBUSY; | 252 | return -EBUSY; |
| 231 | } | 253 | } |
| 232 | |||
| 233 | switch (port) { | ||
| 234 | case 1: | ||
| 235 | irq = IRQ_SSP; | ||
| 236 | break; | ||
| 237 | #if defined (CONFIG_PXA27x) | ||
| 238 | case 2: | ||
| 239 | irq = IRQ_SSP2; | ||
| 240 | break; | ||
| 241 | case 3: | ||
| 242 | irq = IRQ_SSP3; | ||
| 243 | break; | ||
| 244 | #else | ||
| 245 | case 2: | ||
| 246 | irq = IRQ_NSSP; | ||
| 247 | break; | ||
| 248 | case 3: | ||
| 249 | irq = IRQ_ASSP; | ||
| 250 | break; | ||
| 251 | #endif | ||
| 252 | default: | ||
| 253 | return -ENODEV; | ||
| 254 | } | ||
| 255 | |||
| 256 | dev->port = port; | 254 | dev->port = port; |
| 257 | 255 | ||
| 258 | ret = request_irq(irq, ssp_interrupt, 0, "SSP", dev); | 256 | /* do we need to get irq */ |
| 259 | if (ret) | 257 | if (!(init_flags & SSP_NO_IRQ)) { |
| 260 | goto out_region; | 258 | ret = request_irq(ssp_info[port-1].irq, ssp_interrupt, |
| 259 | 0, "SSP", dev); | ||
| 260 | if (ret) | ||
| 261 | goto out_region; | ||
| 262 | dev->irq = ssp_info[port-1].irq; | ||
| 263 | } else | ||
| 264 | dev->irq = 0; | ||
| 261 | 265 | ||
| 262 | /* turn on SSP port clock */ | 266 | /* turn on SSP port clock */ |
| 263 | switch (dev->port) { | 267 | pxa_set_cken(ssp_info[port-1].clock, 1); |
| 264 | #if defined (CONFIG_PXA27x) | ||
| 265 | case 1: | ||
| 266 | pxa_set_cken(CKEN23_SSP1, 1); | ||
| 267 | break; | ||
| 268 | case 2: | ||
| 269 | pxa_set_cken(CKEN3_SSP2, 1); | ||
| 270 | break; | ||
| 271 | case 3: | ||
| 272 | pxa_set_cken(CKEN4_SSP3, 1); | ||
| 273 | break; | ||
| 274 | #else | ||
| 275 | case 1: | ||
| 276 | pxa_set_cken(CKEN3_SSP, 1); | ||
| 277 | break; | ||
| 278 | case 2: | ||
| 279 | pxa_set_cken(CKEN9_NSSP, 1); | ||
| 280 | break; | ||
| 281 | case 3: | ||
| 282 | pxa_set_cken(CKEN10_ASSP, 1); | ||
| 283 | break; | ||
| 284 | #endif | ||
| 285 | } | ||
| 286 | |||
| 287 | up(&sem); | 268 | up(&sem); |
| 288 | return 0; | 269 | return 0; |
| 289 | 270 | ||
| @@ -301,46 +282,17 @@ out_region: | |||
| 301 | */ | 282 | */ |
| 302 | void ssp_exit(struct ssp_dev *dev) | 283 | void ssp_exit(struct ssp_dev *dev) |
| 303 | { | 284 | { |
| 304 | int irq; | ||
| 305 | |||
| 306 | down(&sem); | 285 | down(&sem); |
| 307 | SSCR0_P(dev->port) &= ~SSCR0_SSE; | 286 | SSCR0_P(dev->port) &= ~SSCR0_SSE; |
| 308 | 287 | ||
| 309 | /* find irq, save power and turn off SSP port clock */ | 288 | if (dev->port > PXA_SSP_PORTS || dev->port == 0) { |
| 310 | switch (dev->port) { | 289 | printk(KERN_WARNING "SSP: tried to close invalid port\n"); |
| 311 | #if defined (CONFIG_PXA27x) | 290 | return; |
| 312 | case 1: | ||
| 313 | irq = IRQ_SSP; | ||
| 314 | pxa_set_cken(CKEN23_SSP1, 0); | ||
| 315 | break; | ||
| 316 | case 2: | ||
| 317 | irq = IRQ_SSP2; | ||
| 318 | pxa_set_cken(CKEN3_SSP2, 0); | ||
| 319 | break; | ||
| 320 | case 3: | ||
| 321 | irq = IRQ_SSP3; | ||
| 322 | pxa_set_cken(CKEN4_SSP3, 0); | ||
| 323 | break; | ||
| 324 | #else | ||
| 325 | case 1: | ||
| 326 | irq = IRQ_SSP; | ||
| 327 | pxa_set_cken(CKEN3_SSP, 0); | ||
| 328 | break; | ||
| 329 | case 2: | ||
| 330 | irq = IRQ_NSSP; | ||
| 331 | pxa_set_cken(CKEN9_NSSP, 0); | ||
| 332 | break; | ||
| 333 | case 3: | ||
| 334 | irq = IRQ_ASSP; | ||
| 335 | pxa_set_cken(CKEN10_ASSP, 0); | ||
| 336 | break; | ||
| 337 | #endif | ||
| 338 | default: | ||
| 339 | printk(KERN_WARNING "SSP: tried to close invalid port\n"); | ||
| 340 | return; | ||
| 341 | } | 291 | } |
| 342 | 292 | ||
| 343 | free_irq(irq, dev); | 293 | pxa_set_cken(ssp_info[dev->port-1].clock, 0); |
| 294 | if (dev->irq) | ||
| 295 | free_irq(dev->irq, dev); | ||
| 344 | release_mem_region(__PREG(SSCR0_P(dev->port)), 0x2c); | 296 | release_mem_region(__PREG(SSCR0_P(dev->port)), 0x2c); |
| 345 | use_count[dev->port - 1]--; | 297 | use_count[dev->port - 1]--; |
| 346 | up(&sem); | 298 | up(&sem); |
diff --git a/include/asm-arm/arch-pxa/ssp.h b/include/asm-arm/arch-pxa/ssp.h index 6ec67b018c09..949878c0d908 100644 --- a/include/asm-arm/arch-pxa/ssp.h +++ b/include/asm-arm/arch-pxa/ssp.h | |||
| @@ -18,6 +18,11 @@ | |||
| 18 | #ifndef SSP_H | 18 | #ifndef SSP_H |
| 19 | #define SSP_H | 19 | #define SSP_H |
| 20 | 20 | ||
| 21 | /* | ||
| 22 | * SSP initialisation flags | ||
| 23 | */ | ||
| 24 | #define SSP_NO_IRQ 0x1 /* don't register an irq handler in SSP driver */ | ||
| 25 | |||
| 21 | struct ssp_state { | 26 | struct ssp_state { |
| 22 | u32 cr0; | 27 | u32 cr0; |
| 23 | u32 cr1; | 28 | u32 cr1; |
| @@ -31,6 +36,7 @@ struct ssp_dev { | |||
| 31 | u32 flags; | 36 | u32 flags; |
| 32 | u32 psp_flags; | 37 | u32 psp_flags; |
| 33 | u32 speed; | 38 | u32 speed; |
| 39 | int irq; | ||
| 34 | }; | 40 | }; |
| 35 | 41 | ||
| 36 | int ssp_write_word(struct ssp_dev *dev, u32 data); | 42 | int ssp_write_word(struct ssp_dev *dev, u32 data); |
| @@ -40,7 +46,7 @@ void ssp_enable(struct ssp_dev *dev); | |||
| 40 | void ssp_disable(struct ssp_dev *dev); | 46 | void ssp_disable(struct ssp_dev *dev); |
| 41 | void ssp_save_state(struct ssp_dev *dev, struct ssp_state *ssp); | 47 | void ssp_save_state(struct ssp_dev *dev, struct ssp_state *ssp); |
| 42 | void ssp_restore_state(struct ssp_dev *dev, struct ssp_state *ssp); | 48 | void ssp_restore_state(struct ssp_dev *dev, struct ssp_state *ssp); |
| 43 | int ssp_init(struct ssp_dev *dev, u32 port); | 49 | int ssp_init(struct ssp_dev *dev, u32 port, u32 init_flags); |
| 44 | int ssp_config(struct ssp_dev *dev, u32 mode, u32 flags, u32 psp_flags, u32 speed); | 50 | int ssp_config(struct ssp_dev *dev, u32 mode, u32 flags, u32 psp_flags, u32 speed); |
| 45 | void ssp_exit(struct ssp_dev *dev); | 51 | void ssp_exit(struct ssp_dev *dev); |
| 46 | 52 | ||
