Why does ioremap fail?

585 views
Skip to first unread message

jutra...@gmail.com

unread,
Dec 17, 2015, 3:39:57 PM12/17/15
to BeagleBoard
I am trying to access the McASP control registers. Reading from the first one fails with the  kernel oops stating "external abort on non-linefetch (0x1028)". I dont know what that means. A minimum failing example of the code is below:

#include <linux/module.h>
#include <linux/printk.h>
#include <asm/io.h>

#define MCASP_START 0x48038000
#define MCASP_LENGTH    0x2000
#define PFUNC_REG_OFFSET 0x10

static int start(void)
{
   pr_info
("Calling for ioremap\n");
   
void *mcasp = ioremap(MCASP_START, MCASP_LENGTH);
   
if(mcasp == NULL) {
      pr_info
("ioremap failed!\n");
     
return -1;
   
}

   u32 pfunc_reg
= ioread32(mcasp + PFUNC_REG_OFFSET); // Kernel Oops here!
   pr_info
("Success! PFUNC=%08X\n", test);
   iounmap
(mcasp);
   
return 0;
}
module_init
(start);

I have also tried request_mem_region around it, but that changes nothing. The sound drivers are not loaded, and the devicetree entry for the McASP is disabled, so there shouldn't be any problems with conflicts.

Any help is greatly appreciated.
Marc

John Syne

unread,
Dec 17, 2015, 4:11:13 PM12/17/15
to beagl...@googlegroups.com
I believe ioremap works on virtual memory and not on physical memory so you have to take into account the MMU translation. Look in 

arch/arm/mach-omap2/iomap.h

#define MA33XX_L4_WK_IO_OFFSET 0Xb5000000

This will translate your McASP address to 0xfa038000. Try that and see if that works.


Regards,
John




--
For more options, visit http://beagleboard.org/discuss
---
You received this message because you are subscribed to the Google Groups "BeagleBoard" group.
To unsubscribe from this group and stop receiving emails from it, send an email to beagleboard...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Charles Steinkuehler

unread,
Dec 17, 2015, 4:59:59 PM12/17/15
to beagl...@googlegroups.com
On 12/17/2015 2:04 PM, jutra...@gmail.com wrote:
> I am trying to access the McASP control registers. Reading from the first
> one fails with the kernel oops stating "external abort on non-linefetch
> (0x1028)". I dont know what that means. A minimum failing example of the
> code is below:

<snip>

> I have also tried request_mem_region around it, but that changes nothing.
> The sound drivers are not loaded, and the devicetree entry for the McASP is
> disabled, so there shouldn't be any problems with conflicts.

One way to get this error is if the hardware you are talking to is
disabled. You need to either enable the hardware via the device tree,
or otherwise manage to setup the low-level SoC registers so the McASP
is provided a clock, power, and is taken out of reset.

Most of the hardware blocks on the AM335x series can be individually
enabled or shut-down to save power.

--
Charles Steinkuehler
cha...@steinkuehler.net

John Syne

unread,
Dec 17, 2015, 5:15:17 PM12/17/15
to beagl...@googlegroups.com
That is a good point. To understand how to enable the power and clock for McASP, look at the Starterware examples for McASP as they do everything you need to make this work.

Regards,
John
>
> --
> Charles Steinkuehler
> cha...@steinkuehler.net

William Hermans

unread,
Dec 17, 2015, 6:00:27 PM12/17/15
to beagl...@googlegroups.com
That is a good point. To understand how to enable the power and clock for McASP, look at the Starterware examples for McASP as they do everything you need to make this work.

Probably easier, and more productive to read the TRM for the AM335x processors . . . All address offsets should be listed there as well, and the introduction for hardware module will give a short explanation of what needs doing, in order to bring the module up.

John Syne

unread,
Dec 17, 2015, 6:09:16 PM12/17/15
to beagl...@googlegroups.com
On Dec 17, 2015, at 3:00 PM, William Hermans <yyr...@gmail.com> wrote:

That is a good point. To understand how to enable the power and clock for McASP, look at the Starterware examples for McASP as they do everything you need to make this work.

