diff options
Diffstat (limited to 'arch/arm/mach-shmobile/board-ap4evb.c')
| -rw-r--r-- | arch/arm/mach-shmobile/board-ap4evb.c | 167 |
1 files changed, 146 insertions, 21 deletions
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c index 46ca4d4abf91..d440e5f456ad 100644 --- a/arch/arm/mach-shmobile/board-ap4evb.c +++ b/arch/arm/mach-shmobile/board-ap4evb.c | |||
| @@ -163,11 +163,13 @@ static struct mtd_partition nor_flash_partitions[] = { | |||
| 163 | .name = "loader", | 163 | .name = "loader", |
| 164 | .offset = 0x00000000, | 164 | .offset = 0x00000000, |
| 165 | .size = 512 * 1024, | 165 | .size = 512 * 1024, |
| 166 | .mask_flags = MTD_WRITEABLE, | ||
| 166 | }, | 167 | }, |
| 167 | { | 168 | { |
| 168 | .name = "bootenv", | 169 | .name = "bootenv", |
| 169 | .offset = MTDPART_OFS_APPEND, | 170 | .offset = MTDPART_OFS_APPEND, |
| 170 | .size = 512 * 1024, | 171 | .size = 512 * 1024, |
| 172 | .mask_flags = MTD_WRITEABLE, | ||
| 171 | }, | 173 | }, |
| 172 | { | 174 | { |
| 173 | .name = "kernel_ro", | 175 | .name = "kernel_ro", |
| @@ -565,12 +567,143 @@ static struct platform_device *qhd_devices[] __initdata = { | |||
| 565 | 567 | ||
| 566 | /* FSI */ | 568 | /* FSI */ |
| 567 | #define IRQ_FSI evt2irq(0x1840) | 569 | #define IRQ_FSI evt2irq(0x1840) |
| 570 | static int __fsi_set_rate(struct clk *clk, long rate, int enable) | ||
| 571 | { | ||
| 572 | int ret = 0; | ||
| 573 | |||
| 574 | if (rate <= 0) | ||
| 575 | return ret; | ||
| 576 | |||
| 577 | if (enable) { | ||
| 578 | ret = clk_set_rate(clk, rate); | ||
| 579 | if (0 == ret) | ||
| 580 | ret = clk_enable(clk); | ||
| 581 | } else { | ||
| 582 | clk_disable(clk); | ||
| 583 | } | ||
| 584 | |||
| 585 | return ret; | ||
| 586 | } | ||
| 587 | |||
| 588 | static int __fsi_set_round_rate(struct clk *clk, long rate, int enable) | ||
| 589 | { | ||
| 590 | return __fsi_set_rate(clk, clk_round_rate(clk, rate), enable); | ||
| 591 | } | ||
| 592 | |||
| 593 | static int fsi_ak4642_set_rate(struct device *dev, int rate, int enable) | ||
| 594 | { | ||
| 595 | struct clk *fsia_ick; | ||
| 596 | struct clk *fsiack; | ||
| 597 | int ret = -EIO; | ||
| 598 | |||
| 599 | fsia_ick = clk_get(dev, "icka"); | ||
| 600 | if (IS_ERR(fsia_ick)) | ||
| 601 | return PTR_ERR(fsia_ick); | ||
| 602 | |||
| 603 | /* | ||
| 604 | * FSIACK is connected to AK4642, | ||
| 605 | * and use external clock pin from it. | ||
| 606 | * it is parent of fsia_ick now. | ||
| 607 | */ | ||
| 608 | fsiack = clk_get_parent(fsia_ick); | ||
| 609 | if (!fsiack) | ||
| 610 | goto fsia_ick_out; | ||
| 611 | |||
| 612 | /* | ||
| 613 | * we get 1/1 divided clock by setting same rate to fsiack and fsia_ick | ||
| 614 | * | ||
| 615 | ** FIXME ** | ||
| 616 | * Because the freq_table of external clk (fsiack) are all 0, | ||
| 617 | * the return value of clk_round_rate became 0. | ||
| 618 | * So, it use __fsi_set_rate here. | ||
| 619 | */ | ||
| 620 | ret = __fsi_set_rate(fsiack, rate, enable); | ||
| 621 | if (ret < 0) | ||
| 622 | goto fsiack_out; | ||
| 623 | |||
| 624 | ret = __fsi_set_round_rate(fsia_ick, rate, enable); | ||
| 625 | if ((ret < 0) && enable) | ||
| 626 | __fsi_set_round_rate(fsiack, rate, 0); /* disable FSI ACK */ | ||
| 627 | |||
| 628 | fsiack_out: | ||
| 629 | clk_put(fsiack); | ||
| 630 | |||
| 631 | fsia_ick_out: | ||
| 632 | clk_put(fsia_ick); | ||
| 633 | |||
| 634 | return 0; | ||
| 635 | } | ||
| 636 | |||
| 637 | static int fsi_hdmi_set_rate(struct device *dev, int rate, int enable) | ||
| 638 | { | ||
| 639 | struct clk *fsib_clk; | ||
| 640 | struct clk *fdiv_clk = &sh7372_fsidivb_clk; | ||
| 641 | long fsib_rate = 0; | ||
| 642 | long fdiv_rate = 0; | ||
| 643 | int ackmd_bpfmd; | ||
| 644 | int ret; | ||
| 645 | |||
| 646 | switch (rate) { | ||
| 647 | case 44100: | ||
| 648 | fsib_rate = rate * 256; | ||
| 649 | ackmd_bpfmd = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64; | ||
| 650 | break; | ||
| 651 | case 48000: | ||
| 652 | fsib_rate = 85428000; /* around 48kHz x 256 x 7 */ | ||
| 653 | fdiv_rate = rate * 256; | ||
| 654 | ackmd_bpfmd = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64; | ||
| 655 | break; | ||
| 656 | default: | ||
| 657 | pr_err("unsupported rate in FSI2 port B\n"); | ||
| 658 | return -EINVAL; | ||
| 659 | } | ||
| 660 | |||
| 661 | /* FSI B setting */ | ||
| 662 | fsib_clk = clk_get(dev, "ickb"); | ||
| 663 | if (IS_ERR(fsib_clk)) | ||
| 664 | return -EIO; | ||
| 665 | |||
| 666 | ret = __fsi_set_round_rate(fsib_clk, fsib_rate, enable); | ||
| 667 | clk_put(fsib_clk); | ||
| 668 | if (ret < 0) | ||
| 669 | return ret; | ||
| 670 | |||
| 671 | /* FSI DIV setting */ | ||
| 672 | ret = __fsi_set_round_rate(fdiv_clk, fdiv_rate, enable); | ||
| 673 | if (ret < 0) { | ||
| 674 | /* disable FSI B */ | ||
| 675 | if (enable) | ||
| 676 | __fsi_set_round_rate(fsib_clk, fsib_rate, 0); | ||
| 677 | return ret; | ||
| 678 | } | ||
| 679 | |||
| 680 | return ackmd_bpfmd; | ||
| 681 | } | ||
| 682 | |||
| 683 | static int fsi_set_rate(struct device *dev, int is_porta, int rate, int enable) | ||
| 684 | { | ||
| 685 | int ret; | ||
| 686 | |||
| 687 | if (is_porta) | ||
| 688 | ret = fsi_ak4642_set_rate(dev, rate, enable); | ||
| 689 | else | ||
| 690 | ret = fsi_hdmi_set_rate(dev, rate, enable); | ||
| 691 | |||
| 692 | return ret; | ||
| 693 | } | ||
| 694 | |||
| 568 | static struct sh_fsi_platform_info fsi_info = { | 695 | static struct sh_fsi_platform_info fsi_info = { |
| 569 | .porta_flags = SH_FSI_BRS_INV | | 696 | .porta_flags = SH_FSI_BRS_INV | |
| 570 | SH_FSI_OUT_SLAVE_MODE | | 697 | SH_FSI_OUT_SLAVE_MODE | |
| 571 | SH_FSI_IN_SLAVE_MODE | | 698 | SH_FSI_IN_SLAVE_MODE | |
| 572 | SH_FSI_OFMT(PCM) | | 699 | SH_FSI_OFMT(PCM) | |
| 573 | SH_FSI_IFMT(PCM), | 700 | SH_FSI_IFMT(PCM), |
| 701 | |||
| 702 | .portb_flags = SH_FSI_BRS_INV | | ||
| 703 | SH_FSI_BRM_INV | | ||
| 704 | SH_FSI_LRS_INV | | ||
| 705 | SH_FSI_OFMT(SPDIF), | ||
| 706 | .set_rate = fsi_set_rate, | ||
| 574 | }; | 707 | }; |
| 575 | 708 | ||
| 576 | static struct resource fsi_resources[] = { | 709 | static struct resource fsi_resources[] = { |
| @@ -634,6 +767,7 @@ static struct platform_device lcdc1_device = { | |||
| 634 | static struct sh_mobile_hdmi_info hdmi_info = { | 767 | static struct sh_mobile_hdmi_info hdmi_info = { |
| 635 | .lcd_chan = &sh_mobile_lcdc1_info.ch[0], | 768 | .lcd_chan = &sh_mobile_lcdc1_info.ch[0], |
| 636 | .lcd_dev = &lcdc1_device.dev, | 769 | .lcd_dev = &lcdc1_device.dev, |
| 770 | .flags = HDMI_SND_SRC_SPDIF, | ||
| 637 | }; | 771 | }; |
| 638 | 772 | ||
| 639 | static struct resource hdmi_resources[] = { | 773 | static struct resource hdmi_resources[] = { |
| @@ -835,6 +969,11 @@ static int __init hdmi_init_pm_clock(void) | |||
| 835 | goto out; | 969 | goto out; |
| 836 | } | 970 | } |
| 837 | 971 | ||
| 972 | ret = clk_enable(&sh7372_pllc2_clk); | ||
| 973 | if (ret < 0) { | ||
| 974 | pr_err("Cannot enable pllc2 clock\n"); | ||
| 975 | goto out; | ||
| 976 | } | ||
| 838 | pr_debug("PLLC2 set frequency %lu\n", rate); | 977 | pr_debug("PLLC2 set frequency %lu\n", rate); |
| 839 | 978 | ||
| 840 | ret = clk_set_parent(hdmi_ick, &sh7372_pllc2_clk); | 979 | ret = clk_set_parent(hdmi_ick, &sh7372_pllc2_clk); |
| @@ -851,23 +990,11 @@ out: | |||
| 851 | 990 | ||
| 852 | device_initcall(hdmi_init_pm_clock); | 991 | device_initcall(hdmi_init_pm_clock); |
| 853 | 992 | ||
| 854 | #define FSIACK_DUMMY_RATE 48000 | ||
| 855 | static int __init fsi_init_pm_clock(void) | 993 | static int __init fsi_init_pm_clock(void) |
| 856 | { | 994 | { |
| 857 | struct clk *fsia_ick; | 995 | struct clk *fsia_ick; |
| 858 | int ret; | 996 | int ret; |
| 859 | 997 | ||
| 860 | /* | ||
| 861 | * FSIACK is connected to AK4642, | ||
| 862 | * and the rate is depend on playing sound rate. | ||
| 863 | * So, set dummy rate (= 48k) here | ||
| 864 | */ | ||
| 865 | ret = clk_set_rate(&sh7372_fsiack_clk, FSIACK_DUMMY_RATE); | ||
| 866 | if (ret < 0) { | ||
| 867 | pr_err("Cannot set FSIACK dummy rate: %d\n", ret); | ||
| 868 | return ret; | ||
| 869 | } | ||
| 870 | |||
| 871 | fsia_ick = clk_get(&fsi_device.dev, "icka"); | 998 | fsia_ick = clk_get(&fsi_device.dev, "icka"); |
| 872 | if (IS_ERR(fsia_ick)) { | 999 | if (IS_ERR(fsia_ick)) { |
| 873 | ret = PTR_ERR(fsia_ick); | 1000 | ret = PTR_ERR(fsia_ick); |
| @@ -876,16 +1003,9 @@ static int __init fsi_init_pm_clock(void) | |||
| 876 | } | 1003 | } |
| 877 | 1004 | ||
| 878 | ret = clk_set_parent(fsia_ick, &sh7372_fsiack_clk); | 1005 | ret = clk_set_parent(fsia_ick, &sh7372_fsiack_clk); |
| 879 | if (ret < 0) { | ||
| 880 | pr_err("Cannot set FSI-A parent: %d\n", ret); | ||
| 881 | goto out; | ||
| 882 | } | ||
| 883 | |||
| 884 | ret = clk_set_rate(fsia_ick, FSIACK_DUMMY_RATE); | ||
| 885 | if (ret < 0) | 1006 | if (ret < 0) |
| 886 | pr_err("Cannot set FSI-A rate: %d\n", ret); | 1007 | pr_err("Cannot set FSI-A parent: %d\n", ret); |
| 887 | 1008 | ||
| 888 | out: | ||
| 889 | clk_put(fsia_ick); | 1009 | clk_put(fsia_ick); |
| 890 | 1010 | ||
| 891 | return ret; | 1011 | return ret; |
| @@ -992,6 +1112,7 @@ static void __init ap4evb_map_io(void) | |||
| 992 | 1112 | ||
| 993 | #define GPIO_PORT9CR 0xE6051009 | 1113 | #define GPIO_PORT9CR 0xE6051009 |
| 994 | #define GPIO_PORT10CR 0xE605100A | 1114 | #define GPIO_PORT10CR 0xE605100A |
| 1115 | #define USCCR1 0xE6058144 | ||
| 995 | static void __init ap4evb_init(void) | 1116 | static void __init ap4evb_init(void) |
| 996 | { | 1117 | { |
| 997 | u32 srcr4; | 1118 | u32 srcr4; |
| @@ -1062,7 +1183,7 @@ static void __init ap4evb_init(void) | |||
| 1062 | /* setup USB phy */ | 1183 | /* setup USB phy */ |
| 1063 | __raw_writew(0x8a0a, 0xE6058130); /* USBCR2 */ | 1184 | __raw_writew(0x8a0a, 0xE6058130); /* USBCR2 */ |
| 1064 | 1185 | ||
| 1065 | /* enable FSI2 */ | 1186 | /* enable FSI2 port A (ak4643) */ |
| 1066 | gpio_request(GPIO_FN_FSIAIBT, NULL); | 1187 | gpio_request(GPIO_FN_FSIAIBT, NULL); |
| 1067 | gpio_request(GPIO_FN_FSIAILR, NULL); | 1188 | gpio_request(GPIO_FN_FSIAILR, NULL); |
| 1068 | gpio_request(GPIO_FN_FSIAISLD, NULL); | 1189 | gpio_request(GPIO_FN_FSIAISLD, NULL); |
| @@ -1079,6 +1200,10 @@ static void __init ap4evb_init(void) | |||
| 1079 | gpio_request(GPIO_PORT41, NULL); | 1200 | gpio_request(GPIO_PORT41, NULL); |
| 1080 | gpio_direction_input(GPIO_PORT41); | 1201 | gpio_direction_input(GPIO_PORT41); |
| 1081 | 1202 | ||
| 1203 | /* setup FSI2 port B (HDMI) */ | ||
| 1204 | gpio_request(GPIO_FN_FSIBCK, NULL); | ||
| 1205 | __raw_writew(__raw_readw(USCCR1) & ~(1 << 6), USCCR1); /* use SPDIF */ | ||
| 1206 | |||
| 1082 | /* set SPU2 clock to 119.6 MHz */ | 1207 | /* set SPU2 clock to 119.6 MHz */ |
| 1083 | clk = clk_get(NULL, "spu_clk"); | 1208 | clk = clk_get(NULL, "spu_clk"); |
| 1084 | if (!IS_ERR(clk)) { | 1209 | if (!IS_ERR(clk)) { |
