diff options
-rw-r--r-- | drivers/mfd/sm501.c | 33 | ||||
-rw-r--r-- | include/linux/sm501-regs.h | 5 |
2 files changed, 36 insertions, 2 deletions
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c index 3a0ecfc404e9..e14d70e07418 100644 --- a/drivers/mfd/sm501.c +++ b/drivers/mfd/sm501.c | |||
@@ -855,6 +855,24 @@ static void sm501_init_regs(struct sm501_devdata *sm, | |||
855 | dev_info(sm->dev, "setting MCLK to %ld\n", init->mclk); | 855 | dev_info(sm->dev, "setting MCLK to %ld\n", init->mclk); |
856 | sm501_set_clock(sm->dev, SM501_CLOCK_MCLK, init->mclk); | 856 | sm501_set_clock(sm->dev, SM501_CLOCK_MCLK, init->mclk); |
857 | } | 857 | } |
858 | |||
859 | } | ||
860 | |||
861 | /* Check the PLL sources for the M1CLK and M1XCLK | ||
862 | * | ||
863 | * If the M1CLK and M1XCLKs are not sourced from the same PLL, then | ||
864 | * there is a risk (see errata AB-5) that the SM501 will cease proper | ||
865 | * function. If this happens, then it is likely the SM501 will | ||
866 | * hang the system. | ||
867 | */ | ||
868 | |||
869 | static int sm501_check_clocks(struct sm501_devdata *sm) | ||
870 | { | ||
871 | unsigned long pwrmode = readl(sm->regs + SM501_CURRENT_CLOCK); | ||
872 | unsigned long msrc = (pwrmode & SM501_POWERMODE_M_SRC); | ||
873 | unsigned long m1src = (pwrmode & SM501_POWERMODE_M1_SRC); | ||
874 | |||
875 | return ((msrc == 0 && m1src != 0) || (msrc != 0 && m1src == 0)); | ||
858 | } | 876 | } |
859 | 877 | ||
860 | static unsigned int sm501_mem_local[] = { | 878 | static unsigned int sm501_mem_local[] = { |
@@ -911,6 +929,13 @@ static int sm501_init_dev(struct sm501_devdata *sm) | |||
911 | } | 929 | } |
912 | } | 930 | } |
913 | 931 | ||
932 | ret = sm501_check_clocks(sm); | ||
933 | if (ret) { | ||
934 | dev_err(sm->dev, "M1X and M clocks sourced from different " | ||
935 | "PLLs\n"); | ||
936 | return -EINVAL; | ||
937 | } | ||
938 | |||
914 | /* always create a framebuffer */ | 939 | /* always create a framebuffer */ |
915 | sm501_register_display(sm, &mem_avail); | 940 | sm501_register_display(sm, &mem_avail); |
916 | 941 | ||
@@ -1048,8 +1073,12 @@ static struct sm501_initdata sm501_pci_initdata = { | |||
1048 | }, | 1073 | }, |
1049 | 1074 | ||
1050 | .devices = SM501_USE_ALL, | 1075 | .devices = SM501_USE_ALL, |
1051 | .mclk = 100 * MHZ, | 1076 | |
1052 | .m1xclk = 160 * MHZ, | 1077 | /* Errata AB-3 says that 72MHz is the fastest available |
1078 | * for 33MHZ PCI with proper bus-mastering operation */ | ||
1079 | |||
1080 | .mclk = 72 * MHZ, | ||
1081 | .m1xclk = 144 * MHZ, | ||
1053 | }; | 1082 | }; |
1054 | 1083 | ||
1055 | static struct sm501_platdata_fbsub sm501_pdata_fbsub = { | 1084 | static struct sm501_platdata_fbsub sm501_pdata_fbsub = { |
diff --git a/include/linux/sm501-regs.h b/include/linux/sm501-regs.h index cc9be4a11861..8b4ecf02f9dc 100644 --- a/include/linux/sm501-regs.h +++ b/include/linux/sm501-regs.h | |||
@@ -64,6 +64,11 @@ | |||
64 | #define SM501_DEBUG_CONTROL (0x000034) | 64 | #define SM501_DEBUG_CONTROL (0x000034) |
65 | 65 | ||
66 | /* power management */ | 66 | /* power management */ |
67 | #define SM501_POWERMODE_P2X_SRC (1<<29) | ||
68 | #define SM501_POWERMODE_V2X_SRC (1<<20) | ||
69 | #define SM501_POWERMODE_M_SRC (1<<12) | ||
70 | #define SM501_POWERMODE_M1_SRC (1<<4) | ||
71 | |||
67 | #define SM501_CURRENT_GATE (0x000038) | 72 | #define SM501_CURRENT_GATE (0x000038) |
68 | #define SM501_CURRENT_CLOCK (0x00003C) | 73 | #define SM501_CURRENT_CLOCK (0x00003C) |
69 | #define SM501_POWER_MODE_0_GATE (0x000040) | 74 | #define SM501_POWER_MODE_0_GATE (0x000040) |