diff options
author | Paul Walmsley <paul@pwsan.com> | 2011-12-16 01:30:44 -0500 |
---|---|---|
committer | Paul Walmsley <paul@pwsan.com> | 2011-12-16 03:34:46 -0500 |
commit | a52e2ab66d4a9305e1ba64d9b9d25754b6c70895 (patch) | |
tree | 64d18a452c3db39ba381f73ff5a150b1adfd1b19 | |
parent | af88fa9aa77c5623983c29cb219d6d746cafc852 (diff) |
ARM: OMAP3: hwmod data: disable multiblock reads on MMC1/2 on OMAP34xx/35xx <= ES2.1
The HSMMC1/HSMMC2 host controllers on OMAP34xx and
OMAP3503/3515/3525/3530 chips at ES levels prior to 3.0 can't do multiple
block reads[1]. Mark the hwmod data appropriately.
Reported by Dave Hylands <dhylands@gmail.com> and Steve Sakoman
<sakoman@gmail.com>. Thanks to Steve Sakoman for further help
testing this patch.
1. See for example Advisory 2.1.1.128 "MMC: Multiple Block Read
Operation Issue" in _OMAP3530/3525/3515/3503 Silicon Errata_
Revision F (October 2010) (SPRZ278F), available from
http://focus.ti.com/lit/er/sprz278f/sprz278f.pdf
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Cc: Dave Hylands <dhylands@gmail.com>
Cc: Steve Sakoman <sakoman@gmail.com>
-rw-r--r-- | arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 94 |
1 files changed, 90 insertions, 4 deletions
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index 905fc44ae909..27f2fad49160 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | |||
@@ -3125,7 +3125,35 @@ static struct omap_mmc_dev_attr mmc1_dev_attr = { | |||
3125 | .flags = OMAP_HSMMC_SUPPORTS_DUAL_VOLT, | 3125 | .flags = OMAP_HSMMC_SUPPORTS_DUAL_VOLT, |
3126 | }; | 3126 | }; |
3127 | 3127 | ||
3128 | static struct omap_hwmod omap3xxx_mmc1_hwmod = { | 3128 | /* See 35xx errata 2.1.1.128 in SPRZ278F */ |
3129 | static struct omap_mmc_dev_attr mmc1_pre_es3_dev_attr = { | ||
3130 | .flags = (OMAP_HSMMC_SUPPORTS_DUAL_VOLT | | ||
3131 | OMAP_HSMMC_BROKEN_MULTIBLOCK_READ), | ||
3132 | }; | ||
3133 | |||
3134 | static struct omap_hwmod omap3xxx_pre_es3_mmc1_hwmod = { | ||
3135 | .name = "mmc1", | ||
3136 | .mpu_irqs = omap34xx_mmc1_mpu_irqs, | ||
3137 | .sdma_reqs = omap34xx_mmc1_sdma_reqs, | ||
3138 | .opt_clks = omap34xx_mmc1_opt_clks, | ||
3139 | .opt_clks_cnt = ARRAY_SIZE(omap34xx_mmc1_opt_clks), | ||
3140 | .main_clk = "mmchs1_fck", | ||
3141 | .prcm = { | ||
3142 | .omap2 = { | ||
3143 | .module_offs = CORE_MOD, | ||
3144 | .prcm_reg_id = 1, | ||
3145 | .module_bit = OMAP3430_EN_MMC1_SHIFT, | ||
3146 | .idlest_reg_id = 1, | ||
3147 | .idlest_idle_bit = OMAP3430_ST_MMC1_SHIFT, | ||
3148 | }, | ||
3149 | }, | ||
3150 | .dev_attr = &mmc1_pre_es3_dev_attr, | ||
3151 | .slaves = omap3xxx_mmc1_slaves, | ||
3152 | .slaves_cnt = ARRAY_SIZE(omap3xxx_mmc1_slaves), | ||
3153 | .class = &omap34xx_mmc_class, | ||
3154 | }; | ||
3155 | |||
3156 | static struct omap_hwmod omap3xxx_es3plus_mmc1_hwmod = { | ||
3129 | .name = "mmc1", | 3157 | .name = "mmc1", |
3130 | .mpu_irqs = omap34xx_mmc1_mpu_irqs, | 3158 | .mpu_irqs = omap34xx_mmc1_mpu_irqs, |
3131 | .sdma_reqs = omap34xx_mmc1_sdma_reqs, | 3159 | .sdma_reqs = omap34xx_mmc1_sdma_reqs, |
@@ -3168,7 +3196,34 @@ static struct omap_hwmod_ocp_if *omap3xxx_mmc2_slaves[] = { | |||
3168 | &omap3xxx_l4_core__mmc2, | 3196 | &omap3xxx_l4_core__mmc2, |
3169 | }; | 3197 | }; |
3170 | 3198 | ||
3171 | static struct omap_hwmod omap3xxx_mmc2_hwmod = { | 3199 | /* See 35xx errata 2.1.1.128 in SPRZ278F */ |
3200 | static struct omap_mmc_dev_attr mmc2_pre_es3_dev_attr = { | ||
3201 | .flags = OMAP_HSMMC_BROKEN_MULTIBLOCK_READ, | ||
3202 | }; | ||
3203 | |||
3204 | static struct omap_hwmod omap3xxx_pre_es3_mmc2_hwmod = { | ||
3205 | .name = "mmc2", | ||
3206 | .mpu_irqs = omap34xx_mmc2_mpu_irqs, | ||
3207 | .sdma_reqs = omap34xx_mmc2_sdma_reqs, | ||
3208 | .opt_clks = omap34xx_mmc2_opt_clks, | ||
3209 | .opt_clks_cnt = ARRAY_SIZE(omap34xx_mmc2_opt_clks), | ||
3210 | .main_clk = "mmchs2_fck", | ||
3211 | .prcm = { | ||
3212 | .omap2 = { | ||
3213 | .module_offs = CORE_MOD, | ||
3214 | .prcm_reg_id = 1, | ||
3215 | .module_bit = OMAP3430_EN_MMC2_SHIFT, | ||
3216 | .idlest_reg_id = 1, | ||
3217 | .idlest_idle_bit = OMAP3430_ST_MMC2_SHIFT, | ||
3218 | }, | ||
3219 | }, | ||
3220 | .dev_attr = &mmc2_pre_es3_dev_attr, | ||
3221 | .slaves = omap3xxx_mmc2_slaves, | ||
3222 | .slaves_cnt = ARRAY_SIZE(omap3xxx_mmc2_slaves), | ||
3223 | .class = &omap34xx_mmc_class, | ||
3224 | }; | ||
3225 | |||
3226 | static struct omap_hwmod omap3xxx_es3plus_mmc2_hwmod = { | ||
3172 | .name = "mmc2", | 3227 | .name = "mmc2", |
3173 | .mpu_irqs = omap34xx_mmc2_mpu_irqs, | 3228 | .mpu_irqs = omap34xx_mmc2_mpu_irqs, |
3174 | .sdma_reqs = omap34xx_mmc2_sdma_reqs, | 3229 | .sdma_reqs = omap34xx_mmc2_sdma_reqs, |
@@ -3447,8 +3502,6 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = { | |||
3447 | &omap3xxx_l4_core_hwmod, | 3502 | &omap3xxx_l4_core_hwmod, |
3448 | &omap3xxx_l4_per_hwmod, | 3503 | &omap3xxx_l4_per_hwmod, |
3449 | &omap3xxx_l4_wkup_hwmod, | 3504 | &omap3xxx_l4_wkup_hwmod, |
3450 | &omap3xxx_mmc1_hwmod, | ||
3451 | &omap3xxx_mmc2_hwmod, | ||
3452 | &omap3xxx_mmc3_hwmod, | 3505 | &omap3xxx_mmc3_hwmod, |
3453 | &omap3xxx_mpu_hwmod, | 3506 | &omap3xxx_mpu_hwmod, |
3454 | 3507 | ||
@@ -3531,6 +3584,20 @@ static __initdata struct omap_hwmod *omap3430es2plus_hwmods[] = { | |||
3531 | NULL | 3584 | NULL |
3532 | }; | 3585 | }; |
3533 | 3586 | ||
3587 | /* <= 3430ES3-only hwmods */ | ||
3588 | static struct omap_hwmod *omap3430_pre_es3_hwmods[] __initdata = { | ||
3589 | &omap3xxx_pre_es3_mmc1_hwmod, | ||
3590 | &omap3xxx_pre_es3_mmc2_hwmod, | ||
3591 | NULL | ||
3592 | }; | ||
3593 | |||
3594 | /* 3430ES3+-only hwmods */ | ||
3595 | static struct omap_hwmod *omap3430_es3plus_hwmods[] __initdata = { | ||
3596 | &omap3xxx_es3plus_mmc1_hwmod, | ||
3597 | &omap3xxx_es3plus_mmc2_hwmod, | ||
3598 | NULL | ||
3599 | }; | ||
3600 | |||
3534 | /* 34xx-only hwmods (all ES revisions) */ | 3601 | /* 34xx-only hwmods (all ES revisions) */ |
3535 | static __initdata struct omap_hwmod *omap34xx_hwmods[] = { | 3602 | static __initdata struct omap_hwmod *omap34xx_hwmods[] = { |
3536 | &omap3xxx_iva_hwmod, | 3603 | &omap3xxx_iva_hwmod, |
@@ -3551,6 +3618,8 @@ static __initdata struct omap_hwmod *omap36xx_hwmods[] = { | |||
3551 | &omap3xxx_mailbox_hwmod, | 3618 | &omap3xxx_mailbox_hwmod, |
3552 | &omap3xxx_usb_host_hs_hwmod, | 3619 | &omap3xxx_usb_host_hs_hwmod, |
3553 | &omap3xxx_usb_tll_hs_hwmod, | 3620 | &omap3xxx_usb_tll_hs_hwmod, |
3621 | &omap3xxx_es3plus_mmc1_hwmod, | ||
3622 | &omap3xxx_es3plus_mmc2_hwmod, | ||
3554 | NULL | 3623 | NULL |
3555 | }; | 3624 | }; |
3556 | 3625 | ||
@@ -3560,6 +3629,8 @@ static __initdata struct omap_hwmod *am35xx_hwmods[] = { | |||
3560 | &am35xx_uart4_hwmod, | 3629 | &am35xx_uart4_hwmod, |
3561 | &omap3xxx_usb_host_hs_hwmod, | 3630 | &omap3xxx_usb_host_hs_hwmod, |
3562 | &omap3xxx_usb_tll_hs_hwmod, | 3631 | &omap3xxx_usb_tll_hs_hwmod, |
3632 | &omap3xxx_es3plus_mmc1_hwmod, | ||
3633 | &omap3xxx_es3plus_mmc2_hwmod, | ||
3563 | NULL | 3634 | NULL |
3564 | }; | 3635 | }; |
3565 | 3636 | ||
@@ -3619,6 +3690,21 @@ int __init omap3xxx_hwmod_init(void) | |||
3619 | h = omap3430es2plus_hwmods; | 3690 | h = omap3430es2plus_hwmods; |
3620 | }; | 3691 | }; |
3621 | 3692 | ||
3693 | if (h) { | ||
3694 | r = omap_hwmod_register(h); | ||
3695 | if (r < 0) | ||
3696 | return r; | ||
3697 | } | ||
3698 | |||
3699 | h = NULL; | ||
3700 | if (rev == OMAP3430_REV_ES1_0 || rev == OMAP3430_REV_ES2_0 || | ||
3701 | rev == OMAP3430_REV_ES2_1) { | ||
3702 | h = omap3430_pre_es3_hwmods; | ||
3703 | } else if (rev == OMAP3430_REV_ES3_0 || rev == OMAP3430_REV_ES3_1 || | ||
3704 | rev == OMAP3430_REV_ES3_1_2) { | ||
3705 | h = omap3430_es3plus_hwmods; | ||
3706 | }; | ||
3707 | |||
3622 | if (h) | 3708 | if (h) |
3623 | r = omap_hwmod_register(h); | 3709 | r = omap_hwmod_register(h); |
3624 | 3710 | ||