diff options
Diffstat (limited to 'arch/arm/common')
-rw-r--r-- | arch/arm/common/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/common/dmabounce.c | 2 | ||||
-rw-r--r-- | arch/arm/common/locomo.c | 72 | ||||
-rw-r--r-- | arch/arm/common/rtctime.c | 108 | ||||
-rw-r--r-- | arch/arm/common/sa1111.c | 48 | ||||
-rw-r--r-- | arch/arm/common/scoop.c | 6 | ||||
-rw-r--r-- | arch/arm/common/sharpsl_pm.c | 10 | ||||
-rw-r--r-- | arch/arm/common/uengine.c | 473 | ||||
-rw-r--r-- | arch/arm/common/vic.c | 49 |
9 files changed, 594 insertions, 175 deletions
diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile index c81a2ff6b5be..847e3e6356c6 100644 --- a/arch/arm/common/Makefile +++ b/arch/arm/common/Makefile | |||
@@ -15,3 +15,4 @@ obj-$(CONFIG_SHARP_LOCOMO) += locomo.o | |||
15 | obj-$(CONFIG_SHARP_PARAM) += sharpsl_param.o | 15 | obj-$(CONFIG_SHARP_PARAM) += sharpsl_param.o |
16 | obj-$(CONFIG_SHARPSL_PM) += sharpsl_pm.o | 16 | obj-$(CONFIG_SHARPSL_PM) += sharpsl_pm.o |
17 | obj-$(CONFIG_SHARP_SCOOP) += scoop.o | 17 | obj-$(CONFIG_SHARP_SCOOP) += scoop.o |
18 | obj-$(CONFIG_ARCH_IXP2000) += uengine.o | ||
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c index ad6c89a555bb..7971d0dc6892 100644 --- a/arch/arm/common/dmabounce.c +++ b/arch/arm/common/dmabounce.c | |||
@@ -5,7 +5,7 @@ | |||
5 | * limited DMA windows. These functions utilize bounce buffers to | 5 | * limited DMA windows. These functions utilize bounce buffers to |
6 | * copy data to/from buffers located outside the DMA region. This | 6 | * copy data to/from buffers located outside the DMA region. This |
7 | * only works for systems in which DMA memory is at the bottom of | 7 | * only works for systems in which DMA memory is at the bottom of |
8 | * RAM and the remainder of memory is at the top an the DMA memory | 8 | * RAM, the remainder of memory is at the top and the DMA memory |
9 | * can be marked as ZONE_DMA. Anything beyond that such as discontigous | 9 | * can be marked as ZONE_DMA. Anything beyond that such as discontigous |
10 | * DMA windows will require custom implementations that reserve memory | 10 | * DMA windows will require custom implementations that reserve memory |
11 | * areas at early bootup. | 11 | * areas at early bootup. |
diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c index 159ad7ed7a40..a7dc1370695b 100644 --- a/arch/arm/common/locomo.c +++ b/arch/arm/common/locomo.c | |||
@@ -60,7 +60,7 @@ struct locomo { | |||
60 | unsigned long phys; | 60 | unsigned long phys; |
61 | unsigned int irq; | 61 | unsigned int irq; |
62 | spinlock_t lock; | 62 | spinlock_t lock; |
63 | void *base; | 63 | void __iomem *base; |
64 | }; | 64 | }; |
65 | 65 | ||
66 | struct locomo_dev_info { | 66 | struct locomo_dev_info { |
@@ -162,7 +162,7 @@ static void locomo_handler(unsigned int irq, struct irqdesc *desc, | |||
162 | { | 162 | { |
163 | int req, i; | 163 | int req, i; |
164 | struct irqdesc *d; | 164 | struct irqdesc *d; |
165 | void *mapbase = get_irq_chipdata(irq); | 165 | void __iomem *mapbase = get_irq_chipdata(irq); |
166 | 166 | ||
167 | /* Acknowledge the parent IRQ */ | 167 | /* Acknowledge the parent IRQ */ |
168 | desc->chip->ack(irq); | 168 | desc->chip->ack(irq); |
@@ -189,7 +189,7 @@ static void locomo_ack_irq(unsigned int irq) | |||
189 | 189 | ||
190 | static void locomo_mask_irq(unsigned int irq) | 190 | static void locomo_mask_irq(unsigned int irq) |
191 | { | 191 | { |
192 | void *mapbase = get_irq_chipdata(irq); | 192 | void __iomem *mapbase = get_irq_chipdata(irq); |
193 | unsigned int r; | 193 | unsigned int r; |
194 | r = locomo_readl(mapbase + LOCOMO_ICR); | 194 | r = locomo_readl(mapbase + LOCOMO_ICR); |
195 | r &= ~(0x0010 << (irq - LOCOMO_IRQ_START)); | 195 | r &= ~(0x0010 << (irq - LOCOMO_IRQ_START)); |
@@ -198,7 +198,7 @@ static void locomo_mask_irq(unsigned int irq) | |||
198 | 198 | ||
199 | static void locomo_unmask_irq(unsigned int irq) | 199 | static void locomo_unmask_irq(unsigned int irq) |
200 | { | 200 | { |
201 | void *mapbase = get_irq_chipdata(irq); | 201 | void __iomem *mapbase = get_irq_chipdata(irq); |
202 | unsigned int r; | 202 | unsigned int r; |
203 | r = locomo_readl(mapbase + LOCOMO_ICR); | 203 | r = locomo_readl(mapbase + LOCOMO_ICR); |
204 | r |= (0x0010 << (irq - LOCOMO_IRQ_START)); | 204 | r |= (0x0010 << (irq - LOCOMO_IRQ_START)); |
@@ -215,7 +215,7 @@ static void locomo_key_handler(unsigned int irq, struct irqdesc *desc, | |||
215 | struct pt_regs *regs) | 215 | struct pt_regs *regs) |
216 | { | 216 | { |
217 | struct irqdesc *d; | 217 | struct irqdesc *d; |
218 | void *mapbase = get_irq_chipdata(irq); | 218 | void __iomem *mapbase = get_irq_chipdata(irq); |
219 | 219 | ||
220 | if (locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC) & 0x0001) { | 220 | if (locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC) & 0x0001) { |
221 | d = irq_desc + LOCOMO_IRQ_KEY_START; | 221 | d = irq_desc + LOCOMO_IRQ_KEY_START; |
@@ -225,7 +225,7 @@ static void locomo_key_handler(unsigned int irq, struct irqdesc *desc, | |||
225 | 225 | ||
226 | static void locomo_key_ack_irq(unsigned int irq) | 226 | static void locomo_key_ack_irq(unsigned int irq) |
227 | { | 227 | { |
228 | void *mapbase = get_irq_chipdata(irq); | 228 | void __iomem *mapbase = get_irq_chipdata(irq); |
229 | unsigned int r; | 229 | unsigned int r; |
230 | r = locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC); | 230 | r = locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC); |
231 | r &= ~(0x0100 << (irq - LOCOMO_IRQ_KEY_START)); | 231 | r &= ~(0x0100 << (irq - LOCOMO_IRQ_KEY_START)); |
@@ -234,7 +234,7 @@ static void locomo_key_ack_irq(unsigned int irq) | |||
234 | 234 | ||
235 | static void locomo_key_mask_irq(unsigned int irq) | 235 | static void locomo_key_mask_irq(unsigned int irq) |
236 | { | 236 | { |
237 | void *mapbase = get_irq_chipdata(irq); | 237 | void __iomem *mapbase = get_irq_chipdata(irq); |
238 | unsigned int r; | 238 | unsigned int r; |
239 | r = locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC); | 239 | r = locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC); |
240 | r &= ~(0x0010 << (irq - LOCOMO_IRQ_KEY_START)); | 240 | r &= ~(0x0010 << (irq - LOCOMO_IRQ_KEY_START)); |
@@ -243,7 +243,7 @@ static void locomo_key_mask_irq(unsigned int irq) | |||
243 | 243 | ||
244 | static void locomo_key_unmask_irq(unsigned int irq) | 244 | static void locomo_key_unmask_irq(unsigned int irq) |
245 | { | 245 | { |
246 | void *mapbase = get_irq_chipdata(irq); | 246 | void __iomem *mapbase = get_irq_chipdata(irq); |
247 | unsigned int r; | 247 | unsigned int r; |
248 | r = locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC); | 248 | r = locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC); |
249 | r |= (0x0010 << (irq - LOCOMO_IRQ_KEY_START)); | 249 | r |= (0x0010 << (irq - LOCOMO_IRQ_KEY_START)); |
@@ -261,7 +261,7 @@ static void locomo_gpio_handler(unsigned int irq, struct irqdesc *desc, | |||
261 | { | 261 | { |
262 | int req, i; | 262 | int req, i; |
263 | struct irqdesc *d; | 263 | struct irqdesc *d; |
264 | void *mapbase = get_irq_chipdata(irq); | 264 | void __iomem *mapbase = get_irq_chipdata(irq); |
265 | 265 | ||
266 | req = locomo_readl(mapbase + LOCOMO_GIR) & | 266 | req = locomo_readl(mapbase + LOCOMO_GIR) & |
267 | locomo_readl(mapbase + LOCOMO_GPD) & | 267 | locomo_readl(mapbase + LOCOMO_GPD) & |
@@ -280,7 +280,7 @@ static void locomo_gpio_handler(unsigned int irq, struct irqdesc *desc, | |||
280 | 280 | ||
281 | static void locomo_gpio_ack_irq(unsigned int irq) | 281 | static void locomo_gpio_ack_irq(unsigned int irq) |
282 | { | 282 | { |
283 | void *mapbase = get_irq_chipdata(irq); | 283 | void __iomem *mapbase = get_irq_chipdata(irq); |
284 | unsigned int r; | 284 | unsigned int r; |
285 | r = locomo_readl(mapbase + LOCOMO_GWE); | 285 | r = locomo_readl(mapbase + LOCOMO_GWE); |
286 | r |= (0x0001 << (irq - LOCOMO_IRQ_GPIO_START)); | 286 | r |= (0x0001 << (irq - LOCOMO_IRQ_GPIO_START)); |
@@ -297,7 +297,7 @@ static void locomo_gpio_ack_irq(unsigned int irq) | |||
297 | 297 | ||
298 | static void locomo_gpio_mask_irq(unsigned int irq) | 298 | static void locomo_gpio_mask_irq(unsigned int irq) |
299 | { | 299 | { |
300 | void *mapbase = get_irq_chipdata(irq); | 300 | void __iomem *mapbase = get_irq_chipdata(irq); |
301 | unsigned int r; | 301 | unsigned int r; |
302 | r = locomo_readl(mapbase + LOCOMO_GIE); | 302 | r = locomo_readl(mapbase + LOCOMO_GIE); |
303 | r &= ~(0x0001 << (irq - LOCOMO_IRQ_GPIO_START)); | 303 | r &= ~(0x0001 << (irq - LOCOMO_IRQ_GPIO_START)); |
@@ -306,7 +306,7 @@ static void locomo_gpio_mask_irq(unsigned int irq) | |||
306 | 306 | ||
307 | static void locomo_gpio_unmask_irq(unsigned int irq) | 307 | static void locomo_gpio_unmask_irq(unsigned int irq) |
308 | { | 308 | { |
309 | void *mapbase = get_irq_chipdata(irq); | 309 | void __iomem *mapbase = get_irq_chipdata(irq); |
310 | unsigned int r; | 310 | unsigned int r; |
311 | r = locomo_readl(mapbase + LOCOMO_GIE); | 311 | r = locomo_readl(mapbase + LOCOMO_GIE); |
312 | r |= (0x0001 << (irq - LOCOMO_IRQ_GPIO_START)); | 312 | r |= (0x0001 << (irq - LOCOMO_IRQ_GPIO_START)); |
@@ -323,7 +323,7 @@ static void locomo_lt_handler(unsigned int irq, struct irqdesc *desc, | |||
323 | struct pt_regs *regs) | 323 | struct pt_regs *regs) |
324 | { | 324 | { |
325 | struct irqdesc *d; | 325 | struct irqdesc *d; |
326 | void *mapbase = get_irq_chipdata(irq); | 326 | void __iomem *mapbase = get_irq_chipdata(irq); |
327 | 327 | ||
328 | if (locomo_readl(mapbase + LOCOMO_LTINT) & 0x0001) { | 328 | if (locomo_readl(mapbase + LOCOMO_LTINT) & 0x0001) { |
329 | d = irq_desc + LOCOMO_IRQ_LT_START; | 329 | d = irq_desc + LOCOMO_IRQ_LT_START; |
@@ -333,7 +333,7 @@ static void locomo_lt_handler(unsigned int irq, struct irqdesc *desc, | |||
333 | 333 | ||
334 | static void locomo_lt_ack_irq(unsigned int irq) | 334 | static void locomo_lt_ack_irq(unsigned int irq) |
335 | { | 335 | { |
336 | void *mapbase = get_irq_chipdata(irq); | 336 | void __iomem *mapbase = get_irq_chipdata(irq); |
337 | unsigned int r; | 337 | unsigned int r; |
338 | r = locomo_readl(mapbase + LOCOMO_LTINT); | 338 | r = locomo_readl(mapbase + LOCOMO_LTINT); |
339 | r &= ~(0x0100 << (irq - LOCOMO_IRQ_LT_START)); | 339 | r &= ~(0x0100 << (irq - LOCOMO_IRQ_LT_START)); |
@@ -342,7 +342,7 @@ static void locomo_lt_ack_irq(unsigned int irq) | |||
342 | 342 | ||
343 | static void locomo_lt_mask_irq(unsigned int irq) | 343 | static void locomo_lt_mask_irq(unsigned int irq) |
344 | { | 344 | { |
345 | void *mapbase = get_irq_chipdata(irq); | 345 | void __iomem *mapbase = get_irq_chipdata(irq); |
346 | unsigned int r; | 346 | unsigned int r; |
347 | r = locomo_readl(mapbase + LOCOMO_LTINT); | 347 | r = locomo_readl(mapbase + LOCOMO_LTINT); |
348 | r &= ~(0x0010 << (irq - LOCOMO_IRQ_LT_START)); | 348 | r &= ~(0x0010 << (irq - LOCOMO_IRQ_LT_START)); |
@@ -351,7 +351,7 @@ static void locomo_lt_mask_irq(unsigned int irq) | |||
351 | 351 | ||
352 | static void locomo_lt_unmask_irq(unsigned int irq) | 352 | static void locomo_lt_unmask_irq(unsigned int irq) |
353 | { | 353 | { |
354 | void *mapbase = get_irq_chipdata(irq); | 354 | void __iomem *mapbase = get_irq_chipdata(irq); |
355 | unsigned int r; | 355 | unsigned int r; |
356 | r = locomo_readl(mapbase + LOCOMO_LTINT); | 356 | r = locomo_readl(mapbase + LOCOMO_LTINT); |
357 | r |= (0x0010 << (irq - LOCOMO_IRQ_LT_START)); | 357 | r |= (0x0010 << (irq - LOCOMO_IRQ_LT_START)); |
@@ -369,7 +369,7 @@ static void locomo_spi_handler(unsigned int irq, struct irqdesc *desc, | |||
369 | { | 369 | { |
370 | int req, i; | 370 | int req, i; |
371 | struct irqdesc *d; | 371 | struct irqdesc *d; |
372 | void *mapbase = get_irq_chipdata(irq); | 372 | void __iomem *mapbase = get_irq_chipdata(irq); |
373 | 373 | ||
374 | req = locomo_readl(mapbase + LOCOMO_SPIIR) & 0x000F; | 374 | req = locomo_readl(mapbase + LOCOMO_SPIIR) & 0x000F; |
375 | if (req) { | 375 | if (req) { |
@@ -386,7 +386,7 @@ static void locomo_spi_handler(unsigned int irq, struct irqdesc *desc, | |||
386 | 386 | ||
387 | static void locomo_spi_ack_irq(unsigned int irq) | 387 | static void locomo_spi_ack_irq(unsigned int irq) |
388 | { | 388 | { |
389 | void *mapbase = get_irq_chipdata(irq); | 389 | void __iomem *mapbase = get_irq_chipdata(irq); |
390 | unsigned int r; | 390 | unsigned int r; |
391 | r = locomo_readl(mapbase + LOCOMO_SPIWE); | 391 | r = locomo_readl(mapbase + LOCOMO_SPIWE); |
392 | r |= (0x0001 << (irq - LOCOMO_IRQ_SPI_START)); | 392 | r |= (0x0001 << (irq - LOCOMO_IRQ_SPI_START)); |
@@ -403,7 +403,7 @@ static void locomo_spi_ack_irq(unsigned int irq) | |||
403 | 403 | ||
404 | static void locomo_spi_mask_irq(unsigned int irq) | 404 | static void locomo_spi_mask_irq(unsigned int irq) |
405 | { | 405 | { |
406 | void *mapbase = get_irq_chipdata(irq); | 406 | void __iomem *mapbase = get_irq_chipdata(irq); |
407 | unsigned int r; | 407 | unsigned int r; |
408 | r = locomo_readl(mapbase + LOCOMO_SPIIE); | 408 | r = locomo_readl(mapbase + LOCOMO_SPIIE); |
409 | r &= ~(0x0001 << (irq - LOCOMO_IRQ_SPI_START)); | 409 | r &= ~(0x0001 << (irq - LOCOMO_IRQ_SPI_START)); |
@@ -412,7 +412,7 @@ static void locomo_spi_mask_irq(unsigned int irq) | |||
412 | 412 | ||
413 | static void locomo_spi_unmask_irq(unsigned int irq) | 413 | static void locomo_spi_unmask_irq(unsigned int irq) |
414 | { | 414 | { |
415 | void *mapbase = get_irq_chipdata(irq); | 415 | void __iomem *mapbase = get_irq_chipdata(irq); |
416 | unsigned int r; | 416 | unsigned int r; |
417 | r = locomo_readl(mapbase + LOCOMO_SPIIE); | 417 | r = locomo_readl(mapbase + LOCOMO_SPIIE); |
418 | r |= (0x0001 << (irq - LOCOMO_IRQ_SPI_START)); | 418 | r |= (0x0001 << (irq - LOCOMO_IRQ_SPI_START)); |
@@ -428,7 +428,7 @@ static struct irqchip locomo_spi_chip = { | |||
428 | static void locomo_setup_irq(struct locomo *lchip) | 428 | static void locomo_setup_irq(struct locomo *lchip) |
429 | { | 429 | { |
430 | int irq; | 430 | int irq; |
431 | void *irqbase = lchip->base; | 431 | void __iomem *irqbase = lchip->base; |
432 | 432 | ||
433 | /* | 433 | /* |
434 | * Install handler for IRQ_LOCOMO_HW. | 434 | * Install handler for IRQ_LOCOMO_HW. |
@@ -501,12 +501,11 @@ locomo_init_one_child(struct locomo *lchip, struct locomo_dev_info *info) | |||
501 | struct locomo_dev *dev; | 501 | struct locomo_dev *dev; |
502 | int ret; | 502 | int ret; |
503 | 503 | ||
504 | dev = kmalloc(sizeof(struct locomo_dev), GFP_KERNEL); | 504 | dev = kzalloc(sizeof(struct locomo_dev), GFP_KERNEL); |
505 | if (!dev) { | 505 | if (!dev) { |
506 | ret = -ENOMEM; | 506 | ret = -ENOMEM; |
507 | goto out; | 507 | goto out; |
508 | } | 508 | } |
509 | memset(dev, 0, sizeof(struct locomo_dev)); | ||
510 | 509 | ||
511 | strncpy(dev->dev.bus_id,info->name,sizeof(dev->dev.bus_id)); | 510 | strncpy(dev->dev.bus_id,info->name,sizeof(dev->dev.bus_id)); |
512 | /* | 511 | /* |
@@ -629,6 +628,22 @@ static int locomo_resume(struct platform_device *dev) | |||
629 | } | 628 | } |
630 | #endif | 629 | #endif |
631 | 630 | ||
631 | |||
632 | #define LCM_ALC_EN 0x8000 | ||
633 | |||
634 | void frontlight_set(struct locomo *lchip, int duty, int vr, int bpwf) | ||
635 | { | ||
636 | unsigned long flags; | ||
637 | |||
638 | spin_lock_irqsave(&lchip->lock, flags); | ||
639 | locomo_writel(bpwf, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS); | ||
640 | udelay(100); | ||
641 | locomo_writel(duty, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALD); | ||
642 | locomo_writel(bpwf | LCM_ALC_EN, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS); | ||
643 | spin_unlock_irqrestore(&lchip->lock, flags); | ||
644 | } | ||
645 | |||
646 | |||
632 | /** | 647 | /** |
633 | * locomo_probe - probe for a single LoCoMo chip. | 648 | * locomo_probe - probe for a single LoCoMo chip. |
634 | * @phys_addr: physical address of device. | 649 | * @phys_addr: physical address of device. |
@@ -648,12 +663,10 @@ __locomo_probe(struct device *me, struct resource *mem, int irq) | |||
648 | unsigned long r; | 663 | unsigned long r; |
649 | int i, ret = -ENODEV; | 664 | int i, ret = -ENODEV; |
650 | 665 | ||
651 | lchip = kmalloc(sizeof(struct locomo), GFP_KERNEL); | 666 | lchip = kzalloc(sizeof(struct locomo), GFP_KERNEL); |
652 | if (!lchip) | 667 | if (!lchip) |
653 | return -ENOMEM; | 668 | return -ENOMEM; |
654 | 669 | ||
655 | memset(lchip, 0, sizeof(struct locomo)); | ||
656 | |||
657 | spin_lock_init(&lchip->lock); | 670 | spin_lock_init(&lchip->lock); |
658 | 671 | ||
659 | lchip->dev = me; | 672 | lchip->dev = me; |
@@ -688,6 +701,11 @@ __locomo_probe(struct device *me, struct resource *mem, int irq) | |||
688 | /* FrontLight */ | 701 | /* FrontLight */ |
689 | locomo_writel(0, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS); | 702 | locomo_writel(0, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS); |
690 | locomo_writel(0, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALD); | 703 | locomo_writel(0, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALD); |
704 | |||
705 | /* Same constants can be used for collie and poodle | ||
706 | (depending on CONFIG options in original sharp code)? */ | ||
707 | frontlight_set(lchip, 163, 0, 148); | ||
708 | |||
691 | /* Longtime timer */ | 709 | /* Longtime timer */ |
692 | locomo_writel(0, lchip->base + LOCOMO_LTINT); | 710 | locomo_writel(0, lchip->base + LOCOMO_LTINT); |
693 | /* SPI */ | 711 | /* SPI */ |
@@ -767,6 +785,8 @@ static int locomo_probe(struct platform_device *dev) | |||
767 | if (!mem) | 785 | if (!mem) |
768 | return -EINVAL; | 786 | return -EINVAL; |
769 | irq = platform_get_irq(dev, 0); | 787 | irq = platform_get_irq(dev, 0); |
788 | if (irq < 0) | ||
789 | return -ENXIO; | ||
770 | 790 | ||
771 | return __locomo_probe(&dev->dev, mem, irq); | 791 | return __locomo_probe(&dev->dev, mem, irq); |
772 | } | 792 | } |
diff --git a/arch/arm/common/rtctime.c b/arch/arm/common/rtctime.c index e851d86c212c..35c9a64ac14c 100644 --- a/arch/arm/common/rtctime.c +++ b/arch/arm/common/rtctime.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/capability.h> | 20 | #include <linux/capability.h> |
21 | #include <linux/device.h> | 21 | #include <linux/device.h> |
22 | #include <linux/mutex.h> | 22 | #include <linux/mutex.h> |
23 | #include <linux/rtc.h> | ||
23 | 24 | ||
24 | #include <asm/rtc.h> | 25 | #include <asm/rtc.h> |
25 | #include <asm/semaphore.h> | 26 | #include <asm/semaphore.h> |
@@ -42,89 +43,6 @@ static struct rtc_ops *rtc_ops; | |||
42 | 43 | ||
43 | #define rtc_epoch 1900UL | 44 | #define rtc_epoch 1900UL |
44 | 45 | ||
45 | static const unsigned char days_in_month[] = { | ||
46 | 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 | ||
47 | }; | ||
48 | |||
49 | #define LEAPS_THRU_END_OF(y) ((y)/4 - (y)/100 + (y)/400) | ||
50 | #define LEAP_YEAR(year) ((!(year % 4) && (year % 100)) || !(year % 400)) | ||
51 | |||
52 | static int month_days(unsigned int month, unsigned int year) | ||
53 | { | ||
54 | return days_in_month[month] + (LEAP_YEAR(year) && month == 1); | ||
55 | } | ||
56 | |||
57 | /* | ||
58 | * Convert seconds since 01-01-1970 00:00:00 to Gregorian date. | ||
59 | */ | ||
60 | void rtc_time_to_tm(unsigned long time, struct rtc_time *tm) | ||
61 | { | ||
62 | int days, month, year; | ||
63 | |||
64 | days = time / 86400; | ||
65 | time -= days * 86400; | ||
66 | |||
67 | tm->tm_wday = (days + 4) % 7; | ||
68 | |||
69 | year = 1970 + days / 365; | ||
70 | days -= (year - 1970) * 365 | ||
71 | + LEAPS_THRU_END_OF(year - 1) | ||
72 | - LEAPS_THRU_END_OF(1970 - 1); | ||
73 | if (days < 0) { | ||
74 | year -= 1; | ||
75 | days += 365 + LEAP_YEAR(year); | ||
76 | } | ||
77 | tm->tm_year = year - 1900; | ||
78 | tm->tm_yday = days + 1; | ||
79 | |||
80 | for (month = 0; month < 11; month++) { | ||
81 | int newdays; | ||
82 | |||
83 | newdays = days - month_days(month, year); | ||
84 | if (newdays < 0) | ||
85 | break; | ||
86 | days = newdays; | ||
87 | } | ||
88 | tm->tm_mon = month; | ||
89 | tm->tm_mday = days + 1; | ||
90 | |||
91 | tm->tm_hour = time / 3600; | ||
92 | time -= tm->tm_hour * 3600; | ||
93 | tm->tm_min = time / 60; | ||
94 | tm->tm_sec = time - tm->tm_min * 60; | ||
95 | } | ||
96 | EXPORT_SYMBOL(rtc_time_to_tm); | ||
97 | |||
98 | /* | ||
99 | * Does the rtc_time represent a valid date/time? | ||
100 | */ | ||
101 | int rtc_valid_tm(struct rtc_time *tm) | ||
102 | { | ||
103 | if (tm->tm_year < 70 || | ||
104 | tm->tm_mon >= 12 || | ||
105 | tm->tm_mday < 1 || | ||
106 | tm->tm_mday > month_days(tm->tm_mon, tm->tm_year + 1900) || | ||
107 | tm->tm_hour >= 24 || | ||
108 | tm->tm_min >= 60 || | ||
109 | tm->tm_sec >= 60) | ||
110 | return -EINVAL; | ||
111 | |||
112 | return 0; | ||
113 | } | ||
114 | EXPORT_SYMBOL(rtc_valid_tm); | ||
115 | |||
116 | /* | ||
117 | * Convert Gregorian date to seconds since 01-01-1970 00:00:00. | ||
118 | */ | ||
119 | int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time) | ||
120 | { | ||
121 | *time = mktime(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, | ||
122 | tm->tm_hour, tm->tm_min, tm->tm_sec); | ||
123 | |||
124 | return 0; | ||
125 | } | ||
126 | EXPORT_SYMBOL(rtc_tm_to_time); | ||
127 | |||
128 | /* | 46 | /* |
129 | * Calculate the next alarm time given the requested alarm time mask | 47 | * Calculate the next alarm time given the requested alarm time mask |
130 | * and the current time. | 48 | * and the current time. |
@@ -151,13 +69,13 @@ void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now, struct rtc | |||
151 | } | 69 | } |
152 | } | 70 | } |
153 | 71 | ||
154 | static inline int rtc_read_time(struct rtc_ops *ops, struct rtc_time *tm) | 72 | static inline int rtc_arm_read_time(struct rtc_ops *ops, struct rtc_time *tm) |
155 | { | 73 | { |
156 | memset(tm, 0, sizeof(struct rtc_time)); | 74 | memset(tm, 0, sizeof(struct rtc_time)); |
157 | return ops->read_time(tm); | 75 | return ops->read_time(tm); |
158 | } | 76 | } |
159 | 77 | ||
160 | static inline int rtc_set_time(struct rtc_ops *ops, struct rtc_time *tm) | 78 | static inline int rtc_arm_set_time(struct rtc_ops *ops, struct rtc_time *tm) |
161 | { | 79 | { |
162 | int ret; | 80 | int ret; |
163 | 81 | ||
@@ -168,7 +86,7 @@ static inline int rtc_set_time(struct rtc_ops *ops, struct rtc_time *tm) | |||
168 | return ret; | 86 | return ret; |
169 | } | 87 | } |
170 | 88 | ||
171 | static inline int rtc_read_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm) | 89 | static inline int rtc_arm_read_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm) |
172 | { | 90 | { |
173 | int ret = -EINVAL; | 91 | int ret = -EINVAL; |
174 | if (ops->read_alarm) { | 92 | if (ops->read_alarm) { |
@@ -178,7 +96,7 @@ static inline int rtc_read_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm) | |||
178 | return ret; | 96 | return ret; |
179 | } | 97 | } |
180 | 98 | ||
181 | static inline int rtc_set_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm) | 99 | static inline int rtc_arm_set_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm) |
182 | { | 100 | { |
183 | int ret = -EINVAL; | 101 | int ret = -EINVAL; |
184 | if (ops->set_alarm) | 102 | if (ops->set_alarm) |
@@ -266,7 +184,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
266 | 184 | ||
267 | switch (cmd) { | 185 | switch (cmd) { |
268 | case RTC_ALM_READ: | 186 | case RTC_ALM_READ: |
269 | ret = rtc_read_alarm(ops, &alrm); | 187 | ret = rtc_arm_read_alarm(ops, &alrm); |
270 | if (ret) | 188 | if (ret) |
271 | break; | 189 | break; |
272 | ret = copy_to_user(uarg, &alrm.time, sizeof(tm)); | 190 | ret = copy_to_user(uarg, &alrm.time, sizeof(tm)); |
@@ -288,11 +206,11 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
288 | alrm.time.tm_wday = -1; | 206 | alrm.time.tm_wday = -1; |
289 | alrm.time.tm_yday = -1; | 207 | alrm.time.tm_yday = -1; |
290 | alrm.time.tm_isdst = -1; | 208 | alrm.time.tm_isdst = -1; |
291 | ret = rtc_set_alarm(ops, &alrm); | 209 | ret = rtc_arm_set_alarm(ops, &alrm); |
292 | break; | 210 | break; |
293 | 211 | ||
294 | case RTC_RD_TIME: | 212 | case RTC_RD_TIME: |
295 | ret = rtc_read_time(ops, &tm); | 213 | ret = rtc_arm_read_time(ops, &tm); |
296 | if (ret) | 214 | if (ret) |
297 | break; | 215 | break; |
298 | ret = copy_to_user(uarg, &tm, sizeof(tm)); | 216 | ret = copy_to_user(uarg, &tm, sizeof(tm)); |
@@ -310,7 +228,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
310 | ret = -EFAULT; | 228 | ret = -EFAULT; |
311 | break; | 229 | break; |
312 | } | 230 | } |
313 | ret = rtc_set_time(ops, &tm); | 231 | ret = rtc_arm_set_time(ops, &tm); |
314 | break; | 232 | break; |
315 | 233 | ||
316 | case RTC_EPOCH_SET: | 234 | case RTC_EPOCH_SET: |
@@ -341,11 +259,11 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
341 | ret = -EFAULT; | 259 | ret = -EFAULT; |
342 | break; | 260 | break; |
343 | } | 261 | } |
344 | ret = rtc_set_alarm(ops, &alrm); | 262 | ret = rtc_arm_set_alarm(ops, &alrm); |
345 | break; | 263 | break; |
346 | 264 | ||
347 | case RTC_WKALM_RD: | 265 | case RTC_WKALM_RD: |
348 | ret = rtc_read_alarm(ops, &alrm); | 266 | ret = rtc_arm_read_alarm(ops, &alrm); |
349 | if (ret) | 267 | if (ret) |
350 | break; | 268 | break; |
351 | ret = copy_to_user(uarg, &alrm, sizeof(alrm)); | 269 | ret = copy_to_user(uarg, &alrm, sizeof(alrm)); |
@@ -435,7 +353,7 @@ static int rtc_read_proc(char *page, char **start, off_t off, int count, int *eo | |||
435 | struct rtc_time tm; | 353 | struct rtc_time tm; |
436 | char *p = page; | 354 | char *p = page; |
437 | 355 | ||
438 | if (rtc_read_time(ops, &tm) == 0) { | 356 | if (rtc_arm_read_time(ops, &tm) == 0) { |
439 | p += sprintf(p, | 357 | p += sprintf(p, |
440 | "rtc_time\t: %02d:%02d:%02d\n" | 358 | "rtc_time\t: %02d:%02d:%02d\n" |
441 | "rtc_date\t: %04d-%02d-%02d\n" | 359 | "rtc_date\t: %04d-%02d-%02d\n" |
@@ -445,7 +363,7 @@ static int rtc_read_proc(char *page, char **start, off_t off, int count, int *eo | |||
445 | rtc_epoch); | 363 | rtc_epoch); |
446 | } | 364 | } |
447 | 365 | ||
448 | if (rtc_read_alarm(ops, &alrm) == 0) { | 366 | if (rtc_arm_read_alarm(ops, &alrm) == 0) { |
449 | p += sprintf(p, "alrm_time\t: "); | 367 | p += sprintf(p, "alrm_time\t: "); |
450 | if ((unsigned int)alrm.time.tm_hour <= 24) | 368 | if ((unsigned int)alrm.time.tm_hour <= 24) |
451 | p += sprintf(p, "%02d:", alrm.time.tm_hour); | 369 | p += sprintf(p, "%02d:", alrm.time.tm_hour); |
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c index 1475089f9b42..3f68db84e5e6 100644 --- a/arch/arm/common/sa1111.c +++ b/arch/arm/common/sa1111.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
27 | #include <linux/spinlock.h> | 27 | #include <linux/spinlock.h> |
28 | #include <linux/dma-mapping.h> | 28 | #include <linux/dma-mapping.h> |
29 | #include <linux/clk.h> | ||
29 | 30 | ||
30 | #include <asm/hardware.h> | 31 | #include <asm/hardware.h> |
31 | #include <asm/mach-types.h> | 32 | #include <asm/mach-types.h> |
@@ -36,10 +37,6 @@ | |||
36 | 37 | ||
37 | #include <asm/hardware/sa1111.h> | 38 | #include <asm/hardware/sa1111.h> |
38 | 39 | ||
39 | #ifdef CONFIG_ARCH_PXA | ||
40 | #include <asm/arch/pxa-regs.h> | ||
41 | #endif | ||
42 | |||
43 | extern void __init sa1110_mb_enable(void); | 40 | extern void __init sa1110_mb_enable(void); |
44 | 41 | ||
45 | /* | 42 | /* |
@@ -51,6 +48,7 @@ extern void __init sa1110_mb_enable(void); | |||
51 | */ | 48 | */ |
52 | struct sa1111 { | 49 | struct sa1111 { |
53 | struct device *dev; | 50 | struct device *dev; |
51 | struct clk *clk; | ||
54 | unsigned long phys; | 52 | unsigned long phys; |
55 | int irq; | 53 | int irq; |
56 | spinlock_t lock; | 54 | spinlock_t lock; |
@@ -451,19 +449,7 @@ static void sa1111_wake(struct sa1111 *sachip) | |||
451 | 449 | ||
452 | spin_lock_irqsave(&sachip->lock, flags); | 450 | spin_lock_irqsave(&sachip->lock, flags); |
453 | 451 | ||
454 | #ifdef CONFIG_ARCH_SA1100 | 452 | clk_enable(sachip->clk); |
455 | /* | ||
456 | * First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111: | ||
457 | * (SA-1110 Developer's Manual, section 9.1.2.1) | ||
458 | */ | ||
459 | GAFR |= GPIO_32_768kHz; | ||
460 | GPDR |= GPIO_32_768kHz; | ||
461 | TUCR = TUCR_3_6864MHz; | ||
462 | #elif CONFIG_ARCH_PXA | ||
463 | pxa_gpio_mode(GPIO11_3_6MHz_MD); | ||
464 | #else | ||
465 | #error missing clock setup | ||
466 | #endif | ||
467 | 453 | ||
468 | /* | 454 | /* |
469 | * Turn VCO on, and disable PLL Bypass. | 455 | * Turn VCO on, and disable PLL Bypass. |
@@ -555,12 +541,11 @@ sa1111_init_one_child(struct sa1111 *sachip, struct resource *parent, | |||
555 | struct sa1111_dev *dev; | 541 | struct sa1111_dev *dev; |
556 | int ret; | 542 | int ret; |
557 | 543 | ||
558 | dev = kmalloc(sizeof(struct sa1111_dev), GFP_KERNEL); | 544 | dev = kzalloc(sizeof(struct sa1111_dev), GFP_KERNEL); |
559 | if (!dev) { | 545 | if (!dev) { |
560 | ret = -ENOMEM; | 546 | ret = -ENOMEM; |
561 | goto out; | 547 | goto out; |
562 | } | 548 | } |
563 | memset(dev, 0, sizeof(struct sa1111_dev)); | ||
564 | 549 | ||
565 | snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id), | 550 | snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id), |
566 | "%4.4lx", info->offset); | 551 | "%4.4lx", info->offset); |
@@ -635,11 +620,15 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq) | |||
635 | unsigned int has_devs, val; | 620 | unsigned int has_devs, val; |
636 | int i, ret = -ENODEV; | 621 | int i, ret = -ENODEV; |
637 | 622 | ||
638 | sachip = kmalloc(sizeof(struct sa1111), GFP_KERNEL); | 623 | sachip = kzalloc(sizeof(struct sa1111), GFP_KERNEL); |
639 | if (!sachip) | 624 | if (!sachip) |
640 | return -ENOMEM; | 625 | return -ENOMEM; |
641 | 626 | ||
642 | memset(sachip, 0, sizeof(struct sa1111)); | 627 | sachip->clk = clk_get(me, "GPIO27_CLK"); |
628 | if (!sachip->clk) { | ||
629 | ret = PTR_ERR(sachip->clk); | ||
630 | goto err_free; | ||
631 | } | ||
643 | 632 | ||
644 | spin_lock_init(&sachip->lock); | 633 | spin_lock_init(&sachip->lock); |
645 | 634 | ||
@@ -656,7 +645,7 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq) | |||
656 | sachip->base = ioremap(mem->start, PAGE_SIZE * 2); | 645 | sachip->base = ioremap(mem->start, PAGE_SIZE * 2); |
657 | if (!sachip->base) { | 646 | if (!sachip->base) { |
658 | ret = -ENOMEM; | 647 | ret = -ENOMEM; |
659 | goto out; | 648 | goto err_clkput; |
660 | } | 649 | } |
661 | 650 | ||
662 | /* | 651 | /* |
@@ -666,7 +655,7 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq) | |||
666 | if ((id & SKID_ID_MASK) != SKID_SA1111_ID) { | 655 | if ((id & SKID_ID_MASK) != SKID_SA1111_ID) { |
667 | printk(KERN_DEBUG "SA1111 not detected: ID = %08lx\n", id); | 656 | printk(KERN_DEBUG "SA1111 not detected: ID = %08lx\n", id); |
668 | ret = -ENODEV; | 657 | ret = -ENODEV; |
669 | goto unmap; | 658 | goto err_unmap; |
670 | } | 659 | } |
671 | 660 | ||
672 | printk(KERN_INFO "SA1111 Microprocessor Companion Chip: " | 661 | printk(KERN_INFO "SA1111 Microprocessor Companion Chip: " |
@@ -726,9 +715,11 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq) | |||
726 | 715 | ||
727 | return 0; | 716 | return 0; |
728 | 717 | ||
729 | unmap: | 718 | err_unmap: |
730 | iounmap(sachip->base); | 719 | iounmap(sachip->base); |
731 | out: | 720 | err_clkput: |
721 | clk_put(sachip->clk); | ||
722 | err_free: | ||
732 | kfree(sachip); | 723 | kfree(sachip); |
733 | return ret; | 724 | return ret; |
734 | } | 725 | } |
@@ -751,6 +742,8 @@ static void __sa1111_remove(struct sa1111 *sachip) | |||
751 | sa1111_writel(0, irqbase + SA1111_WAKEEN0); | 742 | sa1111_writel(0, irqbase + SA1111_WAKEEN0); |
752 | sa1111_writel(0, irqbase + SA1111_WAKEEN1); | 743 | sa1111_writel(0, irqbase + SA1111_WAKEEN1); |
753 | 744 | ||
745 | clk_disable(sachip->clk); | ||
746 | |||
754 | if (sachip->irq != NO_IRQ) { | 747 | if (sachip->irq != NO_IRQ) { |
755 | set_irq_chained_handler(sachip->irq, NULL); | 748 | set_irq_chained_handler(sachip->irq, NULL); |
756 | set_irq_data(sachip->irq, NULL); | 749 | set_irq_data(sachip->irq, NULL); |
@@ -759,6 +752,7 @@ static void __sa1111_remove(struct sa1111 *sachip) | |||
759 | } | 752 | } |
760 | 753 | ||
761 | iounmap(sachip->base); | 754 | iounmap(sachip->base); |
755 | clk_put(sachip->clk); | ||
762 | kfree(sachip); | 756 | kfree(sachip); |
763 | } | 757 | } |
764 | 758 | ||
@@ -857,6 +851,8 @@ static int sa1111_suspend(struct platform_device *dev, pm_message_t state) | |||
857 | sa1111_writel(0, sachip->base + SA1111_SKPWM0); | 851 | sa1111_writel(0, sachip->base + SA1111_SKPWM0); |
858 | sa1111_writel(0, sachip->base + SA1111_SKPWM1); | 852 | sa1111_writel(0, sachip->base + SA1111_SKPWM1); |
859 | 853 | ||
854 | clk_disable(sachip->clk); | ||
855 | |||
860 | spin_unlock_irqrestore(&sachip->lock, flags); | 856 | spin_unlock_irqrestore(&sachip->lock, flags); |
861 | 857 | ||
862 | return 0; | 858 | return 0; |
@@ -943,6 +939,8 @@ static int sa1111_probe(struct platform_device *pdev) | |||
943 | if (!mem) | 939 | if (!mem) |
944 | return -EINVAL; | 940 | return -EINVAL; |
945 | irq = platform_get_irq(pdev, 0); | 941 | irq = platform_get_irq(pdev, 0); |
942 | if (irq < 0) | ||
943 | return -ENXIO; | ||
946 | 944 | ||
947 | return __sa1111_probe(&pdev->dev, mem, irq); | 945 | return __sa1111_probe(&pdev->dev, mem, irq); |
948 | } | 946 | } |
diff --git a/arch/arm/common/scoop.c b/arch/arm/common/scoop.c index a2dfe0b0f1ec..5e830f444c6c 100644 --- a/arch/arm/common/scoop.c +++ b/arch/arm/common/scoop.c | |||
@@ -132,12 +132,10 @@ int __init scoop_probe(struct platform_device *pdev) | |||
132 | if (!mem) | 132 | if (!mem) |
133 | return -EINVAL; | 133 | return -EINVAL; |
134 | 134 | ||
135 | devptr = kmalloc(sizeof(struct scoop_dev), GFP_KERNEL); | 135 | devptr = kzalloc(sizeof(struct scoop_dev), GFP_KERNEL); |
136 | |||
137 | if (!devptr) | 136 | if (!devptr) |
138 | return -ENOMEM; | 137 | return -ENOMEM; |
139 | 138 | ||
140 | memset(devptr, 0, sizeof(struct scoop_dev)); | ||
141 | spin_lock_init(&devptr->scoop_lock); | 139 | spin_lock_init(&devptr->scoop_lock); |
142 | 140 | ||
143 | inf = pdev->dev.platform_data; | 141 | inf = pdev->dev.platform_data; |
diff --git a/arch/arm/common/sharpsl_pm.c b/arch/arm/common/sharpsl_pm.c index 978d32e82d39..3cd8c9ee4510 100644 --- a/arch/arm/common/sharpsl_pm.c +++ b/arch/arm/common/sharpsl_pm.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
23 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
24 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
25 | #include <linux/leds.h> | ||
25 | 26 | ||
26 | #include <asm/hardware.h> | 27 | #include <asm/hardware.h> |
27 | #include <asm/mach-types.h> | 28 | #include <asm/mach-types.h> |
@@ -75,6 +76,7 @@ static void sharpsl_battery_thread(void *private_); | |||
75 | struct sharpsl_pm_status sharpsl_pm; | 76 | struct sharpsl_pm_status sharpsl_pm; |
76 | DECLARE_WORK(toggle_charger, sharpsl_charge_toggle, NULL); | 77 | DECLARE_WORK(toggle_charger, sharpsl_charge_toggle, NULL); |
77 | DECLARE_WORK(sharpsl_bat, sharpsl_battery_thread, NULL); | 78 | DECLARE_WORK(sharpsl_bat, sharpsl_battery_thread, NULL); |
79 | DEFINE_LED_TRIGGER(sharpsl_charge_led_trigger); | ||
78 | 80 | ||
79 | 81 | ||
80 | static int get_percentage(int voltage) | 82 | static int get_percentage(int voltage) |
@@ -190,10 +192,10 @@ void sharpsl_pm_led(int val) | |||
190 | dev_err(sharpsl_pm.dev, "Charging Error!\n"); | 192 | dev_err(sharpsl_pm.dev, "Charging Error!\n"); |
191 | } else if (val == SHARPSL_LED_ON) { | 193 | } else if (val == SHARPSL_LED_ON) { |
192 | dev_dbg(sharpsl_pm.dev, "Charge LED On\n"); | 194 | dev_dbg(sharpsl_pm.dev, "Charge LED On\n"); |
193 | 195 | led_trigger_event(sharpsl_charge_led_trigger, LED_FULL); | |
194 | } else { | 196 | } else { |
195 | dev_dbg(sharpsl_pm.dev, "Charge LED Off\n"); | 197 | dev_dbg(sharpsl_pm.dev, "Charge LED Off\n"); |
196 | 198 | led_trigger_event(sharpsl_charge_led_trigger, LED_OFF); | |
197 | } | 199 | } |
198 | } | 200 | } |
199 | 201 | ||
@@ -786,6 +788,8 @@ static int __init sharpsl_pm_probe(struct platform_device *pdev) | |||
786 | init_timer(&sharpsl_pm.chrg_full_timer); | 788 | init_timer(&sharpsl_pm.chrg_full_timer); |
787 | sharpsl_pm.chrg_full_timer.function = sharpsl_chrg_full_timer; | 789 | sharpsl_pm.chrg_full_timer.function = sharpsl_chrg_full_timer; |
788 | 790 | ||
791 | led_trigger_register_simple("sharpsl-charge", &sharpsl_charge_led_trigger); | ||
792 | |||
789 | sharpsl_pm.machinfo->init(); | 793 | sharpsl_pm.machinfo->init(); |
790 | 794 | ||
791 | device_create_file(&pdev->dev, &dev_attr_battery_percentage); | 795 | device_create_file(&pdev->dev, &dev_attr_battery_percentage); |
@@ -807,6 +811,8 @@ static int sharpsl_pm_remove(struct platform_device *pdev) | |||
807 | device_remove_file(&pdev->dev, &dev_attr_battery_percentage); | 811 | device_remove_file(&pdev->dev, &dev_attr_battery_percentage); |
808 | device_remove_file(&pdev->dev, &dev_attr_battery_voltage); | 812 | device_remove_file(&pdev->dev, &dev_attr_battery_voltage); |
809 | 813 | ||
814 | led_trigger_unregister_simple(sharpsl_charge_led_trigger); | ||
815 | |||
810 | sharpsl_pm.machinfo->exit(); | 816 | sharpsl_pm.machinfo->exit(); |
811 | 817 | ||
812 | del_timer_sync(&sharpsl_pm.chrg_full_timer); | 818 | del_timer_sync(&sharpsl_pm.chrg_full_timer); |
diff --git a/arch/arm/common/uengine.c b/arch/arm/common/uengine.c new file mode 100644 index 000000000000..a1310b71004e --- /dev/null +++ b/arch/arm/common/uengine.c | |||
@@ -0,0 +1,473 @@ | |||
1 | /* | ||
2 | * Generic library functions for the microengines found on the Intel | ||
3 | * IXP2000 series of network processors. | ||
4 | * | ||
5 | * Copyright (C) 2004, 2005 Lennert Buytenhek <buytenh@wantstofly.org> | ||
6 | * Dedicated to Marija Kulikova. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU Lesser General Public License as | ||
10 | * published by the Free Software Foundation; either version 2.1 of the | ||
11 | * License, or (at your option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/config.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/string.h> | ||
20 | #include <asm/hardware.h> | ||
21 | #include <asm/arch/ixp2000-regs.h> | ||
22 | #include <asm/hardware/uengine.h> | ||
23 | #include <asm/io.h> | ||
24 | |||
25 | #define USTORE_ADDRESS 0x000 | ||
26 | #define USTORE_DATA_LOWER 0x004 | ||
27 | #define USTORE_DATA_UPPER 0x008 | ||
28 | #define CTX_ENABLES 0x018 | ||
29 | #define CC_ENABLE 0x01c | ||
30 | #define CSR_CTX_POINTER 0x020 | ||
31 | #define INDIRECT_CTX_STS 0x040 | ||
32 | #define ACTIVE_CTX_STS 0x044 | ||
33 | #define INDIRECT_CTX_SIG_EVENTS 0x048 | ||
34 | #define INDIRECT_CTX_WAKEUP_EVENTS 0x050 | ||
35 | #define NN_PUT 0x080 | ||
36 | #define NN_GET 0x084 | ||
37 | #define TIMESTAMP_LOW 0x0c0 | ||
38 | #define TIMESTAMP_HIGH 0x0c4 | ||
39 | #define T_INDEX_BYTE_INDEX 0x0f4 | ||
40 | #define LOCAL_CSR_STATUS 0x180 | ||
41 | |||
42 | u32 ixp2000_uengine_mask; | ||
43 | |||
44 | static void *ixp2000_uengine_csr_area(int uengine) | ||
45 | { | ||
46 | return ((void *)IXP2000_UENGINE_CSR_VIRT_BASE) + (uengine << 10); | ||
47 | } | ||
48 | |||
49 | /* | ||
50 | * LOCAL_CSR_STATUS=1 after a read or write to a microengine's CSR | ||
51 | * space means that the microengine we tried to access was also trying | ||
52 | * to access its own CSR space on the same clock cycle as we did. When | ||
53 | * this happens, we lose the arbitration process by default, and the | ||
54 | * read or write we tried to do was not actually performed, so we try | ||
55 | * again until it succeeds. | ||
56 | */ | ||
57 | u32 ixp2000_uengine_csr_read(int uengine, int offset) | ||
58 | { | ||
59 | void *uebase; | ||
60 | u32 *local_csr_status; | ||
61 | u32 *reg; | ||
62 | u32 value; | ||
63 | |||
64 | uebase = ixp2000_uengine_csr_area(uengine); | ||
65 | |||
66 | local_csr_status = (u32 *)(uebase + LOCAL_CSR_STATUS); | ||
67 | reg = (u32 *)(uebase + offset); | ||
68 | do { | ||
69 | value = ixp2000_reg_read(reg); | ||
70 | } while (ixp2000_reg_read(local_csr_status) & 1); | ||
71 | |||
72 | return value; | ||
73 | } | ||
74 | EXPORT_SYMBOL(ixp2000_uengine_csr_read); | ||
75 | |||
76 | void ixp2000_uengine_csr_write(int uengine, int offset, u32 value) | ||
77 | { | ||
78 | void *uebase; | ||
79 | u32 *local_csr_status; | ||
80 | u32 *reg; | ||
81 | |||
82 | uebase = ixp2000_uengine_csr_area(uengine); | ||
83 | |||
84 | local_csr_status = (u32 *)(uebase + LOCAL_CSR_STATUS); | ||
85 | reg = (u32 *)(uebase + offset); | ||
86 | do { | ||
87 | ixp2000_reg_write(reg, value); | ||
88 | } while (ixp2000_reg_read(local_csr_status) & 1); | ||
89 | } | ||
90 | EXPORT_SYMBOL(ixp2000_uengine_csr_write); | ||
91 | |||
92 | void ixp2000_uengine_reset(u32 uengine_mask) | ||
93 | { | ||
94 | ixp2000_reg_wrb(IXP2000_RESET1, uengine_mask & ixp2000_uengine_mask); | ||
95 | ixp2000_reg_wrb(IXP2000_RESET1, 0); | ||
96 | } | ||
97 | EXPORT_SYMBOL(ixp2000_uengine_reset); | ||
98 | |||
99 | void ixp2000_uengine_set_mode(int uengine, u32 mode) | ||
100 | { | ||
101 | /* | ||
102 | * CTL_STR_PAR_EN: unconditionally enable parity checking on | ||
103 | * control store. | ||
104 | */ | ||
105 | mode |= 0x10000000; | ||
106 | ixp2000_uengine_csr_write(uengine, CTX_ENABLES, mode); | ||
107 | |||
108 | /* | ||
109 | * Enable updating of condition codes. | ||
110 | */ | ||
111 | ixp2000_uengine_csr_write(uengine, CC_ENABLE, 0x00002000); | ||
112 | |||
113 | /* | ||
114 | * Initialise other per-microengine registers. | ||
115 | */ | ||
116 | ixp2000_uengine_csr_write(uengine, NN_PUT, 0x00); | ||
117 | ixp2000_uengine_csr_write(uengine, NN_GET, 0x00); | ||
118 | ixp2000_uengine_csr_write(uengine, T_INDEX_BYTE_INDEX, 0); | ||
119 | } | ||
120 | EXPORT_SYMBOL(ixp2000_uengine_set_mode); | ||
121 | |||
122 | static int make_even_parity(u32 x) | ||
123 | { | ||
124 | return hweight32(x) & 1; | ||
125 | } | ||
126 | |||
127 | static void ustore_write(int uengine, u64 insn) | ||
128 | { | ||
129 | /* | ||
130 | * Generate even parity for top and bottom 20 bits. | ||
131 | */ | ||
132 | insn |= (u64)make_even_parity((insn >> 20) & 0x000fffff) << 41; | ||
133 | insn |= (u64)make_even_parity(insn & 0x000fffff) << 40; | ||
134 | |||
135 | /* | ||
136 | * Write to microstore. The second write auto-increments | ||
137 | * the USTORE_ADDRESS index register. | ||
138 | */ | ||
139 | ixp2000_uengine_csr_write(uengine, USTORE_DATA_LOWER, (u32)insn); | ||
140 | ixp2000_uengine_csr_write(uengine, USTORE_DATA_UPPER, (u32)(insn >> 32)); | ||
141 | } | ||
142 | |||
143 | void ixp2000_uengine_load_microcode(int uengine, u8 *ucode, int insns) | ||
144 | { | ||
145 | int i; | ||
146 | |||
147 | /* | ||
148 | * Start writing to microstore at address 0. | ||
149 | */ | ||
150 | ixp2000_uengine_csr_write(uengine, USTORE_ADDRESS, 0x80000000); | ||
151 | for (i = 0; i < insns; i++) { | ||
152 | u64 insn; | ||
153 | |||
154 | insn = (((u64)ucode[0]) << 32) | | ||
155 | (((u64)ucode[1]) << 24) | | ||
156 | (((u64)ucode[2]) << 16) | | ||
157 | (((u64)ucode[3]) << 8) | | ||
158 | ((u64)ucode[4]); | ||
159 | ucode += 5; | ||
160 | |||
161 | ustore_write(uengine, insn); | ||
162 | } | ||
163 | |||
164 | /* | ||
165 | * Pad with a few NOPs at the end (to avoid the microengine | ||
166 | * aborting as it prefetches beyond the last instruction), unless | ||
167 | * we run off the end of the instruction store first, at which | ||
168 | * point the address register will wrap back to zero. | ||
169 | */ | ||
170 | for (i = 0; i < 4; i++) { | ||
171 | u32 addr; | ||
172 | |||
173 | addr = ixp2000_uengine_csr_read(uengine, USTORE_ADDRESS); | ||
174 | if (addr == 0x80000000) | ||
175 | break; | ||
176 | ustore_write(uengine, 0xf0000c0300ULL); | ||
177 | } | ||
178 | |||
179 | /* | ||
180 | * End programming. | ||
181 | */ | ||
182 | ixp2000_uengine_csr_write(uengine, USTORE_ADDRESS, 0x00000000); | ||
183 | } | ||
184 | EXPORT_SYMBOL(ixp2000_uengine_load_microcode); | ||
185 | |||
186 | void ixp2000_uengine_init_context(int uengine, int context, int pc) | ||
187 | { | ||
188 | /* | ||
189 | * Select the right context for indirect access. | ||
190 | */ | ||
191 | ixp2000_uengine_csr_write(uengine, CSR_CTX_POINTER, context); | ||
192 | |||
193 | /* | ||
194 | * Initialise signal masks to immediately go to Ready state. | ||
195 | */ | ||
196 | ixp2000_uengine_csr_write(uengine, INDIRECT_CTX_SIG_EVENTS, 1); | ||
197 | ixp2000_uengine_csr_write(uengine, INDIRECT_CTX_WAKEUP_EVENTS, 1); | ||
198 | |||
199 | /* | ||
200 | * Set program counter. | ||
201 | */ | ||
202 | ixp2000_uengine_csr_write(uengine, INDIRECT_CTX_STS, pc); | ||
203 | } | ||
204 | EXPORT_SYMBOL(ixp2000_uengine_init_context); | ||
205 | |||
206 | void ixp2000_uengine_start_contexts(int uengine, u8 ctx_mask) | ||
207 | { | ||
208 | u32 mask; | ||
209 | |||
210 | /* | ||
211 | * Enable the specified context to go to Executing state. | ||
212 | */ | ||
213 | mask = ixp2000_uengine_csr_read(uengine, CTX_ENABLES); | ||
214 | mask |= ctx_mask << 8; | ||
215 | ixp2000_uengine_csr_write(uengine, CTX_ENABLES, mask); | ||
216 | } | ||
217 | EXPORT_SYMBOL(ixp2000_uengine_start_contexts); | ||
218 | |||
219 | void ixp2000_uengine_stop_contexts(int uengine, u8 ctx_mask) | ||
220 | { | ||
221 | u32 mask; | ||
222 | |||
223 | /* | ||
224 | * Disable the Ready->Executing transition. Note that this | ||
225 | * does not stop the context until it voluntarily yields. | ||
226 | */ | ||
227 | mask = ixp2000_uengine_csr_read(uengine, CTX_ENABLES); | ||
228 | mask &= ~(ctx_mask << 8); | ||
229 | ixp2000_uengine_csr_write(uengine, CTX_ENABLES, mask); | ||
230 | } | ||
231 | EXPORT_SYMBOL(ixp2000_uengine_stop_contexts); | ||
232 | |||
233 | static int check_ixp_type(struct ixp2000_uengine_code *c) | ||
234 | { | ||
235 | u32 product_id; | ||
236 | u32 rev; | ||
237 | |||
238 | product_id = ixp2000_reg_read(IXP2000_PRODUCT_ID); | ||
239 | if (((product_id >> 16) & 0x1f) != 0) | ||
240 | return 0; | ||
241 | |||
242 | switch ((product_id >> 8) & 0xff) { | ||
243 | case 0: /* IXP2800 */ | ||
244 | if (!(c->cpu_model_bitmask & 4)) | ||
245 | return 0; | ||
246 | break; | ||
247 | |||
248 | case 1: /* IXP2850 */ | ||
249 | if (!(c->cpu_model_bitmask & 8)) | ||
250 | return 0; | ||
251 | break; | ||
252 | |||
253 | case 2: /* IXP2400 */ | ||
254 | if (!(c->cpu_model_bitmask & 2)) | ||
255 | return 0; | ||
256 | break; | ||
257 | |||
258 | default: | ||
259 | return 0; | ||
260 | } | ||
261 | |||
262 | rev = product_id & 0xff; | ||
263 | if (rev < c->cpu_min_revision || rev > c->cpu_max_revision) | ||
264 | return 0; | ||
265 | |||
266 | return 1; | ||
267 | } | ||
268 | |||
269 | static void generate_ucode(u8 *ucode, u32 *gpr_a, u32 *gpr_b) | ||
270 | { | ||
271 | int offset; | ||
272 | int i; | ||
273 | |||
274 | offset = 0; | ||
275 | |||
276 | for (i = 0; i < 128; i++) { | ||
277 | u8 b3; | ||
278 | u8 b2; | ||
279 | u8 b1; | ||
280 | u8 b0; | ||
281 | |||
282 | b3 = (gpr_a[i] >> 24) & 0xff; | ||
283 | b2 = (gpr_a[i] >> 16) & 0xff; | ||
284 | b1 = (gpr_a[i] >> 8) & 0xff; | ||
285 | b0 = gpr_a[i] & 0xff; | ||
286 | |||
287 | // immed[@ai, (b1 << 8) | b0] | ||
288 | // 11110000 0000VVVV VVVV11VV VVVVVV00 1IIIIIII | ||
289 | ucode[offset++] = 0xf0; | ||
290 | ucode[offset++] = (b1 >> 4); | ||
291 | ucode[offset++] = (b1 << 4) | 0x0c | (b0 >> 6); | ||
292 | ucode[offset++] = (b0 << 2); | ||
293 | ucode[offset++] = 0x80 | i; | ||
294 | |||
295 | // immed_w1[@ai, (b3 << 8) | b2] | ||
296 | // 11110100 0100VVVV VVVV11VV VVVVVV00 1IIIIIII | ||
297 | ucode[offset++] = 0xf4; | ||
298 | ucode[offset++] = 0x40 | (b3 >> 4); | ||
299 | ucode[offset++] = (b3 << 4) | 0x0c | (b2 >> 6); | ||
300 | ucode[offset++] = (b2 << 2); | ||
301 | ucode[offset++] = 0x80 | i; | ||
302 | } | ||
303 | |||
304 | for (i = 0; i < 128; i++) { | ||
305 | u8 b3; | ||
306 | u8 b2; | ||
307 | u8 b1; | ||
308 | u8 b0; | ||
309 | |||
310 | b3 = (gpr_b[i] >> 24) & 0xff; | ||
311 | b2 = (gpr_b[i] >> 16) & 0xff; | ||
312 | b1 = (gpr_b[i] >> 8) & 0xff; | ||
313 | b0 = gpr_b[i] & 0xff; | ||
314 | |||
315 | // immed[@bi, (b1 << 8) | b0] | ||
316 | // 11110000 0000VVVV VVVV001I IIIIII11 VVVVVVVV | ||
317 | ucode[offset++] = 0xf0; | ||
318 | ucode[offset++] = (b1 >> 4); | ||
319 | ucode[offset++] = (b1 << 4) | 0x02 | (i >> 6); | ||
320 | ucode[offset++] = (i << 2) | 0x03; | ||
321 | ucode[offset++] = b0; | ||
322 | |||
323 | // immed_w1[@bi, (b3 << 8) | b2] | ||
324 | // 11110100 0100VVVV VVVV001I IIIIII11 VVVVVVVV | ||
325 | ucode[offset++] = 0xf4; | ||
326 | ucode[offset++] = 0x40 | (b3 >> 4); | ||
327 | ucode[offset++] = (b3 << 4) | 0x02 | (i >> 6); | ||
328 | ucode[offset++] = (i << 2) | 0x03; | ||
329 | ucode[offset++] = b2; | ||
330 | } | ||
331 | |||
332 | // ctx_arb[kill] | ||
333 | ucode[offset++] = 0xe0; | ||
334 | ucode[offset++] = 0x00; | ||
335 | ucode[offset++] = 0x01; | ||
336 | ucode[offset++] = 0x00; | ||
337 | ucode[offset++] = 0x00; | ||
338 | } | ||
339 | |||
340 | static int set_initial_registers(int uengine, struct ixp2000_uengine_code *c) | ||
341 | { | ||
342 | int per_ctx_regs; | ||
343 | u32 *gpr_a; | ||
344 | u32 *gpr_b; | ||
345 | u8 *ucode; | ||
346 | int i; | ||
347 | |||
348 | gpr_a = kmalloc(128 * sizeof(u32), GFP_KERNEL); | ||
349 | gpr_b = kmalloc(128 * sizeof(u32), GFP_KERNEL); | ||
350 | ucode = kmalloc(513 * 5, GFP_KERNEL); | ||
351 | if (gpr_a == NULL || gpr_b == NULL || ucode == NULL) { | ||
352 | kfree(ucode); | ||
353 | kfree(gpr_b); | ||
354 | kfree(gpr_a); | ||
355 | return 1; | ||
356 | } | ||
357 | |||
358 | per_ctx_regs = 16; | ||
359 | if (c->uengine_parameters & IXP2000_UENGINE_4_CONTEXTS) | ||
360 | per_ctx_regs = 32; | ||
361 | |||
362 | memset(gpr_a, 0, sizeof(gpr_a)); | ||
363 | memset(gpr_b, 0, sizeof(gpr_b)); | ||
364 | for (i = 0; i < 256; i++) { | ||
365 | struct ixp2000_reg_value *r = c->initial_reg_values + i; | ||
366 | u32 *bank; | ||
367 | int inc; | ||
368 | int j; | ||
369 | |||
370 | if (r->reg == -1) | ||
371 | break; | ||
372 | |||
373 | bank = (r->reg & 0x400) ? gpr_b : gpr_a; | ||
374 | inc = (r->reg & 0x80) ? 128 : per_ctx_regs; | ||
375 | |||
376 | j = r->reg & 0x7f; | ||
377 | while (j < 128) { | ||
378 | bank[j] = r->value; | ||
379 | j += inc; | ||
380 | } | ||
381 | } | ||
382 | |||
383 | generate_ucode(ucode, gpr_a, gpr_b); | ||
384 | ixp2000_uengine_load_microcode(uengine, ucode, 513); | ||
385 | ixp2000_uengine_init_context(uengine, 0, 0); | ||
386 | ixp2000_uengine_start_contexts(uengine, 0x01); | ||
387 | for (i = 0; i < 100; i++) { | ||
388 | u32 status; | ||
389 | |||
390 | status = ixp2000_uengine_csr_read(uengine, ACTIVE_CTX_STS); | ||
391 | if (!(status & 0x80000000)) | ||
392 | break; | ||
393 | } | ||
394 | ixp2000_uengine_stop_contexts(uengine, 0x01); | ||
395 | |||
396 | kfree(ucode); | ||
397 | kfree(gpr_b); | ||
398 | kfree(gpr_a); | ||
399 | |||
400 | return !!(i == 100); | ||
401 | } | ||
402 | |||
403 | int ixp2000_uengine_load(int uengine, struct ixp2000_uengine_code *c) | ||
404 | { | ||
405 | int ctx; | ||
406 | |||
407 | if (!check_ixp_type(c)) | ||
408 | return 1; | ||
409 | |||
410 | if (!(ixp2000_uengine_mask & (1 << uengine))) | ||
411 | return 1; | ||
412 | |||
413 | ixp2000_uengine_reset(1 << uengine); | ||
414 | ixp2000_uengine_set_mode(uengine, c->uengine_parameters); | ||
415 | if (set_initial_registers(uengine, c)) | ||
416 | return 1; | ||
417 | ixp2000_uengine_load_microcode(uengine, c->insns, c->num_insns); | ||
418 | |||
419 | for (ctx = 0; ctx < 8; ctx++) | ||
420 | ixp2000_uengine_init_context(uengine, ctx, 0); | ||
421 | |||
422 | return 0; | ||
423 | } | ||
424 | EXPORT_SYMBOL(ixp2000_uengine_load); | ||
425 | |||
426 | |||
427 | static int __init ixp2000_uengine_init(void) | ||
428 | { | ||
429 | int uengine; | ||
430 | u32 value; | ||
431 | |||
432 | /* | ||
433 | * Determine number of microengines present. | ||
434 | */ | ||
435 | switch ((ixp2000_reg_read(IXP2000_PRODUCT_ID) >> 8) & 0x1fff) { | ||
436 | case 0: /* IXP2800 */ | ||
437 | case 1: /* IXP2850 */ | ||
438 | ixp2000_uengine_mask = 0x00ff00ff; | ||
439 | break; | ||
440 | |||
441 | case 2: /* IXP2400 */ | ||
442 | ixp2000_uengine_mask = 0x000f000f; | ||
443 | break; | ||
444 | |||
445 | default: | ||
446 | printk(KERN_INFO "Detected unknown IXP2000 model (%.8x)\n", | ||
447 | (unsigned int)ixp2000_reg_read(IXP2000_PRODUCT_ID)); | ||
448 | ixp2000_uengine_mask = 0x00000000; | ||
449 | break; | ||
450 | } | ||
451 | |||
452 | /* | ||
453 | * Reset microengines. | ||
454 | */ | ||
455 | ixp2000_uengine_reset(ixp2000_uengine_mask); | ||
456 | |||
457 | /* | ||
458 | * Synchronise timestamp counters across all microengines. | ||
459 | */ | ||
460 | value = ixp2000_reg_read(IXP2000_MISC_CONTROL); | ||
461 | ixp2000_reg_wrb(IXP2000_MISC_CONTROL, value & ~0x80); | ||
462 | for (uengine = 0; uengine < 32; uengine++) { | ||
463 | if (ixp2000_uengine_mask & (1 << uengine)) { | ||
464 | ixp2000_uengine_csr_write(uengine, TIMESTAMP_LOW, 0); | ||
465 | ixp2000_uengine_csr_write(uengine, TIMESTAMP_HIGH, 0); | ||
466 | } | ||
467 | } | ||
468 | ixp2000_reg_wrb(IXP2000_MISC_CONTROL, value | 0x80); | ||
469 | |||
470 | return 0; | ||
471 | } | ||
472 | |||
473 | subsys_initcall(ixp2000_uengine_init); | ||
diff --git a/arch/arm/common/vic.c b/arch/arm/common/vic.c index a45ed1687a59..a19bc4a6196d 100644 --- a/arch/arm/common/vic.c +++ b/arch/arm/common/vic.c | |||
@@ -22,22 +22,21 @@ | |||
22 | #include <linux/list.h> | 22 | #include <linux/list.h> |
23 | 23 | ||
24 | #include <asm/io.h> | 24 | #include <asm/io.h> |
25 | #include <asm/irq.h> | ||
26 | #include <asm/mach/irq.h> | 25 | #include <asm/mach/irq.h> |
27 | #include <asm/hardware/vic.h> | 26 | #include <asm/hardware/vic.h> |
28 | 27 | ||
29 | static void __iomem *vic_base; | ||
30 | |||
31 | static void vic_mask_irq(unsigned int irq) | 28 | static void vic_mask_irq(unsigned int irq) |
32 | { | 29 | { |
33 | irq -= IRQ_VIC_START; | 30 | void __iomem *base = get_irq_chipdata(irq); |
34 | writel(1 << irq, vic_base + VIC_INT_ENABLE_CLEAR); | 31 | irq &= 31; |
32 | writel(1 << irq, base + VIC_INT_ENABLE_CLEAR); | ||
35 | } | 33 | } |
36 | 34 | ||
37 | static void vic_unmask_irq(unsigned int irq) | 35 | static void vic_unmask_irq(unsigned int irq) |
38 | { | 36 | { |
39 | irq -= IRQ_VIC_START; | 37 | void __iomem *base = get_irq_chipdata(irq); |
40 | writel(1 << irq, vic_base + VIC_INT_ENABLE); | 38 | irq &= 31; |
39 | writel(1 << irq, base + VIC_INT_ENABLE); | ||
41 | } | 40 | } |
42 | 41 | ||
43 | static struct irqchip vic_chip = { | 42 | static struct irqchip vic_chip = { |
@@ -46,43 +45,49 @@ static struct irqchip vic_chip = { | |||
46 | .unmask = vic_unmask_irq, | 45 | .unmask = vic_unmask_irq, |
47 | }; | 46 | }; |
48 | 47 | ||
49 | void __init vic_init(void __iomem *base, u32 vic_sources) | 48 | /** |
49 | * vic_init - initialise a vectored interrupt controller | ||
50 | * @base: iomem base address | ||
51 | * @irq_start: starting interrupt number, must be muliple of 32 | ||
52 | * @vic_sources: bitmask of interrupt sources to allow | ||
53 | */ | ||
54 | void __init vic_init(void __iomem *base, unsigned int irq_start, | ||
55 | u32 vic_sources) | ||
50 | { | 56 | { |
51 | unsigned int i; | 57 | unsigned int i; |
52 | 58 | ||
53 | vic_base = base; | ||
54 | |||
55 | /* Disable all interrupts initially. */ | 59 | /* Disable all interrupts initially. */ |
56 | 60 | ||
57 | writel(0, vic_base + VIC_INT_SELECT); | 61 | writel(0, base + VIC_INT_SELECT); |
58 | writel(0, vic_base + VIC_INT_ENABLE); | 62 | writel(0, base + VIC_INT_ENABLE); |
59 | writel(~0, vic_base + VIC_INT_ENABLE_CLEAR); | 63 | writel(~0, base + VIC_INT_ENABLE_CLEAR); |
60 | writel(0, vic_base + VIC_IRQ_STATUS); | 64 | writel(0, base + VIC_IRQ_STATUS); |
61 | writel(0, vic_base + VIC_ITCR); | 65 | writel(0, base + VIC_ITCR); |
62 | writel(~0, vic_base + VIC_INT_SOFT_CLEAR); | 66 | writel(~0, base + VIC_INT_SOFT_CLEAR); |
63 | 67 | ||
64 | /* | 68 | /* |
65 | * Make sure we clear all existing interrupts | 69 | * Make sure we clear all existing interrupts |
66 | */ | 70 | */ |
67 | writel(0, vic_base + VIC_VECT_ADDR); | 71 | writel(0, base + VIC_VECT_ADDR); |
68 | for (i = 0; i < 19; i++) { | 72 | for (i = 0; i < 19; i++) { |
69 | unsigned int value; | 73 | unsigned int value; |
70 | 74 | ||
71 | value = readl(vic_base + VIC_VECT_ADDR); | 75 | value = readl(base + VIC_VECT_ADDR); |
72 | writel(value, vic_base + VIC_VECT_ADDR); | 76 | writel(value, base + VIC_VECT_ADDR); |
73 | } | 77 | } |
74 | 78 | ||
75 | for (i = 0; i < 16; i++) { | 79 | for (i = 0; i < 16; i++) { |
76 | void __iomem *reg = vic_base + VIC_VECT_CNTL0 + (i * 4); | 80 | void __iomem *reg = base + VIC_VECT_CNTL0 + (i * 4); |
77 | writel(VIC_VECT_CNTL_ENABLE | i, reg); | 81 | writel(VIC_VECT_CNTL_ENABLE | i, reg); |
78 | } | 82 | } |
79 | 83 | ||
80 | writel(32, vic_base + VIC_DEF_VECT_ADDR); | 84 | writel(32, base + VIC_DEF_VECT_ADDR); |
81 | 85 | ||
82 | for (i = 0; i < 32; i++) { | 86 | for (i = 0; i < 32; i++) { |
83 | unsigned int irq = IRQ_VIC_START + i; | 87 | unsigned int irq = irq_start + i; |
84 | 88 | ||
85 | set_irq_chip(irq, &vic_chip); | 89 | set_irq_chip(irq, &vic_chip); |
90 | set_irq_chipdata(irq, base); | ||
86 | 91 | ||
87 | if (vic_sources & (1 << i)) { | 92 | if (vic_sources & (1 << i)) { |
88 | set_irq_handler(irq, do_level_IRQ); | 93 | set_irq_handler(irq, do_level_IRQ); |