diff options
-rw-r--r-- | arch/arm/mach-shmobile/board-mackerel.c | 225 |
1 files changed, 160 insertions, 65 deletions
diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c index 776f20560e72..1037bd2ffdb9 100644 --- a/arch/arm/mach-shmobile/board-mackerel.c +++ b/arch/arm/mach-shmobile/board-mackerel.c | |||
@@ -126,7 +126,7 @@ | |||
126 | * ------+--------------------+--------------------+------- | 126 | * ------+--------------------+--------------------+------- |
127 | * IRQ0 | ICR1A.IRQ0SA=0010 | SDHI2 card detect | Low | 127 | * IRQ0 | ICR1A.IRQ0SA=0010 | SDHI2 card detect | Low |
128 | * IRQ6 | ICR1A.IRQ6SA=0011 | Ether(LAN9220) | High | 128 | * IRQ6 | ICR1A.IRQ6SA=0011 | Ether(LAN9220) | High |
129 | * IRQ7 | ICR1A.IRQ7SA=0010 | LCD Tuch Panel | Low | 129 | * IRQ7 | ICR1A.IRQ7SA=0010 | LCD Touch Panel | Low |
130 | * IRQ8 | ICR2A.IRQ8SA=0010 | MMC/SD card detect | Low | 130 | * IRQ8 | ICR2A.IRQ8SA=0010 | MMC/SD card detect | Low |
131 | * IRQ9 | ICR2A.IRQ9SA=0010 | KEY(TCA6408) | Low | 131 | * IRQ9 | ICR2A.IRQ9SA=0010 | KEY(TCA6408) | Low |
132 | * IRQ21 | ICR4A.IRQ21SA=0011 | Sensor(ADXL345) | High | 132 | * IRQ21 | ICR4A.IRQ21SA=0011 | Sensor(ADXL345) | High |
@@ -165,10 +165,10 @@ | |||
165 | * USB1 can become Host by r8a66597, and become Function by renesas_usbhs. | 165 | * USB1 can become Host by r8a66597, and become Function by renesas_usbhs. |
166 | * But don't select both drivers in same time. | 166 | * But don't select both drivers in same time. |
167 | * These uses same IRQ number for request_irq(), and aren't supporting | 167 | * These uses same IRQ number for request_irq(), and aren't supporting |
168 | * IRQF_SHARD / IORESOURCE_IRQ_SHAREABLE. | 168 | * IRQF_SHARED / IORESOURCE_IRQ_SHAREABLE. |
169 | * | 169 | * |
170 | * Actually these are old/new version of USB driver. | 170 | * Actually these are old/new version of USB driver. |
171 | * This mean its register will be broken if it supports SHARD IRQ, | 171 | * This mean its register will be broken if it supports shared IRQ, |
172 | */ | 172 | */ |
173 | 173 | ||
174 | /* | 174 | /* |
@@ -562,7 +562,136 @@ out: | |||
562 | clk_put(hdmi_ick); | 562 | clk_put(hdmi_ick); |
563 | } | 563 | } |
564 | 564 | ||
565 | /* USB1 (Host) */ | 565 | /* USBHS0 is connected to CN22 which takes a USB Mini-B plug |
566 | * | ||
567 | * The sh7372 SoC has IRQ7 set aside for USBHS0 hotplug, | ||
568 | * but on this particular board IRQ7 is already used by | ||
569 | * the touch screen. This leaves us with software polling. | ||
570 | */ | ||
571 | #define USBHS0_POLL_INTERVAL (HZ * 5) | ||
572 | |||
573 | struct usbhs_private { | ||
574 | unsigned int usbphyaddr; | ||
575 | unsigned int usbcrcaddr; | ||
576 | struct renesas_usbhs_platform_info info; | ||
577 | struct delayed_work work; | ||
578 | struct platform_device *pdev; | ||
579 | }; | ||
580 | |||
581 | #define usbhs_get_priv(pdev) \ | ||
582 | container_of(renesas_usbhs_get_info(pdev), \ | ||
583 | struct usbhs_private, info) | ||
584 | |||
585 | #define usbhs_is_connected(priv) \ | ||
586 | (!((1 << 7) & __raw_readw(priv->usbcrcaddr))) | ||
587 | |||
588 | static int usbhs_get_vbus(struct platform_device *pdev) | ||
589 | { | ||
590 | return usbhs_is_connected(usbhs_get_priv(pdev)); | ||
591 | } | ||
592 | |||
593 | static void usbhs_phy_reset(struct platform_device *pdev) | ||
594 | { | ||
595 | struct usbhs_private *priv = usbhs_get_priv(pdev); | ||
596 | |||
597 | /* init phy */ | ||
598 | __raw_writew(0x8a0a, priv->usbcrcaddr); | ||
599 | } | ||
600 | |||
601 | static int usbhs0_get_id(struct platform_device *pdev) | ||
602 | { | ||
603 | return USBHS_GADGET; | ||
604 | } | ||
605 | |||
606 | static void usbhs0_work_function(struct work_struct *work) | ||
607 | { | ||
608 | struct usbhs_private *priv = container_of(work, struct usbhs_private, | ||
609 | work.work); | ||
610 | |||
611 | renesas_usbhs_call_notify_hotplug(priv->pdev); | ||
612 | schedule_delayed_work(&priv->work, USBHS0_POLL_INTERVAL); | ||
613 | } | ||
614 | |||
615 | static int usbhs0_hardware_init(struct platform_device *pdev) | ||
616 | { | ||
617 | struct usbhs_private *priv = usbhs_get_priv(pdev); | ||
618 | |||
619 | priv->pdev = pdev; | ||
620 | INIT_DELAYED_WORK(&priv->work, usbhs0_work_function); | ||
621 | schedule_delayed_work(&priv->work, USBHS0_POLL_INTERVAL); | ||
622 | return 0; | ||
623 | } | ||
624 | |||
625 | static void usbhs0_hardware_exit(struct platform_device *pdev) | ||
626 | { | ||
627 | struct usbhs_private *priv = usbhs_get_priv(pdev); | ||
628 | |||
629 | cancel_delayed_work_sync(&priv->work); | ||
630 | } | ||
631 | |||
632 | static u32 usbhs0_pipe_cfg[] = { | ||
633 | USB_ENDPOINT_XFER_CONTROL, | ||
634 | USB_ENDPOINT_XFER_ISOC, | ||
635 | USB_ENDPOINT_XFER_ISOC, | ||
636 | USB_ENDPOINT_XFER_BULK, | ||
637 | USB_ENDPOINT_XFER_BULK, | ||
638 | USB_ENDPOINT_XFER_BULK, | ||
639 | USB_ENDPOINT_XFER_INT, | ||
640 | USB_ENDPOINT_XFER_INT, | ||
641 | USB_ENDPOINT_XFER_INT, | ||
642 | USB_ENDPOINT_XFER_BULK, | ||
643 | }; | ||
644 | |||
645 | static struct usbhs_private usbhs0_private = { | ||
646 | .usbcrcaddr = 0xe605810c, /* USBCR2 */ | ||
647 | .info = { | ||
648 | .platform_callback = { | ||
649 | .hardware_init = usbhs0_hardware_init, | ||
650 | .hardware_exit = usbhs0_hardware_exit, | ||
651 | .phy_reset = usbhs_phy_reset, | ||
652 | .get_id = usbhs0_get_id, | ||
653 | .get_vbus = usbhs_get_vbus, | ||
654 | }, | ||
655 | .driver_param = { | ||
656 | .buswait_bwait = 4, | ||
657 | .pipe_type = usbhs0_pipe_cfg, | ||
658 | .pipe_size = ARRAY_SIZE(usbhs0_pipe_cfg), | ||
659 | }, | ||
660 | }, | ||
661 | }; | ||
662 | |||
663 | static struct resource usbhs0_resources[] = { | ||
664 | [0] = { | ||
665 | .name = "USBHS0", | ||
666 | .start = 0xe6890000, | ||
667 | .end = 0xe68900e6 - 1, | ||
668 | .flags = IORESOURCE_MEM, | ||
669 | }, | ||
670 | [1] = { | ||
671 | .start = evt2irq(0x1ca0) /* USB0_USB0I0 */, | ||
672 | .flags = IORESOURCE_IRQ, | ||
673 | }, | ||
674 | }; | ||
675 | |||
676 | static struct platform_device usbhs0_device = { | ||
677 | .name = "renesas_usbhs", | ||
678 | .id = 0, | ||
679 | .dev = { | ||
680 | .platform_data = &usbhs0_private.info, | ||
681 | }, | ||
682 | .num_resources = ARRAY_SIZE(usbhs0_resources), | ||
683 | .resource = usbhs0_resources, | ||
684 | }; | ||
685 | |||
686 | /* USBHS1 is connected to CN31 which takes a USB Mini-AB plug | ||
687 | * | ||
688 | * Use J30 to select between Host and Function. This setting | ||
689 | * can however not be detected by software. Hotplug of USBHS1 | ||
690 | * is provided via IRQ8. | ||
691 | */ | ||
692 | #define IRQ8 evt2irq(0x0300) | ||
693 | |||
694 | /* USBHS1 USB Host support via r8a66597_hcd */ | ||
566 | static void usb1_host_port_power(int port, int power) | 695 | static void usb1_host_port_power(int port, int power) |
567 | { | 696 | { |
568 | if (!power) /* only power-on is supported for now */ | 697 | if (!power) /* only power-on is supported for now */ |
@@ -579,9 +708,9 @@ static struct r8a66597_platdata usb1_host_data = { | |||
579 | 708 | ||
580 | static struct resource usb1_host_resources[] = { | 709 | static struct resource usb1_host_resources[] = { |
581 | [0] = { | 710 | [0] = { |
582 | .name = "USBHS", | 711 | .name = "USBHS1", |
583 | .start = 0xE68B0000, | 712 | .start = 0xe68b0000, |
584 | .end = 0xE68B00E6 - 1, | 713 | .end = 0xe68b00e6 - 1, |
585 | .flags = IORESOURCE_MEM, | 714 | .flags = IORESOURCE_MEM, |
586 | }, | 715 | }, |
587 | [1] = { | 716 | [1] = { |
@@ -602,37 +731,14 @@ static struct platform_device usb1_host_device = { | |||
602 | .resource = usb1_host_resources, | 731 | .resource = usb1_host_resources, |
603 | }; | 732 | }; |
604 | 733 | ||
605 | /* USB1 (Function) */ | 734 | /* USBHS1 USB Function support via renesas_usbhs */ |
735 | |||
606 | #define USB_PHY_MODE (1 << 4) | 736 | #define USB_PHY_MODE (1 << 4) |
607 | #define USB_PHY_INT_EN ((1 << 3) | (1 << 2)) | 737 | #define USB_PHY_INT_EN ((1 << 3) | (1 << 2)) |
608 | #define USB_PHY_ON (1 << 1) | 738 | #define USB_PHY_ON (1 << 1) |
609 | #define USB_PHY_OFF (1 << 0) | 739 | #define USB_PHY_OFF (1 << 0) |
610 | #define USB_PHY_INT_CLR (USB_PHY_ON | USB_PHY_OFF) | 740 | #define USB_PHY_INT_CLR (USB_PHY_ON | USB_PHY_OFF) |
611 | 741 | ||
612 | struct usbhs_private { | ||
613 | unsigned int irq; | ||
614 | unsigned int usbphyaddr; | ||
615 | unsigned int usbcrcaddr; | ||
616 | struct renesas_usbhs_platform_info info; | ||
617 | }; | ||
618 | |||
619 | #define usbhs_get_priv(pdev) \ | ||
620 | container_of(renesas_usbhs_get_info(pdev), \ | ||
621 | struct usbhs_private, info) | ||
622 | |||
623 | #define usbhs_is_connected(priv) \ | ||
624 | (!((1 << 7) & __raw_readw(priv->usbcrcaddr))) | ||
625 | |||
626 | static int usbhs1_get_id(struct platform_device *pdev) | ||
627 | { | ||
628 | return USBHS_GADGET; | ||
629 | } | ||
630 | |||
631 | static int usbhs1_get_vbus(struct platform_device *pdev) | ||
632 | { | ||
633 | return usbhs_is_connected(usbhs_get_priv(pdev)); | ||
634 | } | ||
635 | |||
636 | static irqreturn_t usbhs1_interrupt(int irq, void *data) | 742 | static irqreturn_t usbhs1_interrupt(int irq, void *data) |
637 | { | 743 | { |
638 | struct platform_device *pdev = data; | 744 | struct platform_device *pdev = data; |
@@ -654,12 +760,10 @@ static int usbhs1_hardware_init(struct platform_device *pdev) | |||
654 | struct usbhs_private *priv = usbhs_get_priv(pdev); | 760 | struct usbhs_private *priv = usbhs_get_priv(pdev); |
655 | int ret; | 761 | int ret; |
656 | 762 | ||
657 | irq_set_irq_type(priv->irq, IRQ_TYPE_LEVEL_HIGH); | ||
658 | |||
659 | /* clear interrupt status */ | 763 | /* clear interrupt status */ |
660 | __raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->usbphyaddr); | 764 | __raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->usbphyaddr); |
661 | 765 | ||
662 | ret = request_irq(priv->irq, usbhs1_interrupt, 0, | 766 | ret = request_irq(IRQ8, usbhs1_interrupt, IRQF_TRIGGER_HIGH, |
663 | dev_name(&pdev->dev), pdev); | 767 | dev_name(&pdev->dev), pdev); |
664 | if (ret) { | 768 | if (ret) { |
665 | dev_err(&pdev->dev, "request_irq err\n"); | 769 | dev_err(&pdev->dev, "request_irq err\n"); |
@@ -679,15 +783,7 @@ static void usbhs1_hardware_exit(struct platform_device *pdev) | |||
679 | /* clear interrupt status */ | 783 | /* clear interrupt status */ |
680 | __raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->usbphyaddr); | 784 | __raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->usbphyaddr); |
681 | 785 | ||
682 | free_irq(priv->irq, pdev); | 786 | free_irq(IRQ8, pdev); |
683 | } | ||
684 | |||
685 | static void usbhs1_phy_reset(struct platform_device *pdev) | ||
686 | { | ||
687 | struct usbhs_private *priv = usbhs_get_priv(pdev); | ||
688 | |||
689 | /* init phy */ | ||
690 | __raw_writew(0x8a0a, priv->usbcrcaddr); | ||
691 | } | 787 | } |
692 | 788 | ||
693 | static u32 usbhs1_pipe_cfg[] = { | 789 | static u32 usbhs1_pipe_cfg[] = { |
@@ -710,16 +806,14 @@ static u32 usbhs1_pipe_cfg[] = { | |||
710 | }; | 806 | }; |
711 | 807 | ||
712 | static struct usbhs_private usbhs1_private = { | 808 | static struct usbhs_private usbhs1_private = { |
713 | .irq = evt2irq(0x0300), /* IRQ8 */ | 809 | .usbphyaddr = 0xe60581e2, /* USBPHY1INTAP */ |
714 | .usbphyaddr = 0xE60581E2, /* USBPHY1INTAP */ | 810 | .usbcrcaddr = 0xe6058130, /* USBCR4 */ |
715 | .usbcrcaddr = 0xE6058130, /* USBCR4 */ | ||
716 | .info = { | 811 | .info = { |
717 | .platform_callback = { | 812 | .platform_callback = { |
718 | .hardware_init = usbhs1_hardware_init, | 813 | .hardware_init = usbhs1_hardware_init, |
719 | .hardware_exit = usbhs1_hardware_exit, | 814 | .hardware_exit = usbhs1_hardware_exit, |
720 | .phy_reset = usbhs1_phy_reset, | 815 | .phy_reset = usbhs_phy_reset, |
721 | .get_id = usbhs1_get_id, | 816 | .get_vbus = usbhs_get_vbus, |
722 | .get_vbus = usbhs1_get_vbus, | ||
723 | }, | 817 | }, |
724 | .driver_param = { | 818 | .driver_param = { |
725 | .buswait_bwait = 4, | 819 | .buswait_bwait = 4, |
@@ -731,9 +825,9 @@ static struct usbhs_private usbhs1_private = { | |||
731 | 825 | ||
732 | static struct resource usbhs1_resources[] = { | 826 | static struct resource usbhs1_resources[] = { |
733 | [0] = { | 827 | [0] = { |
734 | .name = "USBHS", | 828 | .name = "USBHS1", |
735 | .start = 0xE68B0000, | 829 | .start = 0xe68b0000, |
736 | .end = 0xE68B00E6 - 1, | 830 | .end = 0xe68b00e6 - 1, |
737 | .flags = IORESOURCE_MEM, | 831 | .flags = IORESOURCE_MEM, |
738 | }, | 832 | }, |
739 | [1] = { | 833 | [1] = { |
@@ -752,7 +846,6 @@ static struct platform_device usbhs1_device = { | |||
752 | .resource = usbhs1_resources, | 846 | .resource = usbhs1_resources, |
753 | }; | 847 | }; |
754 | 848 | ||
755 | |||
756 | /* LED */ | 849 | /* LED */ |
757 | static struct gpio_led mackerel_leds[] = { | 850 | static struct gpio_led mackerel_leds[] = { |
758 | { | 851 | { |
@@ -1203,6 +1296,7 @@ static struct platform_device *mackerel_devices[] __initdata = { | |||
1203 | &nor_flash_device, | 1296 | &nor_flash_device, |
1204 | &smc911x_device, | 1297 | &smc911x_device, |
1205 | &lcdc_device, | 1298 | &lcdc_device, |
1299 | &usbhs0_device, | ||
1206 | &usb1_host_device, | 1300 | &usb1_host_device, |
1207 | &usbhs1_device, | 1301 | &usbhs1_device, |
1208 | &leds_device, | 1302 | &leds_device, |
@@ -1301,6 +1395,7 @@ static void __init mackerel_map_io(void) | |||
1301 | 1395 | ||
1302 | #define GPIO_PORT9CR 0xE6051009 | 1396 | #define GPIO_PORT9CR 0xE6051009 |
1303 | #define GPIO_PORT10CR 0xE605100A | 1397 | #define GPIO_PORT10CR 0xE605100A |
1398 | #define GPIO_PORT167CR 0xE60520A7 | ||
1304 | #define GPIO_PORT168CR 0xE60520A8 | 1399 | #define GPIO_PORT168CR 0xE60520A8 |
1305 | #define SRCR4 0xe61580bc | 1400 | #define SRCR4 0xe61580bc |
1306 | #define USCCR1 0xE6058144 | 1401 | #define USCCR1 0xE6058144 |
@@ -1354,17 +1449,17 @@ static void __init mackerel_init(void) | |||
1354 | gpio_request(GPIO_PORT151, NULL); /* LCDDON */ | 1449 | gpio_request(GPIO_PORT151, NULL); /* LCDDON */ |
1355 | gpio_direction_output(GPIO_PORT151, 1); | 1450 | gpio_direction_output(GPIO_PORT151, 1); |
1356 | 1451 | ||
1357 | /* USB enable */ | 1452 | /* USBHS0 */ |
1358 | gpio_request(GPIO_FN_VBUS0_1, NULL); | 1453 | gpio_request(GPIO_FN_VBUS0_0, NULL); |
1359 | gpio_request(GPIO_FN_IDIN_1_18, NULL); | 1454 | gpio_pull_down(GPIO_PORT168CR); /* VBUS0_0 pull down */ |
1360 | gpio_request(GPIO_FN_PWEN_1_115, NULL); | 1455 | |
1361 | gpio_request(GPIO_FN_OVCN_1_114, NULL); | 1456 | /* USBHS1 */ |
1362 | gpio_request(GPIO_FN_EXTLP_1, NULL); | 1457 | gpio_request(GPIO_FN_VBUS0_1, NULL); |
1363 | gpio_request(GPIO_FN_OVCN2_1, NULL); | 1458 | gpio_pull_down(GPIO_PORT167CR); /* VBUS0_1 pull down */ |
1364 | gpio_pull_down(GPIO_PORT168CR); | 1459 | gpio_request(GPIO_FN_IDIN_1_113, NULL); |
1365 | 1460 | ||
1366 | /* setup USB phy */ | 1461 | /* USB phy tweak to make the r8a66597_hcd host driver work */ |
1367 | __raw_writew(0x8a0a, 0xE6058130); /* USBCR4 */ | 1462 | __raw_writew(0x8a0a, 0xe6058130); /* USBCR4 */ |
1368 | 1463 | ||
1369 | /* enable FSI2 port A (ak4643) */ | 1464 | /* enable FSI2 port A (ak4643) */ |
1370 | gpio_request(GPIO_FN_FSIAIBT, NULL); | 1465 | gpio_request(GPIO_FN_FSIAIBT, NULL); |