Re: [RFC][PATCH 2/3] ARM:OMAP4 iommu:add omap4 support in iommu
From: "ext Kanigeri, Hari" Subject: RE: [RFC][PATCH 2/3] ARM:OMAP4 iommu:add omap4 support in iommu Date: Tue, 28 Jul 2009 17:42:21 +0200 > Hi Hiroshi, > > > > > This "omap iommu" driver is used in OMAP4 IPC and its interface is a > > character device node. IOW, the client of this device will be an > > userland process and kernel won't know if it uses or not, but kernel > > just provides "/dev/iommu?" for userland. So I don't think that we > > have to care about the dependency of the existance of clients, at > > least, for a moment. > > > > > > The first patch set that I sent is to provide support in IOMMU for OMAP4 just > like how it is done in OMAP3 today. The define "CONFIG_MPU_TESLA_IOMMU" is > used for now because in the first phase we are planning to use DSP-Bridge to > communicate with Tesla (until we move the new user-land IPC to replace > DSP-Bridge for OMAP4). > IMHO, let's go ahead with these changes and any changes to support > IOMMU from user-land we can address them in next set of patches. Got it. Let's go for it;) I'll queue them up if you send the updated ones. -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH] musb: cleanup the nop registration for OMAP3EVM
> On Friday 03 July 2009, Ajay Kumar Gupta wrote: > > OMAP3EVM uses ISP1504 phy which doesn't require any > > programming and thus has to use NOP otg transceiver. > > > > Cleanups being done: > > - Remove unwanted code in usb-musb.c file > > - Register nop in OMAP3EVM board file using > > usb_nop_xceiv_register(). > > - Select NOP_USB_XCEIV for OMAP3EVM boards. > > > > Signed-off-by: Ajay Kumar Gupta > > Acked-by: David Brownell > > ... another for-2.6.31 bugfix. Greg, Here is the refreshed version of this patch. Thanks, Ajay cut here = OMAP3EVM uses ISP1504 phy which doesn't require any programming and thus has to use NOP otg transceiver. Cleanups being done: - Remove unwanted code in usb-musb.c file - Register NOP in OMAP3EVM board file using usb_nop_xceiv_register(). - Select NOP_USB_XCEIV for OMAP3EVM boards. - Don't enable TWL4030_USB in omap3_evm_defconfig Signed-off-by: Ajay Kumar Gupta Signed-off-by: Eino-Ville Talvala --- Resubmitting with below changes. - Refreshed against linus tree - Combining recent patch from Eino-Ville Talvala on "Removing TWL4030_USB from omap3_evm_defconfig" - Register nop under #ifdef to avoid compilation warning when USB itself it not selected in OMAP3EVM build. arch/arm/configs/omap3_evm_defconfig |2 +- arch/arm/mach-omap2/board-omap3evm.c |5 + arch/arm/mach-omap2/usb-musb.c | 21 - drivers/usb/musb/Kconfig |1 + 4 files changed, 7 insertions(+), 22 deletions(-) diff --git a/arch/arm/configs/omap3_evm_defconfig b/arch/arm/configs/omap3_evm_defconfig index 28be17f..d5ff477 100644 --- a/arch/arm/configs/omap3_evm_defconfig +++ b/arch/arm/configs/omap3_evm_defconfig @@ -1107,7 +1107,7 @@ CONFIG_USB_ZERO=m CONFIG_USB_OTG_UTILS=y # CONFIG_USB_GPIO_VBUS is not set # CONFIG_ISP1301_OMAP is not set -CONFIG_TWL4030_USB=y +# CONFIG_TWL4030_USB is not set # CONFIG_NOP_USB_XCEIV is not set CONFIG_MMC=y # CONFIG_MMC_DEBUG is not set diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c index d3cc145..cf3dd77 100644 --- a/arch/arm/mach-omap2/board-omap3evm.c +++ b/arch/arm/mach-omap2/board-omap3evm.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -307,6 +308,10 @@ static void __init omap3_evm_init(void) ARRAY_SIZE(omap3evm_spi_board_info)); omap_serial_init(); +#ifdef CONFIG_NOP_USB_XCEIV + /* OMAP3EVM uses ISP1504 phy and so register nop transceiver */ + usb_nop_xceiv_register(); +#endif usb_musb_init(); ads7846_dev_init(); } diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c index d85296d..739e59e 100644 --- a/arch/arm/mach-omap2/usb-musb.c +++ b/arch/arm/mach-omap2/usb-musb.c @@ -155,20 +155,6 @@ static struct platform_device musb_device = { .resource = musb_resources, }; -#ifdef CONFIG_NOP_USB_XCEIV -static u64 nop_xceiv_dmamask = DMA_BIT_MASK(32); - -static struct platform_device nop_xceiv_device = { - .name = "nop_usb_xceiv", - .id = -1, - .dev = { - .dma_mask = &nop_xceiv_dmamask, - .coherent_dma_mask = DMA_BIT_MASK(32), - .platform_data = NULL, - }, -}; -#endif - void __init usb_musb_init(void) { if (cpu_is_omap243x()) @@ -183,13 +169,6 @@ void __init usb_musb_init(void) */ musb_plat.clock = "ick"; -#ifdef CONFIG_NOP_USB_XCEIV - if (platform_device_register(&nop_xceiv_device) < 0) { - printk(KERN_ERR "Unable to register NOP-XCEIV device\n"); - return; - } -#endif - if (platform_device_register(&musb_device) < 0) { printk(KERN_ERR "Unable to register HS-USB (MUSB) device\n"); return; diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index 70073b1..803adcb 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig @@ -12,6 +12,7 @@ config USB_MUSB_HDRC depends on !SUPERH select NOP_USB_XCEIV if ARCH_DAVINCI select TWL4030_USB if MACH_OMAP_3430SDP + select NOP_USB_XCEIV if MACH_OMAP3EVM select USB_OTG_UTILS tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)' help -- 1.6.2.4 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: OMAP camera with BT-656 sensor
Hi Thomas, > -Original Message- > From: Gary Thomas [mailto:g...@mlbassoc.com] > Sent: Tuesday, July 28, 2009 6:15 PM > To: Hiremath, Vaibhav > Cc: Aguirre Rodriguez, Sergio Alberto; linux-omap@vger.kernel.org > Subject: Re: OMAP camera with BT-656 sensor > > Hiremath, Vaibhav wrote: > >> -Original Message- > >> From: linux-omap-ow...@vger.kernel.org [mailto:linux-omap- > >> ow...@vger.kernel.org] On Behalf Of Aguirre Rodriguez, Sergio > >> Alberto > >> Sent: Tuesday, July 28, 2009 1:45 AM > >> To: Gary Thomas > >> Cc: linux-omap@vger.kernel.org > >> Subject: RE: OMAP camera with BT-656 sensor > >> > >> > >> > >>> -Original Message- > >>> From: Gary Thomas [mailto:g...@mlbassoc.com] > >>> Sent: Monday, July 27, 2009 2:59 PM > >>> To: Aguirre Rodriguez, Sergio Alberto > >>> Cc: linux-omap@vger.kernel.org > >>> Subject: Re: OMAP camera with BT-656 sensor > >>> > >>> Aguirre Rodriguez, Sergio Alberto wrote: > > -Original Message- > > From: Gary Thomas [mailto:g...@mlbassoc.com] > > Sent: Monday, July 27, 2009 2:11 PM > > To: Aguirre Rodriguez, Sergio Alberto > > Cc: linux-omap@vger.kernel.org > > Subject: OMAP camera with BT-656 sensor > >>>... snip > >>> > > Bottom line, I'm confused as to how I should go about getting > > my driver/system working. Do I use your work, or just stick > > with the PSP base (why?)?? > What I do feel is that the PSP base will fulfill better your > >> immediate > >>> needs, but in the future, as I'm getting aware of Vaibhav > changes, > >> I'll be > >>> interested in making them part of my tree aswell, so Vaibhav > could > >> avoid > >>> rebasing the BT646 support internally everytime... > >>> > >>> Is there a GIT tree for this? > >> AFAIK, this is the latest tree Vaibhav is exposing: > >> > >> http://arago-project.org/git/people/vaibhav/ti-psp-omap-video.git > >> > >> He maintains a camera and a DSS2 branch exactly to make both work > on > >> his 3530EVM. > >> > > [Hiremath, Vaibhav] Thanks Sergio for taking this up. Just to add > on top of Sergio's comments, the current status of above tree is, > DSS2 is already merged to latest kernel (Even on PM branch) > baseline. > > > > http://arago-project.org/git/people/?p=vaibhav/ti-psp-omap- > video.git;a=shortlog;h=refs/heads/ti_display > > > > http://arago-project.org/git/people/?p=vaibhav/ti-psp-omap- > video.git;a=shortlog;h=refs/heads/pm > > > > > > The next PSP release will contain 2.6.31(PM) + DSS2 + Camera + > Resizer modules together in one release. I have started with Camera > modules merging on top of 2.6.31 + DSS2; hopefully I should be able > to complete this by next week (provided that I don't get any > interrupts) > > > > You should be looking to Arago tree for all the developments which > I do under Arago. > > > > Please let me know if you have any issues/doubts OR if you are > looking for some quick solutions. > > I'd like to use the latest tree with DSS2 (ti_display seems to be > it), but > the OMAP3 camera support is not present. [Hiremath, Vaibhav] Yes you are correct. > * How hard would it be to merge the ti_omap3camera and ti_display > branches? [Hiremath, Vaibhav] Should not be that hard but I would suggest to go with latest Camera changes. > * Would this be a reasonable way forward? [Hiremath, Vaibhav] It would be really difficult to maintain the old code base, which in my opinion waste of efforts. > > It would be nice if I could wait for your next release, but alas, my > project is already weeks late and every hour counts... > > >>> A [hopefully] minor complication is that I'm using Tomi's DSS2 > >>> tree for the base of my port. How can I move/merge the PSP > >>> based support into it? Can I just pick up the whole > drivers/media > >>> subtree and put in in place of what I have? > >> I recommend looking at the git tree above... I think that job is > >> already done... > >> > >>> Thanks for your help - this myriad of trees and very disparate > >>> support levels is really confusing to those of us on the > >> outside... > >> > >> I know, and the lack of proper documentation is one of the first > >> issues for me to look at... > >> > >> You're welcome. > > > -- > > Gary Thomas | Consulting for the > MLB Associates |Embedded world > -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC][PATCH v2 4/4] OMAP4: PMIC: Update TWL mfd driver to create twl6030 regulators
From: Rajendra Nayak This version of patch series enables RUN TIME selection of TWL4030 or TWL6030. This patch adds initial support for creating twl6030 PMIC specific voltage regulators in the twl mfd driver. Board specific regulator configurations will have to be passed from respective board files. Signed-off-by: Rajendra Nayak --- drivers/mfd/twl-core.c | 56 +- include/linux/i2c/twl.h | 18 +++ 2 files changed, 63 insertions(+), 11 deletions(-) diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index f505537..747289c 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c @@ -76,9 +76,9 @@ #define twl_has_gpio() false #endif -#if defined(CONFIG_REGULATOR_TWL4030) \ - || defined(CONFIG_REGULATOR_TWL4030_MODULE) -#define twl_has_regulator()true +#if defined(CONFIG_REGULATOR_TWL) \ + || defined(CONFIG_REGULATOR_TWL_MODULE) +#define twl_has_regulator() true #else #define twl_has_regulator()false #endif @@ -636,7 +636,7 @@ add_children(struct twl_platform_data *pdata, unsigned long features) return PTR_ERR(child); } - if (twl_has_regulator()) { + if (twl_has_regulator() && is_class_twl4030()) { /* child = add_regulator(TWL4030_REG_VPLL1, pdata->vpll1); if (IS_ERR(child)) @@ -659,7 +659,7 @@ add_children(struct twl_platform_data *pdata, unsigned long features) return PTR_ERR(child); } - if (twl_has_regulator() && usb_transceiver) { + if (twl_has_regulator() && is_class_twl4030() && usb_transceiver) { static struct regulator_consumer_supply usb1v5 = { .supply = "usb1v5", }; @@ -701,7 +701,8 @@ add_children(struct twl_platform_data *pdata, unsigned long features) } /* maybe add LDOs that are omitted on cost-reduced parts */ - if (twl_has_regulator() && !(features & TPS_SUBSET)) { + if (twl_has_regulator() && is_class_twl4030() + && !(features & TPS_SUBSET)) { child = add_regulator(TWL4030_REG_VPLL2, pdata->vpll2); if (IS_ERR(child)) return PTR_ERR(child); @@ -727,6 +728,49 @@ add_children(struct twl_platform_data *pdata, unsigned long features) return PTR_ERR(child); } + /* twl6030 regulators */ + if (twl_has_regulator() && is_class_twl4030()) { + child = add_regulator(TWL6030_REG_VMMC, pdata->vmmc); + if (IS_ERR(child)) + return PTR_ERR(child); + + child = add_regulator(TWL6030_REG_VPP, pdata->vpp); + if (IS_ERR(child)) + return PTR_ERR(child); + + child = add_regulator(TWL6030_REG_VUSIM, pdata->vusim); + if (IS_ERR(child)) + return PTR_ERR(child); + + child = add_regulator(TWL6030_REG_VANA, pdata->vana); + if (IS_ERR(child)) + return PTR_ERR(child); + + child = add_regulator(TWL6030_REG_VCXIO, pdata->vcxio); + if (IS_ERR(child)) + return PTR_ERR(child); + + child = add_regulator(TWL6030_REG_VDAC, pdata->vdac); + if (IS_ERR(child)) + return PTR_ERR(child); + + child = add_regulator(TWL6030_REG_VUSB, pdata->vusb); + if (IS_ERR(child)) + return PTR_ERR(child); + + child = add_regulator(TWL6030_REG_VAUX1_6030, pdata->vaux1); + if (IS_ERR(child)) + return PTR_ERR(child); + + child = add_regulator(TWL6030_REG_VAUX2_6030, pdata->vaux2); + if (IS_ERR(child)) + return PTR_ERR(child); + + child = add_regulator(TWL6030_REG_VAUX3_6030, pdata->vaux3); + if (IS_ERR(child)) + return PTR_ERR(child); + } + return 0; } diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h index 53d9360..1f678ed 100644 --- a/include/linux/i2c/twl.h +++ b/include/linux/i2c/twl.h @@ -306,6 +306,7 @@ int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes); #define TWL4030_INT_PWR_EDR2 0x6 #define TWL4030_INT_PWR_SIH_CTRL 0x7 + /*--*/ /* Power bus message definitions */ @@ -424,18 +425,25 @@ struct twl_platform_data { struct twl_keypad_data *keypad; struct twl_usb_data *usb; - /* LDO regulators */ + /* LDO regulators common to TWL4030/TWL6030 */ struct regulator_init_data *vdac; + struct regulator_init_data *vaux1; + struct regulator_init_data *vaux2; + str
[RFC][PATCH v2 3/4] OMAP4: PMIC: Add support for twl6030 regulators
From: Rajendra Nayak This version of patch series enables RUN TIME selection of TWL4030 or TWL6030. This patch updates the regulator driver to add support for TWL6030 PMIC specific LDO regulators. SMPS resources are not yet supported for TWL6030 and also .set_mode and .get_status for LDO's are yet to be implemented for TWL6030. Signed-off-by: Rajendra Nayak --- drivers/mfd/twl-core.c|3 +- drivers/regulator/Kconfig |6 +- drivers/regulator/Makefile|2 +- drivers/regulator/twl-regulator.c | 134 +++-- include/linux/i2c/twl.h | 37 ++ 5 files changed, 155 insertions(+), 27 deletions(-) diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index 78109ca..f505537 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c @@ -126,7 +126,7 @@ #define REG_SUB_CHIP_ID SUB_CHIP_ID3 /* Last - for index max*/ -#define TWL4030_MODULE_LASTTWL4030_MODULE_SECURED_REG +#define TWL4030_MODULE_LASTTWL_MODULE_PM_SLAVE_LDO #define TWL_MODULE_LAST TWL4030_MODULE_LAST /* Base Address defns for twl4030_map[] */ @@ -277,6 +277,7 @@ static struct twl_mapping twl4030_map[TWL4030_MODULE_LAST + 1] = { { 3, TWL4030_BASEADD_PM_RECEIVER }, { 3, TWL4030_BASEADD_RTC }, { 3, TWL4030_BASEADD_SECURED_REG }, + { 3, TWL4030_BASEADD_PM_RECEIVER }, }; static struct twl_mapping twl6030_map[] = { diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index f431779..7f5987e 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -75,9 +75,9 @@ config REGULATOR_MAX1586 regulator via I2C bus. The provided regulator is suitable for PXA27x chips to control VCC_CORE and VCC_USIM voltages. -config REGULATOR_TWL4030 - bool "TI TWL4030/TWL5030/TPS695x0 PMIC" - depends on TWL4030_CORE +config REGULATOR_TWL + bool "TI TWL4030/TWL5030/TWL6030/TPS695x0 PMIC" + depends on TWL_CORE help This driver supports the voltage regulators provided by this family of companion chips. diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 0653ce8..712f733 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -11,7 +11,7 @@ obj-$(CONFIG_REGULATOR_USERSPACE_CONSUMER) += userspace-consumer.o obj-$(CONFIG_REGULATOR_BQ24022) += bq24022.o obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o -obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o +obj-$(CONFIG_REGULATOR_TWL) += twl-regulator.o obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o obj-$(CONFIG_REGULATOR_DA903X) += da903x.o diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index d01aa4e..8182290 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -52,27 +52,38 @@ struct twlreg_info { * The first three registers of all power resource banks help hardware to * manage the various resource groups. */ +/* Common offset in TWL4030/6030 */ #define VREG_GRP 0 +/* TWL4030 register offsets */ #define VREG_TYPE 1 #define VREG_REMAP 2 -#define VREG_DEDICATED 3 /* LDO control */ - +#define VREG_DEDICATED 3 +/* TWL6030 register offsets */ +#define VREG_TRANS 1 +#define VREG_STATE 2 +#define VREG_VOLTAGE 3 +/* TWL6030 Misc register offsets */ +#define VREG_BC_ALL1 +#define VREG_BC_REF2 +#define VREG_BC_PROC 3 +#define VREG_BC_CLK_RST4 static inline int -twlreg_read(struct twlreg_info *info, unsigned offset) +twlreg_read(struct twlreg_info *info, unsigned slave_subgp, unsigned offset) { u8 value; int status; - status = twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, + status = twl_i2c_read_u8(slave_subgp, &value, info->base + offset); return (status < 0) ? status : value; } static inline int -twlreg_write(struct twlreg_info *info, unsigned offset, u8 value) +twlreg_write(struct twlreg_info *info, unsigned slave_subgp, unsigned offset, +u8 value) { - return twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, + return twl_i2c_write_u8(slave_subgp, value, info->base + offset); } @@ -82,17 +93,22 @@ twlreg_write(struct twlreg_info *info, unsigned offset, u8 value) static int twlreg_grp(struct regulator_dev *rdev) { - return twlreg_read(rdev_get_drvdata(rdev), VREG_GRP); + return twlreg_read(rdev_get_drvdata(rdev), TWL_MODULE_PM_SLAVE_LDO, +VREG_GRP); } /* * Enable/disable regulators by joining/leaving the P1 (processor) group. * We assume nobody else is updating the DEV_GRP registers
[RFC][PATCH v2 2/4] OMAP4: PMIC: Add support for twl6030 RTC
From: Balaji T K This version of patch series enables RUN TIME selection of TWL4030 or TWL6030. This patch adds support for RTC in phoenix TWL6030. Register offset addresses have changed in TWL6030 rtc-twl.c will hence forth support all twl RTC (4030, 5030, 6030 ..) Signed-off-by: Balaji T K Signed-off-by: Santosh Shilimkar --- drivers/mfd/twl-core.c |2 +- drivers/rtc/Kconfig|8 ++-- drivers/rtc/Makefile |2 +- drivers/rtc/rtc-twl.c | 113 4 files changed, 91 insertions(+), 34 deletions(-) diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index 4066b2f..78109ca 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c @@ -89,7 +89,7 @@ #define twl_has_madc() false #endif -#if defined(CONFIG_RTC_DRV_TWL4030) || defined(CONFIG_RTC_DRV_TWL4030_MODULE) +#if defined(CONFIG_RTC_DRV_TWL) || defined(CONFIG_RTC_DRV_TWL_MODULE) #define twl_has_rtc() true #else #define twl_has_rtc() false diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 81adbdb..bb94924 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -257,15 +257,15 @@ config RTC_DRV_TWL92330 platforms. The support is integrated with the rest of the Menelaus driver; it's not separate module. -config RTC_DRV_TWL4030 - tristate "TI TWL4030/TWL5030/TPS659x0" - depends on RTC_CLASS && TWL4030_CORE +config RTC_DRV_TWL + tristate "TI TWL4030/TWL5030/TWL6030/TPS659x0" + depends on RTC_CLASS && TWL_CORE help If you say yes here you get support for the RTC on the TWL4030 family chips, used mostly with OMAP3 platforms. This driver can also be built as a module. If so, the module - will be called rtc-twl4030. + will be called rtc-twl. config RTC_DRV_S35390A tristate "Seiko Instruments S-35390A" diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index e331b1c..c32e21d 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -70,7 +70,7 @@ obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o obj-$(CONFIG_RTC_DRV_SH) += rtc-sh.o obj-$(CONFIG_RTC_DRV_STK17TA8) += rtc-stk17ta8.o obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o -obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl.o +obj-$(CONFIG_RTC_DRV_TWL) += rtc-twl.o obj-$(CONFIG_RTC_DRV_TX4939) += rtc-tx4939.o obj-$(CONFIG_RTC_DRV_V3020)+= rtc-v3020.o obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c index 630acb7..1e9f90d 100644 --- a/drivers/rtc/rtc-twl.c +++ b/drivers/rtc/rtc-twl.c @@ -34,27 +34,75 @@ /* * RTC block register offsets (use TWL_MODULE_RTC) */ -#define REG_SECONDS_REG 0x00 -#define REG_MINUTES_REG 0x01 -#define REG_HOURS_REG0x02 -#define REG_DAYS_REG 0x03 -#define REG_MONTHS_REG 0x04 -#define REG_YEARS_REG0x05 -#define REG_WEEKS_REG0x06 - -#define REG_ALARM_SECONDS_REG0x07 -#define REG_ALARM_MINUTES_REG0x08 -#define REG_ALARM_HOURS_REG 0x09 -#define REG_ALARM_DAYS_REG 0x0A -#define REG_ALARM_MONTHS_REG 0x0B -#define REG_ALARM_YEARS_REG 0x0C - -#define REG_RTC_CTRL_REG 0x0D -#define REG_RTC_STATUS_REG 0x0E -#define REG_RTC_INTERRUPTS_REG 0x0F - -#define REG_RTC_COMP_LSB_REG 0x10 -#define REG_RTC_COMP_MSB_REG 0x11 +enum { + REG_SECONDS_REG = 0, + REG_MINUTES_REG, + REG_HOURS_REG, + REG_DAYS_REG, + REG_MONTHS_REG, + REG_YEARS_REG, + REG_WEEKS_REG, + + REG_ALARM_SECONDS_REG, + REG_ALARM_MINUTES_REG, + REG_ALARM_HOURS_REG, + REG_ALARM_DAYS_REG, + REG_ALARM_MONTHS_REG, + REG_ALARM_YEARS_REG, + + REG_RTC_CTRL_REG, + REG_RTC_STATUS_REG, + REG_RTC_INTERRUPTS_REG, + + REG_RTC_COMP_LSB_REG, + REG_RTC_COMP_MSB_REG, +}; +const static u8 twl4030_rtc_reg_map[] = { + [REG_SECONDS_REG] = 0x00, + [REG_MINUTES_REG] = 0x01, + [REG_HOURS_REG] = 0x02, + [REG_DAYS_REG] = 0x03, + [REG_MONTHS_REG] = 0x04, + [REG_YEARS_REG] = 0x05, + [REG_WEEKS_REG] = 0x06, + + [REG_ALARM_SECONDS_REG] = 0x07, + [REG_ALARM_MINUTES_REG] = 0x08, + [REG_ALARM_HOURS_REG] = 0x09, + [REG_ALARM_DAYS_REG] = 0x0A, + [REG_ALARM_MONTHS_REG] = 0x0B, + [REG_ALARM_YEARS_REG] = 0x0C, + + [REG_RTC_CTRL_REG] = 0x0D, + [REG_RTC_STATUS_REG] = 0x0E, + [REG_RTC_INTERRUPTS_REG] = 0x0F, + + [REG_RTC_COMP_LSB_REG] = 0x10, + [REG_RTC_COMP_MSB_REG] = 0x11, +}; +const static u8 twl6030_rtc_reg_map[] = { + [REG_SECONDS_REG] = 0x00, + [REG
[RFC][PATCH v2 1/4] OMAP4: PMIC: Add support for twl6030 irq framework
From: Balaji T K This version of patch series enables RUN TIME selection of TWL4030 or TWL6030. CONFIG_TWL4030_CORE and CONFIG_TWL6030_CORE is replaced by CONFIG_TWL_CORE This patch adds support for phoenix interrupt framework. New Interrupt status register A, B, C are introduced in Phoenix and are cleared on write. Due to difference in interrupt handling with respect to TWL4030, twl6030-irq.c is created for TWL6030 PMIC Signed-off-by: Rajendra Nayak Signed-off-by: Balaji T K Signed-off-by: Santosh Shilimkar --- arch/arm/plat-omap/include/mach/irqs.h | 18 ++- drivers/mfd/Kconfig|4 +- drivers/mfd/Makefile |2 +- drivers/mfd/twl-core.c | 128 -- drivers/mfd/twl4030-irq.c |4 +- drivers/mfd/twl6030-irq.c | 301 include/linux/i2c/twl.h| 64 +++- 7 files changed, 498 insertions(+), 23 deletions(-) create mode 100644 drivers/mfd/twl6030-irq.c diff --git a/arch/arm/plat-omap/include/mach/irqs.h b/arch/arm/plat-omap/include/mach/irqs.h index fb7cb77..e9e0500 100644 --- a/arch/arm/plat-omap/include/mach/irqs.h +++ b/arch/arm/plat-omap/include/mach/irqs.h @@ -531,7 +531,7 @@ /* External TWL4030 can handle interrupts on 2430 and 34xx boards */ #defineTWL4030_IRQ_BASE(OMAP_FPGA_IRQ_END) -#ifdef CONFIG_TWL4030_CORE +#ifdef CONFIG_TWL_CORE #defineTWL4030_BASE_NR_IRQS8 #defineTWL4030_PWR_NR_IRQS 8 #else @@ -551,8 +551,22 @@ #endif #define TWL4030_GPIO_IRQ_END (TWL4030_GPIO_IRQ_BASE + TWL4030_GPIO_NR_IRQS) +#defineTWL6030_IRQ_BASE(OMAP_FPGA_IRQ_END) +#ifdef CONFIG_TWL_CORE +#defineTWL6030_BASE_NR_IRQS20 +#else +#defineTWL6030_BASE_NR_IRQS0 +#endif +#define TWL6030_IRQ_END(TWL6030_IRQ_BASE + TWL6030_BASE_NR_IRQS) + /* Total number of interrupts depends on the enabled blocks above */ -#define NR_IRQSTWL4030_GPIO_IRQ_END +#if (TWL4030_GPIO_IRQ_END > TWL6030_IRQ_END) +#define TWL_IRQ_ENDTWL4030_GPIO_IRQ_END +#else +#define TWL_IRQ_ENDTWL6030_IRQ_END +#endif + +#define NR_IRQSTWL_IRQ_END #define OMAP_IRQ_BIT(irq) (1 << ((irq) % 32)) diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 491ac0f..38ad70b 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -94,11 +94,11 @@ config MENELAUS and other features that are often used in portable devices like cell phones and PDAs. -config TWL4030_CORE +config TWL_CORE bool "Texas Instruments TWL4030/TPS659x0 Support" depends on I2C=y && GENERIC_HARDIRQS help - Say yes here if you have TWL4030 family chip on your board. + Say yes here if you have TWL4030 / TWL6030 family chip on your board. This core driver provides register access and IRQ handling facilities, and registers devices for the various functions so that function-specific drivers can bind to them. diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 4e9d513..c733440 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -22,7 +22,7 @@ obj-$(CONFIG_MFD_WM8350_I2C) += wm8350-i2c.o obj-$(CONFIG_TPS65010) += tps65010.o obj-$(CONFIG_MENELAUS) += menelaus.o -obj-$(CONFIG_TWL4030_CORE) += twl-core.o twl4030-irq.o +obj-$(CONFIG_TWL_CORE) += twl-core.o twl4030-irq.o twl6030-irq.o obj-$(CONFIG_MFD_CORE) += mfd-core.o diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index 6122db2..4066b2f 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c @@ -163,6 +163,35 @@ /* Triton Core internal information (END) */ +/* subchip/slave 0 0x48 - POWER */ +#define TWL6030_BASEADD_RTC0x +#define TWL6030_BASEADD_MEM0x0017 +#define TWL6030_BASEADD_PM_MASTER 0x001F +#define TWL6030_BASEADD_PM_SLAVE_MISC 0x0030 +#define TWL6030_BASEADD_PM_SLAVE_SMPS 0x0040 +#define TWL6030_BASEADD_PM_SLAVE_LDO 0x0080 +#define TWL6030_BASEADD_PM_SLAVE_RES 0x00AD +#define TWL6030_BASEADD_PM_MISC0x00E3 +#define TWL6030_BASEADD_PM_PUPD0x00F0 + +/* subchip/slave 1 0x49 - FEATURE */ +#define TWL6030_BASEADD_USB0x +#define TWL6030_BASEADD_GPADC_CTRL 0x0030 +#define TWL6030_BASEADD_GPADC_RT 0x0035 +#define TWL6030_BASEADD_GPADC 0x005D +#define TWL6030_BASEADD_AUX0x0090 +#define TWL6030_BASEADD_PWM0x00BA +#define TWL6030_BASEADD_GASGAUGE 0x00C0 +#define TWL6030_BASEADD_PIH0x00D0 +#define TWL6030_BASEADD_CHARGER0x00E0 + +/* subchip/slave 2 0x4A - DFT */ +#define TWL6030_BASEADD_DIEID 0x00C0 + +/* subchip/slave 3 0x4B - AUDIO */ +#define TWL6030_BASEADD_AUDIO 0x +#define TWL6030_BASEADD_RSV0x + /* Few power values */ #define
drivers that require headers in mach-omap
Omap folks, how are drivers that require access to prm and cm registers via cm_read_mod_reg() etc... suppose to access these? For example if drivers/usb/host/ohci-omap.c wanted to call: cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, CM_IDLEST); It seems some of the headers in mach-omap2 should be in plat-omap/include/mach, or is there a more elegant way? The other alternatives are to register calls in all the board files, or #include ../../.. both do not seem very elegant to me. -- Mike -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] OMAP3: PM: Move the clk stabilization delay to the right place
On Fri, 26 Jun 2009, Rajendra Nayak wrote: > The clock stabilization delay post a M2 divider change is needed > even before a SDRC interface clock re-enable and not only before > jumping back to SDRAM. > > Signed-off-by: Rajendra Nayak For the archives: this patch has been accepted and sent upstream for 2.6.31-rc fixes. - Paul > --- > arch/arm/mach-omap2/sram34xx.S |4 ++-- > 1 files changed, 2 insertions(+), 2 deletions(-) > > diff --git a/arch/arm/mach-omap2/sram34xx.S b/arch/arm/mach-omap2/sram34xx.S > index f41f8d9..481f912 100644 > --- a/arch/arm/mach-omap2/sram34xx.S > +++ b/arch/arm/mach-omap2/sram34xx.S > @@ -97,6 +97,8 @@ ENTRY(omap3_sram_configure_core_dpll) > blnelock_dll > bl sdram_in_selfrefresh@ put SDRAM in self refresh, idle SDRC > bl configure_core_dpll @ change the DPLL3 M2 divider > + mov r12, r5 > + bl wait_clk_stable @ wait for SDRC to stabilize > bl enable_sdrc @ take SDRC out of idle > cmp r4, #SDRC_UNLOCK_DLL@ wait for DLL status to change > bleqwait_dll_unlock > @@ -104,8 +106,6 @@ ENTRY(omap3_sram_configure_core_dpll) > cmp r7, #1 @ if increasing SDRC clk rate, > beq return_to_sdram @ return to SDRAM code, otherwise, > bl configure_sdrc @ reprogram SDRC regs now > - mov r12, r5 > - bl wait_clk_stable @ wait for SDRC to stabilize > return_to_sdram: > isb @ prevent speculative exec past here > mov r0, #0 @ return value > -- > 1.5.4.7 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-omap" in > the body of a message to majord...@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > - Paul -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [alsa-devel] [RFC] [PATCH 1/3] ASoC: Add support for Conexant CX20442-11 voice modem codec
On Tue, Jul 28, 2009 at 06:36:01PM +0200, Janusz Krzysztofik wrote: > Tuesday 28 July 2009 18:11:32 Mark Brown wrote: > > Like I say, I'd suggest always keeping the controls registered and just > > masking and unmasking from user space - the control indexes get used so > > removing them will just confuse things. > However, in order for the machine driver to unmask/mask a machine specific > control, the codec driver must drop the machine driver a message about the > line discipline being activeted/deactivated, right? The only such existing > feedback I can see the codec is able to use is via snd_soc_init_card() that > calls snd_soc_dai_link.init() in turn. Am I missing something? Well, the machine driver can look up controls by name (this is going to be required in order to find the controls anyway...). Besides, given that the machine driver is already entirely CODEC-specific there'd no problem with it calling into CODEC-specific APIs to do things. -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [alsa-devel] [RFC] [PATCH 1/3] ASoC: Add support for Conexant CX20442-11 voice modem codec
Tuesday 28 July 2009 18:11:32 Mark Brown wrote: > On Tue, Jul 28, 2009 at 06:07:29PM +0200, Janusz Krzysztofik wrote: > > now. Activation of the line discipline would deregister the codec device > > from the platform bus and reregister it again, now as the line discipline > > provided device. Is this possible with current ASoC framework? > > No, not currently. But why would you do that, anyway? > > Like I say, I'd suggest always keeping the controls registered and just > masking and unmasking from user space - the control indexes get used so > removing them will just confuse things. However, in order for the machine driver to unmask/mask a machine specific control, the codec driver must drop the machine driver a message about the line discipline being activeted/deactivated, right? The only such existing feedback I can see the codec is able to use is via snd_soc_init_card() that calls snd_soc_dai_link.init() in turn. Am I missing something? Janusz -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [alsa-devel] [RFC] [PATCH 1/3] ASoC: Add support for Conexant CX20442-11 voice modem codec
On Tue, Jul 28, 2009 at 06:07:29PM +0200, Janusz Krzysztofik wrote: > What I would like to retain from the current codec driver are those two modes > of operation: without and with the line discipline activated. Initially, the > codec would be registered as a platform device, as it is now. Activation of > the line discipline would deregister the codec device from the platform bus > and reregister it again, now as the line discipline provided device. Is this > possible with current ASoC framework? No, not currently. But why would you do that, anyway? Like I say, I'd suggest always keeping the controls registered and just masking and unmasking from user space - the control indexes get used so removing them will just confuse things. -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [alsa-devel] [RFC] [PATCH 1/3] ASoC: Add support for Conexant CX20442-11 voice modem codec
Tuesday 28 July 2009 17:07:27 Mark Brown wrote: > On Tue, Jul 28, 2009 at 04:59:33PM +0200, Janusz Krzysztofik wrote: > > Following that model, the line discipline code didn't seam to belong to a > > codec driver for me. If it could be recognized as a new bus dirver, it > > should be pushed down probably into a separate module. However, if it was > > rather some kind of a bus adapter driver, it seamed to belong to the > > machine code. > > The way it looks with the current code the line discipline itself is > going to apply equally well to any serial port that's used - I'm not > clear what's system-specific about it. The bit that connects the line > discipline to the line is a different matter but the bit that interacts > with the TTY layer after registration is working through a pluggable > abstraction layer and shouldn't, I'd expect, be specific to the > particular serial port. Mark, I think I can't tell anything more before I try to implement it in a way you suggest, so I will. What I would like to retain from the current codec driver are those two modes of operation: without and with the line discipline activated. Initially, the codec would be registered as a platform device, as it is now. Activation of the line discipline would deregister the codec device from the platform bus and reregister it again, now as the line discipline provided device. Is this possible with current ASoC framework? Thanks, Janusz -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [RFC][PATCH 2/3] ARM:OMAP4 iommu:add omap4 support in iommu
Hi Hiroshi, > > This "omap iommu" driver is used in OMAP4 IPC and its interface is a > character device node. IOW, the client of this device will be an > userland process and kernel won't know if it uses or not, but kernel > just provides "/dev/iommu?" for userland. So I don't think that we > have to care about the dependency of the existance of clients, at > least, for a moment. > > > The first patch set that I sent is to provide support in IOMMU for OMAP4 just like how it is done in OMAP3 today. The define "CONFIG_MPU_TESLA_IOMMU" is used for now because in the first phase we are planning to use DSP-Bridge to communicate with Tesla (until we move the new user-land IPC to replace DSP-Bridge for OMAP4). IMHO, let's go ahead with these changes and any changes to support IOMMU from user-land we can address them in next set of patches. Thank you, Best regards, Hari > -Original Message- > From: Hiroshi DOYU [mailto:hiroshi.d...@nokia.com] > Sent: Monday, July 27, 2009 1:48 AM > To: Kanigeri, Hari > Cc: t...@atomide.com; linux-omap@vger.kernel.org; Gupta, Ramesh; > r...@arm.linux.org.uk; Pasam, Vijay > Subject: Re: [RFC][PATCH 2/3] ARM:OMAP4 iommu:add omap4 support in iommu > > From: "ext Kanigeri, Hari" > Subject: RE: [RFC][PATCH 2/3] ARM:OMAP4 iommu:add omap4 support in iommu > Date: Mon, 27 Jul 2009 02:18:21 +0200 > > > Hi Hiroshi, > > > > > > +static const struct iommu_platform_data omap4_iommu_pdata[] > __initconst > > > = { > > > > + { > > > > + .name = "ducati", > > > > + .nr_tlb_entries = 32, > > > > + .clk_name = "ducati_ick", > > > > + }, > > > > +#if defined(CONFIG_MPU_TESLA_IOMMU) > > > > + { > > > > + .name = "tesla", > > > > + .nr_tlb_entries = 32, > > > > + .clk_name = "tesla_ick", > > > > + }, > > > > +#endif > > > > +}; > > > > > > If iommu is used as a character device driver, is the above config > still > > > necessary? > > > > -- My apologies, I am not sure what you mean by this. Can you please > elaborate a bit more. > > Well...I'm trying to explain;), > > This "omap iommu" driver is used in OMAP4 IPC and its interface is a > character device node. IOW, the client of this device will be an > userland process and kernel won't know if it uses or not, but kernel > just provides "/dev/iommu?" for userland. So I don't think that we > have to care about the dependency of the existance of clients, at > least, for a moment. > > > > > Thank you, > > Best regards, > > Hari > > > > > -Original Message- > > > From: Hiroshi DOYU [mailto:hiroshi.d...@nokia.com] > > > Sent: Friday, July 24, 2009 1:22 PM > > > To: Kanigeri, Hari > > > Cc: t...@atomide.com; linux-omap@vger.kernel.org; Gupta, Ramesh; > > > r...@arm.linux.org.uk; Pasam, Vijay > > > Subject: Re: [RFC][PATCH 2/3] ARM:OMAP4 iommu:add omap4 support in > iommu > > > > > > From: "ext Kanigeri, Hari" > > > Subject: [RFC][PATCH 2/3] ARM:OMAP4 iommu:add omap4 support in iommu > > > Date: Fri, 24 Jul 2009 19:22:32 +0200 > > > > > > > This patch adds omap4 support in iommu > > > > module. This creates OMAP4 platform specific file > > > > for iommu and defines the Ducati MMU fault interrupt. > > > > > > > > Signed-off-by: Hari Kanigeri > > > > --- > > > > arch/arm/mach-omap2/omap4-iommu.c | 112 > > > > > > > arch/arm/plat-omap/include/mach/irqs.h |2 +- > > > > 2 files changed, 113 insertions(+), 1 deletions(-) > > > > create mode 100644 arch/arm/mach-omap2/omap4-iommu.c > > > > > > > > diff --git a/arch/arm/mach-omap2/omap4-iommu.c b/arch/arm/mach- > > > omap2/omap4-iommu.c > > > > new file mode 100644 > > > > index 000..5a782df > > > > --- /dev/null > > > > +++ b/arch/arm/mach-omap2/omap4-iommu.c > > > > @@ -0,0 +1,112 @@ > > > > +/* > > > > + * omap iommu: omap4 device registration > > > > + * > > > > + * Copyright (C) 2009-2010 Nokia Corporation > > > > + * > > > > + * Written by Hari Kanigeri > > > > + * > > > > + * Added support for OMAP4. This is based on original file > > > > + * omap3-iommu.c > > > > + * > > > > + * This program is free software; you can redistribute it and/or > modify > > > > + * it under the terms of the GNU General Public License version 2 > as > > > > + * published by the Free Software Foundation. > > > > + */ > > > > + > > > > +#include > > > > + > > > > +#include > > > > +#include > > > > + > > > > +#define OMAP4_MMU1_BASE0x55082000 > > > > +#define OMAP4_MMU2_BASE0x4A066000 > > > > + > > > > +#define OMAP4_MMU1_IRQ INT_44XX_DUCATI_MMU_IRQ > > > > +#define OMAP4_MMU2_IRQ INT_44XX_DSP_MMU > > > > + > > > > + > > > > + > > > > +static unsigned long iommu_base[] __initdata = { > > > > + OMAP4_MMU1_BASE, > > > > + OMAP4_MMU2_BASE, > > > > +}; > > > > + > > > > +static int iommu_irq[] __initdata = { > > > > + OMAP4_MMU1_IRQ, > > > > + OMAP4_MMU2_IRQ, > > > > +}; > > > > + > > > > +static const st
Re: [alsa-devel] [RFC] [PATCH 1/3] ASoC: Add support for Conexant CX20442-11 voice modem codec
On Tue, Jul 28, 2009 at 04:59:33PM +0200, Janusz Krzysztofik wrote: > Following that model, the line discipline code didn't seam to belong to a > codec driver for me. If it could be recognized as a new bus dirver, it should > be pushed down probably into a separate module. However, if it was rather > some kind of a bus adapter driver, it seamed to belong to the machine code. The way it looks with the current code the line discipline itself is going to apply equally well to any serial port that's used - I'm not clear what's system-specific about it. The bit that connects the line discipline to the line is a different matter but the bit that interacts with the TTY layer after registration is working through a pluggable abstraction layer and shouldn't, I'd expect, be specific to the particular serial port. -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [alsa-devel] [RFC] [PATCH 1/3] ASoC: Add support for Conexant CX20442-11 voice modem codec
Wednesday 22 July 2009 12:10:28 Mark Brown wrote: > On Wed, Jul 22, 2009 at 05:22:28AM +0200, Janusz Krzysztofik wrote: > > This patch adds support for Conexant CX20442-11 voice modem codec, > > suitable for use by the ASoC board driver for Amstrad E3 (Delta) > > videophone. Related sound card driver will follow. > > > You'll want to run checkpatch over it and send a followup fixing the > issues it identifies. Looking at this I suspect that it may be possible > to refactor things so that more of the line discipline interaction is > pushed down into the CODEC driver but that can also be done as a > followup. > > would also be nice to add some documentation somewhere explaining how > the hw_write() function is expected to be set up since it's a little > surprising (if the line discipline stuff were pushed down into the code > that'd become a lot more obvious). Mark, I am ready with a followup that corrects those minor issues, as well as with a new, corrected version of the machine driver. However, before I submit them, I'd like to discuss again your idea of pushing down the line discipline code into the codec driver. As you may have noticed, my codec driver was ready for adopting it to one or more additional buses of different types, in a way similiar to those implemented in other codec drivers. There was a room for a hypothetical cx20442_xxx_probe() function, invoked by a hypothetical xxx bus driver after the bus comes up or a device is detected on it. That function could then set up its own codec->control_data and codec->hw_write pointers for talking to the codec via a hypothetical xxx bus adapter using its write method. In particular, that could be a line discipline provided acceess to the codec assosociated modem. Following that model, the line discipline code didn't seam to belong to a codec driver for me. If it could be recognized as a new bus dirver, it should be pushed down probably into a separate module. However, if it was rather some kind of a bus adapter driver, it seamed to belong to the machine code. As I had got no positive feedback to my RFC on inventing a new bus (votes were rather neutral, and I agreed with them[1]), I decided to put the line discipline code into the machine driver. If you see things somehow different, please let me know, I can try to follow your ideas and rearrange the code. Cheers, Janusz [1] http://www.spinics.net/lists/linux-serial/msg01856.html -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: OMAP camera with BT-656 sensor
Hiremath, Vaibhav wrote: >> -Original Message- >> From: linux-omap-ow...@vger.kernel.org [mailto:linux-omap- >> ow...@vger.kernel.org] On Behalf Of Aguirre Rodriguez, Sergio >> Alberto >> Sent: Tuesday, July 28, 2009 1:45 AM >> To: Gary Thomas >> Cc: linux-omap@vger.kernel.org >> Subject: RE: OMAP camera with BT-656 sensor >> >> >> >>> -Original Message- >>> From: Gary Thomas [mailto:g...@mlbassoc.com] >>> Sent: Monday, July 27, 2009 2:59 PM >>> To: Aguirre Rodriguez, Sergio Alberto >>> Cc: linux-omap@vger.kernel.org >>> Subject: Re: OMAP camera with BT-656 sensor >>> >>> Aguirre Rodriguez, Sergio Alberto wrote: > -Original Message- > From: Gary Thomas [mailto:g...@mlbassoc.com] > Sent: Monday, July 27, 2009 2:11 PM > To: Aguirre Rodriguez, Sergio Alberto > Cc: linux-omap@vger.kernel.org > Subject: OMAP camera with BT-656 sensor >>>... snip >>> > Bottom line, I'm confused as to how I should go about getting > my driver/system working. Do I use your work, or just stick > with the PSP base (why?)?? What I do feel is that the PSP base will fulfill better your >> immediate >>> needs, but in the future, as I'm getting aware of Vaibhav changes, >> I'll be >>> interested in making them part of my tree aswell, so Vaibhav could >> avoid >>> rebasing the BT646 support internally everytime... >>> >>> Is there a GIT tree for this? >> AFAIK, this is the latest tree Vaibhav is exposing: >> >> http://arago-project.org/git/people/vaibhav/ti-psp-omap-video.git >> >> He maintains a camera and a DSS2 branch exactly to make both work on >> his 3530EVM. >> > [Hiremath, Vaibhav] Thanks Sergio for taking this up. Just to add on top of > Sergio's comments, the current status of above tree is, DSS2 is already > merged to latest kernel (Even on PM branch) baseline. > > http://arago-project.org/git/people/?p=vaibhav/ti-psp-omap-video.git;a=shortlog;h=refs/heads/ti_display > > http://arago-project.org/git/people/?p=vaibhav/ti-psp-omap-video.git;a=shortlog;h=refs/heads/pm > > > The next PSP release will contain 2.6.31(PM) + DSS2 + Camera + Resizer > modules together in one release. I have started with Camera modules merging > on top of 2.6.31 + DSS2; hopefully I should be able to complete this by next > week (provided that I don't get any interrupts) > > You should be looking to Arago tree for all the developments which I do under > Arago. > > Please let me know if you have any issues/doubts OR if you are looking for > some quick solutions. I'd like to use the latest tree with DSS2 (ti_display seems to be it), but the OMAP3 camera support is not present. * How hard would it be to merge the ti_omap3camera and ti_display branches? * Would this be a reasonable way forward? It would be nice if I could wait for your next release, but alas, my project is already weeks late and every hour counts... >>> A [hopefully] minor complication is that I'm using Tomi's DSS2 >>> tree for the base of my port. How can I move/merge the PSP >>> based support into it? Can I just pick up the whole drivers/media >>> subtree and put in in place of what I have? >> I recommend looking at the git tree above... I think that job is >> already done... >> >>> Thanks for your help - this myriad of trees and very disparate >>> support levels is really confusing to those of us on the >> outside... >> >> I know, and the lack of proper documentation is one of the first >> issues for me to look at... >> >> You're welcome. -- Gary Thomas | Consulting for the MLB Associates |Embedded world -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V2 1/32] mmc: add 'enable' and 'disable' methods to mmc host
>From 4610f1ede273078f99214c6284202998aa537a1d Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Wed, 22 Apr 2009 12:50:45 +0300 Subject: [PATCH] mmc: add 'enable' and 'disable' methods to mmc host MMC hosts that support power saving can use the 'enable' and 'disable' methods to exit and enter power saving states. An explanation of their use is provided in the comments added to include/linux/mmc/host.h. Signed-off-by: Adrian Hunter --- drivers/mmc/core/core.c | 177 -- drivers/mmc/core/host.c |1 + drivers/mmc/core/host.h |2 + include/linux/mmc/host.h | 47 4 files changed, 221 insertions(+), 6 deletions(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index d84c880..9bc8d27 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -344,6 +344,101 @@ unsigned int mmc_align_data_size(struct mmc_card *card, unsigned int sz) EXPORT_SYMBOL(mmc_align_data_size); /** + * mmc_host_enable - enable a host. + * @host: mmc host to enable + * + * Hosts that support power saving can use the 'enable' and 'disable' + * methods to exit and enter power saving states. For more information + * see comments for struct mmc_host_ops. + */ +int mmc_host_enable(struct mmc_host *host) +{ + if (!(host->caps & MMC_CAP_DISABLE)) + return 0; + + if (host->en_dis_recurs) + return 0; + + if (host->nesting_cnt++) + return 0; + + cancel_delayed_work_sync(&host->disable); + + if (host->enabled) + return 0; + + if (host->ops->enable) { + int err; + + host->en_dis_recurs = 1; + err = host->ops->enable(host); + host->en_dis_recurs = 0; + + if (err) { + pr_debug("%s: enable error %d\n", +mmc_hostname(host), err); + return err; + } + } + host->enabled = 1; + return 0; +} +EXPORT_SYMBOL(mmc_host_enable); + +static int mmc_host_do_disable(struct mmc_host *host, int lazy) +{ + if (host->ops->disable) { + int err; + + host->en_dis_recurs = 1; + err = host->ops->disable(host, lazy); + host->en_dis_recurs = 0; + + if (err < 0) { + pr_debug("%s: disable error %d\n", +mmc_hostname(host), err); + return err; + } + if (err > 0) { + unsigned long delay = msecs_to_jiffies(err); + + mmc_schedule_delayed_work(&host->disable, delay); + } + } + host->enabled = 0; + return 0; +} + +/** + * mmc_host_disable - disable a host. + * @host: mmc host to disable + * + * Hosts that support power saving can use the 'enable' and 'disable' + * methods to exit and enter power saving states. For more information + * see comments for struct mmc_host_ops. + */ +int mmc_host_disable(struct mmc_host *host) +{ + int err; + + if (!(host->caps & MMC_CAP_DISABLE)) + return 0; + + if (host->en_dis_recurs) + return 0; + + if (--host->nesting_cnt) + return 0; + + if (!host->enabled) + return 0; + + err = mmc_host_do_disable(host, 0); + return err; +} +EXPORT_SYMBOL(mmc_host_disable); + +/** * __mmc_claim_host - exclusively claim a host * @host: mmc host to claim * @abort: whether or not the operation should be aborted @@ -379,11 +474,81 @@ int __mmc_claim_host(struct mmc_host *host, atomic_t *abort) wake_up(&host->wq); spin_unlock_irqrestore(&host->lock, flags); remove_wait_queue(&host->wq, &wait); + if (!stop) + mmc_host_enable(host); return stop; } EXPORT_SYMBOL(__mmc_claim_host); +static int mmc_try_claim_host(struct mmc_host *host) +{ + int claimed_host = 0; + unsigned long flags; + + spin_lock_irqsave(&host->lock, flags); + if (!host->claimed) { + host->claimed = 1; + claimed_host = 1; + } + spin_unlock_irqrestore(&host->lock, flags); + return claimed_host; +} + +static void mmc_do_release_host(struct mmc_host *host) +{ + unsigned long flags; + + spin_lock_irqsave(&host->lock, flags); + host->claimed = 0; + spin_unlock_irqrestore(&host->lock, flags); + + wake_up(&host->wq); +} + +void mmc_host_deeper_disable(struct work_struct *work) +{ + struct mmc_host *host = + container_of(work, struct mmc_host, disable.work); + + /* If the host is claimed then we do not want to disable it anymore */ + if (!mmc_try_claim_host(host)) + return; + mmc_host_do_disable(host, 1); + mmc_do_release_ho
[PATCH V2 8/32] mmc: check status after MMC SWITCH command
>From 98c0aabb4c04bcdf7d166c0fb7e2c859e33f8c70 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Wed, 3 Jun 2009 12:22:29 +0300 Subject: [PATCH] mmc: check status after MMC SWITCH command According to the standard, the SWITCH command should be followed by a SEND_STATUS command to check for errors. Signed-off-by: Adrian Hunter --- drivers/mmc/core/mmc.c | 24 ++-- drivers/mmc/core/mmc_ops.c | 23 +++ include/linux/mmc/mmc.h|1 + 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 8e2e3d2..f87cc0b 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -416,12 +416,17 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, (host->caps & MMC_CAP_MMC_HIGHSPEED)) { err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, 1); - if (err) + if (err && err != -EBADMSG) goto free_card; - mmc_card_set_highspeed(card); - - mmc_set_timing(card->host, MMC_TIMING_MMC_HS); + if (err) { + printk(KERN_WARNING "%s: switch to highspeed failed\n", + mmc_hostname(card->host)); + err = 0; + } else { + mmc_card_set_highspeed(card); + mmc_set_timing(card->host, MMC_TIMING_MMC_HS); + } } /* @@ -456,10 +461,17 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH, ext_csd_bit); - if (err) + if (err && err != -EBADMSG) goto free_card; - mmc_set_bus_width(card->host, bus_width); + if (err) { + printk(KERN_WARNING "%s: switch to bus width %d " + "failed\n", mmc_hostname(card->host), + 1 << bus_width); + err = 0; + } else { + mmc_set_bus_width(card->host, bus_width); + } } if (!oldcard) diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 355c604..d2cb5c6 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -390,6 +390,7 @@ int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value) { int err; struct mmc_command cmd; + u32 status; BUG_ON(!card); BUG_ON(!card->host); @@ -407,6 +408,28 @@ int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value) if (err) return err; + /* Must check status to be sure of no errors */ + do { + err = mmc_send_status(card, &status); + if (err) + return err; + if (card->host->caps & MMC_CAP_WAIT_WHILE_BUSY) + break; + if (mmc_host_is_spi(card->host)) + break; + } while (R1_CURRENT_STATE(status) == 7); + + if (mmc_host_is_spi(card->host)) { + if (status & R1_SPI_ILLEGAL_COMMAND) + return -EBADMSG; + } else { + if (status & 0xFDFFA000) + printk(KERN_WARNING "%s: unexpected status %#x after " + "switch", mmc_hostname(card->host), status); + if (status & R1_SWITCH_ERROR) + return -EBADMSG; + } + return 0; } diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h index b2b4095..c02c8db 100644 --- a/include/linux/mmc/mmc.h +++ b/include/linux/mmc/mmc.h @@ -128,6 +128,7 @@ #define R1_STATUS(x)(x & 0xE000) #define R1_CURRENT_STATE(x)((x & 0x1E00) >> 9) /* sx, b (4 bits) */ #define R1_READY_FOR_DATA (1 << 8)/* sx, a */ +#define R1_SWITCH_ERROR(1 << 7)/* sx, c */ #define R1_APP_CMD (1 << 5)/* sr, c */ /* -- 1.5.6.3 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V2 12/32] omap_hsmmc: keep track of power mode
>From 3592682a0965d32d3498f7da11073ff4d88f1bf7 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 7 Jul 2009 16:44:11 +0300 Subject: [PATCH] omap_hsmmc: keep track of power mode This patch is preparation for adding context save and restore support. Keep track of the current power mode so that the context restore function can avoid restoring the context for a card if the power has been switched off. If the power is off, the card must be reinitialized anyway which will re-establish the context. Signed-off-by: Adrian Hunter --- drivers/mmc/host/omap_hsmmc.c | 27 +++ 1 files changed, 19 insertions(+), 8 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index f9b7cfe..c28d055 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -141,6 +141,7 @@ struct mmc_omap_host { unsigned intdma_len; unsigned intdma_sg_idx; unsigned char bus_mode; + unsigned char power_mode; u32 *buffer; u32 bytesleft; int suspended; @@ -856,16 +857,25 @@ static void omap_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) unsigned long regval; unsigned long timeout; u32 con; + int do_send_init_stream = 0; mmc_host_enable(host->mmc); - switch (ios->power_mode) { - case MMC_POWER_OFF: - mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0); - break; - case MMC_POWER_UP: - mmc_slot(host).set_power(host->dev, host->slot_id, 1, ios->vdd); - break; + if (ios->power_mode != host->power_mode) { + switch (ios->power_mode) { + case MMC_POWER_OFF: + mmc_slot(host).set_power(host->dev, host->slot_id, +0, 0); + break; + case MMC_POWER_UP: + mmc_slot(host).set_power(host->dev, host->slot_id, +1, ios->vdd); + break; + case MMC_POWER_ON: + do_send_init_stream = 1; + break; + } + host->power_mode = ios->power_mode; } con = OMAP_HSMMC_READ(host->base, CON); @@ -931,7 +941,7 @@ static void omap_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) OMAP_HSMMC_WRITE(host->base, SYSCTL, OMAP_HSMMC_READ(host->base, SYSCTL) | CEN); - if (ios->power_mode == MMC_POWER_ON) + if (do_send_init_stream) send_init_stream(host); if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) @@ -1109,6 +1119,7 @@ static int __init omap_mmc_probe(struct platform_device *pdev) host->slot_id = 0; host->mapbase = res->start; host->base = ioremap(host->mapbase, SZ_4K); + host->power_mode = -1; platform_set_drvdata(pdev, host); INIT_WORK(&host->mmc_carddetect_work, mmc_omap_detect); -- 1.5.6.3 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V2 21/32] omap_hsmmc: add mmc card sleep and awake support
>From 372d05a33f04d6a664ad1d3a80bed3d9ae80e495 Mon Sep 17 00:00:00 2001 From: Jarkko Lavinen Date: Tue, 12 May 2009 19:46:14 +0300 Subject: [PATCH] omap_hsmmc: add mmc card sleep and awake support After 1 second of inactivity, put card and/or regulator to sleep. After 8 seconds of inactivity, turn off the power. Signed-off-by: Jarkko Lavinen Signed-off-by: Adrian Hunter --- drivers/mmc/host/omap_hsmmc.c | 162 ++--- 1 files changed, 88 insertions(+), 74 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 7a17901..d5fb066 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -113,7 +114,8 @@ /* Timeouts for entering power saving states on inactivity, msec */ #define OMAP_MMC_DISABLED_TIMEOUT 100 -#define OMAP_MMC_OFF_TIMEOUT 1000 +#define OMAP_MMC_SLEEP_TIMEOUT 1000 +#define OMAP_MMC_OFF_TIMEOUT 8000 /* * One controller can have multiple slots, like on some omap boards using @@ -1175,20 +1177,21 @@ static void omap_hsmmc_init(struct mmc_omap_host *host) /* * Dynamic power saving handling, FSM: - * ENABLED -> DISABLED -> OFF / REGSLEEP - * ^___| | - * |__| + * ENABLED -> DISABLED -> CARDSLEEP / REGSLEEP -> OFF + * ^___| | | + * |__|__| * * ENABLED: mmc host is fully functional * DISABLED: fclk is off - * OFF: fclk is off,voltage regulator is off - * REGSLEEP: fclk is off,voltage regulator is asleep + * CARDSLEEP: fclk is off, card is asleep, voltage regulator is asleep + * REGSLEEP: fclk is off, voltage regulator is asleep + * OFF: fclk is off, voltage regulator is off * * Transition handlers return the timeout for the next state transition * or negative error. */ -enum {ENABLED = 0, DISABLED, REGSLEEP, OFF}; +enum {ENABLED = 0, DISABLED, CARDSLEEP, REGSLEEP, OFF}; /* Handler for [ENABLED -> DISABLED] transition */ static int omap_mmc_enabled_to_disabled(struct mmc_omap_host *host) @@ -1202,46 +1205,72 @@ static int omap_mmc_enabled_to_disabled(struct mmc_omap_host *host) if (host->power_mode == MMC_POWER_OFF) return 0; - return msecs_to_jiffies(OMAP_MMC_OFF_TIMEOUT); + return msecs_to_jiffies(OMAP_MMC_SLEEP_TIMEOUT); } -/* Handler for [DISABLED -> OFF] transition */ -static int omap_mmc_disabled_to_off(struct mmc_omap_host *host) +/* Handler for [DISABLED -> REGSLEEP / CARDSLEEP] transition */ +static int omap_mmc_disabled_to_sleep(struct mmc_omap_host *host) { - int new_state; - - dev_dbg(mmc_dev(host->mmc), "DISABLED -> OFF\n"); + int err, new_state; if (!mmc_try_claim_host(host->mmc)) return 0; clk_enable(host->fclk); - omap_mmc_restore_ctx(host); + if (mmc_card_can_sleep(host->mmc)) { + err = mmc_card_sleep(host->mmc); + if (err < 0) { + clk_disable(host->fclk); + mmc_release_host(host->mmc); + return err; + } + new_state = CARDSLEEP; + } else + new_state = REGSLEEP; + if (mmc_slot(host).set_sleep) + mmc_slot(host).set_sleep(host->dev, host->slot_id, 1, 0, +new_state == CARDSLEEP); + /* FIXME: turn off bus power and perhaps interrupts too */ + clk_disable(host->fclk); + host->dpm_state = new_state; + + mmc_release_host(host->mmc); + + dev_dbg(mmc_dev(host->mmc), "DISABLED -> %s\n", + host->dpm_state == CARDSLEEP ? "CARDSLEEP" : "REGSLEEP"); if ((host->mmc->caps & MMC_CAP_NONREMOVABLE) || mmc_slot(host).card_detect || (mmc_slot(host).get_cover_state && -mmc_slot(host).get_cover_state(host->dev, host->slot_id))) { - mmc_power_save_host(host->mmc); - new_state = OFF; - } else { - if (mmc_slot(host).set_sleep) - mmc_slot(host).set_sleep(host->dev, host->slot_id, -1, 0, 0); - new_state = REGSLEEP; +mmc_slot(host).get_cover_state(host->dev, host->slot_id))) + return msecs_to_jiffies(OMAP_MMC_OFF_TIMEOUT); + + return 0; +} + +/* Handler for [REGSLEEP / CARDSLEEP -> OFF] transition */ +static int omap_mmc_sleep_to_off(struct mmc_omap_host *host) +{ + if (!mmc_try_claim_host(host->mmc)) + return 0; + + if (!((host->mmc->caps & MMC_CAP_NONREMOVABLE) || + mmc_slot(host).card_detect || + (mmc_slot(host).get_cover_state && + mmc_slot(host).get_cover_state(host->dev, host->slot_
[PATCH V2 23/32] omap_hsmmc: cleanup macro usage
>From 6a8acf9de3b12869c76ff2819e61c54c81b2c753 Mon Sep 17 00:00:00 2001 From: Denis Karpov Date: Thu, 14 May 2009 09:11:38 +0200 Subject: [PATCH] omap_hsmmc: cleanup macro usage Use macro mmc_slot() in omap_hsmmc. Signed-off-by: Denis Karpov Signed-off-by: Adrian Hunter --- drivers/mmc/host/omap_hsmmc.c | 42 ++-- 1 files changed, 19 insertions(+), 23 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 4309031..0373bdd 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -366,9 +366,8 @@ int mmc_omap_cover_is_closed(struct mmc_omap_host *host) { int r = 1; - if (host->pdata->slots[host->slot_id].get_cover_state) - r = host->pdata->slots[host->slot_id].get_cover_state(host->dev, - host->slot_id); + if (mmc_slot(host).get_cover_state) + r = mmc_slot(host).get_cover_state(host->dev, host->slot_id); return r; } @@ -391,9 +390,8 @@ mmc_omap_show_slot_name(struct device *dev, struct device_attribute *attr, { struct mmc_host *mmc = container_of(dev, struct mmc_host, class_dev); struct mmc_omap_host *host = mmc_priv(mmc); - struct omap_mmc_slot_data slot = host->pdata->slots[host->slot_id]; - return sprintf(buf, "%s\n", slot.name); + return sprintf(buf, "%s\n", mmc_slot(host).name); } static DEVICE_ATTR(slot_name, S_IRUGO, mmc_omap_show_slot_name, NULL); @@ -625,7 +623,8 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id) (status & CMD_CRC)) { if (host->cmd) { if (status & CMD_TIMEOUT) { - mmc_omap_reset_controller_fsm(host, SRC); + mmc_omap_reset_controller_fsm(host, + SRC); host->cmd->error = -ETIMEDOUT; } else { host->cmd->error = -EILSEQ; @@ -768,7 +767,7 @@ static void mmc_omap_detect(struct work_struct *work) sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch"); - if (mmc_slot(host).card_detect) + if (slot->card_detect) carddetect = slot->card_detect(slot->card_detect_irq); else carddetect = -ENOSYS; @@ -823,7 +822,7 @@ static void mmc_omap_config_dma_params(struct mmc_omap_host *host, sg_dma_address(sgl), 0, 0); } else { omap_set_dma_src_params(dma_ch, 0, OMAP_DMA_AMODE_CONSTANT, - (host->mapbase + OMAP_HSMMC_DATA), 0, 0); + (host->mapbase + OMAP_HSMMC_DATA), 0, 0); omap_set_dma_dest_params(dma_ch, 0, OMAP_DMA_AMODE_POST_INC, sg_dma_address(sgl), 0, 0); } @@ -911,7 +910,7 @@ mmc_omap_start_dma_transfer(struct mmc_omap_host *host, struct mmc_request *req) } ret = omap_request_dma(mmc_omap_get_dma_sync_dev(host, data), "MMC/SD", - mmc_omap_dma_cb,host, &dma_ch); + mmc_omap_dma_cb, host, &dma_ch); if (ret != 0) { dev_err(mmc_dev(host->mmc), "%s: omap_request_dma() failed with %d\n", @@ -1131,21 +1130,19 @@ static void omap_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) static int omap_hsmmc_get_cd(struct mmc_host *mmc) { struct mmc_omap_host *host = mmc_priv(mmc); - struct omap_mmc_platform_data *pdata = host->pdata; - if (!pdata->slots[0].card_detect) + if (!mmc_slot(host).card_detect) return -ENOSYS; - return pdata->slots[0].card_detect(pdata->slots[0].card_detect_irq); + return mmc_slot(host).card_detect(mmc_slot(host).card_detect_irq); } static int omap_hsmmc_get_ro(struct mmc_host *mmc) { struct mmc_omap_host *host = mmc_priv(mmc); - struct omap_mmc_platform_data *pdata = host->pdata; - if (!pdata->slots[0].get_ro) + if (!mmc_slot(host).get_ro) return -ENOSYS; - return pdata->slots[0].get_ro(host->dev, 0); + return mmc_slot(host).get_ro(host->dev, 0); } static void omap_hsmmc_init(struct mmc_omap_host *host) @@ -1556,7 +1553,7 @@ static int __init omap_mmc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, host); INIT_WORK(&host->mmc_carddetect_work, mmc_omap_detect); - if (pdata->slots[host->slot_id].power_saving) + if (mmc_slot(host).power_saving) mmc->ops= &mmc_omap_ps_ops; else mmc->ops= &mmc_omap_ops; @@ -1626,12 +1623,12 @@ static int __init omap_mmc_probe(struct platform_device *pdev) mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPE
[PATCH V2 32/32] ARM: OMAP: RX51: set MMC capabilities and power-saving flag
>From 3f9b4e7c30012bbad4f5cf678f2e02e943000b67 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 10 Jul 2009 10:32:44 +0300 Subject: [PATCH] ARM: OMAP: RX51: set MMC capabilities and power-saving flag Specify MMC capabilities and set the power-saving flag for RX51. Signed-off-by: Adrian Hunter --- arch/arm/mach-omap2/board-rx51-peripherals.c |5 + 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index 9a0bf67..d2ce938 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -102,6 +103,8 @@ static struct twl4030_hsmmc_info mmc[] = { .cover_only = true, .gpio_cd= 160, .gpio_wp= -EINVAL, + .power_saving = true, + .caps = MMC_CAP_SD, }, { .name = "internal", @@ -109,6 +112,8 @@ static struct twl4030_hsmmc_info mmc[] = { .wires = 8, .gpio_cd= -EINVAL, .gpio_wp= -EINVAL, + .power_saving = true, + .caps = MMC_CAP_MMC | MMC_CAP_NONREMOVABLE, }, {} /* Terminator */ }; -- 1.5.6.3 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V2 29/32] omap_hsmmc: protect the card when the cover is open
>From f1228758121aab11ba2265f2c6fe37f65b3aae03 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 22 May 2009 16:53:49 +0300 Subject: [PATCH] omap_hsmmc: protect the card when the cover is open Depending on the manufacturer, there is a small possibility that removing a card while it is being written to, can render the card permanently unusable. To prevent that, the card is made inaccessible when the cover is open. Signed-off-by: Adrian Hunter --- drivers/mmc/host/omap_hsmmc.c | 63 +++- 1 files changed, 61 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index c2b334d..32d5aef 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -165,6 +165,8 @@ struct omap_hsmmc_host { int context_loss; int dpm_state; int vdd; + int protect_card; + int reqs_blocked; struct omap_mmc_platform_data *pdata; }; @@ -349,6 +351,9 @@ static void send_init_stream(struct omap_hsmmc_host *host) int reg = 0; unsigned long timeout; + if (host->protect_card) + return; + disable_irq(host->irq); OMAP_HSMMC_WRITE(host->base, CON, OMAP_HSMMC_READ(host->base, CON) | INIT_STREAM); @@ -779,6 +784,30 @@ err: return ret; } +/* Protect the card while the cover is open */ +static void omap_hsmmc_protect_card(struct omap_hsmmc_host *host) +{ + if (!mmc_slot(host).get_cover_state) + return; + + host->reqs_blocked = 0; + if (mmc_slot(host).get_cover_state(host->dev, host->slot_id)) { + if (host->protect_card) { + printk(KERN_INFO "%s: cover is closed, " +"card is now accessible\n", +mmc_hostname(host->mmc)); + host->protect_card = 0; + } + } else { + if (!host->protect_card) { + printk(KERN_INFO "%s: cover is open, " +"card is now inaccessible\n", +mmc_hostname(host->mmc)); + host->protect_card = 1; + } + } +} + /* * Work Item to notify the core about card insertion/removal */ @@ -796,8 +825,10 @@ static void omap_hsmmc_detect(struct work_struct *work) if (slot->card_detect) carddetect = slot->card_detect(slot->card_detect_irq); - else + else { + omap_hsmmc_protect_card(host); carddetect = -ENOSYS; + } if (carddetect) { mmc_detect_change(host->mmc, (HZ * 200) / 1000); @@ -1033,8 +1064,32 @@ static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req) * interrupts, but not if we are already in interrupt context i.e. * retries. */ - if (!in_interrupt()) + if (!in_interrupt()) { spin_lock_irqsave(&host->irq_lock, host->flags); + /* +* Protect the card from I/O if there is a possibility +* it can be removed. +*/ + if (host->protect_card) { + if (host->reqs_blocked < 3) { + /* +* Ensure the controller is left in a consistent +* state by resetting the command and data state +* machines. +*/ + omap_hsmmc_reset_controller_fsm(host, SRD); + omap_hsmmc_reset_controller_fsm(host, SRC); + host->reqs_blocked += 1; + } + req->cmd->error = -EBADF; + if (req->data) + req->data->error = -EBADF; + spin_unlock_irqrestore(&host->irq_lock, host->flags); + mmc_request_done(mmc, req); + return; + } else if (host->reqs_blocked) + host->reqs_blocked = 0; + } WARN_ON(host->mrq != NULL); host->mrq = req; err = omap_hsmmc_prepare_data(host, req); @@ -1728,6 +1783,8 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) mmc_host_lazy_disable(host->mmc); + omap_hsmmc_protect_card(host); + mmc_add_host(mmc); if (mmc_slot(host).name != NULL) { @@ -1893,6 +1950,8 @@ static int omap_hsmmc_resume(struct platform_device *pdev) "Unmask interrupt failed\n"); } + omap_hsmmc_protect_card(host); + /* Notify the core t
[PATCH V2 27/32] omap_hsmmc: pass host capabilities for SD only and MMC only
>From 6ed0f09877e25af46579c1e7754600d31356e302 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Mon, 18 May 2009 11:33:26 +0300 Subject: [PATCH] omap_hsmmc: pass host capabilities for SD only and MMC only Some hosts can accept only certain types of cards. For example, an eMMC is MMC only and a uSD slot may be SD only. Pass host capabilities from the board through to the driver. Signed-off-by: Adrian Hunter --- arch/arm/mach-omap2/mmc-twl4030.c |5 ++--- arch/arm/mach-omap2/mmc-twl4030.h |2 +- arch/arm/plat-omap/include/mach/mmc.h |6 +++--- drivers/mmc/host/omap_hsmmc.c |7 --- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/arch/arm/mach-omap2/mmc-twl4030.c b/arch/arm/mach-omap2/mmc-twl4030.c index f95c702..48765bf 100644 --- a/arch/arm/mach-omap2/mmc-twl4030.c +++ b/arch/arm/mach-omap2/mmc-twl4030.c @@ -464,12 +464,11 @@ void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers) } else mmc->slots[0].gpio_wp = -EINVAL; - if (c->nonremovable) - mmc->slots[0].nonremovable = 1; - if (c->power_saving) mmc->slots[0].power_saving = 1; + mmc->slots[0].caps = c->caps; + /* NOTE: MMC slots should have a Vcc regulator set up. * This may be from a TWL4030-family chip, another * controllable regulator, or a fixed supply. diff --git a/arch/arm/mach-omap2/mmc-twl4030.h b/arch/arm/mach-omap2/mmc-twl4030.h index a47e685..cb43f52 100644 --- a/arch/arm/mach-omap2/mmc-twl4030.h +++ b/arch/arm/mach-omap2/mmc-twl4030.h @@ -12,8 +12,8 @@ struct twl4030_hsmmc_info { booltransceiver;/* MMC-2 option */ boolext_clock; /* use external pin for input clock */ boolcover_only; /* No card detect - just cover switch */ - boolnonremovable; /* Nonremovable e.g. eMMC */ boolpower_saving; /* Try to sleep or power off when possible */ + unsigned long caps; /* MMC host capabilities */ int gpio_cd;/* or -EINVAL */ int gpio_wp;/* or -EINVAL */ char*name; /* or NULL for default */ diff --git a/arch/arm/plat-omap/include/mach/mmc.h b/arch/arm/plat-omap/include/mach/mmc.h index 9390297..48cf2de 100644 --- a/arch/arm/plat-omap/include/mach/mmc.h +++ b/arch/arm/plat-omap/include/mach/mmc.h @@ -83,12 +83,12 @@ struct omap_mmc_platform_data { /* use the internal clock */ unsigned internal_clock:1; - /* nonremovable e.g. eMMC */ - unsigned nonremovable:1; - /* Try to sleep or power off when possible */ unsigned power_saving:1; + /* MMC host capabilities */ + unsigned long caps; + int switch_pin; /* gpio (card detect) */ int gpio_wp;/* gpio (write protect) */ diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 5213d87..42dfc49 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -1664,10 +1664,11 @@ static int __init omap_mmc_probe(struct platform_device *pdev) else if (mmc_slot(host).wires >= 4) mmc->caps |= MMC_CAP_4_BIT_DATA; - if (mmc_slot(host).nonremovable) - mmc->caps |= MMC_CAP_NONREMOVABLE; + mmc->caps |= mmc_slot(host).caps; - mmc->caps |= MMC_CAP_SDIO | MMC_CAP_SD | MMC_CAP_MMC; + /* If no card caps specified then assume them all */ + if (!(mmc->caps & (MMC_CAP_SDIO | MMC_CAP_SD | MMC_CAP_MMC))) + mmc->caps |= MMC_CAP_SDIO | MMC_CAP_SD | MMC_CAP_MMC; omap_hsmmc_init(host); -- 1.5.6.3 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V2 22/32] omap_hsmmc: fix NULL pointer dereference
>From 0f00e61d9f963d44771f655deaa8f5f4951606a8 Mon Sep 17 00:00:00 2001 From: Jarkko Lavinen Date: Tue, 12 May 2009 19:46:14 +0300 Subject: [PATCH] omap_hsmmc: fix NULL pointer dereference Do not call 'mmc_omap_xfer_done()' if the request is already done. Signed-off-by: Jarkko Lavinen Signed-off-by: Adrian Hunter --- drivers/mmc/host/omap_hsmmc.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index d5fb066..4309031 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -670,7 +670,7 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id) if (end_cmd || ((status & CC) && host->cmd)) mmc_omap_cmd_done(host, host->cmd); - if (end_trans || (status & TC)) + if ((end_trans || (status & TC)) && host->mrq) mmc_omap_xfer_done(host, data); return IRQ_HANDLED; -- 1.5.6.3 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V2 15/32] omap_hsmmc: ensure workqueues are empty before suspend
>From 00dc421d613a159f9b3b9991e62e1c4f3866377f Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 24 Apr 2009 13:13:20 +0300 Subject: [PATCH] omap_hsmmc: ensure workqueues are empty before suspend Signed-off-by: Adrian Hunter --- drivers/mmc/host/omap_hsmmc.c | 50 +++- 1 files changed, 34 insertions(+), 16 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 2b242c2..a9f7b74 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -149,7 +149,6 @@ struct mmc_omap_host { u32 bytesleft; int suspended; int irq; - int carddetect; int use_dma, dma_ch; int dma_line_tx, dma_line_rx; int slot_id; @@ -754,14 +753,19 @@ static void mmc_omap_detect(struct work_struct *work) struct mmc_omap_host *host = container_of(work, struct mmc_omap_host, mmc_carddetect_work); struct omap_mmc_slot_data *slot = &mmc_slot(host); + int carddetect; + + if (host->suspended) + return; + + sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch"); if (mmc_slot(host).card_detect) - host->carddetect = slot->card_detect(slot->card_detect_irq); + carddetect = slot->card_detect(slot->card_detect_irq); else - host->carddetect = -ENOSYS; + carddetect = -ENOSYS; - sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch"); - if (host->carddetect) { + if (carddetect) { mmc_detect_change(host->mmc, (HZ * 200) / 1000); } else { mmc_host_enable(host->mmc); @@ -778,6 +782,8 @@ static irqreturn_t omap_mmc_cd_handler(int irq, void *dev_id) { struct mmc_omap_host *host = (struct mmc_omap_host *)dev_id; + if (host->suspended) + return IRQ_HANDLED; schedule_work(&host->mmc_carddetect_work); return IRQ_HANDLED; @@ -1519,30 +1525,42 @@ static int omap_mmc_suspend(struct platform_device *pdev, pm_message_t state) return 0; if (host) { + host->suspended = 1; + if (host->pdata->suspend) { + ret = host->pdata->suspend(&pdev->dev, + host->slot_id); + if (ret) { + dev_dbg(mmc_dev(host->mmc), + "Unable to handle MMC board" + " level suspend\n"); + host->suspended = 0; + return ret; + } + } + cancel_work_sync(&host->mmc_carddetect_work); mmc_host_enable(host->mmc); ret = mmc_suspend_host(host->mmc, state); if (ret == 0) { - host->suspended = 1; - OMAP_HSMMC_WRITE(host->base, ISE, 0); OMAP_HSMMC_WRITE(host->base, IE, 0); - if (host->pdata->suspend) { - ret = host->pdata->suspend(&pdev->dev, - host->slot_id); - if (ret) - dev_dbg(mmc_dev(host->mmc), - "Unable to handle MMC board" - " level suspend\n"); - } OMAP_HSMMC_WRITE(host->base, HCTL, OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP); mmc_host_disable(host->mmc); clk_disable(host->iclk); clk_disable(host->dbclk); - } else + } else { + host->suspended = 0; + if (host->pdata->resume) { + ret = host->pdata->resume(&pdev->dev, + host->slot_id); + if (ret) + dev_dbg(mmc_dev(host->mmc), + "Unmask interrupt failed\n"); + } mmc_host_disable(host->mmc); + } } return ret; -- 1.5.6.3 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V2 14/32] omap_hsmmc: set open drain bit correctly
>From 60dc8abdafb94824a5984f769a05c9b82f784e6b Mon Sep 17 00:00:00 2001 From: Denis Karpov Date: Thu, 23 Apr 2009 16:44:58 +0300 Subject: [PATCH] omap_hsmmc: set open drain bit correctly The code could set the bit to 1 but not reset it to 0. Signed-off-by: Denis Karpov Signed-off-by: Adrian Hunter --- drivers/mmc/host/omap_hsmmc.c |6 -- 1 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index ac1a3bf..2b242c2 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -,9 +,11 @@ static void omap_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) if (do_send_init_stream) send_init_stream(host); + con = OMAP_HSMMC_READ(host->base, CON); if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) - OMAP_HSMMC_WRITE(host->base, CON, - OMAP_HSMMC_READ(host->base, CON) | OD); + OMAP_HSMMC_WRITE(host->base, CON, con | OD); + else + OMAP_HSMMC_WRITE(host->base, CON, con & ~OD); mmc_host_lazy_disable(host->mmc); } -- 1.5.6.3 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V2 11/32] ARM: OMAP: mmc-twl4030: add context loss counter support
>From 53270a4f00a21cdf90bc6d93fa4cfc229096cc15 Mon Sep 17 00:00:00 2001 From: Denis Karpov Date: Tue, 7 Jul 2009 15:54:44 +0300 Subject: [PATCH] ARM: OMAP: mmc-twl4030: add context loss counter support PM dynamic OFF state results in context loss. That is, the host controller has been powered off at some point, which means the registers have been reset. The driver must detect when this happens, and restore the context. This patch adds the means to detect context loss. Note, the PM side is not yet implemented. Signed-off-by: Denis Karpov Signed-off-by: Adrian Hunter --- arch/arm/mach-omap2/mmc-twl4030.c | 15 +++ arch/arm/plat-omap/include/mach/mmc.h |3 +++ 2 files changed, 18 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-omap2/mmc-twl4030.c b/arch/arm/mach-omap2/mmc-twl4030.c index 1541fd4..5be3111 100644 --- a/arch/arm/mach-omap2/mmc-twl4030.c +++ b/arch/arm/mach-omap2/mmc-twl4030.c @@ -192,6 +192,18 @@ static int twl_mmc_resume(struct device *dev, int slot) #define twl_mmc_resume NULL #endif +#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM) + +static int twl4030_mmc_get_context_loss(struct device *dev) +{ + /* FIXME: PM DPS not implemented yet */ + return 0; +} + +#else +#define twl4030_mmc_get_context_loss NULL +#endif + static int twl_mmc1_set_power(struct device *dev, int slot, int power_on, int vdd) { @@ -384,6 +396,9 @@ void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers) } else mmc->slots[0].switch_pin = -EINVAL; + mmc->get_context_loss_count = + twl4030_mmc_get_context_loss; + /* write protect normally uses an OMAP gpio */ if (gpio_is_valid(c->gpio_wp)) { gpio_request(c->gpio_wp, "mmc_wp"); diff --git a/arch/arm/plat-omap/include/mach/mmc.h b/arch/arm/plat-omap/include/mach/mmc.h index 81d5b36..2f7cf31 100644 --- a/arch/arm/plat-omap/include/mach/mmc.h +++ b/arch/arm/plat-omap/include/mach/mmc.h @@ -59,6 +59,9 @@ struct omap_mmc_platform_data { int (*suspend)(struct device *dev, int slot); int (*resume)(struct device *dev, int slot); + /* Return context loss count due to PM states changing */ + int (*get_context_loss_count)(struct device *dev); + u64 dma_mask; struct omap_mmc_slot_data { -- 1.5.6.3 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V2 9/32] omap_hsmmc: add debugfs entry (host registers)
>From 4ea575689bc8933cb7370871fb10696c3b226b2d Mon Sep 17 00:00:00 2001 From: Denis Karpov Date: Wed, 22 Apr 2009 14:21:34 +0200 Subject: [PATCH] omap_hsmmc: add debugfs entry (host registers) Adds /kernel/debug/mmc/regs entry, contents show registers' state and some driver internal state variables. Signed-off-by: Denis Karpov Signed-off-by: Adrian Hunter --- drivers/mmc/host/omap_hsmmc.c | 57 + 1 files changed, 57 insertions(+), 0 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 056bcaf..0444de1 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -17,6 +17,8 @@ #include #include +#include +#include #include #include #include @@ -967,6 +969,59 @@ static struct mmc_host_ops mmc_omap_ops = { /* NYET -- enable_sdio_irq */ }; +#ifdef CONFIG_DEBUG_FS + +static int mmc_regs_show(struct seq_file *s, void *data) +{ + struct mmc_host *mmc = s->private; + struct mmc_omap_host *host = mmc_priv(mmc); + + seq_printf(s, "mmc%d regs:\n", mmc->index); + + seq_printf(s, "SYSCONFIG:\t0x%08x\n", + OMAP_HSMMC_READ(host->base, SYSCONFIG)); + seq_printf(s, "CON:\t\t0x%08x\n", + OMAP_HSMMC_READ(host->base, CON)); + seq_printf(s, "HCTL:\t\t0x%08x\n", + OMAP_HSMMC_READ(host->base, HCTL)); + seq_printf(s, "SYSCTL:\t\t0x%08x\n", + OMAP_HSMMC_READ(host->base, SYSCTL)); + seq_printf(s, "IE:\t\t0x%08x\n", + OMAP_HSMMC_READ(host->base, IE)); + seq_printf(s, "ISE:\t\t0x%08x\n", + OMAP_HSMMC_READ(host->base, ISE)); + seq_printf(s, "CAPA:\t\t0x%08x\n", + OMAP_HSMMC_READ(host->base, CAPA)); + return 0; +} + +static int mmc_regs_open(struct inode *inode, struct file *file) +{ + return single_open(file, mmc_regs_show, inode->i_private); +} + +static const struct file_operations mmc_regs_fops = { + .open = mmc_regs_open, + .read = seq_read, + .llseek = seq_lseek, + .release= single_release, +}; + +static void omap_mmc_debugfs(struct mmc_host *mmc) +{ + if (mmc->debugfs_root) + debugfs_create_file("regs", S_IRUSR, mmc->debugfs_root, + mmc, &mmc_regs_fops); +} + +#else + +static void omap_mmc_debugfs(struct mmc_host *mmc) +{ +} + +#endif + static int __init omap_mmc_probe(struct platform_device *pdev) { struct omap_mmc_platform_data *pdata = pdev->dev.platform_data; @@ -1152,6 +1207,8 @@ static int __init omap_mmc_probe(struct platform_device *pdev) goto err_cover_switch; } + omap_mmc_debugfs(mmc); + return 0; err_cover_switch: -- 1.5.6.3 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V2 2/32] mmc: allow host claim / release nesting
>From 93e60ec163a4ef242e88056c9c642c227f256628 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Mon, 27 Apr 2009 13:38:42 +0300 Subject: [PATCH] mmc: allow host claim / release nesting This change allows the MMC host to be claimed in situations where the host may or may not have already been claimed. Also 'mmc_try_claim_host()' is now exported. Signed-off-by: Adrian Hunter --- drivers/mmc/core/core.c | 34 +- include/linux/mmc/core.h |1 + include/linux/mmc/host.h |2 ++ 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 9bc8d27..bab5015 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -461,16 +461,18 @@ int __mmc_claim_host(struct mmc_host *host, atomic_t *abort) while (1) { set_current_state(TASK_UNINTERRUPTIBLE); stop = abort ? atomic_read(abort) : 0; - if (stop || !host->claimed) + if (stop || !host->claimed || host->claimer == current) break; spin_unlock_irqrestore(&host->lock, flags); schedule(); spin_lock_irqsave(&host->lock, flags); } set_current_state(TASK_RUNNING); - if (!stop) + if (!stop) { host->claimed = 1; - else + host->claimer = current; + host->claim_cnt += 1; + } else wake_up(&host->wq); spin_unlock_irqrestore(&host->lock, flags); remove_wait_queue(&host->wq, &wait); @@ -481,29 +483,43 @@ int __mmc_claim_host(struct mmc_host *host, atomic_t *abort) EXPORT_SYMBOL(__mmc_claim_host); -static int mmc_try_claim_host(struct mmc_host *host) +/** + * mmc_try_claim_host - try exclusively to claim a host + * @host: mmc host to claim + * + * Returns %1 if the host is claimed, %0 otherwise. + */ +int mmc_try_claim_host(struct mmc_host *host) { int claimed_host = 0; unsigned long flags; spin_lock_irqsave(&host->lock, flags); - if (!host->claimed) { + if (!host->claimed || host->claimer == current) { host->claimed = 1; + host->claimer = current; + host->claim_cnt += 1; claimed_host = 1; } spin_unlock_irqrestore(&host->lock, flags); return claimed_host; } +EXPORT_SYMBOL(mmc_try_claim_host); static void mmc_do_release_host(struct mmc_host *host) { unsigned long flags; spin_lock_irqsave(&host->lock, flags); - host->claimed = 0; - spin_unlock_irqrestore(&host->lock, flags); - - wake_up(&host->wq); + if (--host->claim_cnt) { + /* Release for nested claim */ + spin_unlock_irqrestore(&host->lock, flags); + } else { + host->claimed = 0; + host->claimer = NULL; + spin_unlock_irqrestore(&host->lock, flags); + wake_up(&host->wq); + } } void mmc_host_deeper_disable(struct work_struct *work) diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h index 7ac8b50..e4898e9 100644 --- a/include/linux/mmc/core.h +++ b/include/linux/mmc/core.h @@ -139,6 +139,7 @@ extern unsigned int mmc_align_data_size(struct mmc_card *, unsigned int); extern int __mmc_claim_host(struct mmc_host *host, atomic_t *abort); extern void mmc_release_host(struct mmc_host *host); +extern int mmc_try_claim_host(struct mmc_host *host); /** * mmc_claim_host - exclusively claim a host diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 338a9b3..631a2fe 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -182,6 +182,8 @@ struct mmc_host { struct mmc_card *card; /* device attached to this host */ wait_queue_head_t wq; + struct task_struct *claimer; /* task that has host claimed */ + int claim_cnt; /* "claim" nesting count */ struct delayed_work detect; -- 1.5.6.3 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V2 31/32] omap_hsmmc: set a large data timeout for commands with busy signal
>From d9cb1021a2d64c89bbc5763dbbcece68bcc0147c Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 26 Jun 2009 11:29:20 +0300 Subject: [PATCH] omap_hsmmc: set a large data timeout for commands with busy signal Commands like SWITCH (CMD6) send a response and then signal busy while the operation is completed. These commands are expected to always succeed (otherwise the response would have indicated an error). Set an arbitrarily large data timeout value (100ms) for these commands to ensure that premature timeouts do not occur. Signed-off-by: Adrian Hunter --- drivers/mmc/host/omap_hsmmc.c | 15 +++ 1 files changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index abe1fa1..f5f207d 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -990,7 +990,8 @@ static int omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host, } static void set_data_timeout(struct omap_hsmmc_host *host, -struct mmc_request *req) +unsigned int timeout_ns, +unsigned int timeout_clks) { unsigned int timeout, cycle_ns; uint32_t reg, clkd, dto = 0; @@ -1001,8 +1002,8 @@ static void set_data_timeout(struct omap_hsmmc_host *host, clkd = 1; cycle_ns = 10 / (clk_get_rate(host->fclk) / clkd); - timeout = req->data->timeout_ns / cycle_ns; - timeout += req->data->timeout_clks; + timeout = timeout_ns / cycle_ns; + timeout += timeout_clks; if (timeout) { while ((timeout & 0x8000) == 0) { dto += 1; @@ -1036,12 +1037,18 @@ omap_hsmmc_prepare_data(struct omap_hsmmc_host *host, struct mmc_request *req) if (req->data == NULL) { OMAP_HSMMC_WRITE(host->base, BLK, 0); + /* +* Set an arbitrary 100ms data timeout for commands with +* busy signal. +*/ + if (req->cmd->flags & MMC_RSP_BUSY) + set_data_timeout(host, 1U, 0); return 0; } OMAP_HSMMC_WRITE(host->base, BLK, (req->data->blksz) | (req->data->blocks << 16)); - set_data_timeout(host, req); + set_data_timeout(host, req->data->timeout_ns, req->data->timeout_clks); if (host->use_dma) { ret = omap_hsmmc_start_dma_transfer(host, req); -- 1.5.6.3 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V2 30/32] omap_hsmmc: ensure all clock enables and disables are paired
>From 946bac7ddcc387a15c1391e416b54c3041798883 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Sun, 31 May 2009 19:27:36 +0300 Subject: [PATCH] omap_hsmmc: ensure all clock enables and disables are paired Signed-off-by: Adrian Hunter --- drivers/mmc/host/omap_hsmmc.c | 26 ++ 1 files changed, 14 insertions(+), 12 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 32d5aef..abe1fa1 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -735,22 +735,24 @@ static int omap_hsmmc_switch_opcond(struct omap_hsmmc_host *host, int vdd) /* Disable the clocks */ clk_disable(host->fclk); clk_disable(host->iclk); - clk_disable(host->dbclk); + if (host->dbclk_enabled) + clk_disable(host->dbclk); /* Turn the power off */ ret = mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0); - if (ret != 0) - goto err; /* Turn the power ON with given VDD 1.8 or 3.0v */ - ret = mmc_slot(host).set_power(host->dev, host->slot_id, 1, vdd); + if (!ret) + ret = mmc_slot(host).set_power(host->dev, host->slot_id, 1, + vdd); + clk_enable(host->iclk); + if (host->dbclk_enabled) + clk_enable(host->dbclk); + clk_enable(host->fclk); + if (ret != 0) goto err; - clk_enable(host->fclk); - clk_enable(host->iclk); - clk_enable(host->dbclk); - OMAP_HSMMC_WRITE(host->base, HCTL, OMAP_HSMMC_READ(host->base, HCTL) & SDVSCLR); reg_val = OMAP_HSMMC_READ(host->base, HCTL); @@ -1901,7 +1903,8 @@ static int omap_hsmmc_suspend(struct platform_device *pdev, pm_message_t state) OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP); mmc_host_disable(host->mmc); clk_disable(host->iclk); - clk_disable(host->dbclk); + if (host->dbclk_enabled) + clk_disable(host->dbclk); } else { host->suspended = 0; if (host->pdata->resume) { @@ -1932,9 +1935,8 @@ static int omap_hsmmc_resume(struct platform_device *pdev) if (ret) goto clk_en_err; - if (clk_enable(host->dbclk) != 0) - dev_dbg(mmc_dev(host->mmc), - "Enabling debounce clk failed\n"); + if (host->dbclk_enabled) + clk_enable(host->dbclk); if (mmc_host_enable(host->mmc) != 0) { clk_disable(host->iclk); -- 1.5.6.3 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V2 28/32] omap_hsmmc: code refactoring
>From c3c78e273388f1b74be248ea1c3cb2964b6897a3 Mon Sep 17 00:00:00 2001 From: Denis Karpov Date: Mon, 18 May 2009 13:29:18 +0300 Subject: [PATCH] omap_hsmmc: code refactoring Functions', structures', variables' names are changed to start with omap_hsmmc_ prefix. Signed-off-by: Denis Karpov Signed-off-by: Adrian Hunter --- drivers/mmc/host/omap_hsmmc.c | 322 + 1 files changed, 162 insertions(+), 160 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 42dfc49..c2b334d 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -133,7 +133,7 @@ #define OMAP_HSMMC_WRITE(base, reg, val) \ __raw_writel((val), (base) + OMAP_HSMMC_##reg) -struct mmc_omap_host { +struct omap_hsmmc_host { struct device *dev; struct mmc_host*mmc; struct mmc_request *mrq; @@ -172,7 +172,7 @@ struct mmc_omap_host { /* * Stop clock to the card */ -static void omap_mmc_stop_clock(struct mmc_omap_host *host) +static void omap_hsmmc_stop_clock(struct omap_hsmmc_host *host) { OMAP_HSMMC_WRITE(host->base, SYSCTL, OMAP_HSMMC_READ(host->base, SYSCTL) & ~CEN); @@ -186,7 +186,7 @@ static void omap_mmc_stop_clock(struct mmc_omap_host *host) * Restore the MMC host context, if it was lost as result of a * power state change. */ -static int omap_mmc_restore_ctx(struct mmc_omap_host *host) +static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host) { struct mmc_ios *ios = &host->mmc->ios; struct omap_mmc_platform_data *pdata = host->pdata; @@ -314,7 +314,7 @@ out: /* * Save the MMC host context (store the number of power state changes so far). */ -static void omap_mmc_save_ctx(struct mmc_omap_host *host) +static void omap_hsmmc_context_save(struct omap_hsmmc_host *host) { struct omap_mmc_platform_data *pdata = host->pdata; int context_loss; @@ -329,12 +329,12 @@ static void omap_mmc_save_ctx(struct mmc_omap_host *host) #else -static int omap_mmc_restore_ctx(struct mmc_omap_host *host) +static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host) { return 0; } -static void omap_mmc_save_ctx(struct mmc_omap_host *host) +static void omap_hsmmc_context_save(struct omap_hsmmc_host *host) { } @@ -344,7 +344,7 @@ static void omap_mmc_save_ctx(struct mmc_omap_host *host) * Send init stream sequence to card * before sending IDLE command */ -static void send_init_stream(struct mmc_omap_host *host) +static void send_init_stream(struct omap_hsmmc_host *host) { int reg = 0; unsigned long timeout; @@ -368,7 +368,7 @@ static void send_init_stream(struct mmc_omap_host *host) } static inline -int mmc_omap_cover_is_closed(struct mmc_omap_host *host) +int omap_hsmmc_cover_is_closed(struct omap_hsmmc_host *host) { int r = 1; @@ -378,35 +378,35 @@ int mmc_omap_cover_is_closed(struct mmc_omap_host *host) } static ssize_t -mmc_omap_show_cover_switch(struct device *dev, struct device_attribute *attr, +omap_hsmmc_show_cover_switch(struct device *dev, struct device_attribute *attr, char *buf) { struct mmc_host *mmc = container_of(dev, struct mmc_host, class_dev); - struct mmc_omap_host *host = mmc_priv(mmc); + struct omap_hsmmc_host *host = mmc_priv(mmc); - return sprintf(buf, "%s\n", mmc_omap_cover_is_closed(host) ? "closed" : - "open"); + return sprintf(buf, "%s\n", + omap_hsmmc_cover_is_closed(host) ? "closed" : "open"); } -static DEVICE_ATTR(cover_switch, S_IRUGO, mmc_omap_show_cover_switch, NULL); +static DEVICE_ATTR(cover_switch, S_IRUGO, omap_hsmmc_show_cover_switch, NULL); static ssize_t -mmc_omap_show_slot_name(struct device *dev, struct device_attribute *attr, +omap_hsmmc_show_slot_name(struct device *dev, struct device_attribute *attr, char *buf) { struct mmc_host *mmc = container_of(dev, struct mmc_host, class_dev); - struct mmc_omap_host *host = mmc_priv(mmc); + struct omap_hsmmc_host *host = mmc_priv(mmc); return sprintf(buf, "%s\n", mmc_slot(host).name); } -static DEVICE_ATTR(slot_name, S_IRUGO, mmc_omap_show_slot_name, NULL); +static DEVICE_ATTR(slot_name, S_IRUGO, omap_hsmmc_show_slot_name, NULL); /* * Configure the response type and send the cmd. */ static void -mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd, +omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd, struct mmc_data *data) { int cmdreg = 0, resptype = 0, cmdtype = 0; @@ -467,7 +467,7 @@ mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd, } static int -mmc_omap_get_dma_dir(struct mmc_omap_host *host, struct mmc_data *data) +omap_hsmmc_get_dma_dir(struct omap_hsmmc_host *host, struct mmc_data *data) {
[PATCH V2 26/32] omap_hsmmc: prevent races with irq handler
>From 4252559187e96877a2a7ab5a5b0d0631aa51c7d2 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Sat, 16 May 2009 10:32:34 +0300 Subject: [PATCH] omap_hsmmc: prevent races with irq handler If an unexpected interrupt occurs while preparing the next request, an oops can occur. For example, a new request is setting up DMA for data transfer so host->data is not NULL. An unexpected transfer complete (TC) interrupt comes along and the interrupt handler sets host->data to NULL. Oops! Prevent that by adding a spinlock. Signed-off-by: Adrian Hunter --- drivers/mmc/host/omap_hsmmc.c | 25 + 1 files changed, 25 insertions(+), 0 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 5121277..5213d87 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -146,6 +146,8 @@ struct mmc_omap_host { struct work_struct mmc_carddetect_work; void__iomem *base; resource_size_t mapbase; + spinlock_t irq_lock; /* Prevent races with irq handler */ + unsigned long flags; unsigned intid; unsigned intdma_len; unsigned intdma_sg_idx; @@ -452,6 +454,14 @@ mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd, if (host->use_dma) cmdreg |= DMA_EN; + /* +* In an interrupt context (i.e. STOP command), the spinlock is unlocked +* by the interrupt handler, otherwise (i.e. for a new request) it is +* unlocked here. +*/ + if (!in_interrupt()) + spin_unlock_irqrestore(&host->irq_lock, host->flags); + OMAP_HSMMC_WRITE(host->base, ARG, cmd->arg); OMAP_HSMMC_WRITE(host->base, CMD, cmdreg); } @@ -614,11 +624,14 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id) struct mmc_data *data; int end_cmd = 0, end_trans = 0, status; + spin_lock(&host->irq_lock); + if (host->mrq == NULL) { OMAP_HSMMC_WRITE(host->base, STAT, OMAP_HSMMC_READ(host->base, STAT)); /* Flush posted write */ OMAP_HSMMC_READ(host->base, STAT); + spin_unlock(&host->irq_lock); return IRQ_HANDLED; } @@ -683,6 +696,8 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id) if ((end_trans || (status & TC)) && host->mrq) mmc_omap_xfer_done(host, data); + spin_unlock(&host->irq_lock); + return IRQ_HANDLED; } @@ -1011,6 +1026,13 @@ static void omap_mmc_request(struct mmc_host *mmc, struct mmc_request *req) struct mmc_omap_host *host = mmc_priv(mmc); int err; + /* +* Prevent races with the interrupt handler because of unexpected +* interrupts, but not if we are already in interrupt context i.e. +* retries. +*/ + if (!in_interrupt()) + spin_lock_irqsave(&host->irq_lock, host->flags); WARN_ON(host->mrq != NULL); host->mrq = req; err = mmc_omap_prepare_data(host, req); @@ -1019,6 +1041,8 @@ static void omap_mmc_request(struct mmc_host *mmc, struct mmc_request *req) if (req->data) req->data->error = err; host->mrq = NULL; + if (!in_interrupt()) + spin_unlock_irqrestore(&host->irq_lock, host->flags); mmc_request_done(mmc, req); return; } @@ -1573,6 +1597,7 @@ static int __init omap_mmc_probe(struct platform_device *pdev) mmc->f_max = 5200; sema_init(&host->sem, 1); + spin_lock_init(&host->irq_lock); host->iclk = clk_get(&pdev->dev, "ick"); if (IS_ERR(host->iclk)) { -- 1.5.6.3 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V2 25/32] omap_hsmmc: cater for weird CMD6 behaviour
>From 8520f6fd74c073a76121619403808f1e3da0f587 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Sat, 16 May 2009 10:05:40 +0300 Subject: [PATCH] omap_hsmmc: cater for weird CMD6 behaviour Sometimes the controller unexpectedly produces a TC (transfer complete) interrupt before the CC (command complete) interrupt for command 6 (SWITCH). This is a problem because the CC interrupt can get mixed up with the next request. Add a hack for CMD6. Signed-off-by: Adrian Hunter --- drivers/mmc/host/omap_hsmmc.c |7 +++ 1 files changed, 7 insertions(+), 0 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index c7a6d88..5121277 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -474,6 +474,13 @@ mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data) if (!data) { struct mmc_request *mrq = host->mrq; + /* TC before CC from CMD6 - don't know why, but it happens */ + if (host->cmd && host->cmd->opcode == 6 && + host->response_busy) { + host->response_busy = 0; + return; + } + host->mrq = NULL; mmc_request_done(host->mmc, mrq); return; -- 1.5.6.3 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V2 24/32] omap_hsmmc: clear interrupt status after init sequence
>From 1aa0e844f89f4349a6e940079343efbf9e8130d6 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Sat, 16 May 2009 09:35:17 +0300 Subject: [PATCH] omap_hsmmc: clear interrupt status after init sequence Clear the interrupt status after sending the initialization sequence, as specified in the TRM. Signed-off-by: Adrian Hunter --- drivers/mmc/host/omap_hsmmc.c |4 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 0373bdd..c7a6d88 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -358,6 +358,10 @@ static void send_init_stream(struct mmc_omap_host *host) OMAP_HSMMC_WRITE(host->base, CON, OMAP_HSMMC_READ(host->base, CON) & ~INIT_STREAM); + + OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR); + OMAP_HSMMC_READ(host->base, STAT); + enable_irq(host->irq); } -- 1.5.6.3 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V2 20/32] omap_hsmmc: put MMC regulator to sleep
>From a5e206faac032a8e52721904dbdda0bd4ba01ecf Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 12 May 2009 20:54:51 +0300 Subject: [PATCH] omap_hsmmc: put MMC regulator to sleep When a card is not in use, the voltage regulator can be put to sleep. This is an alternative to powering the card off, when powering off is not safe because the card might be replaced without the driver being aware of it. That situation happens if: - the card is removable i.e. not eMMC - and there is no card detect - and there is a cover switch but the cover is open Signed-off-by: Adrian Hunter --- drivers/mmc/host/omap_hsmmc.c | 59 +--- 1 files changed, 54 insertions(+), 5 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index a3418b5..7a17901 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -160,6 +160,7 @@ struct mmc_omap_host { int response_busy; int context_loss; int dpm_state; + int vdd; struct omap_mmc_platform_data *pdata; }; @@ -1031,10 +1032,12 @@ static void omap_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) case MMC_POWER_OFF: mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0); + host->vdd = 0; break; case MMC_POWER_UP: mmc_slot(host).set_power(host->dev, host->slot_id, 1, ios->vdd); + host->vdd = ios->vdd; break; case MMC_POWER_ON: do_send_init_stream = 1; @@ -1172,19 +1175,20 @@ static void omap_hsmmc_init(struct mmc_omap_host *host) /* * Dynamic power saving handling, FSM: - * ENABLED -> DISABLED -> OFF + * ENABLED -> DISABLED -> OFF / REGSLEEP * ^___| | * |__| * * ENABLED: mmc host is fully functional * DISABLED: fclk is off * OFF: fclk is off,voltage regulator is off + * REGSLEEP: fclk is off,voltage regulator is asleep * * Transition handlers return the timeout for the next state transition * or negative error. */ -enum {ENABLED = 0, DISABLED, OFF}; +enum {ENABLED = 0, DISABLED, REGSLEEP, OFF}; /* Handler for [ENABLED -> DISABLED] transition */ static int omap_mmc_enabled_to_disabled(struct mmc_omap_host *host) @@ -1221,8 +1225,12 @@ static int omap_mmc_disabled_to_off(struct mmc_omap_host *host) mmc_slot(host).get_cover_state(host->dev, host->slot_id))) { mmc_power_save_host(host->mmc); new_state = OFF; - } else - new_state = DISABLED; + } else { + if (mmc_slot(host).set_sleep) + mmc_slot(host).set_sleep(host->dev, host->slot_id, +1, 0, 0); + new_state = REGSLEEP; + } OMAP_HSMMC_WRITE(host->base, ISE, 0); OMAP_HSMMC_WRITE(host->base, IE, 0); @@ -1279,6 +1287,44 @@ static int omap_mmc_off_to_enabled(struct mmc_omap_host *host) return 0; } +/* Handler for [REGSLEEP -> ENABLED] transition */ +static int omap_mmc_regsleep_to_enabled(struct mmc_omap_host *host) +{ + unsigned long timeout; + + dev_dbg(mmc_dev(host->mmc), "REGSLEEP -> ENABLED\n"); + + clk_enable(host->fclk); + clk_enable(host->iclk); + + if (clk_enable(host->dbclk)) + dev_dbg(mmc_dev(host->mmc), + "Enabling debounce clk failed\n"); + + omap_mmc_restore_ctx(host); + + /* +* We turned off interrupts and bus power. Interrupts +* are turned on by 'mmc_omap_start_command()' so we +* just need to turn on the bus power here. +*/ + OMAP_HSMMC_WRITE(host->base, HCTL, +OMAP_HSMMC_READ(host->base, HCTL) | SDBP); + + timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS); + while ((OMAP_HSMMC_READ(host->base, HCTL) & SDBP) != SDBP && + time_before(jiffies, timeout)) + ; + + if (mmc_slot(host).set_sleep) + mmc_slot(host).set_sleep(host->dev, host->slot_id, +0, host->vdd, 0); + + host->dpm_state = ENABLED; + + return 0; +} + /* * Bring MMC host to ENABLED from any other PM state. */ @@ -1289,6 +1335,8 @@ static int omap_mmc_enable(struct mmc_host *mmc) switch (host->dpm_state) { case DISABLED: return omap_mmc_disabled_to_enabled(host); + case REGSLEEP: + return omap_mmc_regsleep_to_enabled(host); case OFF: return omap_mmc_off_to_enabled(host); default: @@
[PATCH V2 18/32] omap_hsmmc: support for deeper power saving states
>From ad38a2788cc03924eebc353159561566dc4911e5 Mon Sep 17 00:00:00 2001 From: Denis Karpov Date: Mon, 11 May 2009 14:41:30 +0300 Subject: [PATCH] omap_hsmmc: support for deeper power saving states Support for multi-level dynamic power saving states in omap_hsmmc (ENABLED->DISABLED->OFF). In the "deepest" state (OFF) we switch off the voltage regulators. Signed-off-by: Denis Karpov Signed-off-by: Adrian Hunter --- arch/arm/mach-omap2/mmc-twl4030.c |3 + arch/arm/mach-omap2/mmc-twl4030.h |1 + arch/arm/plat-omap/include/mach/mmc.h |3 + drivers/mmc/host/omap_hsmmc.c | 245 + 4 files changed, 222 insertions(+), 30 deletions(-) diff --git a/arch/arm/mach-omap2/mmc-twl4030.c b/arch/arm/mach-omap2/mmc-twl4030.c index 67c22c6..3678f0e 100644 --- a/arch/arm/mach-omap2/mmc-twl4030.c +++ b/arch/arm/mach-omap2/mmc-twl4030.c @@ -412,6 +412,9 @@ void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers) if (c->nonremovable) mmc->slots[0].nonremovable = 1; + if (c->power_saving) + mmc->slots[0].power_saving = 1; + /* NOTE: MMC slots should have a Vcc regulator set up. * This may be from a TWL4030-family chip, another * controllable regulator, or a fixed supply. diff --git a/arch/arm/mach-omap2/mmc-twl4030.h b/arch/arm/mach-omap2/mmc-twl4030.h index 75b0c64..a47e685 100644 --- a/arch/arm/mach-omap2/mmc-twl4030.h +++ b/arch/arm/mach-omap2/mmc-twl4030.h @@ -13,6 +13,7 @@ struct twl4030_hsmmc_info { boolext_clock; /* use external pin for input clock */ boolcover_only; /* No card detect - just cover switch */ boolnonremovable; /* Nonremovable e.g. eMMC */ + boolpower_saving; /* Try to sleep or power off when possible */ int gpio_cd;/* or -EINVAL */ int gpio_wp;/* or -EINVAL */ char*name; /* or NULL for default */ diff --git a/arch/arm/plat-omap/include/mach/mmc.h b/arch/arm/plat-omap/include/mach/mmc.h index bab486c..82f1e29 100644 --- a/arch/arm/plat-omap/include/mach/mmc.h +++ b/arch/arm/plat-omap/include/mach/mmc.h @@ -86,6 +86,9 @@ struct omap_mmc_platform_data { /* nonremovable e.g. eMMC */ unsigned nonremovable:1; + /* Try to sleep or power off when possible */ + unsigned power_saving:1; + int switch_pin; /* gpio (card detect) */ int gpio_wp;/* gpio (write protect) */ diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index e618bc0..a3418b5 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -111,6 +111,10 @@ #define OMAP_MMC_MASTER_CLOCK 9600 #define DRIVER_NAME"mmci-omap-hs" +/* Timeouts for entering power saving states on inactivity, msec */ +#define OMAP_MMC_DISABLED_TIMEOUT 100 +#define OMAP_MMC_OFF_TIMEOUT 1000 + /* * One controller can have multiple slots, like on some omap boards using * omap.c controller driver. Luckily this is not currently done on any known @@ -155,6 +159,7 @@ struct mmc_omap_host { int dbclk_enabled; int response_busy; int context_loss; + int dpm_state; struct omap_mmc_platform_data *pdata; }; @@ -985,29 +990,6 @@ mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req) return 0; } -static int omap_mmc_enable(struct mmc_host *mmc) -{ - struct mmc_omap_host *host = mmc_priv(mmc); - int err; - - err = clk_enable(host->fclk); - if (err) - return err; - dev_dbg(mmc_dev(host->mmc), "mmc_fclk: enabled\n"); - omap_mmc_restore_ctx(host); - return 0; -} - -static int omap_mmc_disable(struct mmc_host *mmc, int lazy) -{ - struct mmc_omap_host *host = mmc_priv(mmc); - - omap_mmc_save_ctx(host); - clk_disable(host->fclk); - dev_dbg(mmc_dev(host->mmc), "mmc_fclk: disabled\n"); - return 0; -} - /* * Request function. for read/write operation */ @@ -1061,6 +1043,8 @@ static void omap_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) host->power_mode = ios->power_mode; } + /* FIXME: set registers based only on changes to ios */ + con = OMAP_HSMMC_READ(host->base, CON); switch (mmc->ios.bus_width) { case MMC_BUS_WIDTH_8: @@ -1133,7 +1117,10 @@ static void omap_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) else OMAP_HSMMC_WRITE(host->base, CON, con & ~OD); - mmc_host_lazy_disable(host->mmc); + if (host->power_mode == MMC_POWER_OFF) + mmc_host_disable(host->mmc); + else + mmc_host_l
[PATCH V2 19/32] ARM: OMAP: mmc-twl4030: add regulator sleep / wake function
>From b5f863cd167b6e3a1fb06be4e51513964fa83cb4 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Wed, 8 Jul 2009 13:20:30 +0300 Subject: [PATCH] ARM: OMAP: mmc-twl4030: add regulator sleep / wake function Add the ability for the driver to put the card power regulators to sleep and wake them up again. Signed-off-by: Adrian Hunter --- arch/arm/mach-omap2/mmc-twl4030.c | 57 + arch/arm/plat-omap/include/mach/mmc.h |2 + 2 files changed, 59 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-omap2/mmc-twl4030.c b/arch/arm/mach-omap2/mmc-twl4030.c index 3678f0e..f95c702 100644 --- a/arch/arm/mach-omap2/mmc-twl4030.c +++ b/arch/arm/mach-omap2/mmc-twl4030.c @@ -334,6 +334,61 @@ static int twl_mmc23_set_power(struct device *dev, int slot, int power_on, int v return ret; } +static int twl_mmc1_set_sleep(struct device *dev, int slot, int sleep, int vdd, + int cardsleep) +{ + struct twl_mmc_controller *c = &hsmmc[0]; + int mode = sleep ? REGULATOR_MODE_STANDBY : REGULATOR_MODE_NORMAL; + + return regulator_set_mode(c->vcc, mode); +} + +static int twl_mmc23_set_sleep(struct device *dev, int slot, int sleep, int vdd, + int cardsleep) +{ + struct twl_mmc_controller *c = NULL; + struct omap_mmc_platform_data *mmc = dev->platform_data; + int i, err, mode; + + for (i = 1; i < ARRAY_SIZE(hsmmc); i++) { + if (mmc == hsmmc[i].mmc) { + c = &hsmmc[i]; + break; + } + } + + if (c == NULL) + return -ENODEV; + + /* +* If we don't see a Vcc regulator, assume it's a fixed +* voltage always-on regulator. +*/ + if (!c->vcc) + return 0; + + mode = sleep ? REGULATOR_MODE_STANDBY : REGULATOR_MODE_NORMAL; + + if (!c->vcc_aux) + return regulator_set_mode(c->vcc, mode); + + if (cardsleep) { + /* VCC can be turned off if card is asleep */ + struct regulator *vcc_aux = c->vcc_aux; + + c->vcc_aux = NULL; + if (sleep) + err = twl_mmc23_set_power(dev, slot, 0, 0); + else + err = twl_mmc23_set_power(dev, slot, 1, vdd); + c->vcc_aux = vcc_aux; + } else + err = regulator_set_mode(c->vcc, mode); + if (err) + return err; + return regulator_set_mode(c->vcc_aux, mode); +} + static struct omap_mmc_platform_data *hsmmc_data[OMAP34XX_NR_MMC] __initdata; void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers) @@ -427,6 +482,7 @@ void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers) case 1: /* on-chip level shifting via PBIAS0/PBIAS1 */ mmc->slots[0].set_power = twl_mmc1_set_power; + mmc->slots[0].set_sleep = twl_mmc1_set_sleep; break; case 2: if (c->ext_clock) @@ -437,6 +493,7 @@ void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers) case 3: /* off-chip level shifting, or none */ mmc->slots[0].set_power = twl_mmc23_set_power; + mmc->slots[0].set_sleep = twl_mmc23_set_sleep; break; default: pr_err("MMC%d configuration not supported!\n", c->mmc); diff --git a/arch/arm/plat-omap/include/mach/mmc.h b/arch/arm/plat-omap/include/mach/mmc.h index 82f1e29..9390297 100644 --- a/arch/arm/plat-omap/include/mach/mmc.h +++ b/arch/arm/plat-omap/include/mach/mmc.h @@ -95,6 +95,8 @@ struct omap_mmc_platform_data { int (* set_bus_mode)(struct device *dev, int slot, int bus_mode); int (* set_power)(struct device *dev, int slot, int power_on, int vdd); int (* get_ro)(struct device *dev, int slot); + int (*set_sleep)(struct device *dev, int slot, int sleep, +int vdd, int cardsleep); /* return MMC cover switch state, can be NULL if not supported. * -- 1.5.6.3 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V2 17/32] omap_hsmmc: make use of new MMC_CAP_NONREMOVABLE host capability
>From a5af29d59b76a8c09c3d02e46ab25754c1bb2ec6 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Mon, 11 May 2009 10:06:38 +0300 Subject: [PATCH] omap_hsmmc: make use of new MMC_CAP_NONREMOVABLE host capability Let the board specify that a card is nonremovable e.g. eMMC Signed-off-by: Adrian Hunter --- arch/arm/mach-omap2/mmc-twl4030.c |3 +++ arch/arm/mach-omap2/mmc-twl4030.h |1 + arch/arm/plat-omap/include/mach/mmc.h |3 +++ drivers/mmc/host/omap_hsmmc.c |3 +++ 4 files changed, 10 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-omap2/mmc-twl4030.c b/arch/arm/mach-omap2/mmc-twl4030.c index 5be3111..67c22c6 100644 --- a/arch/arm/mach-omap2/mmc-twl4030.c +++ b/arch/arm/mach-omap2/mmc-twl4030.c @@ -409,6 +409,9 @@ void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers) } else mmc->slots[0].gpio_wp = -EINVAL; + if (c->nonremovable) + mmc->slots[0].nonremovable = 1; + /* NOTE: MMC slots should have a Vcc regulator set up. * This may be from a TWL4030-family chip, another * controllable regulator, or a fixed supply. diff --git a/arch/arm/mach-omap2/mmc-twl4030.h b/arch/arm/mach-omap2/mmc-twl4030.h index 3807c45..75b0c64 100644 --- a/arch/arm/mach-omap2/mmc-twl4030.h +++ b/arch/arm/mach-omap2/mmc-twl4030.h @@ -12,6 +12,7 @@ struct twl4030_hsmmc_info { booltransceiver;/* MMC-2 option */ boolext_clock; /* use external pin for input clock */ boolcover_only; /* No card detect - just cover switch */ + boolnonremovable; /* Nonremovable e.g. eMMC */ int gpio_cd;/* or -EINVAL */ int gpio_wp;/* or -EINVAL */ char*name; /* or NULL for default */ diff --git a/arch/arm/plat-omap/include/mach/mmc.h b/arch/arm/plat-omap/include/mach/mmc.h index 2f7cf31..bab486c 100644 --- a/arch/arm/plat-omap/include/mach/mmc.h +++ b/arch/arm/plat-omap/include/mach/mmc.h @@ -83,6 +83,9 @@ struct omap_mmc_platform_data { /* use the internal clock */ unsigned internal_clock:1; + /* nonremovable e.g. eMMC */ + unsigned nonremovable:1; + int switch_pin; /* gpio (card detect) */ int gpio_wp;/* gpio (write protect) */ diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 6222940..e618bc0 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -1383,6 +1383,9 @@ static int __init omap_mmc_probe(struct platform_device *pdev) else if (pdata->slots[host->slot_id].wires >= 4) mmc->caps |= MMC_CAP_4_BIT_DATA; + if (pdata->slots[host->slot_id].nonremovable) + mmc->caps |= MMC_CAP_NONREMOVABLE; + mmc->caps |= MMC_CAP_SDIO | MMC_CAP_SD | MMC_CAP_MMC; omap_hsmmc_init(host); -- 1.5.6.3 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V2 16/32] omap_hsmmc: fix scatter-gather list sanity checking
>From e37dab1cd1f8ac4bf4e2050a744a842d3d7ffdc1 Mon Sep 17 00:00:00 2001 From: Jarkko Lavinen Date: Fri, 24 Apr 2009 14:20:43 +0300 Subject: [PATCH] omap_hsmmc: fix scatter-gather list sanity checking Do not use host->dma_len when it is uninitialzed. Finish the request with an error if the mmc_omap_prepare_data() fails. Signed-off-by: Jarkko Lavinen Signed-off-by: Adrian Hunter --- drivers/mmc/host/omap_hsmmc.c | 14 -- 1 files changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index a9f7b74..6222940 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -871,7 +871,7 @@ mmc_omap_start_dma_transfer(struct mmc_omap_host *host, struct mmc_request *req) struct mmc_data *data = req->data; /* Sanity check: all the SG entries must be aligned by block size. */ - for (i = 0; i < host->dma_len; i++) { + for (i = 0; i < data->sg_len; i++) { struct scatterlist *sgl; sgl = data->sg + i; @@ -1014,10 +1014,20 @@ static int omap_mmc_disable(struct mmc_host *mmc, int lazy) static void omap_mmc_request(struct mmc_host *mmc, struct mmc_request *req) { struct mmc_omap_host *host = mmc_priv(mmc); + int err; WARN_ON(host->mrq != NULL); host->mrq = req; - mmc_omap_prepare_data(host, req); + err = mmc_omap_prepare_data(host, req); + if (err) { + req->cmd->error = err; + if (req->data) + req->data->error = err; + host->mrq = NULL; + mmc_request_done(mmc, req); + return; + } + mmc_omap_start_command(host, req->cmd, req->data); } -- 1.5.6.3 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V2 10/32] omap_hsmmc: make use of new enable/disable interface
>From 4ce5c79ed1c42938ee1d42d7cf172e6d1265106d Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 23 Apr 2009 10:01:29 +0300 Subject: [PATCH] omap_hsmmc: make use of new enable/disable interface For the moment enable / disable just turns the fclk on and off. Signed-off-by: Adrian Hunter --- drivers/mmc/host/omap_hsmmc.c | 68 +++-- 1 files changed, 58 insertions(+), 10 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 0444de1..f9b7cfe 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -598,7 +598,9 @@ static void mmc_omap_detect(struct work_struct *work) if (host->carddetect) { mmc_detect_change(host->mmc, (HZ * 200) / 1000); } else { + mmc_host_enable(host->mmc); mmc_omap_reset_controller_fsm(host, SRD); + mmc_host_lazy_disable(host->mmc); mmc_detect_change(host->mmc, (HZ * 50) / 1000); } } @@ -811,6 +813,27 @@ mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req) return 0; } +static int omap_mmc_enable(struct mmc_host *mmc) +{ + struct mmc_omap_host *host = mmc_priv(mmc); + int err; + + err = clk_enable(host->fclk); + if (err) + return err; + dev_dbg(mmc_dev(host->mmc), "mmc_fclk: enabled\n"); + return 0; +} + +static int omap_mmc_disable(struct mmc_host *mmc, int lazy) +{ + struct mmc_omap_host *host = mmc_priv(mmc); + + clk_disable(host->fclk); + dev_dbg(mmc_dev(host->mmc), "mmc_fclk: disabled\n"); + return 0; +} + /* * Request function. for read/write operation */ @@ -834,6 +857,8 @@ static void omap_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) unsigned long timeout; u32 con; + mmc_host_enable(host->mmc); + switch (ios->power_mode) { case MMC_POWER_OFF: mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0); @@ -912,6 +937,8 @@ static void omap_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) OMAP_HSMMC_WRITE(host->base, CON, OMAP_HSMMC_READ(host->base, CON) | OD); + + mmc_host_lazy_disable(host->mmc); } static int omap_hsmmc_get_cd(struct mmc_host *mmc) @@ -962,6 +989,8 @@ static void omap_hsmmc_init(struct mmc_omap_host *host) } static struct mmc_host_ops mmc_omap_ops = { + .enable = omap_mmc_enable, + .disable = omap_mmc_disable, .request = omap_mmc_request, .set_ios = omap_mmc_set_ios, .get_cd = omap_hsmmc_get_cd, @@ -976,7 +1005,16 @@ static int mmc_regs_show(struct seq_file *s, void *data) struct mmc_host *mmc = s->private; struct mmc_omap_host *host = mmc_priv(mmc); - seq_printf(s, "mmc%d regs:\n", mmc->index); + seq_printf(s, "mmc%d:\n" + " enabled:\t%d\n" + " nesting_cnt:\t%d\n" + "\nregs:\n", + mmc->index, mmc->enabled ? 1 : 0, mmc->nesting_cnt); + + if (clk_enable(host->fclk) != 0) { + seq_printf(s, "can't read the regs\n"); + goto err; + } seq_printf(s, "SYSCONFIG:\t0x%08x\n", OMAP_HSMMC_READ(host->base, SYSCONFIG)); @@ -992,6 +1030,9 @@ static int mmc_regs_show(struct seq_file *s, void *data) OMAP_HSMMC_READ(host->base, ISE)); seq_printf(s, "CAPA:\t\t0x%08x\n", OMAP_HSMMC_READ(host->base, CAPA)); + + clk_disable(host->fclk); +err: return 0; } @@ -1092,14 +1133,16 @@ static int __init omap_mmc_probe(struct platform_device *pdev) goto err1; } - if (clk_enable(host->fclk) != 0) { + mmc->caps |= MMC_CAP_DISABLE; + mmc_set_disable_delay(mmc, 100); + if (mmc_host_enable(host->mmc) != 0) { clk_put(host->iclk); clk_put(host->fclk); goto err1; } if (clk_enable(host->iclk) != 0) { - clk_disable(host->fclk); + mmc_host_disable(host->mmc); clk_put(host->iclk); clk_put(host->fclk); goto err1; @@ -1192,6 +1235,8 @@ static int __init omap_mmc_probe(struct platform_device *pdev) OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK); OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK); + mmc_host_lazy_disable(host->mmc); + mmc_add_host(mmc); if (host->pdata->slots[host->slot_id].name != NULL) { @@ -1220,7 +1265,7 @@ err_irq_cd: err_irq_cd_init: free_irq(host->irq, host); err_irq: - clk_disable(host->fclk); + mmc_host_disable(host->mmc); clk_disable(host->iclk); clk_put(host->fclk); clk_put(host->iclk); @@ -1245,6 +1290,7 @@ stati
[PATCH V2 13/32] omap_hsmmc: context save/restore support
>From 43e9fa346d7e386328876a8535dc8619bd1f47ae Mon Sep 17 00:00:00 2001 From: Denis Karpov Date: Wed, 22 Apr 2009 16:04:25 +0200 Subject: [PATCH] omap_hsmmc: context save/restore support Keep the context over PM dynamic OFF states. Signed-off-by: Denis Karpov Signed-off-by: Adrian Hunter --- drivers/mmc/host/omap_hsmmc.c | 194 ++-- 1 files changed, 184 insertions(+), 10 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index c28d055..ac1a3bf 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -37,6 +37,7 @@ /* OMAP HSMMC Host Controller Registers */ #define OMAP_HSMMC_SYSCONFIG 0x0010 +#define OMAP_HSMMC_SYSSTATUS 0x0014 #define OMAP_HSMMC_CON 0x002C #define OMAP_HSMMC_BLK 0x0104 #define OMAP_HSMMC_ARG 0x0108 @@ -94,6 +95,8 @@ #define DUAL_VOLT_OCR_BIT 7 #define SRC(1 << 25) #define SRD(1 << 26) +#define SOFTRESET (1 << 1) +#define RESETDONE (1 << 0) /* * FIXME: Most likely all the data using these _DEVID defines should come @@ -152,6 +155,8 @@ struct mmc_omap_host { int slot_id; int dbclk_enabled; int response_busy; + int context_loss; + struct omap_mmc_platform_data *pdata; }; @@ -166,6 +171,166 @@ static void omap_mmc_stop_clock(struct mmc_omap_host *host) dev_dbg(mmc_dev(host->mmc), "MMC Clock is not stoped\n"); } +#ifdef CONFIG_PM + +/* + * Restore the MMC host context, if it was lost as result of a + * power state change. + */ +static int omap_mmc_restore_ctx(struct mmc_omap_host *host) +{ + struct mmc_ios *ios = &host->mmc->ios; + struct omap_mmc_platform_data *pdata = host->pdata; + int context_loss = 0; + u32 hctl, capa, con; + u16 dsor = 0; + unsigned long timeout; + + if (pdata->get_context_loss_count) { + context_loss = pdata->get_context_loss_count(host->dev); + if (context_loss < 0) + return 1; + } + + dev_dbg(mmc_dev(host->mmc), "context was %slost\n", + context_loss == host->context_loss ? "not " : ""); + if (host->context_loss == context_loss) + return 1; + + /* Wait for hardware reset */ + timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS); + while ((OMAP_HSMMC_READ(host->base, SYSSTATUS) & RESETDONE) != RESETDONE + && time_before(jiffies, timeout)) + ; + + /* Do software reset */ + OMAP_HSMMC_WRITE(host->base, SYSCONFIG, SOFTRESET); + timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS); + while ((OMAP_HSMMC_READ(host->base, SYSSTATUS) & RESETDONE) != RESETDONE + && time_before(jiffies, timeout)) + ; + + OMAP_HSMMC_WRITE(host->base, SYSCONFIG, + OMAP_HSMMC_READ(host->base, SYSCONFIG) | AUTOIDLE); + + if (host->id == OMAP_MMC1_DEVID) { + if (host->power_mode != MMC_POWER_OFF && + (1 << ios->vdd) <= MMC_VDD_23_24) + hctl = SDVS18; + else + hctl = SDVS30; + capa = VS30 | VS18; + } else { + hctl = SDVS18; + capa = VS18; + } + + OMAP_HSMMC_WRITE(host->base, HCTL, + OMAP_HSMMC_READ(host->base, HCTL) | hctl); + + OMAP_HSMMC_WRITE(host->base, CAPA, + OMAP_HSMMC_READ(host->base, CAPA) | capa); + + OMAP_HSMMC_WRITE(host->base, HCTL, + OMAP_HSMMC_READ(host->base, HCTL) | SDBP); + + timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS); + while ((OMAP_HSMMC_READ(host->base, HCTL) & SDBP) != SDBP + && time_before(jiffies, timeout)) + ; + + OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR); + OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK); + OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK); + + /* Do not initialize card-specific things if the power is off */ + if (host->power_mode == MMC_POWER_OFF) + goto out; + + con = OMAP_HSMMC_READ(host->base, CON); + switch (ios->bus_width) { + case MMC_BUS_WIDTH_8: + OMAP_HSMMC_WRITE(host->base, CON, con | DW8); + break; + case MMC_BUS_WIDTH_4: + OMAP_HSMMC_WRITE(host->base, CON, con & ~DW8); + OMAP_HSMMC_WRITE(host->base, HCTL, + OMAP_HSMMC_READ(host->base, HCTL) | FOUR_BIT); + break; + case MMC_BUS_WIDTH_1: + OMAP_HSMMC_WRITE(host->base, CON, con & ~DW8); + OMAP_HSMMC_WRITE(host->base, HCTL, + OMAP_HSMMC_READ(host->base, HCTL) & ~FOUR_BIT); + break;
[PATCH V2 7/32] mmc: add host capabilities for SD only and MMC only
>From f22d0fb3d25771f4e380176e99d55068b78f0c17 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Sat, 25 Jul 2009 23:52:37 + Subject: [PATCH] mmc: add host capabilities for SD only and MMC only Some hosts can accept only certain types of cards. For example, an eMMC is MMC only and a uSD slot may be SD only. However the MMC card scanning logic checks for all card types one by one. Add host capabilities to specify which card types can be used, and amend the card scanning logic to skip scanning for those types which cannot be used. Signed-off-by: Matt Fleming Cc: Adrian Hunter Cc: Ian Molton Cc: "Roberto A. Foglietta" Cc: Jarkko Lavinen Cc: Denis Karpov Cc: Pierre Ossman Cc: Andrew Morton --- drivers/mmc/core/core.c | 16 +++- drivers/mmc/host/at91_mci.c |2 +- drivers/mmc/host/atmel-mci.c |1 + drivers/mmc/host/au1xmmc.c|3 ++- drivers/mmc/host/cb710-mmc.c |3 ++- drivers/mmc/host/imxmmc.c |3 ++- drivers/mmc/host/mmc_spi.c|2 +- drivers/mmc/host/mmci.c |2 ++ drivers/mmc/host/mvsdio.c |3 ++- drivers/mmc/host/mxcmmc.c |3 ++- drivers/mmc/host/omap.c |2 +- drivers/mmc/host/omap_hsmmc.c |2 ++ drivers/mmc/host/pxamci.c |2 +- drivers/mmc/host/s3cmci.c |3 ++- drivers/mmc/host/sdhci.c |2 +- drivers/mmc/host/sdricoh_cs.c |3 ++- drivers/mmc/host/tifm_sd.c|3 ++- drivers/mmc/host/tmio_mmc.c |3 ++- drivers/mmc/host/via-sdmmc.c |3 ++- drivers/mmc/host/wbsd.c |3 ++- include/linux/mmc/host.h |3 +++ 21 files changed, 50 insertions(+), 17 deletions(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 8d03da4..5fe51ff 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1069,7 +1069,11 @@ void mmc_rescan(struct work_struct *work) mmc_power_up(host); mmc_go_idle(host); - mmc_send_if_cond(host, host->ocr_avail); + if ((host->caps & MMC_CAP_SDIO) || (host->caps & MMC_CAP_SD)) + mmc_send_if_cond(host, host->ocr_avail); + + if (!(host->caps & MMC_CAP_SDIO)) + goto not_sdio; /* * First we search for SDIO... @@ -1081,6 +1085,10 @@ void mmc_rescan(struct work_struct *work) goto out; } +not_sdio: + if (!(host->caps & MMC_CAP_SD)) + goto not_sd; + /* * ...then normal SD... */ @@ -1091,6 +1099,10 @@ void mmc_rescan(struct work_struct *work) goto out; } +not_sd: + if (!(host->caps & MMC_CAP_MMC)) + goto not_mmc; + /* * ...and finally MMC. */ @@ -1101,6 +1113,8 @@ void mmc_rescan(struct work_struct *work) goto out; } +not_mmc: + mmc_release_host(host); mmc_power_off(host); diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c index e556d42..aa541a5 100644 --- a/drivers/mmc/host/at91_mci.c +++ b/drivers/mmc/host/at91_mci.c @@ -1007,7 +1007,7 @@ static int __init at91_mci_probe(struct platform_device *pdev) mmc->f_min = 375000; mmc->f_max = 2500; mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; - mmc->caps = MMC_CAP_SDIO_IRQ; + mmc->caps = MMC_CAP_SDIO_IRQ | MMC_CAP_SDIO | MMC_CAP_SD | MMC_CAP_MMC; mmc->max_blk_size = 4095; mmc->max_blk_count = mmc->max_req_size; diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 7b603e4..907841a 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -1467,6 +1467,7 @@ static int __init atmci_init_slot(struct atmel_mci *host, mmc->f_min = DIV_ROUND_UP(host->bus_hz, 512); mmc->f_max = host->bus_hz / 2; mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; + mmc->caps = MMC_CAP_SDIO | MMC_CAP_SD | MMC_CAP_MMC; if (slot_data->bus_width >= 4) mmc->caps |= MMC_CAP_4_BIT_DATA; diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c index d3f5561..4aae609 100644 --- a/drivers/mmc/host/au1xmmc.c +++ b/drivers/mmc/host/au1xmmc.c @@ -1003,7 +1003,8 @@ static int __devinit au1xmmc_probe(struct platform_device *pdev) mmc->max_blk_count = 512; mmc->ocr_avail = AU1XMMC_OCR; - mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ; + mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ | + MMC_CAP_SDIO | MMC_CAP_SD | MMC_CAP_MMC; host->status = HOST_S_IDLE; diff --git a/drivers/mmc/host/cb710-mmc.c b/drivers/mmc/host/cb710-mmc.c index 11efefb..622b420 100644 --- a/drivers/mmc/host/cb710-mmc.c +++ b/drivers/mmc/host/cb710-mmc.c @@ -721,7 +721,8 @@ static int __devinit cb710_mmc_init(struct platform_device *pdev) mmc->f_max = val; mmc->f_min = val >> cb710_clock_divider_log2[CB710_MAX_DIVIDER_IDX]; mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34; - mmc->caps = M
[PATCH V2 6/32] mmc: power off once at removal
>From cf9505241b8ac5da1a3ebd0b77c1e0f5a149e461 Mon Sep 17 00:00:00 2001 From: Denis Karpov Date: Thu, 14 May 2009 09:11:38 +0200 Subject: [PATCH] mmc: power off once at removal Fix MMC host stop sequence: power off once. Signed-off-by: Denis Karpov Signed-off-by: Adrian Hunter --- drivers/mmc/core/core.c |2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 0611bf7..8d03da4 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1137,6 +1137,8 @@ void mmc_stop_host(struct mmc_host *host) mmc_claim_host(host); mmc_detach_bus(host); mmc_release_host(host); + mmc_bus_put(host); + return; } mmc_bus_put(host); -- 1.5.6.3 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V2 5/32] mmc: add mmc card sleep and awake support
>From 44a818d58544b3f796e2e4a7e2331d4f1d14a3f1 Mon Sep 17 00:00:00 2001 From: Jarkko Lavinen Date: Tue, 12 May 2009 19:46:14 +0300 Subject: [PATCH] mmc: add mmc card sleep and awake support Add support for the new MMC command SLEEP_AWAKE. Signed-off-by: Jarkko Lavinen Signed-off-by: Adrian Hunter --- drivers/mmc/core/core.c| 40 drivers/mmc/core/core.h|2 + drivers/mmc/core/mmc.c | 54 +++ drivers/mmc/core/mmc_ops.c | 36 + drivers/mmc/core/mmc_ops.h |1 + include/linux/mmc/card.h |2 + include/linux/mmc/host.h |5 include/linux/mmc/mmc.h|2 + 8 files changed, 137 insertions(+), 5 deletions(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 39f7bd1..0611bf7 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1179,6 +1179,46 @@ void mmc_power_restore_host(struct mmc_host *host) } EXPORT_SYMBOL(mmc_power_restore_host); +int mmc_card_awake(struct mmc_host *host) +{ + int err = -ENOSYS; + + mmc_bus_get(host); + + if (host->bus_ops && !host->bus_dead && host->bus_ops->awake) + err = host->bus_ops->awake(host); + + mmc_bus_put(host); + + return err; +} +EXPORT_SYMBOL(mmc_card_awake); + +int mmc_card_sleep(struct mmc_host *host) +{ + int err = -ENOSYS; + + mmc_bus_get(host); + + if (host->bus_ops && !host->bus_dead && host->bus_ops->awake) + err = host->bus_ops->sleep(host); + + mmc_bus_put(host); + + return err; +} +EXPORT_SYMBOL(mmc_card_sleep); + +int mmc_card_can_sleep(struct mmc_host *host) +{ + struct mmc_card *card = host->card; + + if (card && mmc_card_mmc(card) && card->ext_csd.rev >= 3) + return 1; + return 0; +} +EXPORT_SYMBOL(mmc_card_can_sleep); + #ifdef CONFIG_PM /** diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index f7eb4c4..c386348 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h @@ -16,6 +16,8 @@ #define MMC_CMD_RETRIES3 struct mmc_bus_ops { + int (*awake)(struct mmc_host *); + int (*sleep)(struct mmc_host *); void (*remove)(struct mmc_host *); void (*detect)(struct mmc_host *); void (*suspend)(struct mmc_host *); diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 01f7226..8e2e3d2 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -160,7 +160,6 @@ static int mmc_read_ext_csd(struct mmc_card *card) { int err; u8 *ext_csd; - unsigned int ext_csd_struct; BUG_ON(!card); @@ -207,16 +206,16 @@ static int mmc_read_ext_csd(struct mmc_card *card) goto out; } - ext_csd_struct = ext_csd[EXT_CSD_REV]; - if (ext_csd_struct > 3) { + card->ext_csd.rev = ext_csd[EXT_CSD_REV]; + if (card->ext_csd.rev > 3) { printk(KERN_ERR "%s: unrecognised EXT_CSD structure " "version %d\n", mmc_hostname(card->host), - ext_csd_struct); + card->ext_csd.rev); err = -EINVAL; goto out; } - if (ext_csd_struct >= 2) { + if (card->ext_csd.rev >= 2) { card->ext_csd.sectors = ext_csd[EXT_CSD_SEC_CNT + 0] << 0 | ext_csd[EXT_CSD_SEC_CNT + 1] << 8 | @@ -241,6 +240,15 @@ static int mmc_read_ext_csd(struct mmc_card *card) goto out; } + if (card->ext_csd.rev >= 3) { + u8 sa_shift = ext_csd[EXT_CSD_S_A_TIMEOUT]; + + /* Sleep / awake timeout in 100ns units */ + if (sa_shift > 0 && sa_shift <= 0x17) + card->ext_csd.sa_timeout = + 1 << ext_csd[EXT_CSD_S_A_TIMEOUT]; + } + out: kfree(ext_csd); @@ -557,9 +565,41 @@ static void mmc_power_restore(struct mmc_host *host) mmc_release_host(host); } +static int mmc_sleep(struct mmc_host *host) +{ + struct mmc_card *card = host->card; + int err = -ENOSYS; + + if (card && card->ext_csd.rev >= 3) { + err = mmc_card_sleepawake(host, 1); + if (err < 0) + pr_debug("%s: Error %d while putting card into sleep", +mmc_hostname(host), err); + } + + return err; +} + +static int mmc_awake(struct mmc_host *host) +{ + struct mmc_card *card = host->card; + int err = -ENOSYS; + + if (card && card->ext_csd.rev >= 3) { + err = mmc_card_sleepawake(host, 0); + if (err < 0) + pr_debug("%s: Error %d while awaking sleeping card", +mmc_hostname(host), err); + } + + return err; +} + #ifdef CONFIG_MMC_UNSAFE_RESUME static const struct
[PATCH V2 4/32] mmc: add ability to save power by powering off cards
>From e6355578d082d94707c8fda1e1342c478019b5c8 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Mon, 11 May 2009 12:20:57 +0300 Subject: [PATCH] mmc: add ability to save power by powering off cards Power can be saved by powering off cards that are not in use. This is similar to suspend / resume except it is under the control of the driver, and does not require any power management support. It can only be used when the driver can monitor whether the card is removed, otherwise it is unsafe. This is possible because, unlike suspend, the driver still receives card detect and / or cover switch interrupts. Signed-off-by: Adrian Hunter --- drivers/mmc/core/core.c | 34 ++ drivers/mmc/core/core.h |2 ++ drivers/mmc/core/mmc.c | 11 +++ drivers/mmc/core/sd.c| 11 +++ include/linux/mmc/host.h |3 +++ 5 files changed, 61 insertions(+), 0 deletions(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index bab5015..39f7bd1 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1145,6 +1145,40 @@ void mmc_stop_host(struct mmc_host *host) mmc_power_off(host); } +void mmc_power_save_host(struct mmc_host *host) +{ + mmc_bus_get(host); + + if (!host->bus_ops || host->bus_dead || !host->bus_ops->power_restore) { + mmc_bus_put(host); + return; + } + + if (host->bus_ops->power_save) + host->bus_ops->power_save(host); + + mmc_bus_put(host); + + mmc_power_off(host); +} +EXPORT_SYMBOL(mmc_power_save_host); + +void mmc_power_restore_host(struct mmc_host *host) +{ + mmc_bus_get(host); + + if (!host->bus_ops || host->bus_dead || !host->bus_ops->power_restore) { + mmc_bus_put(host); + return; + } + + mmc_power_up(host); + host->bus_ops->power_restore(host); + + mmc_bus_put(host); +} +EXPORT_SYMBOL(mmc_power_restore_host); + #ifdef CONFIG_PM /** diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index c819eff..f7eb4c4 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h @@ -20,6 +20,8 @@ struct mmc_bus_ops { void (*detect)(struct mmc_host *); void (*suspend)(struct mmc_host *); void (*resume)(struct mmc_host *); + void (*power_save)(struct mmc_host *); + void (*power_restore)(struct mmc_host *); }; void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops); diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 3e35075..01f7226 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -549,6 +549,14 @@ static void mmc_resume(struct mmc_host *host) } +static void mmc_power_restore(struct mmc_host *host) +{ + host->card->state &= ~MMC_STATE_HIGHSPEED; + mmc_claim_host(host); + mmc_init_card(host, host->ocr, host->card); + mmc_release_host(host); +} + #ifdef CONFIG_MMC_UNSAFE_RESUME static const struct mmc_bus_ops mmc_ops = { @@ -556,6 +564,7 @@ static const struct mmc_bus_ops mmc_ops = { .detect = mmc_detect, .suspend = mmc_suspend, .resume = mmc_resume, + .power_restore = mmc_power_restore, }; static void mmc_attach_bus_ops(struct mmc_host *host) @@ -570,6 +579,7 @@ static const struct mmc_bus_ops mmc_ops = { .detect = mmc_detect, .suspend = NULL, .resume = NULL, + .power_restore = mmc_power_restore, }; static const struct mmc_bus_ops mmc_ops_unsafe = { @@ -577,6 +587,7 @@ static const struct mmc_bus_ops mmc_ops_unsafe = { .detect = mmc_detect, .suspend = mmc_suspend, .resume = mmc_resume, + .power_restore = mmc_power_restore, }; static void mmc_attach_bus_ops(struct mmc_host *host) diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 80cccd2..debe26e 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -603,6 +603,14 @@ static void mmc_sd_resume(struct mmc_host *host) } +static void mmc_sd_power_restore(struct mmc_host *host) +{ + host->card->state &= ~MMC_STATE_HIGHSPEED; + mmc_claim_host(host); + mmc_sd_init_card(host, host->ocr, host->card); + mmc_release_host(host); +} + #ifdef CONFIG_MMC_UNSAFE_RESUME static const struct mmc_bus_ops mmc_sd_ops = { @@ -610,6 +618,7 @@ static const struct mmc_bus_ops mmc_sd_ops = { .detect = mmc_sd_detect, .suspend = mmc_sd_suspend, .resume = mmc_sd_resume, + .power_restore = mmc_sd_power_restore, }; static void mmc_sd_attach_bus_ops(struct mmc_host *host) @@ -624,6 +633,7 @@ static const struct mmc_bus_ops mmc_sd_ops = { .detect = mmc_sd_detect, .suspend = NULL, .resume = NULL, + .power_restore = mmc_sd_power_restore, }; static const struct mmc_bus_ops mmc_sd_ops_unsafe = { @@ -631,6 +641,7 @@ static const struct mmc_bus_ops mmc_sd_ops_unsafe = { .detect = mmc_sd_detect
[PATCH V2 3/32] mmc: add MMC_CAP_NONREMOVABLE host capability
>From 447937e379db91975b4e834f19dfb1805d813fc4 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Mon, 11 May 2009 10:03:41 +0300 Subject: [PATCH] mmc: add MMC_CAP_NONREMOVABLE host capability eMMC's are not removable, so unsafe resume is OK always. To permit this a new host capability MMC_CAP_NONREMOVABLE has been added and suspend / resume updated accordingly. Signed-off-by: Adrian Hunter --- drivers/mmc/core/mmc.c | 41 ++--- drivers/mmc/core/sd.c| 41 ++--- include/linux/mmc/host.h |1 + 3 files changed, 69 insertions(+), 14 deletions(-) diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 06084db..3e35075 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -507,8 +507,6 @@ static void mmc_detect(struct mmc_host *host) } } -#ifdef CONFIG_MMC_UNSAFE_RESUME - /* * Suspend callback from host. */ @@ -551,20 +549,49 @@ static void mmc_resume(struct mmc_host *host) } -#else +#ifdef CONFIG_MMC_UNSAFE_RESUME -#define mmc_suspend NULL -#define mmc_resume NULL +static const struct mmc_bus_ops mmc_ops = { + .remove = mmc_remove, + .detect = mmc_detect, + .suspend = mmc_suspend, + .resume = mmc_resume, +}; -#endif +static void mmc_attach_bus_ops(struct mmc_host *host) +{ + mmc_attach_bus(host, &mmc_ops); +} + +#else static const struct mmc_bus_ops mmc_ops = { .remove = mmc_remove, .detect = mmc_detect, + .suspend = NULL, + .resume = NULL, +}; + +static const struct mmc_bus_ops mmc_ops_unsafe = { + .remove = mmc_remove, + .detect = mmc_detect, .suspend = mmc_suspend, .resume = mmc_resume, }; +static void mmc_attach_bus_ops(struct mmc_host *host) +{ + const struct mmc_bus_ops *bus_ops; + + if (host->caps & MMC_CAP_NONREMOVABLE) + bus_ops = &mmc_ops_unsafe; + else + bus_ops = &mmc_ops; + mmc_attach_bus(host, bus_ops); +} + +#endif + /* * Starting point for MMC card init. */ @@ -575,7 +602,7 @@ int mmc_attach_mmc(struct mmc_host *host, u32 ocr) BUG_ON(!host); WARN_ON(!host->claimed); - mmc_attach_bus(host, &mmc_ops); + mmc_attach_bus_ops(host); /* * We need to get OCR a different way for SPI. diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index cd81c39..80cccd2 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -561,8 +561,6 @@ static void mmc_sd_detect(struct mmc_host *host) } } -#ifdef CONFIG_MMC_UNSAFE_RESUME - /* * Suspend callback from host. */ @@ -605,20 +603,49 @@ static void mmc_sd_resume(struct mmc_host *host) } -#else +#ifdef CONFIG_MMC_UNSAFE_RESUME -#define mmc_sd_suspend NULL -#define mmc_sd_resume NULL +static const struct mmc_bus_ops mmc_sd_ops = { + .remove = mmc_sd_remove, + .detect = mmc_sd_detect, + .suspend = mmc_sd_suspend, + .resume = mmc_sd_resume, +}; -#endif +static void mmc_sd_attach_bus_ops(struct mmc_host *host) +{ + mmc_attach_bus(host, &mmc_sd_ops); +} + +#else static const struct mmc_bus_ops mmc_sd_ops = { .remove = mmc_sd_remove, .detect = mmc_sd_detect, + .suspend = NULL, + .resume = NULL, +}; + +static const struct mmc_bus_ops mmc_sd_ops_unsafe = { + .remove = mmc_sd_remove, + .detect = mmc_sd_detect, .suspend = mmc_sd_suspend, .resume = mmc_sd_resume, }; +static void mmc_sd_attach_bus_ops(struct mmc_host *host) +{ + const struct mmc_bus_ops *bus_ops; + + if (host->caps & MMC_CAP_NONREMOVABLE) + bus_ops = &mmc_sd_ops_unsafe; + else + bus_ops = &mmc_sd_ops; + mmc_attach_bus(host, bus_ops); +} + +#endif + /* * Starting point for SD card init. */ @@ -629,7 +656,7 @@ int mmc_attach_sd(struct mmc_host *host, u32 ocr) BUG_ON(!host); WARN_ON(!host->claimed); - mmc_attach_bus(host, &mmc_sd_ops); + mmc_sd_attach_bus_ops(host); /* * We need to get OCR a different way for SPI. diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 631a2fe..bb867d2 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -148,6 +148,7 @@ struct mmc_host { #define MMC_CAP_NEEDS_POLL (1 << 5)/* Needs polling for card-detection */ #define MMC_CAP_8_BIT_DATA (1 << 6)/* Can the host do 8 bit transfers */ #define MMC_CAP_DISABLE(1 << 7)/* Can the host be disabled */ +#define MMC_CAP_NONREMOVABLE (1 << 8)/* Nonremovable e.g. eMMC */ /* host specific block data */ unsigned intmax_seg_size; /* see blk_queue_max_segment_size */ -- 1.5.6.3 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/m
[PATCH V2 0/32] mmc and omap_hsmmc patches
Hi Here is version 2 of our 32 patches for mmc and omap_hsmmc. They include Matt Fleming's change for card caps, and 2 other fixes: - use a spin lock rather than enable / diable irq - make disable delay specified in milliseconds not jiffies because the value is an int, and jiffies are unsigned long (also millisecs are better anyway) They split into 2 groups: the first 8 affect mmc core only and the remaining ones affect omap_hsmmc only. Adrian Hunter (19): mmc: add 'enable' and 'disable' methods to mmc host mmc: allow host claim / release nesting mmc: add MMC_CAP_NONREMOVABLE host capability mmc: add ability to save power by powering off cards mmc: check status after MMC SWITCH command omap_hsmmc: make use of new enable/disable interface omap_hsmmc: keep track of power mode omap_hsmmc: ensure workqueues are empty before suspend omap_hsmmc: make use of new MMC_CAP_NONREMOVABLE host capability ARM: OMAP: mmc-twl4030: add regulator sleep / wake function omap_hsmmc: put MMC regulator to sleep omap_hsmmc: clear interrupt status after init sequence omap_hsmmc: cater for weird CMD6 behaviour omap_hsmmc: prevent races with irq handler omap_hsmmc: pass host capabilities for SD only and MMC only omap_hsmmc: protect the card when the cover is open omap_hsmmc: ensure all clock enables and disables are paired omap_hsmmc: set a large data timeout for commands with busy signal ARM: OMAP: RX51: set MMC capabilities and power-saving flag Denis Karpov (8): mmc: power off once at removal omap_hsmmc: add debugfs entry (host registers) ARM: OMAP: mmc-twl4030: add context loss counter support omap_hsmmc: context save/restore support omap_hsmmc: set open drain bit correctly omap_hsmmc: support for deeper power saving states omap_hsmmc: cleanup macro usage omap_hsmmc: code refactoring Jarkko Lavinen (4): mmc: add mmc card sleep and awake support omap_hsmmc: fix scatter-gather list sanity checking omap_hsmmc: add mmc card sleep and awake support omap_hsmmc: fix NULL pointer dereference Matt Fleming (1): mmc: add host capabilities for SD only and MMC only arch/arm/mach-omap2/board-rx51-peripherals.c |5 + arch/arm/mach-omap2/mmc-twl4030.c| 77 ++ arch/arm/mach-omap2/mmc-twl4030.h|2 + arch/arm/plat-omap/include/mach/mmc.h| 11 + drivers/mmc/core/core.c | 291 +++- drivers/mmc/core/core.h |4 + drivers/mmc/core/host.c |1 + drivers/mmc/core/host.h |2 + drivers/mmc/core/mmc.c | 130 +++- drivers/mmc/core/mmc_ops.c | 59 ++ drivers/mmc/core/mmc_ops.h |1 + drivers/mmc/core/sd.c| 52 ++- drivers/mmc/host/at91_mci.c |2 +- drivers/mmc/host/atmel-mci.c |1 + drivers/mmc/host/au1xmmc.c |3 +- drivers/mmc/host/cb710-mmc.c |3 +- drivers/mmc/host/imxmmc.c|3 +- drivers/mmc/host/mmc_spi.c |2 +- drivers/mmc/host/mmci.c |2 + drivers/mmc/host/mvsdio.c|3 +- drivers/mmc/host/mxcmmc.c|3 +- drivers/mmc/host/omap.c |2 +- drivers/mmc/host/omap_hsmmc.c| 1038 +- drivers/mmc/host/pxamci.c|2 +- drivers/mmc/host/s3cmci.c|3 +- drivers/mmc/host/sdhci.c |2 +- drivers/mmc/host/sdricoh_cs.c|3 +- drivers/mmc/host/tifm_sd.c |3 +- drivers/mmc/host/tmio_mmc.c |3 +- drivers/mmc/host/via-sdmmc.c |3 +- drivers/mmc/host/wbsd.c |3 +- include/linux/mmc/card.h |2 + include/linux/mmc/core.h |1 + include/linux/mmc/host.h | 61 ++ include/linux/mmc/mmc.h |3 + 35 files changed, 1554 insertions(+), 232 deletions(-) Regards Adrian -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: Camera Interface VS/HS Issue
2009/7/27 matthias schwarz : > -- Forwarded message -- > From: matthias schwarz > Date: 2009/7/27 > Subject: Re: Camera Interface VS/HS Issue > To: "Aguirre Rodriguez, Sergio Alberto" > > > 2009/7/27 Aguirre Rodriguez, Sergio Alberto : >> >> >>> -Original Message- >>> From: matthias schwarz [mailto:matthias.s...@googlemail.com] >>> Sent: Monday, July 27, 2009 12:37 PM >>> To: Aguirre Rodriguez, Sergio Alberto >>> Cc: linux-omap@vger.kernel.org >>> Subject: Re: Camera Interface VS/HS Issue >>> >>> 2009/7/27 Aguirre Rodriguez, Sergio Alberto : >>> > >>> > >>> >> -Original Message- >>> >> From: matthias schwarz [mailto:matthias.s...@googlemail.com] >>> >> Sent: Monday, July 27, 2009 11:12 AM >>> >> To: Aguirre Rodriguez, Sergio Alberto >>> >> Cc: linux-omap@vger.kernel.org >>> >> Subject: Re: Camera Interface VS/HS Issue >>> >> >>> >> 2009/7/27 Aguirre Rodriguez, Sergio Alberto : >>> >> > >>> >> > >>> >> >> -Original Message- >>> >> >> From: matthias schwarz [mailto:matthias.s...@googlemail.com] >>> >> >> Sent: Monday, July 27, 2009 10:59 AM >>> >> >> To: Aguirre Rodriguez, Sergio Alberto >>> >> >> Cc: linux-omap@vger.kernel.org >>> >> >> Subject: Re: Camera Interface VS/HS Issue >>> >> >> >>> >> >> 2009/7/27 Aguirre Rodriguez, Sergio Alberto : >>> >> >> > Matthias, >>> >> >> > >>> >> >> > Please avoid top-posting, because its prohibited by the mailing >>> list >>> >> >> rules. I'm readjusting it for you below >>> >> >> >>> >> >> Oh, i am sorry about that, it is not going to happen again, promise. >>> >> >> And thank you for readjusting. >>> >> > >>> >> > Anytime :) >>> >> >> >>> >> >> > >>> >> >> > From: matthias schwarz [mailto:matthias.s...@googlemail.com] >>> >> >> >> 2009/7/27 matthias schwarz : >>> >> >> >> > 2009/7/27 Aguirre Rodriguez, Sergio Alberto : >>> >> >> >> >> (rearranging mail to avoid top posting..) >>> >> >> >> >> >>> >> >> >> >> From: matthias schwarz [mailto:matthias.s...@googlemail.com] >>> >> >> >> >>> 2009/7/27 Aguirre Rodriguez, Sergio Alberto >>> : >>> >> >> >> >>> > >>> >> >> >> >>> > >>> >> >> >> >>> >> -Original Message- >>> >> >> >> >>> >> From: linux-omap-ow...@vger.kernel.org [mailto:linux-omap- >>> >> >> >> >>> >> ow...@vger.kernel.org] On Behalf Of matthias schwarz >>> >> >> >> >>> >> Sent: Monday, July 27, 2009 7:47 AM >>> >> >> >> >>> >> To: linux-omap@vger.kernel.org >>> >> >> >> >>> >> Subject: Camera Interface VS/HS Issue >>> >> >> >> >>> >> >>> >> >> >> >>> >> Hi there, >>> >> >> >> >>> >> >>> >> >> >> >>> >> i just recently ran into a problem when trying to let the >>> ISP >>> >> >> >> >>> >> (OMAP3530) generate HS/VS signals in SYNC mode. >>> >> >> >> >>> >> I am building a module to do so. >>> >> >> >> >>> >> >>> >> >> >> >>> >> It basically enables the three clocks (cam_ick, cam_mclk >>> and >>> >> >> >> >>> >> csi2_96m_fck), >>> >> >> >> >>> >> then sets >>> >> >> >> >>> >> >>> >> >> >> >>> >> ISPCCDC_PIX_LINES_PPLN >>> >> >> >> >>> >> ISPCCDC_PIX_LINES_HLPRF >>> >> >> >> >>> >> ISPCCDC_HD_VD_WID_VDW >>> >> >> >> >>> >> ISPCCDC_HD_VD_WID_HDW >>> >> >> >> >>> >> ISPCCDC_SYN_MODE_VDHDEN >>> >> >> >> >>> >> ISPCCDC_SYN_MODE_VDHDOUT >>> >> >> >> >>> >> ISPCCDC_CFG_VDLC >>> >> >> >> >>> >> ISPTCTRL_CTRL_DIVA >>> >> >> >> >>> >> ISPTCTRL_CTRL_DIVB >>> >> >> >> >>> >> ISPCCDC_PCR >>> >> >> >> >>> >> >>> >> >> >> >>> >> via some calls to ioremap and ioread32/iowrite32. >>> >> >> >> >>> >> My question now is the following: >>> >> >> >> >>> >> when i hook an oscilloscope to the corresponding pins >>> >> (CAM_VS, >>> >> >> >> CAM_HS, >>> >> >> >> >>> >> CAM_XCLKA) i can see that only the CAM_XCLKA is working >>> >> >> correctly, >>> >> >> >> >>> >> also at the configured frequency. >>> >> >> >> >>> >> Both, CAM_VS and CAM_HS remain at low voltage all the >>> time, >>> >> even >>> >> >> >> when >>> >> >> >> >>> >> i switch their polarities (ISPCCDC_SYN_MODE_VDPOL, >>> >> >> >> >>> >> ISPCCDC_SYN_MODE_HDPOL) that behavior does not change and >>> >> >> signals >>> >> >> >> >>> >> always remain at low voltage. >>> >> >> >> >>> >> >>> >> >> >> >>> >> Could someone help me out, or give me a hint what i might >>> be >>> >> >> >> missing >>> >> >> >> >>> >> to generate those output signals correctly? >>> >> >> >> >>> > >>> >> >> >> >>> > Matthias, >>> >> >> >> >>> > >>> >> >> >> >>> > Can you please provide a register dump of the above values? >>> >> >> >> >>> > >>> >> >> >> >>> > Looks like you're touching the adequate registers though... >>> >> But I >>> >> >> >> can >>> >> >> >> >>> help you more looking at the values. >>> >> >> >> >>> > >>> >> >> >> >>> Sure i can, >>> >> >> >> >>> register values are the following: >>> >> >> >> >>> >>> >> >> >> >>> ccdc_pix_lines: 0x050005a0 >>> >> >> >> >>> >>> >> >> >> >>> ccdc_hd_vd_wid: 0x00320064 >>> >> >> >> >>> >>> >> >> >> >>> ccdc_syn_mode: 0x00050c0c >>> >> >> >> >> >>> >> >> >> >> This is wrong, because: >>> >> >> >> >> >>> >> >> >> >> Bit0 sets directions of cam_hs and cam_vs signals