183 { |
183 { |
184 slavePinSet = slaveAddr > 3 ? 3 : 2; // slaveAddr: 2-3: pin set 2(1*); 4-5: pin set 3(2*) |
184 slavePinSet = slaveAddr > 3 ? 3 : 2; // slaveAddr: 2-3: pin set 2(1*); 4-5: pin set 3(2*) |
185 slaveAddr &= 1; // modulo 2 (i.e. 2 CS for McSPI3) |
185 slaveAddr &= 1; // modulo 2 (i.e. 2 CS for McSPI3) |
186 } |
186 } |
187 |
187 |
|
188 // reconfigure pins if needed.. |
|
189 if(slavePinSet != iCurrSlavePinSet) |
|
190 { |
|
191 iCurrSlavePinSet = slavePinSet; |
|
192 SetupSpiPins(iChannelNumber, iCurrSlavePinSet); |
|
193 } |
|
194 |
188 // store configuration parameters |
195 // store configuration parameters |
189 iCurrSS = slaveAddr; |
196 iCurrSS = slaveAddr; |
190 iCurrSlavePinSet = slavePinSet; |
|
191 iCurrHeader = newHeader; //copy the header.. |
197 iCurrHeader = newHeader; //copy the header.. |
192 |
198 |
193 return KErrNone; |
199 return KErrNone; |
194 } |
200 } |
195 |
201 |
196 // Init the hardware with the data provided in the transaction and slave-address field |
202 // Init the hardware with the data provided in the transaction and slave-address field |
197 // (these values are already stored in the iCurrHeader) |
203 // (these values are already stored in the iCurrHeader) |
198 TInt DSpiMasterBeagle::ConfigureInterface() |
204 TInt DSpiMasterBeagle::ConfigureInterface() |
199 { |
205 { |
200 DBGPRINT(Kern::Printf("ConfigureInterface()")); |
206 DBGPRINT(Kern::Printf("ConfigureInterface()")); |
201 |
|
202 // make sure pins are set up properly (only for McSPI3) |
|
203 if(iCurrSlavePinSet == 2) |
|
204 { |
|
205 SetupSpiPins(iChannelNumber, iCurrSlavePinSet); |
|
206 } |
|
207 |
207 |
208 // soft reset the SPI.. |
208 // soft reset the SPI.. |
209 TUint val = AsspRegister::Read32(iHwBase + MCSPI_SYSCONFIG); |
209 TUint val = AsspRegister::Read32(iHwBase + MCSPI_SYSCONFIG); |
210 val = MCSPI_SYSCONFIG_SOFTRESET; // issue reset |
210 val = MCSPI_SYSCONFIG_SOFTRESET; // issue reset |
211 |
211 |
270 // but at the momment IIC SPI is used in 'single' mode onlny.. |
270 // but at the momment IIC SPI is used in 'single' mode onlny.. |
271 val |= MCSPI_CHxCONF_FFEW; |
271 val |= MCSPI_CHxCONF_FFEW; |
272 // val |= MCSPI_CHxCONF_FFER; // fifo enable for receive.. (TODO) |
272 // val |= MCSPI_CHxCONF_FFER; // fifo enable for receive.. (TODO) |
273 #endif |
273 #endif |
274 |
274 |
|
275 val |= (iCurrHeader.iTransactionWaitCycles & 3) << MCSPI_CHxCONF_TCS_SHIFT; |
|
276 |
275 // update the register.. |
277 // update the register.. |
276 AsspRegister::Write32(iHwBase + MCSPI_CHxCONF(iCurrSS), val); |
278 AsspRegister::Write32(iHwBase + MCSPI_CHxCONF(iCurrSS), val); |
277 |
279 |
278 // set spim_somi pin direction to input |
280 // set spim_somi pin direction to input |
279 val = MCSPI_SYST_SPIDATDIR0; |
281 val = MCSPI_SYST_SPIDATDIR0; |
289 } |
291 } |
290 |
292 |
291 // Set the MS bit to 0 to provide the clock (ie. to setup as master) |
293 // Set the MS bit to 0 to provide the clock (ie. to setup as master) |
292 #ifndef SINGLE_MODE |
294 #ifndef SINGLE_MODE |
293 AsspRegister::Write32(iHwBase + MCSPI_MODULCTRL, MCSPI_MODULCTRL_MS_MASTER); |
295 AsspRegister::Write32(iHwBase + MCSPI_MODULCTRL, MCSPI_MODULCTRL_MS_MASTER); |
|
296 // change the pad config - now the SPI drives the line appropriately.. |
|
297 SetCsActive(iChannelNumber, iCurrSS, iCurrSlavePinSet); |
294 #else |
298 #else |
295 AsspRegister::Write32(iHwBase + MCSPI_MODULCTRL, MCSPI_MODULCTRL_MS_MASTER | MCSPI_MODULCTRL_SINGLE); |
299 AsspRegister::Write32(iHwBase + MCSPI_MODULCTRL, MCSPI_MODULCTRL_MS_MASTER | MCSPI_MODULCTRL_SINGLE); |
296 #endif |
300 #endif |
297 |
301 |
298 return KErrNone; |
302 return KErrNone; |
799 |
803 |
800 void DSpiMasterBeagle::ExitComplete(TInt aErr, TBool aComplete /*= ETrue*/) |
804 void DSpiMasterBeagle::ExitComplete(TInt aErr, TBool aComplete /*= ETrue*/) |
801 { |
805 { |
802 DBGPRINT(Kern::Printf("DSpiMasterBeagle::ExitComplete, aErr %d, aComplete %d", aErr, aComplete)); |
806 DBGPRINT(Kern::Printf("DSpiMasterBeagle::ExitComplete, aErr %d, aComplete %d", aErr, aComplete)); |
803 |
807 |
804 // make sure CS is in inactive state (for the current / last transaction) on error |
|
805 // TODO: add extendable transaction support (..i.e. with no de-assertion of CS pin between such transactions) |
|
806 SetCsInactive(iChannelNumber, iCurrSS, iCurrHeader.iSSPinActiveMode, iCurrSlavePinSet); |
|
807 |
|
808 // disable this channel |
|
809 AsspRegister::Modify32(iHwBase + MCSPI_CHxCTRL(iCurrSS), MCSPI_CHxCTRL_EN, 0); |
|
810 |
808 |
811 // in the case of error - make sure to reset the channel |
809 // in the case of error - make sure to reset the channel |
812 if(aErr != KErrNone) |
810 if(aErr != KErrNone) |
813 { |
811 { |
|
812 // make sure CS is in inactive state (for the current / last transaction) on error |
|
813 // TODO: add extendable transaction support (..i.e. with no de-assertion of CS pin between such transactions) |
|
814 SetCsInactive(iChannelNumber, iCurrSS, iCurrHeader.iSSPinActiveMode, iCurrSlavePinSet); |
|
815 |
|
816 // disable this channel |
|
817 AsspRegister::Modify32(iHwBase + MCSPI_CHxCTRL(iCurrSS), MCSPI_CHxCTRL_EN, 0); |
|
818 |
814 AsspRegister::Write32(iHwBase + MCSPI_SYSCONFIG, MCSPI_SYSCONFIG_SOFTRESET); |
819 AsspRegister::Write32(iHwBase + MCSPI_SYSCONFIG, MCSPI_SYSCONFIG_SOFTRESET); |
815 iCurrSS = -1; // make sure the interface will be re-configured at next transaction |
820 iCurrSS = -1; // make sure the interface will be re-configured at next transaction |
816 } |
821 } |
817 |
822 |
818 // Disable interrupts for the channel |
823 // Disable interrupts for the channel |
861 TConfigSpiV01 &header = (*(TConfigSpiBufV01*) (aHdrBuff))(); |
866 TConfigSpiV01 &header = (*(TConfigSpiBufV01*) (aHdrBuff))(); |
862 |
867 |
863 // check if word width and clock are supported |
868 // check if word width and clock are supported |
864 if(SpiWordWidth(header.iWordWidth) < KMinSpiWordWidth || |
869 if(SpiWordWidth(header.iWordWidth) < KMinSpiWordWidth || |
865 SpiClkValue(header.iClkSpeedHz) < 0 || // == KErrNotSupported |
870 SpiClkValue(header.iClkSpeedHz) < 0 || // == KErrNotSupported |
866 header.iBitOrder == ELsbFirst) // this SPI only transmits MSB fist |
871 header.iBitOrder == ELsbFirst || // this SPI only transmits MSB fist |
|
872 (TUint)header.iTransactionWaitCycles > KMaxTransactionWaitTime) // max 3(+.5) cycles between words |
867 { |
873 { |
868 #ifdef _DEBUG |
874 #ifdef _DEBUG |
869 if(header.iBitOrder == ELsbFirst) |
875 if(header.iBitOrder == ELsbFirst) |
870 DBG_ERR(Kern::Printf("iClkSpeedHz value (%d) is not supported", header.iClkSpeedHz)); |
876 DBG_ERR(Kern::Printf("iClkSpeedHz value (%d) is not supported", header.iClkSpeedHz)); |
871 if(SpiClkValue(header.iClkSpeedHz) < 0) |
877 if(SpiClkValue(header.iClkSpeedHz) < 0) |
872 DBG_ERR(Kern::Printf("iClkSpeedHz: %d is not supported", header.iClkSpeedHz)); |
878 DBG_ERR(Kern::Printf("iClkSpeedHz: %d is not supported", header.iClkSpeedHz)); |
873 if((SpiWordWidth(header.iWordWidth)+ 1) >> MCSPI_CHxCONF_WL_OFFSET < KMinSpiWordWidth) |
879 if((SpiWordWidth(header.iWordWidth)+ 1) >> MCSPI_CHxCONF_WL_OFFSET < KMinSpiWordWidth) |
874 DBG_ERR(Kern::Printf("iWordWidth: %d is not supported, min value is: %d", |
880 DBG_ERR(Kern::Printf("iWordWidth: %d is not supported, min value is: %d", |
875 SpiWordWidth(header.iWordWidth), KMinSpiWordWidth)); |
881 SpiWordWidth(header.iWordWidth), KMinSpiWordWidth)); |
|
882 if((TUint)header.iTransactionWaitCycles > 3) |
|
883 DBG_ERR(Kern::Printf("iTransactionWaitCycles: %d is not supported, value should be from 0 to %d", |
|
884 header.iTransactionWaitCycles, KMaxTransactionWaitTime)); |
|
885 |
876 DumpHeader(header); |
886 DumpHeader(header); |
877 #endif |
887 #endif |
878 r = KErrNotSupported; |
888 r = KErrNotSupported; |
879 DBG_ERR(Kern::Printf("DSpiMasterBeagle::CheckHdr()failed, r = %d", r)); |
889 DBG_ERR(Kern::Printf("DSpiMasterBeagle::CheckHdr()failed, r = %d", r)); |
880 } |
890 } |