aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/sm501.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mfd/sm501.c')
-rw-r--r--drivers/mfd/sm501.c173
1 files changed, 154 insertions, 19 deletions
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
index b0b4458ae90b..8135e4c3bf47 100644
--- a/drivers/mfd/sm501.c
+++ b/drivers/mfd/sm501.c
@@ -41,6 +41,9 @@ struct sm501_devdata {
41 struct resource *regs_claim; 41 struct resource *regs_claim;
42 struct sm501_platdata *platdata; 42 struct sm501_platdata *platdata;
43 43
44 unsigned int in_suspend;
45 unsigned long pm_misc;
46
44 int unit_power[20]; 47 int unit_power[20];
45 unsigned int pdev_id; 48 unsigned int pdev_id;
46 unsigned int irq; 49 unsigned int irq;
@@ -169,10 +172,41 @@ x "M %ld.%ld (%ld), MX1 %ld.%ld (%ld)\n",
169 fmt_freq(decode_div(pll2, pm1, 8, 1<<12, 15, misc_div)), 172 fmt_freq(decode_div(pll2, pm1, 8, 1<<12, 15, misc_div)),
170 fmt_freq(decode_div(pll2, pm1, 0, 1<<4, 15, misc_div))); 173 fmt_freq(decode_div(pll2, pm1, 0, 1<<4, 15, misc_div)));
171} 174}
172#else 175
173static void sm501_dump_clk(struct sm501_devdata *sm) 176static void sm501_dump_regs(struct sm501_devdata *sm)
174{ 177{
178 void __iomem *regs = sm->regs;
179
180 dev_info(sm->dev, "System Control %08x\n",
181 readl(regs + SM501_SYSTEM_CONTROL));
182 dev_info(sm->dev, "Misc Control %08x\n",
183 readl(regs + SM501_MISC_CONTROL));
184 dev_info(sm->dev, "GPIO Control Low %08x\n",
185 readl(regs + SM501_GPIO31_0_CONTROL));
186 dev_info(sm->dev, "GPIO Control Hi %08x\n",
187 readl(regs + SM501_GPIO63_32_CONTROL));
188 dev_info(sm->dev, "DRAM Control %08x\n",
189 readl(regs + SM501_DRAM_CONTROL));
190 dev_info(sm->dev, "Arbitration Ctrl %08x\n",
191 readl(regs + SM501_ARBTRTN_CONTROL));
192 dev_info(sm->dev, "Misc Timing %08x\n",
193 readl(regs + SM501_MISC_TIMING));
175} 194}
195
196static void sm501_dump_gate(struct sm501_devdata *sm)
197{
198 dev_info(sm->dev, "CurrentGate %08x\n",
199 readl(sm->regs + SM501_CURRENT_GATE));
200 dev_info(sm->dev, "CurrentClock %08x\n",
201 readl(sm->regs + SM501_CURRENT_CLOCK));
202 dev_info(sm->dev, "PowerModeControl %08x\n",
203 readl(sm->regs + SM501_POWER_MODE_CONTROL));
204}
205
206#else
207static inline void sm501_dump_gate(struct sm501_devdata *sm) { }
208static inline void sm501_dump_regs(struct sm501_devdata *sm) { }
209static inline void sm501_dump_clk(struct sm501_devdata *sm) { }
176#endif 210#endif
177 211
178/* sm501_sync_regs 212/* sm501_sync_regs
@@ -185,9 +219,21 @@ static void sm501_sync_regs(struct sm501_devdata *sm)
185 readl(sm->regs); 219 readl(sm->regs);
186} 220}
187 221
222static inline void sm501_mdelay(struct sm501_devdata *sm, unsigned int delay)
223{
224 /* during suspend/resume, we are currently not allowed to sleep,
225 * so change to using mdelay() instead of msleep() if we
226 * are in one of these paths */
227
228 if (sm->in_suspend)
229 mdelay(delay);
230 else
231 msleep(delay);
232}
233
188/* sm501_misc_control 234/* sm501_misc_control
189 * 235 *
190 * alters the misceleneous control parameters 236 * alters the miscellaneous control parameters
191*/ 237*/
192 238
193int sm501_misc_control(struct device *dev, 239int sm501_misc_control(struct device *dev,
@@ -368,7 +414,7 @@ int sm501_unit_power(struct device *dev, unsigned int unit, unsigned int to)
368 dev_dbg(sm->dev, "gate %08lx, clock %08lx, mode %08lx\n", 414 dev_dbg(sm->dev, "gate %08lx, clock %08lx, mode %08lx\n",
369 gate, clock, mode); 415 gate, clock, mode);
370 416
371 msleep(16); 417 sm501_mdelay(sm, 16);
372 418
373 already: 419 already:
374 mutex_unlock(&sm->clock_lock); 420 mutex_unlock(&sm->clock_lock);
@@ -538,7 +584,7 @@ unsigned long sm501_set_clock(struct device *dev,
538 dev_info(sm->dev, "gate %08lx, clock %08lx, mode %08lx\n", 584 dev_info(sm->dev, "gate %08lx, clock %08lx, mode %08lx\n",
539 gate, clock, mode); 585 gate, clock, mode);
540 586
541 msleep(16); 587 sm501_mdelay(sm, 16);
542 mutex_unlock(&sm->clock_lock); 588 mutex_unlock(&sm->clock_lock);
543 589
544 sm501_dump_clk(sm); 590 sm501_dump_clk(sm);
@@ -767,6 +813,9 @@ static DEVICE_ATTR(dbg_regs, 0666, sm501_dbg_regs, NULL);
767/* sm501_init_reg 813/* sm501_init_reg
768 * 814 *
769 * Helper function for the init code to setup a register 815 * Helper function for the init code to setup a register
816 *
817 * clear the bits which are set in r->mask, and then set
818 * the bits set in r->set.
770*/ 819*/
771 820
772static inline void sm501_init_reg(struct sm501_devdata *sm, 821static inline void sm501_init_reg(struct sm501_devdata *sm,
@@ -776,8 +825,8 @@ static inline void sm501_init_reg(struct sm501_devdata *sm,
776 unsigned long tmp; 825 unsigned long tmp;
777 826
778 tmp = readl(sm->regs + reg); 827 tmp = readl(sm->regs + reg);
779 tmp |= r->set;
780 tmp &= ~r->mask; 828 tmp &= ~r->mask;
829 tmp |= r->set;
781 writel(tmp, sm->regs + reg); 830 writel(tmp, sm->regs + reg);
782} 831}
783 832
@@ -797,15 +846,33 @@ static void sm501_init_regs(struct sm501_devdata *sm,
797 sm501_init_reg(sm, SM501_GPIO31_0_CONTROL, &init->gpio_low); 846 sm501_init_reg(sm, SM501_GPIO31_0_CONTROL, &init->gpio_low);
798 sm501_init_reg(sm, SM501_GPIO63_32_CONTROL, &init->gpio_high); 847 sm501_init_reg(sm, SM501_GPIO63_32_CONTROL, &init->gpio_high);
799 848
849 if (init->m1xclk) {
850 dev_info(sm->dev, "setting M1XCLK to %ld\n", init->m1xclk);
851 sm501_set_clock(sm->dev, SM501_CLOCK_M1XCLK, init->m1xclk);
852 }
853
800 if (init->mclk) { 854 if (init->mclk) {
801 dev_info(sm->dev, "setting MCLK to %ld\n", init->mclk); 855 dev_info(sm->dev, "setting MCLK to %ld\n", init->mclk);
802 sm501_set_clock(sm->dev, SM501_CLOCK_MCLK, init->mclk); 856 sm501_set_clock(sm->dev, SM501_CLOCK_MCLK, init->mclk);
803 } 857 }
804 858
805 if (init->m1xclk) { 859}
806 dev_info(sm->dev, "setting M1XCLK to %ld\n", init->m1xclk); 860
807 sm501_set_clock(sm->dev, SM501_CLOCK_M1XCLK, init->m1xclk); 861/* Check the PLL sources for the M1CLK and M1XCLK
808 } 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
869static 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));
809} 876}
810 877
811static unsigned int sm501_mem_local[] = { 878static unsigned int sm501_mem_local[] = {
@@ -826,6 +893,7 @@ static int sm501_init_dev(struct sm501_devdata *sm)
826{ 893{
827 resource_size_t mem_avail; 894 resource_size_t mem_avail;
828 unsigned long dramctrl; 895 unsigned long dramctrl;
896 unsigned long devid;
829 int ret; 897 int ret;
830 898
831 mutex_init(&sm->clock_lock); 899 mutex_init(&sm->clock_lock);
@@ -833,17 +901,20 @@ static int sm501_init_dev(struct sm501_devdata *sm)
833 901
834 INIT_LIST_HEAD(&sm->devices); 902 INIT_LIST_HEAD(&sm->devices);
835 903
836 dramctrl = readl(sm->regs + SM501_DRAM_CONTROL); 904 devid = readl(sm->regs + SM501_DEVICEID);
905
906 if ((devid & SM501_DEVICEID_IDMASK) != SM501_DEVICEID_SM501) {
907 dev_err(sm->dev, "incorrect device id %08lx\n", devid);
908 return -EINVAL;
909 }
837 910
911 dramctrl = readl(sm->regs + SM501_DRAM_CONTROL);
838 mem_avail = sm501_mem_local[(dramctrl >> 13) & 0x7]; 912 mem_avail = sm501_mem_local[(dramctrl >> 13) & 0x7];
839 913
840 dev_info(sm->dev, "SM501 At %p: Version %08x, %ld Mb, IRQ %d\n", 914 dev_info(sm->dev, "SM501 At %p: Version %08lx, %ld Mb, IRQ %d\n",
841 sm->regs, readl(sm->regs + SM501_DEVICEID), 915 sm->regs, devid, (unsigned long)mem_avail >> 20, sm->irq);
842 (unsigned long)mem_avail >> 20, sm->irq);
843 916
844 dev_info(sm->dev, "CurrentGate %08x\n", readl(sm->regs+0x38)); 917 sm501_dump_gate(sm);
845 dev_info(sm->dev, "CurrentClock %08x\n", readl(sm->regs+0x3c));
846 dev_info(sm->dev, "PowerModeControl %08x\n", readl(sm->regs+0x54));
847 918
848 ret = device_create_file(sm->dev, &dev_attr_dbg_regs); 919 ret = device_create_file(sm->dev, &dev_attr_dbg_regs);
849 if (ret) 920 if (ret)
@@ -864,6 +935,13 @@ static int sm501_init_dev(struct sm501_devdata *sm)
864 } 935 }
865 } 936 }
866 937
938 ret = sm501_check_clocks(sm);
939 if (ret) {
940 dev_err(sm->dev, "M1X and M clocks sourced from different "
941 "PLLs\n");
942 return -EINVAL;
943 }
944
867 /* always create a framebuffer */ 945 /* always create a framebuffer */
868 sm501_register_display(sm, &mem_avail); 946 sm501_register_display(sm, &mem_avail);
869 947
@@ -933,6 +1011,57 @@ static int sm501_plat_probe(struct platform_device *dev)
933 1011
934} 1012}
935 1013
1014#ifdef CONFIG_PM
1015/* power management support */
1016
1017static int sm501_plat_suspend(struct platform_device *pdev, pm_message_t state)
1018{
1019 struct sm501_devdata *sm = platform_get_drvdata(pdev);
1020
1021 sm->in_suspend = 1;
1022 sm->pm_misc = readl(sm->regs + SM501_MISC_CONTROL);
1023
1024 sm501_dump_regs(sm);
1025 return 0;
1026}
1027
1028static int sm501_plat_resume(struct platform_device *pdev)
1029{
1030 struct sm501_devdata *sm = platform_get_drvdata(pdev);
1031
1032 sm501_dump_regs(sm);
1033 sm501_dump_gate(sm);
1034 sm501_dump_clk(sm);
1035
1036 /* check to see if we are in the same state as when suspended */
1037
1038 if (readl(sm->regs + SM501_MISC_CONTROL) != sm->pm_misc) {
1039 dev_info(sm->dev, "SM501_MISC_CONTROL changed over sleep\n");
1040 writel(sm->pm_misc, sm->regs + SM501_MISC_CONTROL);
1041
1042 /* our suspend causes the controller state to change,
1043 * either by something attempting setup, power loss,
1044 * or an external reset event on power change */
1045
1046 if (sm->platdata && sm->platdata->init) {
1047 sm501_init_regs(sm, sm->platdata->init);
1048 }
1049 }
1050
1051 /* dump our state from resume */
1052
1053 sm501_dump_regs(sm);
1054 sm501_dump_clk(sm);
1055
1056 sm->in_suspend = 0;
1057
1058 return 0;
1059}
1060#else
1061#define sm501_plat_suspend NULL
1062#define sm501_plat_resume NULL
1063#endif
1064
936/* Initialisation data for PCI devices */ 1065/* Initialisation data for PCI devices */
937 1066
938static struct sm501_initdata sm501_pci_initdata = { 1067static struct sm501_initdata sm501_pci_initdata = {
@@ -950,8 +1079,12 @@ static struct sm501_initdata sm501_pci_initdata = {
950 }, 1079 },
951 1080
952 .devices = SM501_USE_ALL, 1081 .devices = SM501_USE_ALL,
953 .mclk = 100 * MHZ, 1082
954 .m1xclk = 160 * MHZ, 1083 /* Errata AB-3 says that 72MHz is the fastest available
1084 * for 33MHZ PCI with proper bus-mastering operation */
1085
1086 .mclk = 72 * MHZ,
1087 .m1xclk = 144 * MHZ,
955}; 1088};
956 1089
957static struct sm501_platdata_fbsub sm501_pdata_fbsub = { 1090static struct sm501_platdata_fbsub sm501_pdata_fbsub = {
@@ -1126,6 +1259,8 @@ static struct platform_driver sm501_plat_drv = {
1126 }, 1259 },
1127 .probe = sm501_plat_probe, 1260 .probe = sm501_plat_probe,
1128 .remove = sm501_plat_remove, 1261 .remove = sm501_plat_remove,
1262 .suspend = sm501_plat_suspend,
1263 .resume = sm501_plat_resume,
1129}; 1264};
1130 1265
1131static int __init sm501_base_init(void) 1266static int __init sm501_base_init(void)