diff options
author | Louis LE GALL <louis.le.gall@intel.com> | 2010-12-09 10:37:40 +0000 |
---|---|---|
committer | Alan Cox <alan@linux.intel.com> | 2010-12-09 10:37:40 +0000 |
commit | 8b052df870fdf763e4acc9cb08fc9d1d2200b006 (patch) | |
tree | 610b6964db560858821c1c5ee38f82533ada7623 /sound/pci/intel_mid_i2s/intel_mid_i2s.h | |
parent | 44c2514121c88ea77f8a754531b38fe4c3393598 (diff) | |
download | mrst-s0i3-test-8b052df870fdf763e4acc9cb08fc9d1d2200b006.tar.gz mrst-s0i3-test-8b052df870fdf763e4acc9cb08fc9d1d2200b006.tar.xz mrst-s0i3-test-8b052df870fdf763e4acc9cb08fc9d1d2200b006.zip |
This patch adds the I2S SSP common driver that supports I2S audio on
Intel MID platforms. It is used for sending/receiving I2S audio samples
It support new DMA interface of kernel 2.6.37
Below is a simple diagram that explain where is the intel_mid_i2s in software
architecture:
+-----------+
| |
|Pulse Audio|
| |
| |
+-----------+
|
|
+------------+------------+
| |
| |
| |
+-----------+ +-----------+
| | |Lib cmt |
|Alsa Lib |------+ |speech |------+
| | | |data | |
| | | | | |
+-----------+ | +-----------+ |
| | |
| | | User
......|............|.........................|.................................
| | | Kernel
| | |
| | |
| | |
| | |
| | |
| | |
\|/ \|/ \|/
V V V
+---------+ ++---------++ ++---------++
| | ||Alsa snd || ||cmt ||
|Intel SST| ||driver || ||speech ||
| "MAD" | ||SSP || ||driver ||
| | ||BT/FM || || ||
+---------+ ++---------++ ++---------++
| | |
| | |
| | |
| | |
\|/ | \|/
V | V
+-----------+ | ++---------++
| | | \ ||intel mid||
|LPE Driver | +------------------>||i2s ||
| | / ||unified ||
| | ||driver ||
+-----------+ ++---------++
| |
| | Kernel
......|......................................|.................................
| | Hardware
\|/ \|/
V V
+-- --+ +-- --+
| | | |
|MSIC | |SSP in I2S |
| | |config |
| | | |
+-- --+ +-- --+
Signed-off-by: Louis LE GALL <louis.le.gall@intel.com>
Diffstat (limited to 'sound/pci/intel_mid_i2s/intel_mid_i2s.h')
-rw-r--r-- | sound/pci/intel_mid_i2s/intel_mid_i2s.h | 502 |
1 files changed, 502 insertions, 0 deletions
diff --git a/sound/pci/intel_mid_i2s/intel_mid_i2s.h b/sound/pci/intel_mid_i2s/intel_mid_i2s.h new file mode 100644 index 00000000000..819164d9d93 --- /dev/null +++ b/sound/pci/intel_mid_i2s/intel_mid_i2s.h @@ -0,0 +1,502 @@ +/* + * <Driver for I2S protocol on SSP (Moorestown and Medfield hardware)> + * Copyright (c) 2010, Intel Corporation. + * Louis LE GALL <louis.le.gall intel.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + */ +#define DRIVER_NAME "I2S SSP Driver" +/* + * Defines + */ +#define MFLD_SSP1_DEVICE_ID 0x0825 /* FOR MFLD */ +#define MRST_SSP0_DEVICE_ID 0x0815 /* FOR MRST */ +#define MFLD_SSP0_DEVICE_ID 0x0832 /* FOR MFLD */ + +#define MRST_LPE_DMA_DEVICE_ID 0x0814 +#define MFLD_LPE_DMA_DEVICE_ID 0x0830 + +/* SSP1 PCI device Base Address Register */ +#define MRST_SSP_BAR 0 +#define MRST_LPE_BAR 1 +#define DMA1C_DEVICE_INSTANCE_SSP0 0 +#define DMA1C_DEVICE_INSTANCE_SSP1 1 +#define OFFSET_SSCR0 0x00 +#define OFFSET_SSCR1 0x04 +#define OFFSET_SSSR 0x08 +#define OFFSET_SSITR 0x0c +#define OFFSET_SSDR 0x10 +#define OFFSET_SSTO 0x28 +#define OFFSET_SSPSP 0x2c +#define OFFSET_SSTSA 0x30 /* SSP Tx Timeslot Active */ +#define OFFSET_SSRSA 0x34 /* SSP Rx Timeslot Active */ +/* SST register map */ +#define OFFSET_LPE_CSR 0x00 +#define OFFSET_LPE_PISR 0x08 +#define OFFSET_LPE_PIMR 0x10 +#define OFFSET_LPE_ISRX 0x18 +#define OFFSET_LPE_IMRX 0x28 +#define OFFSET_LPE_IPCX 0x38 /* IPC IA-SST */ +#define OFFSET_LPE_IPCD 0x40 /* IPC SST-IA */ +#define OFFSET_LPE_ISRD 0x20 /* dummy register for*/ + /* shim workaround */ +#define OFFSET_LPE_SHIM_SIZE 0X44 + +#define SSP_IN_MASTER_MODE 0x0 +#define SSP_IN_SLAVE_MODE 0x1 + +/* + * Macros + */ +#define DEFINE_SSP_REG(reg, off) \ +static inline u32 read_##reg(void *p) { return __raw_readl(p + (off)); } \ +static inline void write_##reg(u32 v, void *p) { __raw_writel(v, p + (off)); } +DEFINE_SSP_REG(SSCR0, 0x00) +DEFINE_SSP_REG(SSCR1, 0x04) +DEFINE_SSP_REG(SSSR, 0x08) +DEFINE_SSP_REG(SSITR, 0x0c) +DEFINE_SSP_REG(SSDR, 0x10) +DEFINE_SSP_REG(SSTO, 0x28) +DEFINE_SSP_REG(SSPSP, 0x2c) +DEFINE_SSP_REG(SSTSA, 0x30) +DEFINE_SSP_REG(SSRSA, 0x34) +DEFINE_SSP_REG(SSTSS, 0x38) +DEFINE_SSP_REG(SSACD, 0x3C) +DEFINE_SSP_REG(I2CCTRL, 0x00); +DEFINE_SSP_REG(I2CDATA, 0x04); +/* + * Langwell SSP serial port register definitions + */ +#define SSCR0_DSS_MASK 0x0F /* Data Size Select [4..16] */ +#define SSCR0_DSS_SHIFT 0 +#define SSCR0_FRF_MASK 0x03 /* FRame Format */ +#define SSCR0_FRF_SHIFT 4 +#define SSCR0_ECS_MASK 0x01 /* External clock select */ +#define SSCR0_ECS_SHIFT 6 +#define SSCR0_SSE_MASK 0x01 /* Synchronous Serial Port Enable */ +#define SSCR0_SSE_SHIFT 7 +#define SSCR0_SCR_MASK 0xFFF /* Not implemented */ +#define SSCR0_SCR_SHIFT 8 +#define SSCR0_EDSS_MASK 0x1 /* Extended data size select */ +#define SSCR0_EDSS_SHIFT 20 +#define SSCR0_NCS_MASK 0x1 /* Network clock select */ +#define SSCR0_NCS_SHIFT 21 +#define SSCR0_RIM_MASK 0x1 /* Receive FIFO overrrun int mask */ +#define SSCR0_RIM_SHIFT 22 +#define SSCR0_TIM_MASK 0x1 /* Transmit FIFO underrun int mask */ +#define SSCR0_TIM_SHIFT 23 +#define SSCR0_FRDC_MASK 0x7 /* Frame Rate Divider Control */ +#define SSCR0_FRDC_SHIFT 24 +#define SSCR0_ACS_MASK 0x1 /* Audio clock select */ +#define SSCR0_ACS_SHIFT 30 +#define SSCR0_MOD_MASK 0x1 /* Mode (normal or network) */ +#define SSCR0_MOD_SHIFT 31 + +#define SSCR0_DataSize(x) ((x) - 1) /* Data Size Select [4..16] */ +#define SSCR0_SlotsPerFrm(x) ((x) - 1) /* Time slots per frame */ +#define SSCR0_SerClkDiv(x) ((x) - 1) /* Divisor [1..4096],... */ + /*...not implemented on Langwell */ +#define SSCR1_TTELP_MASK 0x1 /* TXD Tristate Enable on Last Phase */ +#define SSCR1_TTELP_SHIFT 31 +#define SSCR1_TTE_MASK 0x1 /* TXD Tristate Enable */ +#define SSCR1_TTE_SHIFT 30 +#define SSCR1_EBCEI_MASK 0x1 /* Enable Bit Count Error Interrupt */ +#define SSCR1_EBCEI_SHIFT 29 +#define SSCR1_SCFR_MASK 0x1 /* Slave Clock Running */ +#define SSCR1_SCFR_SHIFT 28 +#define SSCR1_ECRA_MASK 0x1 /* Enable Clock Request A */ +#define SSCR1_ECRA_SHIFT 27 +#define SSCR1_ECRB_MASK 0x1 /* Enable Clock Request B */ +#define SSCR1_ECRB_SHIFT 26 +#define SSCR1_SCLKDIR_MASK 0x1 /* SSPCLK Direction */ +#define SSCR1_SCLKDIR_SHIFT 25 +#define SSCR1_SFRMDIR_MASK 0x1 /* SSPFRM Direction */ +#define SSCR1_SFRMDIR_SHIFT 24 +#define SSCR1_RWOT_MASK 0x1 /* Receive without Transmit */ +#define SSCR1_RWOT_SHIFT 23 +#define SSCR1_TRAIL_MASK 0x1 /* Trailing Byte */ +#define SSCR1_TRAIL_SHIFT 22 +#define SSCR1_TSRE_MASK 0x1 /* DMA Transmit Service Request Enable*/ +#define SSCR1_TSRE_SHIFT 21 +#define SSCR1_RSRE_MASK 0x1 /* DMA Receive Service Request Enable */ +#define SSCR1_RSRE_SHIFT 20 +#define SSCR1_TINTE_MASK 0x1 /* Receiver Time-out Interrupt Enable */ +#define SSCR1_TINTE_SHIFT 19 +#define SSCR1_PINTE_MASK 0x1 /* Periph. Trailing Byte Int. Enable */ +#define SSCR1_PINTE_SHIFT 18 +#define SSCR1_IFS_MASK 0x1 /* Invert Frame Signal */ +#define SSCR1_IFS_SHIFT 16 +#define SSCR1_STFR_MASK 0x1 /* Select FIFO for EFWR: test mode */ +#define SSCR1_STFR_SHIFT 15 +#define SSCR1_EFWR_MASK 0x1 /* Enable FIFO Write/Read: test mode */ +#define SSCR1_EFWR_SHIFT 14 +#define SSCR1_RFT_MASK 0xF /* Receive FIFO Trigger Threshold */ +#define SSCR1_RFT_SHIFT 10 +#define SSCR1_TFT_MASK 0xF /* Transmit FIFO Trigger Threshold */ +#define SSCR1_TFT_SHIFT 6 +#define SSCR1_MWDS_MASK 0x1 /* Microwire Transmit Data Size */ +#define SSCR1_MWDS_SHIFT 5 +#define SSCR1_SPH_MASK 0x1 /* Motorola SPI SSPSCLK phase setting */ +#define SSCR1_SPH_SHIFT 4 +#define SSCR1_SPO_MASK 0x1 /* Motorola SPI SSPSCLK polarity */ +#define SSCR1_SPO_SHIFT 3 +#define SSCR1_LBM_MASK 0x1 /* Loopback mode: test mode */ +#define SSCR1_LBM_SHIFT 2 +#define SSCR1_TIE_MASK 0x1 /* Transmit FIFO Interrupt Enable */ +#define SSCR1_TIE_SHIFT 1 +#define SSCR1_RIE_MASK 0x1 /* Receive FIFO Interrupt Enable */ +#define SSCR1_RIE_SHIFT 0 + +#define SSCR1_RxTresh(x) ((x) - 1) /* level [1..16] */ +#define SSCR1_TxTresh(x) ((x) - 1) /* level [1..16] */ + +#define SSPSP_FSRT_MASK 0x1 /* Frame Sync Relative Timing Bit */ +#define SSPSP_FSRT_SHIFT 25 +#define SSPSP_DMYSTOP_MASK 0x3 /* Dummy Stop in Number of SSPSCLKs:T4*/ +#define SSPSP_DMYSTOP_SHIFT 23 +#define SSPSP_SFRMWDTH_MASK 0x3F /* Serial Frame width : T6 */ +#define SSPSP_SFRMWDTH_SHIFT 16 +#define SSPSP_SFRMDLY_MASK 0x7F /* Serial Fr. Delay in 1/2SSPSCLKs:T5 */ +#define SSPSP_SFRMDLY_SHIFT 9 +#define SSPSP_DMYSTRT_MASK 0x3 /* Dummy Start in Number of SSPSCLKs..*/ +#define SSPSP_DMYSTRT_SHIFT 7 /*...after STRTDLY, T2 (master mode only) */ +#define SSPSP_STRTDLY_MASK 0x7 /* Start Delay, T1 (master mode only) */ +#define SSPSP_STRTDLY_SHIFT 4 +#define SSPSP_ETDS_MASK 0x1 /* End of Transfer Data State */ +#define SSPSP_ETDS_SHIFT 3 +#define SSPSP_SFRMP_MASK 0x1 /* Serial Frame Polarity */ +#define SSPSP_SFRMP_SHIFT 2 +#define SSPSP_SCMODE_MASK 0x3 /* Serial bit-rate Clock Mode */ +#define SSPSP_SCMODE_SHIFT 0 + +#define SSTSA_TTSA_MASK 0xFF +#define SSTSA_TTSA_SHIFT 0 + +#define SSRSA_RTSA_MASK 0xFF +#define SSRSA_RTSA_SHIFT 0 + +#define SSSR_BCE_MASK 0x1 /* Bit Count Error: Read/Write 1 to Clear */ +#define SSSR_BCE_SHIFT 23 +#define SSSR_CSS_MASK 0x1 /* Clock Synchronization Status */ +#define SSSR_CSS_SHIFT 22 +#define SSSR_TUR_MASK 0x1 /* Transmit FIFO UnderRun: Rd/Wr 1 to Clear */ +#define SSSR_TUR_SHIFT 21 +#define SSSR_EOC_MASK 0x1 /* End Of Chain: Read/Write 1 to Clear */ +#define SSSR_EOC_SHIFT 20 +#define SSSR_TINT_MASK 0x1 /* Receiver Time-out Interrupt:... */ +#define SSSR_TINT_SHIFT 19 /* ...Read/Write 1 to Clear */ +#define SSSR_PINT_MASK 0x1 /* Peripheral Trailing Byte Interrupt:... */ +#define SSSR_PINT_SHIFT 18 /* ...Read/Write 1 to Clear */ +#define SSSR_RFL_MASK 0xF /* Receive FIFO Level */ +#define SSSR_RFL_SHIFT 12 +#define SSSR_TFL_MASK 0xF /* Transmit FIFO Level */ +#define SSSR_TFL_SHIFT 8 +#define SSSR_ROR_MASK 0x1 /* Receive FIFO Overrun: Read/Write 1 to Clear*/ +#define SSSR_ROR_SHIFT 7 +#define SSSR_RFS_MASK 0x1 /* Receive FIFO Service Request */ +#define SSSR_RFS_SHIFT 6 +#define SSSR_TFS_MASK 0x1 /* Transmit FIFO Service Request */ +#define SSSR_TFS_SHIFT 5 +#define SSSR_BSY_MASK 0x1 /* SSP Busy */ +#define SSSR_BSY_SHIFT 4 +#define SSSR_RNE_MASK 0x1 /* Receive FIFO not empty */ +#define SSSR_RNE_SHIFT 3 +#define SSSR_TFN_MASK 0x1 /* Transmit FIFO not Full */ +#define SSSR_TFN_SHIFT 2 + + +#define SSP_OFF 0 +#define SSP_ON 1 + +/* bit I2S_PORT_OPENED lock for open/close + * bit I2S_PORT_READ_BUSY lock for read requests (serialized) + * bit I2S_PORT_WRITE_BUSY lock for write requests (serialized) + * bit I2S_PORT_CLOSING means close on going, waiting for pending callbacks. + */ + +enum i2s_flags { + I2S_PORT_OPENED, + I2S_PORT_WRITE_BUSY, + I2S_PORT_READ_BUSY, + I2S_PORT_CLOSING +}; + +#define FIFO_SIZE 16 +/* + * Structures Definition + */ + +/** + * struct intel_mid_i2s_data - context struct to keep SSP I2S data + * @pdev: pci dev pointer corresponding to context + * @paddr: + * @ioaddr: + * @iolen: + * @irq: + * @clear_sr: + * @mask_sr: + * @dmac1: + * @dmas_tx: dma slave structure for transmit + * @dmas_rx: dma slave structure for receive + * @txchan: Dma channel for transmit + * @rxchan: Dma channel for receive + * + * @read_done: + * @read_dst: + * @read_len: + * + * @write_done: + * @write_src: + * @write_len: + * + * @mutex: a mutex to make sure we have once-at-time critical functions. + * + * Longer description + */ + +/* Locking rules: + * + * All the fields, not listed below, are set during probe, and then read only + * So they do not require locking + * + * The fields that require locking are related to the I2S read and write + * requests. + * + * We allow only 1 read at a time, and 1 write at a time. + * We allow read in parallel of write but use separate variables. + * We allow only 1 user per SSP/I2S port. + * Typically this user will be a dedicated PulseAudio RT thread communicating + * with cmt-speech driver which in turns communicates with intel_mid_ssp + * driver. + * PCM mixing is done before access to kernel drivers;typically within + * PulseAudio or after; typically within the modem. + * So no concurrent users, per I2S channel, to this driver are allowed + * The read & write are triggered from a USER context + * The read & write callbacks are called from a BH context + * You should have not callback pending before calling close, close will wait + * for remaining callback calls. + * It is not allowed to call close function from read/write callback threads. + * + * Locking is handled via drv_data->flags & atomic bitwise operations + * + * I2S0 is dedicated for PCM transfer to/from the modem module + * I2S1 is dedicated for PCM transfer to/from the Bluetooth or FM module + * + * read_done: + * read_len: + * read_dst: + * + * write_done: + * write_src: + * write_len: + * + * mutex: a mutex to make sure we have once-at-time critical functions. + * once-at-a-time actions functions are: + * -intel_mid_i2s_open + * -intel_mid_i2s_close + * -intel_mid_i2s_rd_req + * -intel_mid_i2s_wr_req + * -intel_mid_i2s_set_rd_cb + * -intel_mid_i2s_set_wr_cb + * These functions should not be called during a lock() neither in interrupt. + */ + +struct intel_mid_i2s_hdl { + /* Driver model hookup */ + struct pci_dev *pdev; + /* register addresses */ + dma_addr_t paddr; + void __iomem *ioaddr; + u32 iolen; + int irq; + + /* SSP masks */ + u32 clear_sr; + u32 mask_sr; + + /* SSP Configuration */ + /* DMA info */ + struct pci_dev *dmac1; + wait_queue_head_t wq_chan_closing; + + struct intel_mid_dma_slave dmas_tx; + struct intel_mid_dma_slave dmas_rx; + struct dma_chan *txchan; + struct dma_chan *rxchan; + + unsigned int device_instance; + /* Call back functions */ + int (*read_callback)(void *param); + dma_addr_t read_dst; + size_t read_len; /* read_len > 0 <=> read_dma_running */ + void *read_param; /* context param for callback */ + int (*write_callback)(void *param); + dma_addr_t write_src; + size_t write_len; /* write_len > 0 <=> read_dma_running */ + void *write_param; /* context param for callback */ + + unsigned long flags; + struct mutex mutex; + enum intel_mid_i2s_ssp_usage usage; + + struct intel_mid_i2s_settings current_settings; + +}; + +static void i2s_read_done(void *arg); +static void i2s_write_done(void *arg); +static bool chan_filter(struct dma_chan *chan, void *param); +static void i2s_dma_stop(struct intel_mid_i2s_hdl *drv_data); +static int i2s_dma_start(struct intel_mid_i2s_hdl *drv_data); +static void ssp1_dump_registers(struct intel_mid_i2s_hdl *); +static irqreturn_t i2s_int(int irq, void *dev_id); +static void set_ssp_i2s_hw(struct intel_mid_i2s_hdl *drv_data, + const struct intel_mid_i2s_settings *ps_settings); +static int check_device(struct device *device_ptr, void *data); +#ifdef CONFIG_PM +static int intel_mid_i2s_runtime_resume(struct device *device_ptr); +static int intel_mid_i2s_runtime_suspend(struct device *device_ptr); +#endif +static int intel_mid_i2s_probe(struct pci_dev *pdev, + const struct pci_device_id *ent); +static void intel_mid_i2s_remove(struct pci_dev *pdev); +static void i2s_ssp_stop(struct intel_mid_i2s_hdl *drv_data); +/*static int bt_pcm_dma_init(struct intel_mid_i2s_hdl *drv_data);*/ + + +#ifdef CONFIG_PM +static int intel_mid_i2s_driver_suspend(struct pci_dev *dev, + pm_message_t state); +static int intel_mid_i2s_driver_resume(struct pci_dev *dev); +#endif + +/* + * These define will clarify source code when accessing SSCRx registers + */ + +#define SSCR0_reg(regbit, value) \ + (((value) & SSCR0_##regbit##_MASK) << SSCR0_##regbit##_SHIFT) + +#define SSCR1_reg(regbit, value) \ + (((value) & SSCR1_##regbit##_MASK) << SSCR1_##regbit##_SHIFT) + +#define SSPSP_reg(regbit, value) \ + (((value) & SSPSP_##regbit##_MASK) << SSPSP_##regbit##_SHIFT) + +#define SSRSA_reg(regbit, value) \ + (((value) & SSRSA_##regbit##_MASK) << SSRSA_##regbit##_SHIFT) +#define SSTSA_reg(regbit, value) \ + (((value) & SSTSA_##regbit##_MASK) << SSTSA_##regbit##_SHIFT) + + +#define change_SSCR0_reg(reg_pointer, regbit, value) \ + write_SSCR0((read_SSCR0(reg_pointer) \ + & (~((SSCR0_##regbit##_MASK << SSCR0_##regbit##_SHIFT)))) \ + | (((value) & SSCR0_##regbit##_MASK) << SSCR0_##regbit##_SHIFT), \ + reg_pointer); + +#define set_SSCR0_reg(reg_pointer, regbit) \ + write_SSCR0(read_SSCR0(reg_pointer) \ + | (SSCR0_##regbit##_MASK << SSCR0_##regbit##_SHIFT), \ + reg_pointer); + +#define clear_SSCR0_reg(reg_pointer, regbit) \ + write_SSCR0((read_SSCR0(reg_pointer) \ + & (~((SSCR0_##regbit##_MASK << SSCR0_##regbit##_SHIFT)))), \ + reg_pointer); + +#define change_SSCR1_reg(reg_pointer, regbit, value) \ + write_SSCR1((read_SSCR1(reg_pointer) \ + & (~((SSCR1_##regbit##_MASK << SSCR1_##regbit##_SHIFT)))) \ + | (((value) & SSCR1_##regbit##_MASK) << SSCR1_##regbit##_SHIFT), \ + reg_pointer); + +#define set_SSCR1_reg(reg_pointer, regbit) \ + write_SSCR1(read_SSCR1(reg_pointer) \ + | (SSCR1_##regbit##_MASK << SSCR1_##regbit##_SHIFT), \ + reg_pointer); + +#define clear_SSCR1_reg(reg_pointer, regbit) \ + write_SSCR1((read_SSCR1(reg_pointer) \ + & (~((SSCR1_##regbit##_MASK << SSCR1_##regbit##_SHIFT)))), \ + reg_pointer); + +/* RX FIFO level */ +#define GET_SSSR_val(x, regb) \ + ((x & (SSSR_##regb##_MASK<<SSSR_##regb##_SHIFT))>>SSSR_##regb##_SHIFT) + + +/* + * SSP hardware can be configured as I2S, PCM, SPI... + * In order to allow flexibility without modifying the software driver, the + * PCI header uses the configuration register 'adid': + * + * The PCI header associated to SSP devices includes a configuration register. + * It provides information to a driver which is probed for the SSP, specifying + * in which way the SSP is supposed to be used. + * Here is the format of this configuration register (8 bits): + * + * bits 2..0: Mode + * 000: Invalid, the register should be ignored + * 001: SSP to be used as SPI controller + * 010: SSP to be used in I2S/ISS mode + * other: Reserved + * + * bits 5..3: Configuration + * In I2S/ISS mode: + * 000: Invalid + * 001: Bluetooth + * 010: Modem + * other: Reserved + * In SPI mode: + * Value is the SPI bus number connected to the SSP. + * To be used for registration to the Linux SPI + * framework. + * + * bit 6: SPI slave + * Relevant in SPI mode only. If set, indicates the SPI clock + * is not provided by the SSP: SPI slave mode. + * + * bit 7: Reserved (0) + * + * This configuration register is implemented in the adid field of the + * Vendor Specific PCI capability associated to the SSP. The format of + * this capability is: + * + * uint8_t capId; < Capability ID (vendor-specific) + * uint8_t nextCap; < Next Item Ptr + * uint8_t length; < Size of this capability (7) + * uint8_t version; < Version of this capability (1) + * uint8_t lss; < Logical subsystem info + * Bit 7 = PMU (0 = NC, 1 = SC) + * Bits 6:0 = LSS ID + * uint8_t apmc; < Additional PM capabilities + * Bit 7 = Rsvd + * Bit 6 = Wake capable + * Bit 5 = D3 support + * Bit 4 = D2 support + * Bit 3 = D1 support + * Bit 2 = D0i3 support + * Bit 1 = D0i2 support + * Bit 0 = D0i1 support + * uint8_t adid; < Additional device ID (dev-specific) + * uint8_t rsvd; < Reserved for future use + * + * The capability data are in the PCI configuration space and the + * adid field can be modified using BMP tool. + */ +/* ADDID = Additional Device ID */ +#define PCI_CAP_OFFSET_ADID 6 + + |