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.

Word alignment error in Linux PSP with EDMA crossbar code

Other Parts Discussed in Thread: WL1271

When using MMC2 with DMA, I got the following kernel error:

[   60.190765] Alignment trap: not handling instruction f8531022 at [<c0015af8>]
[   60.198242] Unhandled fault: alignment exception (0x001) at 0xf9e10f9d
[   60.205139] Internal error: : 1 [#1]
[   60.208862] Modules linked in: arc4 wl12xx_sdio wl12xx mac80211 cfg80211 rfkill spidev ip_tables x_tables ipv6
[   60.219390] CPU: 0    Not tainted  (3.2.23 #196)
[   60.224273] PC is at map_xbar_event_to_channel+0x4c/0x68
[   60.229827] LR is at map_xbar_event_to_channel+0x39/0x68

This appears to be a problem with the implementation of map_xbar_event_to_channel in:

http://arago-project.org/git/projects/?p=linux-am33x.git;a=commit;f=arch/arm/mach-omap2/devices.c;hb=a7b46224febb00555eba44f0a162d3f774f1eab3

int map_xbar_event_to_channel(unsigned event, unsigned *channel,
798                         struct event_to_channel_map *xbar_event_mapping)
800         unsigned ctrl = 0;
801         unsigned xbar_evt_no = 0;
802         unsigned val = 0;
803         unsigned offset = 0;
804         unsigned mask = 0;
806         ctrl = EDMA_CTLR(event);
807         xbar_evt_no = event - (edma_info[ctrl]->num_channels);
809         if (event < edma_info[ctrl]->num_channels) {
810                 *channel = event;
811         } else if (event < edma_info[ctrl]->num_events) {
812                 *channel = xbar_event_mapping[xbar_evt_no].channel_no;
813                 /* confirm the range */
814                 if (*channel < EDMA_MAX_DMACH)
815                         clear_bit(*channel, edma_info[ctrl]->edma_unused);
816                 mask = (*channel)%4;
817                 offset = (*channel)/4;
818                 offset *= 4;
819                 offset += mask;
820                 val = (unsigned)__raw_readl(AM33XX_CTRL_REGADDR(
821                                         AM33XX_SCM_BASE_EDMA + offset));
822                 val = val & (~(0xFF));
823                 val = val | (xbar_event_mapping[xbar_evt_no].xbar_event_no);
824                 __raw_writel(val,
825                         AM33XX_CTRL_REGADDR(AM33XX_SCM_BASE_EDMA + offset));
826                 return 0;
827         } else {
828                 return -EINVAL;
829         }
831         return 0;
If the mapped channel is odd, then the offset passed to __raw_readl and __raw_writel on lines 820 and 825 will not be on a word-aligned boundary.
I replaced lines 816-825 with this to write the EDMA registers on word boundaries, and this problem went away:

offset = (*channel)/4;

offset *= 4;
val = (unsigned int)__raw_readl(AM33XX_CTRL_REGADDR(
AM33XX_SCM_BASE_EDMA + offset));

mask = ((*channel)%4);
mask *= 8;
val = val & (~((0xFF) << mask));
val = val | (xbar_event_mapping[xbar_evt_no].xbar_event_no << mask);
__raw_writel(val, AM33XX_CTRL_REGADDR(AM33XX_SCM_BASE_EDMA + offset));