Probably easier, and more productive to read the TRM for the AM335x processors . . . All address offsets should be listed there as well, and the introduction for hardware module will give a short explanation of what needs doing, in order to bring the module up.
Yeah, thinking about what Charles said, if he defines the McASP in the device tree, it should setup everything he needs. One problem I’m not sure how to overcome, he needs a device driver defined for the McASP or else the clock and power won’t be setup. But if he has a device driver setup, then it will conflict with his application. So that is why I think he has to do all this manually.

Regards,
John

William Hermans

unread,
Dec 17, 2015, 6:48:18 PM12/17/15
to beagl...@googlegroups.com
I've no idea how ioremap() works, never used it. But if it's similar to how mmap() works on /dev/mem/, it does not matter what state the hardware module is in.  Of course there are a few specified steps one must do in order to get a device working if it's not already. But if the device is already on, and functional, you can essentially override that module with mmap() and /dev/mem/. But it's probably not  good idea, as the kernel will still think it has control . . .

Anyway, I'm not sure I'd exactly call this a "driver" per se, as it's being done in userspace. But others might argue it's what's called a userspace driver . . . and yeah, I do not know about that. If you start changing pixels on your screen by poking at memory locations through /dev/mem/ does that mean you've created a graphics driver ? No . . .

William Hermans

unread,
Dec 17, 2015, 6:53:44 PM12/17/15
to beagl...@googlegroups.com
I'm not familiar with the McSPI hardware module, but this seems to explain a good bit.  And seems analogous( similar ) to how one would enable the ADC module - Which is the only module I have hands on experience with by poking it's registers . .  e.g. turning the clock on, etc.

https://github.com/BeaglePilot/PRUSS-C/blob/master/PRUSS_LIB/AM335X_StarterWare_02_00_01_01/drivers/mcspi.c#L378-L469

William Hermans

unread,
Dec 17, 2015, 6:57:20 PM12/17/15
to beagl...@googlegroups.com

John Syne

unread,
Dec 17, 2015, 7:09:08 PM12/17/15
to beagl...@googlegroups.com
On Dec 17, 2015, at 3:48 PM, William Hermans <yyr...@gmail.com> wrote:

I've no idea how ioremap() works, never used it. But if it's similar to how mmap() works on /dev/mem/, it does not matter what state the hardware module is in.  Of course there are a few specified steps one must do in order to get a device working if it's not already. But if the device is already on, and functional, you can essentially override that module with mmap() and /dev/mem/. But it's probably not  good idea, as the kernel will still think it has control . . .

Anyway, I'm not sure I'd exactly call this a "driver" per se, as it's being done in userspace. But others might argue it's what's called a userspace driver . . . and yeah, I do not know about that. If you start changing pixels on your screen by poking at memory locations through /dev/mem/ does that mean you've created a graphics driver ? No . . .
I was talking about the McASP device driver that is defined in the devicetree as that is the only way to setup the pinctrl, power and clocks for the McASP.

John Syne

unread,
Dec 17, 2015, 7:09:59 PM12/17/15
to beagl...@googlegroups.com
On Dec 17, 2015, at 3:57 PM, William Hermans <yyr...@gmail.com> wrote:

I think he was using McASP, not McSPI ;-)

William Hermans

unread,
Dec 17, 2015, 7:44:20 PM12/17/15
to beagl...@googlegroups.com
Heh ooops. Oh well McASP, McSPI, it's all the same right ? ;) hah

Anyway, theres an mcasp.c file in that same git directory. Looks more complicated.

jutra...@gmail.com

unread,
Jan 21, 2016, 4:52:32 PM1/21/16
to BeagleBoard, jutra...@gmail.com
Thanks for the help everyone, I think I know where to go from here now.
John, I am fairly certain ioremap works with physical addresses. Its declaration is ioremap(phys_addr_t phys_addr, size_t size). I did try 0xFD038000 anyway and it gave the wrong result for the revision number of the McASP.

Charles, after some additional googling, I think you are correct. Because I have the McASP disabled in the device tree, it is turned off and cannot be accessed. I'm not exactly sure how to turn the McASP/clocks on, but will start looking in the TRM.

Robert Nelson

