Other Parts Discussed in Thread: OMAPL138
Tool/software: Linux
Hello,
We need to do use mcbsp on Linux.
Is there any simple example demonstrating mcbsp with Linux ?
I couldn't find any.
Regards,
Ran
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Tool/software: Linux
Hello,
We need to do use mcbsp on Linux.
Is there any simple example demonstrating mcbsp with Linux ?
I couldn't find any.
Regards,
Ran
Hi Pavel,
I understand.
The links shows nothing which can help, even if it was example using the given code from TI mach-omap2/mcbsp.c it could help.
I even didn't find non linux (ccs, u-boot or anything else) example with the same omap2 family.
The best I could find is ti-dvsdk_omapl138-evm_4_01_00_09\psp\linux-driver-examples-psp03.20.00.13\mcbsp\mcbsp_test.c for OMAPL138.
I
thought I could skip "reinventing the wheel", but seems to be that I must do it all from the beginning...
Thanks,
Ran
Ran,
What do you mean by "familiar with CCS demonstration of mcbsp in DM814x" ? If you ask me for official CCS DM814x McBSP demo, no I do not have such. We have some CCS based DM814x McBSP code in the link already provided, but it was defined by you as "shows nothing which can help". The owner of the code (HRi) state that this code work fine for him.
Regards,
Pavel
Hi Pavel,
I try to do tx only, and as simple as possible.
I thought of using interrupt mode, (I think dma is more complex, and not sure if polling as transmit capabilty ?
If I use interrupt, what value is required in tx_irq ?
Best Regards,
Ran
Ran,
Yes, there is polling mode support. Polling mode is easiest comparing with IRQ and DMA, so I would suggest you to start with it. Once ready you can proceed with IRQ and DMA.
The selection between polling mode (OMAP_MCBSP_POLL_IO) and IRQ mode (OMAP_MCBSP_IRQ_IO) is done in omap_mcbsp_set_io_type() function.
In mcbspc. IRQ mode is selected:
omap_mcbsp_probe()
/* Default I/O is IRQ based */
mcbsp->io_type = OMAP_MCBSP_IRQ_IO;
You can see how polling mode is done in dsp-clock.c
omap_mcbsp_set_io_type(MCBSP_ID(clk_id), OMAP_MCBSP_POLL_IO);
The functions used in polling mode are:
omap_mcbsp_pollwrite(id, buf)
omap_mcbsp_pollread(id, buf)
omap_mcbsp_spi_master_xmit_word_poll(id, word)
omap_mcbsp_spi_master_recv_word_poll(id, word)
See also the below e2e threads:
Regards,
Pavel
Hi Pavel,
I hope you can assist on the following mcbsp issue:
I am trying to use poll mode.
I have register mcbsp device, it seems to be registered ok:
from dmesg:
omap2_mcbsp_init....
omap_mcbsp_register_board_cfg
omap_mcbsp_init
ranran mcbsp probe pdata->phys_base 0x47000000
mcbsp finished ok!
Then I insert module which only do tx poll, but it fails to do the write:
omap-mcbsp omap-mcbsp.1: Could not write to McBSP1 Register
I've verfied that it's not issue of CM_ALWON_MCBSP_CLKCTRL :
root@dm814x:~# devmem2 0x4818154C
/dev/mem opened.
Memory mapped at address 0x4033e000.
Read at address 0x4818154C (0x4033e54c): 0x00000002
Do you have any idea why mcbsp poll write fails , i.e. why does it keeps waiting for transmit confirmation ?
attached kernel log, and mcbsp module.
Thank you very much,
Ran
Hi,
One more update...
Trying to use dma does not help.
It keeps waiting for dma completion.
I don't mind if it is dma or polled (or any other method).
We just need to observe tx clock.
I also did *many* configuration trials in mcbsp registers , but it keeps behaving the same in dma/polled.
Thank you for any suggestion,
Ran
Ran,
Ran Shalit said:I have register mcbsp device, it seems to be registered ok:
from dmesg:
omap2_mcbsp_init....
omap_mcbsp_register_board_cfg
omap_mcbsp_init
ranran mcbsp probe pdata->phys_base 0x47000000
mcbsp finished ok!
I see you have the below error reported in the kernel:
omap_mcbsp_init
Error: Driver 'omap-mcbsp' is already registered, aborting...
Seems like mcbsp is registered two times, it is better to fix this.
Ran Shalit said:Then I insert module which only do tx poll, but it fails to do the write:
I would recommend you to implement init and probe functions in the out-of-tree module, see the below device driver as an example:
Ran Shalit said:omap-mcbsp omap-mcbsp.1: Could not write to McBSP1 Register
Can you trace at which line of code exactly this message is generated? At which McBSP register exactly your driver can not write?
Regards,
Pavel
Ran Shalit said:I also suspect that maybe ti81xx mcbsp need to behave like omap24 or omap34 or omap44 ?
We have the same McBSP module in TI81xx, OMAP3 and OMAP4
Regards,
Pavel
Hi Pavel,
Thank you a lot for assistance on this.
It seems that the call to arch_initcall() automatically results in 2 times probe, but seems that the 2nd is ignored according to the printing.
arch_initcall(omap2_mcbsp_init);
arch_initcall(omap_mcbsp_init);
I can try do it all in the out module, but not sure this is the reason for this failure.
The thing I am not sure about is mainly if ti81xx driver should use the code inside is_cpu_omap2xx/is_cpu_omap3xx/is_cpu_omap4xx etc.
Should it use that code ?
"Can you trace at which line of code exactly this message is generated? At which McBSP register exactly your driver can not write?"
Yes, it is in mcbsp.c in omap_mcbsp_pollwrite(), seems that it waits for register status value to change appropriately - which does not happen.
/* polled mcbsp i/o operations */
int omap_mcbsp_pollwrite(unsigned int id, u16 buf)
{...
while (!(MCBSP_READ(mcbsp, SPCR2) & XRDY)) {
....
dev_err(mcbsp->dev, "Could not write to"
" McBSP%d Register\n", mcbsp->id);
return -2;
}
I also tried spi configuration and dma configuration but all fail in similar way:
dma failure: "Unable to request DMA channel for McBSP1"
spi failure: "Mcbsp1 transmitter not ready" (omap_mcbsp_spi_master_recv_word_poll)
I suspected clock issues, but I don't see clock printing errors.
Yet, in mcbsp.c I did the following changes (the original code in comment resulted in error print of clk_get)
mcbsp->iclk = clk_get(NULL, "mcbsp_ick");//clk_get(&pdev->dev, "ick");
if (IS_ERR(mcbsp->iclk)) {
...
mcbsp->fclk = clk_get(NULL,"mcbsp_fck");//(&pdev->dev, "fck");
if (IS_ERR(mcbsp->fclk)) {
Thank you for any suggestion,
Ran
Ran Shalit said:The thing I am not sure about is mainly if ti81xx driver should use the code inside is_cpu_omap2xx/is_cpu_omap3xx/is_cpu_omap4xx etc.
Should it use that code ?
OMAP3 McBSP has sitetone, while OMAP4 and TI81xx McBSP does not. So I would suggest you to use the code under cpu_is_omap44xx, which is configuring the below registers:
- XCCR - Transmit Configuration Control register
- RCCR - Receive Configuration Control Register
- THRSH1 - Receive Buffer Threshold Register
- THRSH2 - Transmit Buffer Threshold Register
I would suggest you to work with both TRMs, DM814x McBSP and OMAP44x McBSP
Regards,
Pavel
Ran Shalit said:Yes, it is in mcbsp.c in omap_mcbsp_pollwrite(), seems that it waits for register status value to change appropriately - which does not happen.
/* polled mcbsp i/o operations */
int omap_mcbsp_pollwrite(unsigned int id, u16 buf)
{...while (!(MCBSP_READ(mcbsp, SPCR2) & XRDY)) {
....
dev_err(mcbsp->dev, "Could not write to"
" McBSP%d Register\n", mcbsp->id);
return -2;
}
From what I understand, in the below code the XRDY bit (SPCR2[1] XRDY) do not transition from 0 to 1 after 1000 attempts (in your case).
/* wait for transmit confirmation */
int attemps = 0;
while (!(MCBSP_READ(mcbsp, SPCR2) & XRDY)) {
if (attemps++ > 1000) {
MCBSP_WRITE(mcbsp, SPCR2,
MCBSP_READ_CACHE(mcbsp, SPCR2) &
(~XRST));
udelay(10);
MCBSP_WRITE(mcbsp, SPCR2,
MCBSP_READ_CACHE(mcbsp, SPCR2) |
(XRST));
udelay(10);
dev_err(mcbsp->dev, "Could not write to"
" McBSP%d Register\n", mcbsp->id);
return -2;
}
Can you provide McBSP register dump before this code and after? May be here is something wrong in the register settings that prevents the transmitter to become ready.
Have you made the McBSP pinmux?
Regards,
Pavel
Hi Pavel,
Please see the printings before and after:
before pollwrite:
*** McBSP regs 0x50080037****
**** addr 0x47000100 value 0xff5d169f ****
**** addr 0x47000104 value 0x0 ****
**** addr 0x47000108 value 0x0 ****
**** addr 0x4700010c value 0x0 ****
**** addr 0x47000110 value 0x0 ****
**** addr 0x47000114 value 0x0 ****
**** addr 0x47000118 value 0x0 ****
**** addr 0x4700011c value 0x0 ****
**** addr 0x47000120 value 0x0 ****
**** addr 0x47000124 value 0x0 ****
**** addr 0x47000128 value 0x2000 ****
**** addr 0x4700012c value 0x1 ****
**** addr 0x47000130 value 0x0 ****
**** addr 0x47000134 value 0x0 ****
**** addr 0x47000138 value 0x0 ****
**** addr 0x4700013c value 0x0 ****
**** addr 0x47000140 value 0x0 ****
**** addr 0x47000144 value 0x0 ****
**** addr 0x47000148 value 0x0 ****
**** addr 0x4700014c value 0x0 ****
**** addr 0x47000150 value 0x0 ****
**** addr 0x47000154 value 0x0 ****
**** addr 0x47000158 value 0x0 ****
**** addr 0x4700015c value 0x0 ****
**** addr 0x47000160 value 0x0 ****
**** addr 0x47000164 value 0x0 ****
**** addr 0x47000168 value 0x0 ****
**** addr 0x4700016c value 0x0 ****
**** addr 0x47000170 value 0x0 ****
**** addr 0x47000174 value 0x0 ****
**** addr 0x47000178 value 0x0 ****
**** addr 0x4700017c value 0x37 ****
**** addr 0x47000180 value 0x0 ****
**** addr 0x47000184 value 0x0 ****
**** addr 0x47000188 value 0x0 ****
**** addr 0x4700018c value 0x200 ****
**** addr 0x47000190 value 0x0 ****
**** addr 0x47000194 value 0x0 ****
**** addr 0x47000198 value 0x0 ****
**** addr 0x4700019c value 0x0 ****
**** addr 0x470001a0 value 0x10 ****
**** addr 0x470001a4 value 0xf0f ****
**** addr 0x470001a8 value 0x0 ****
**** addr 0x470001ac value 0x1008 ****
**** addr 0x470001b0 value 0x808 ****
**** addr 0x470001b4 value 0x80 ****
**** addr 0x470001b8 value 0x0 ****
**** addr 0x470001bc value 0x84 ****
***********************
omap-mcbsp omap-mcbsp.1: Could not write to McBSP1 Register
After pollwrite:
**** McBSP regs 0x50080037****
**** addr 0x47000100 value 0xff5d169f ****
**** addr 0x47000104 value 0x0 ****
**** addr 0x47000108 value 0x0 ****
**** addr 0x4700010c value 0x0 ****
**** addr 0x47000110 value 0x0 ****
**** addr 0x47000114 value 0x0 ****
**** addr 0x47000118 value 0x0 ****
**** addr 0x4700011c value 0x0 ****
**** addr 0x47000120 value 0x0 ****
**** addr 0x47000124 value 0x0 ****
**** addr 0x47000128 value 0x2000 ****
**** addr 0x4700012c value 0x1 ****
**** addr 0x47000130 value 0x0 ****
**** addr 0x47000134 value 0x0 ****
**** addr 0x47000138 value 0x0 ****
**** addr 0x4700013c value 0x0 ****
**** addr 0x47000140 value 0x0 ****
**** addr 0x47000144 value 0x0 ****
**** addr 0x47000148 value 0x0 ****
**** addr 0x4700014c value 0x0 ****
**** addr 0x47000150 value 0x0 ****
**** addr 0x47000154 value 0x0 ****
**** addr 0x47000158 value 0x0 ****
**** addr 0x4700015c value 0x0 ****
**** addr 0x47000160 value 0x0 ****
**** addr 0x47000164 value 0x0 ****
**** addr 0x47000168 value 0x0 ****
**** addr 0x4700016c value 0x0 ****
**** addr 0x47000170 value 0x0 ****
**** addr 0x47000174 value 0x0 ****
**** addr 0x47000178 value 0x0 ****
**** addr 0x4700017c value 0x37 ****
**** addr 0x47000180 value 0x0 ****
**** addr 0x47000184 value 0x0 ****
**** addr 0x47000188 value 0x0 ****
**** addr 0x4700018c value 0x200 ****
**** addr 0x47000190 value 0x0 ****
**** addr 0x47000194 value 0x0 ****
**** addr 0x47000198 value 0x0 ****
**** addr 0x4700019c value 0x0 ****
**** addr 0x470001a0 value 0x10 ****
**** addr 0x470001a4 value 0xf0f ****
**** addr 0x470001a8 value 0x0 ****
**** addr 0x470001ac value 0x1008 ****
**** addr 0x470001b0 value 0x808 ****
**** addr 0x470001b4 value 0x80 ****
**** addr 0x470001b8 value 0x0 ****
**** addr 0x470001bc value 0x84 ****
***********************
attached mcbsp_module.c (I only do insmod mcbsp_module.ko )
As to pinmux, it seems to be OK:
PINCNTL27-PINCNTL30 = MCB_DR,MCB_Dx,MCB_FSX, MCB_CLKX
oot@dm814x:~# devmem2 0x4814086c
/dev/mem opened.
Memory mapped at address 0x40132000.
Read at address 0x4814086C (0x4013286c): 0x00040002
root@dm814x:~# devmem2 0x48140870
/dev/mem opened.
Memory mapped at address 0x400f3000.
Read at address 0x48140870 (0x400f3870): 0x00040002
root@dm814x:~# devmem2 0x48140874
/dev/mem opened.
Memory mapped at address 0x40256000.
Read at address 0x48140874 (0x40256874): 0x00040002
root@dm814x:~#
Thank you ,
Ran
Hi Pavel,
Comparing the register contents , before and after pollwrite (in the previous message), I see that there is no change at all.
Does it indicates what might be wrong ?
Is there any wrong initialization ?
Best Regards,
Ran
Ran,
Ran Shalit said:As to pinmux, it seems to be OK:
PINCNTL27-PINCNTL30 = MCB_DR,MCB_Dx,MCB_FSX, MCB_CLKX
oot@dm814x:~# devmem2 0x4814086c
/dev/mem opened.
Memory mapped at address 0x40132000.
Read at address 0x4814086C (0x4013286c): 0x00040002
root@dm814x:~# devmem2 0x48140870
/dev/mem opened.
Memory mapped at address 0x400f3000.
Read at address 0x48140870 (0x400f3870): 0x00040002
root@dm814x:~# devmem2 0x48140874
/dev/mem opened.
Memory mapped at address 0x40256000.
Read at address 0x48140874 (0x40256874): 0x00040002
root@dm814x:~#
I see bit 19 is 0, while the reset value is 1. You should keep the reset value, see DM814x Silicon errata, Advisory 2.1.88 — Control Module, Pin Configuration (PINCNTLx): ROM Modifies Bit 19
From what I understand DM814x McBSP is the master, it drives the MCB_CLKX, MCB_FSX and MCB_DX pins, and the external chip is the slave, is that correct?
Which clock exactly you are providing to McBSP module? Can you also provide me the values you have in MCBSP_UART_CLKSRC and CM_AUDIOCLK_MCBSP_CLKSEL registers?
From the register dump I see you have:
PCR[7] SCLKME = 0
SRGR2[13] CLKSM = 1
As discussed in the e2e threads provided to you, this combination is not valid. If you want to use the mcbsp fclk coming from the device PRCM, the values should be:
PCR[7] SCLKME = 0
SRGR2[13] CLKSM = 0
Regards,
Pavel
Hi Pavel,
>"I see bit 19 is 0, while the reset value is 1. You should keep the reset value, see DM814x Silicon errata, Advisory 2.1.88 — Control Module, Pin Configuration (PINCNTLx): ROM Modifies Bit 19"
Right, so I'll change and see if it makes a difference.
>"From what I understand DM814x McBSP is the master, it drives the MCB_CLKX, MCB_FSX and MCB_DX pins, and the external chip is the slave, is that correct?"
Yes, this is my understanding too .
At this point I only check transmission, without reception, so I think that the pinmux probably have no effect.
> Which clock exactly you are providing to McBSP module?
static int __devinit omap_mcbsp_probe(struct platform_device *pdev)
{
....
mcbsp->iclk = clk_get(NULL, "mcbsp_ick");//clk_get(&pdev->dev, "ick"); <<--- this is my clock (I had to modify the original code)
if (IS_ERR(mcbsp->iclk)) {
...
}
printk("mcbsp_ick ok\n");
mcbsp->fclk = clk_get(NULL,"mcbsp_fck");//(&pdev->dev, "fck"); <<--- this is my clock (I had to modify the original code)
...
}
> Can you also provide me the values you have in MCBSP_UART_CLKSRC and CM_AUDIOCLK_MCBSP_CLKSEL registers?
I'll check and get back to you.
You can also run this module in your board, if you want. It does the pollwrite just after "insmod <module>.ko"
Thank you,
Ran
Ran,
Ran Shalit said:for some reason the driver expects phy base to be 0x47000100 instead of 0x47000000....
This is common issue for some of the peripherals modules. We have the same issue with McSPI. In Linux driver we have base addr of 0x47000100 and register offset start from 0x0. While in documentation (datasheet, TRM) we have base address of 0x47000000 and register offset start from 0x100. At the end we have the same full address.
Ran Shalit said:Some of driver code is for omap2/omap3/omap4,
Do we need this code with ti81xx too ?
Yes, I think we need the same code as for omap4. See again my replay at the below link:
Regards,
Pavel
Hi Pavel,
I see there is some difference between omap3 and omap4 in driver.
There are some stuff specific for omap3, for example:
if (cpu_is_omap34xx())
omap_st_start(mcbsp);
Do we need the specific omap3 driver code ?
I also tried dma tx, but it seems to be stuck, waiting for completion :
I don't have mcbsp device connected in board yet, but I don't think it should matter with tx, Right ?
I tried to make a dump before dma and after, I get the following dump (and it stays the same after the call - which does not return actually because it is stuck waiting for completion:
*** McBSP regs 0x50080037****
**** addr 0x47000100 value 0xBD511FBB ****
**** addr 0x47000104 value 0x0 ****
**** addr 0x47000108 value 0x0 ****
**** addr 0x4700010c value 0x0 ****
**** addr 0x47000110 value 0x2c3 ****
**** addr 0x47000114 value 0x0 ****
**** addr 0x47000118 value 0x0 ****
**** addr 0x4700011c value 0x0 ****
**** addr 0x47000120 value 0x1 ****
**** addr 0x47000124 value 0x80 ****
**** addr 0x47000128 value 0x5018 ****
**** addr 0x4700012c value 0xf ****
**** addr 0x47000130 value 0x0 ****
**** addr 0x47000134 value 0x0 ****
**** addr 0x47000138 value 0x0 ****
**** addr 0x4700013c value 0x0 ****
**** addr 0x47000140 value 0x0 ****
**** addr 0x47000144 value 0x0 ****
**** addr 0x47000148 value 0xa00 ****
**** addr 0x4700014c value 0x0 ****
**** addr 0x47000150 value 0x0 ****
**** addr 0x47000154 value 0x0 ****
**** addr 0x47000158 value 0x0 ****
**** addr 0x4700015c value 0x0 ****
**** addr 0x47000160 value 0x0 ****
**** addr 0x47000164 value 0x0 ****
**** addr 0x47000168 value 0x0 ****
**** addr 0x4700016c value 0x0 ****
**** addr 0x47000170 value 0x0 ****
**** addr 0x47000174 value 0x0 ****
**** addr 0x47000178 value 0x0 ****
**** addr 0x4700017c value 0x37 ****
**** addr 0x47000180 value 0x0 ****
**** addr 0x47000184 value 0x0 ****
**** addr 0x47000188 value 0x0 ****
**** addr 0x4700018c value 0x10 ****
**** addr 0x47000190 value 0x0 ****
**** addr 0x47000194 value 0x0 ****
**** addr 0x47000198 value 0x0 ****
**** addr 0x4700019c value 0x0 ****
**** addr 0x470001a0 value 0x4f10 ****
**** addr 0x470001a4 value 0x0 ****
**** addr 0x470001a8 value 0x0 ****
**** addr 0x470001ac value 0x808 ****
**** addr 0x470001b0 value 0x0 ****
**** addr 0x470001b4 value 0x80 ****
**** addr 0x470001b8 value 0x0 ****
**** addr 0x470001bc value 0x84 ****
***********************
int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer,
unsigned int length)
{
.....
omap_set_dma_src_params(mcbsp->dma_tx_lch,
dest_port,
OMAP_DMA_AMODE_POST_INC,
buffer,
0, 0);
printk("omap_mcbsp_xmit_buffer 4\n"); <--- this is printed
omap_start_dma(mcbsp->dma_tx_lch);
wait_for_completion(&mcbsp->tx_dma_completion);
printk("omap_mcbsp_xmit_buffer finished ok\n"); <----------------- never get here
return 0;
}
I might leave it with pollwrite, if dma write will not function.
Best Regards,
Ran
Ran Shalit said:I see there is some difference between omap3 and omap4 in driver.
There are some stuff specific for omap3, for example:
if (cpu_is_omap34xx())
omap_st_start(mcbsp);
Do we need the specific omap3 driver code ?
No, TI81xx does not have sidetone (st). See my replay at the below post:
Ran Shalit said:I also tried dma tx, but it seems to be stuck, waiting for completion :
DMA mode will not work such easy. TI81xx has EDMA (Enhanced DMA) while OMAP3/4 has SDMA (System DMA). And mcbsp.c is based on the SDMA driver:
linux-kernel/arch/arm/plat-omap/include/plat/dma.h
linux-kernel/arch/arm/plat-omap/dma.c
You should convert SDMA to EDMA in McBSP driver. You can take as example TI81xx McASP and/or MMC/SD drivers, which use EDMA. There is also file used to convert from SDMA to EDMA, but I am not sure how useful it is, you can have a look.
linux-kernel/arch/arm/plat-omap/sdma2edma.c
Regards,
Pavel
Hi Pavel,
If I may, one more question about dma.
You mentioned that we need to use emda instead of smda.
But according to driver API, it seems that all dma issues are done inside driver, and the driver interface justs expects a pointer to dma allocated buffer:
dma_tx = dma_alloc_coherent( NULL, XBUFF_LEN, &mcbsp->x_dma,GFP_KERNEL | GFP_DMA); << -- test module prepare dma buffer
omap_mcbsp_xmit_buffer( OMAP_MCBSP_ID, dma_tx, XBUFF_LEN); <-- test module send a buffer
Isn't it correct , or do I still need edma ?
Thank you,
Ran
Ran Shalit said:But according to driver API, it seems that all dma issues are done inside driver, and the driver interface justs expects a pointer to dma allocated buffer:
I am not sure I get your point. May be you misunderstood that both drivers (SDMA and EDMA) share the same files?
linux-kernel/arch/arm/plat-omap/include/plat/dma.h
linux-kernel/arch/arm/plat-omap/dma.c
The above driver is SDMA only driver.
Regards,
Pavel