diff -r 29b14275133a -r e5fd00cbb70a omap3530/omap3530_drivers/spi/omap3530_spi.inl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/omap3530/omap3530_drivers/spi/omap3530_spi.inl Tue Sep 21 02:30:11 2010 +0100 @@ -0,0 +1,118 @@ +// This component and the accompanying materials are made available +// under the terms of the License "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// lukasz.forynski@gmail.com +// +// Contributors: +// +// Description: +// omap3530/omap3530_drivers/spi/omap3530_spi.inl +// +// This file contains definitions to internal SPI implementation. +// It is not intended to be exported - SPI registers must not be modified from outside of +// the driver! +// + + +// This sets the CS line to inactive mode (Specify aActiveMode as appropriate for configuration) +// The CS pin will be put back to the opposite mode - using GPIO.. +inline void SetCsInactive(TInt aModule, TInt aChannel, TSpiSsPinMode aActiveMode) + { + //__ASSERT_DEBUG(aModule < KMaxSpiChannelsPerModule, Kern::Fault("omap3530_spi.inl, line: ", __LINE__)); // aChannel > module channels + // set the pin to the opposite to the currently active CS mode.. + TUint16 csPinOptions = aActiveMode == ESpiCSPinActiveLow ? KCsPinModeUp : KCsPinModeDown; + const TPinConfig& csConf = ModulePinConfig[aModule].iCs[aChannel]; + __ASSERT_DEBUG(csConf.iAddress, Kern::Fault("omap3530_spi.inl, line: ", __LINE__)); // aChannel > module channels + + // now switch the pin mode.. + SCM::SetPadConfig(csConf.iAddress, csConf.iMswLsw, SCM::EMode4 | csPinOptions); // always go to mode 4 (gpio) + } + +void SetCsActive(TInt aModule, TInt aChannel, TSpiSsPinMode aActiveMode) + { + //__ASSERT_DEBUG(aModule < KMaxSpiChannelsPerModule, Kern::Fault("omap3530_spi.inl, line: ", __LINE__)); // aChannel > module channels + TUint16 csPinOptions = aActiveMode == ESpiCSPinActiveLow ? KCsPinModeUp : KCsPinModeDown; + const TPinConfig &csConf = ModulePinConfig[aModule].iCs[aChannel]; + __ASSERT_DEBUG(csConf.iAddress, Kern::Fault("omap3530_spi.inl, line: ", __LINE__)); // aChannel > module channels + + // now switch the pin mode back to the SPI + SCM::SetPadConfig(csConf.iAddress, csConf.iMswLsw, csConf.iFlags | csPinOptions); // revert to intended mode + } + + +// Setup pad function for SPI pins.. +void SetupSpiPins(TUint aSpiModule) + { + //__ASSERT_DEBUG(aModule < KMaxSpiChannelsPerModule, Kern::Fault("omap3530_spi.inl, line: ", __LINE__)); // aChannel > module channels + const TSpiPinConfig& pinCnf = ModulePinConfig[aSpiModule]; + SCM::SetPadConfig(pinCnf.iClk.iAddress, pinCnf.iClk.iMswLsw, pinCnf.iClk.iFlags); + SCM::SetPadConfig(pinCnf.iSimo.iAddress, pinCnf.iSimo.iMswLsw, pinCnf.iSimo.iFlags); + SCM::SetPadConfig(pinCnf.iSomi.iAddress, pinCnf.iSomi.iMswLsw, pinCnf.iSomi.iFlags); + // Cs pins are set dynamically during operations. + } + +// helper function - returns appropriate value for the register for a given mode +inline TUint32 SpiClkMode(TSpiClkMode aClkMode) + { + // (POL) (PHA) + // 0 0 Mode 0: spim_clk is active high and sampling occurs on the rising edge. + // 0 1 Mode 1: spim_clk is active high and sampling occurs on the falling edge. + // 1 0 Mode 2: spim_clk is active low and sampling occurs on the falling edge. + // 1 1 Mode 3: spim_clk is active low and sampling occurs on the rising edge. + + TUint val = 0; + switch(aClkMode) + { + //case ESpiPolarityLowRisingEdge: // Active high, odd edges + /*val |= MCSPI_CHxCONF_POL;*/ // 0 (not set) + /*val |= MCSPI_CHxCONF_PHA;*/ // 0 (not set) + //break; // commented out - it's only for reference - there's nothing to change + + case ESpiPolarityLowFallingEdge: // Active high, even edges + /*val |= MCSPI_CHxCONF_POL;*/ // 0 (not set) + val |= MCSPI_CHxCONF_PHA; // 1 + break; + + case ESpiPolarityHighFallingEdge: // Active low, odd edges + val |= MCSPI_CHxCONF_POL; // 1 + /*val |= MCSPI_CHxCONF_PHA;*/ // 0 (not set) + break; + + case ESpiPolarityHighRisingEdge: // Active low, even edges + val |= MCSPI_CHxCONF_POL; // 1 + val |= MCSPI_CHxCONF_PHA; // 1 + break; + } + return val; + } + +// helper function - returns appropriate value for the register for a given frequency (or error->if not found) +inline TInt SpiClkValue(TInt aClkSpeedHz) + { + for (TInt val = 0; val < 0xD; val++) // only loop through all possible values.. + { + if(MCSPI_K48MHz >> val == aClkSpeedHz) + { + return (val << 2); // return value ready for the register + } + } + return KErrNotFound; + } + +inline TInt SpiWordWidth(TSpiWordWidth aWidth) + { + TInt val = 0; + switch(aWidth) + { + case ESpiWordWidth_8: val |= MCSPI_CHxCONF_WL(8); break; + case ESpiWordWidth_10: val |= MCSPI_CHxCONF_WL(10); break; + case ESpiWordWidth_12: val |= MCSPI_CHxCONF_WL(12); break; + case ESpiWordWidth_16: val |= MCSPI_CHxCONF_WL(16); break; +// case ESpiWordWidth_32: val |= MCSPI_CHxCONF_WL(32); break; // TODO uncomment when fix for Bug 3665 is released + } + return val; + } +