unread,
Jan 21, 2016, 5:00:45 PM1/21/16
to Beagle Board, jutra...@gmail.com
On Thu, Jan 21, 2016 at 3:46 PM, <jutra...@gmail.com> wrote:
> Thanks for the help everyone, I think I know where to go from here now.
> John, I am fairly certain ioremap works with physical addresses. Its
> declaration is ioremap(phys_addr_t phys_addr, size_t size). I did try
> 0xFD038000 anyway and it gave the wrong result for the revision number of
> the McASP.
>
> Charles, after some additional googling, I think you are correct. Because I
> have the McASP disabled in the device tree, it is turned off and cannot be
> accessed. I'm not exactly sure how to turn the McASP/clocks on, but will
> start looking in the TRM.

to turn it on just do:

https://github.com/RobertCNelson/dtb-rebuilder/blob/4.1-ti/src/arm/am33xx-overlay-edma-fix.dtsi#L31-L33

in your custom *.dts

Regards,

--
Robert Nelson
https://rcn-ee.com/

jutra...@gmail.com

unread,
Jan 21, 2016, 5:21:36 PM1/21/16
to BeagleBoard, jutra...@gmail.com
Wont this also cause it to load the sound driver and possibly interfere with its operation? I need exclusive access to the device.

Robert Nelson

unread,
Jan 21, 2016, 5:24:12 PM1/21/16
to Beagle Board, jutra...@gmail.com
On Thu, Jan 21, 2016 at 4:11 PM, <jutra...@gmail.com> wrote:
> Wont this also cause it to load the sound driver and possibly interfere with
> its operation? I need exclusive access to the device.

As long as you don't have the "sound" details in the device tree node..

William Hermans

unread,
Jan 21, 2016, 5:33:34 PM1/21/16
to beagl...@googlegroups.com
It should be possible to enable the device without using device tree though, if that's your wish. I've not done this personally with McASP, but I have manually turned on, and used the on die ADC module in such a manner.

Using device tree sure is easier, but in any case you really need to know the hardware well in order to enable a hardware module *exactly* how *you* want it enabled.  Which is why I suggested( before ) reading the TRM section for the hardware module you need / want to understand.

jutra...@gmail.com

unread,
Jan 21, 2016, 7:56:24 PM1/21/16
to BeagleBoard, jutra...@gmail.com
Changing my device tree overlay to include status="okay" does not seem to be enough to enable me to access that address, whether or not the sound stuff is still around. Note that I am only messing with an overlay. Do I need to change the device tree the board is booted with?

Looking into the source for the davinci-mcasp audio driver that gets loaded by default, there are calls to pm_runtime_get_sync(mcasp->dev) and pm_runtime_put(mcasp->dev), which are probably needed in my code. Next step is to figure out how I am going to get a struct device for the McASP.

Robert Nelson

unread,
Jan 21, 2016, 8:00:34 PM1/21/16
to Beagle Board, Marc Jutras
On Thu, Jan 21, 2016 at 6:14 PM, <jutra...@gmail.com> wrote:
> Changing my device tree overlay to include status="okay" does not seem to be
> enough to enable me to access that address, whether or not the sound stuff
> is still around. Note that I am only messing with an overlay. Do I need to
> change the device tree the board is booted with?

Yeap... It's gotta be in the dtb you boot with..

> Looking into the source for the davinci-mcasp audio driver that gets loaded
> by default, there are calls to pm_runtime_get_sync(mcasp->dev) and
> pm_runtime_put(mcasp->dev), which are probably needed in my code. Next step
> is to figure out how I am going to get a struct device for the McASP.

John Syne

unread,
Jan 21, 2016, 11:32:18 PM1/21/16
to beagl...@googlegroups.com
OK, so lets see if we can get a better understanding of what you need to do because this has been confusing to me also. Read Documentation/bus-virt-phys-mapping.txt and you will see they reference ioremap under PCI Memory access; however, accessing physical memory/registers, they talk about using phys-to-virt(phys_addr). 

Also, in arch/arm/include/asm/io.h, line 328

/*
* ioremap and friends
* ioremap takes a PCI memory address, as specified in 
* Documentation/io-mapping.txt
*/

I also agree with Charles about enabling McASP through the DT, but you also need to make sure you have a codec defined to enable the McASP driver. 

Regards,
John




Reply all
Reply to author
Forward
0 new messages