经过2天的折腾,u-boot基本上可以用了。不过之前编译的zImage就是不能启动。
之前不清楚,u-boot的代码实际上github上面的不是最新的。
之后使用了官网上的源码,编译之后还是不能启动之前编译的zImage。
所以在这里做一个记录。
代码地址: http://ftp.denx.de/pub/u-boot/u-boot-2014.07.tar.bz2
编译方法按照之前的方法来做。
在启动kernel时候,include/configs/rpi_b.h里默认的启动选项有点复杂,改简单一点:
#define CONFIG_BOOTCOMMAND \
"mmc dev 0;" \
"fatload mmc 0:1 ${kernel_addr_r} zImage;" \
"setenv bootargs dwc_otg.lpm_enable=0 earlyprintk console=ttyAMA0 console=tty1 root=/dev/mmcblk0p2 rootwait;" \
"bootz ${kernel_addr_r};"
在进入u-boot执行boot之后,出现之下的情况:
在kernel中的sdhci有问题不能启动,不过将zImage转成kernel.img是没问题的。
Uncompressing Linux... done, booting the kernel.
[ 0.000000] Booting Linux on physical CPU 0x0
[ 0.000000] Initializing cgroup subsys cpu
[ 0.000000] Initializing cgroup subsys cpuacct
[ 0.000000] Linux version 3.12.26 (debian@debian) (gcc version 4.7.1 20120402 (prerelease) (crosstool-NG 1.15.2) ) #1 PREEMPT Sat Sep 27 10:43:35 CST 2014
[ 0.000000] CPU: ARMv6-compatible processor [410fb767] revision 7 (ARMv7), cr=00c5387d
[ 0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT nonaliasing instruction cache
[ 0.000000] Machine: BCM2708
[ 0.000000] cma: CMA: reserved 8 MiB at 1b800000
[ 0.000000] Memory policy: ECC disabled, Data cache writeback
[ 0.000000] Built 1 zonelists in Zone order, mobility grouping on. Total pages: 113792
[ 0.000000] Kernel command line: dwc_otg.lpm_enable=0 earlyprintk console=ttyAMA0 console=tty1 root=/dev/mmcblk0p2 rootwait
[ 0.000000] PID hash table entries: 2048 (order: 1, 8192 bytes)
[ 0.000000] Dentry cache hash table entries: 65536 (order: 6, 262144 bytes)
[ 0.000000] Inode-cache hash table entries: 32768 (order: 5, 131072 bytes)
[ 0.000000] Memory: 439632K/458752K available (4405K kernel code, 241K rwdata, 1344K rodata, 143K init, 702K bss, 19120K reserved)
[ 0.000000] Virtual kernel memory layout:
[ 0.000000] vector : 0xffff0000 - 0xffff1000 ( 4 kB)
[ 0.000000] fixmap : 0xfff00000 - 0xfffe0000 ( 896 kB)
[ 0.000000] vmalloc : 0xdc800000 - 0xff000000 ( 552 MB)
[ 0.000000] lowmem : 0xc0000000 - 0xdc000000 ( 448 MB)
[ 0.000000] modules : 0xbf000000 - 0xc0000000 ( 16 MB)
[ 0.000000] .text : 0xc0008000 - 0xc05a571c (5750 kB)
[ 0.000000] .init : 0xc05a6000 - 0xc05c9f6c ( 144 kB)
[ 0.000000] .data : 0xc05ca000 - 0xc0606680 ( 242 kB)
[ 0.000000] .bss : 0xc060668c - 0xc06b5eb8 ( 703 kB)
[ 0.000000] SLUB: HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
[ 0.000000] Preemptible hierarchical RCU implementation.
[ 0.000000] NR_IRQS:394
[ 0.000000] sched_clock: 32 bits at 1000kHz, resolution 1000ns, wraps every 4294967ms
[ 0.000000] Switching to timer-based delay loop
[ 0.000000] Console: colour dummy device 80x30
[ 0.000000] console [tty1] enabled
[ 0.001191] Calibrating delay loop (skipped), value calculated using timer frequency.. 2.00 BogoMIPS (lpj=10000)
[ 0.001253] pid_max: default: 32768 minimum: 301
[ 0.001749] Mount-cache hash table entries: 512
[ 0.002596] Initializing cgroup subsys memory
[ 0.002710] Initializing cgroup subsys devices
[ 0.002751] Initializing cgroup subsys freezer
[ 0.002785] Initializing cgroup subsys blkio
[ 0.002934] CPU: Testing write buffer coherency: ok
[ 0.003415] Setting up static identity map for 0xc042ee18 - 0xc042ee74
[ 0.005365] devtmpfs: initialized
[ 0.021698] VFP support v0.3: implementor 41 architecture 1 part 20 variant b rev 5
[ 0.023302] NET: Registered protocol family 16
[ 0.028552] DMA: preallocated 4096 KiB pool for atomic coherent allocations
[ 0.029231] cpuidle: using governor ladder
[ 0.029279] cpuidle: using governor menu
[ 0.029556] bcm2708.uart_clock = 0
[ 0.031588] hw-breakpoint: found 6 breakpoint and 1 watchpoint registers.
[ 0.031653] hw-breakpoint: maximum watchpoint size is 4 bytes.
[ 0.031689] mailbox: Broadcom VideoCore Mailbox driver
[ 0.031791] bcm2708_vcio: mailbox at f200b880
[ 0.031898] bcm_power: Broadcom power driver
[ 0.031937] bcm_power_open() -> 0
[ 0.031964] bcm_power_request(0, 8)
[ 0.532251] bcm_mailbox_read -> 00000080, 0
[ 0.532293] bcm_power_request -> 0
[ 0.532527] Serial: AMBA PL011 UART driver
[ 0.532702] dev:f1: ttyAMA0 at MMIO 0x20201000 (irq = 83, base_baud = 0) is a PL011 rev3
[ 0.863803] console [ttyAMA0] enabled
[ 0.890208] bio: create slab at 0
[ 0.895759] SCSI subsystem initialized
[ 0.899761] usbcore: registered new interface driver usbfs
[ 0.905480] usbcore: registered new interface driver hub
[ 0.911049] usbcore: registered new device driver usb
[ 0.917494] Switched to clocksource stc
[ 0.921758] FS-Cache: Loaded
[ 0.924921] CacheFiles: Loaded
[ 0.940795] NET: Registered protocol family 2
[ 0.946318] TCP established hash table entries: 4096 (order: 3, 32768 bytes)
[ 0.953732] TCP bind hash table entries: 4096 (order: 2, 16384 bytes)
[ 0.960306] TCP: Hash tables configured (established 4096 bind 4096)
[ 0.966756] TCP: reno registered
[ 0.970053] UDP hash table entries: 256 (order: 0, 4096 bytes)
[ 0.975926] UDP-Lite hash table entries: 256 (order: 0, 4096 bytes)
[ 0.982692] NET: Registered protocol family 1
[ 0.987709] RPC: Registered named UNIX socket transport module.
[ 0.993672] RPC: Registered udp transport module.
[ 0.998471] RPC: Registered tcp transport module.
[ 1.003196] RPC: Registered tcp NFSv4.1 backchannel transport module.
[ 1.010419] bcm2708_dma: DMA manager at f2007000
[ 1.015164] bcm2708_gpio: bcm2708_gpio_probe c05d7ed0
[ 1.020739] vc-mem: phys_addr:0x00000000 mem_base=0x00000000 mem_size:0x00000000(0 MiB)
[ 1.030143] audit: initializing netlink socket (disabled)
[ 1.035649] type=2000 audit(0.910:1): initialized
[ 1.203128] VFS: Disk quotas dquot_6.5.2
[ 1.207403] Dquot-cache hash table entries: 1024 (order 0, 4096 bytes)
[ 1.216410] FS-Cache: Netfs 'nfs' registered for caching
[ 1.223370] NFS: Registering the id_resolver key type
[ 1.228666] Key type id_resolver registered
[ 1.232874] Key type id_legacy registered
[ 1.237715] msgmni has been set to 874
[ 1.243470] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 252)
[ 1.251334] io scheduler noop registered
[ 1.255292] io scheduler deadline registered
[ 1.260010] io scheduler cfq registered (default)
[ 1.265974] BCM2708FB: allocated DMA memory 5bc00000
[ 1.271160] BCM2708FB: allocated DMA channel 4 @ f2007400
[ 1.281860] Console: switching to colour frame buffer device 100x30
[ 1.293095] uart-pl011 dev:f1: no DMA platform data
[ 1.300415] vc-cma: Videocore CMA driver
[ 1.305998] vc-cma: vc_cma_base = 0x00000000
[ 1.312413] vc-cma: vc_cma_size = 0x00000000 (0 MiB)
[ 1.319493] vc-cma: vc_cma_initial = 0x00000000 (0 MiB)
[ 1.335809] brd: module loaded
[ 1.345782] loop: module loaded
[ 1.350795] vchiq: vchiq_init_state: slot_zero = 0xdb800000, is_master = 0
[ 1.360258] Loading iSCSI transport class v2.0-870.
[ 1.367987] usbcore: registered new interface driver smsc95xx
[ 1.375739] dwc_otg: version 3.00a 10-AUG-2012 (platform bus)
[ 1.583297] Core Release: 2.80a
[ 1.588061] Setting default values for core params
[ 1.594370] Finished setting default values for core params
[ 1.801523] Using Buffer DMA mode
[ 1.806378] Periodic Transfer Interrupt Enhancement - disabled
[ 1.813781] Multiprocessor Interrupt Enhancement - disabled
[ 1.820917] OTG VER PARAM: 0, OTG VER FLAG: 0
[ 1.826752] Dedicated Tx FIFOs mode
[ 1.832064] WARN::dwc_otg_hcd_init:1042: FIQ DMA bounce buffers: virt = 0xdbc14000 dma = 0x5bc14000 len=9024
[ 1.845131] FIQ FSM acceleration enabled for :
[ 1.845131] Non-periodic Split Transactions
[ 1.845131] Periodic Split Transactions
[ 1.845131] High-Speed Isochronous Endpoints
[ 1.868307] WARN::hcd_init:473: FIQ at 0xc030ef44
[ 1.874613] WARN::hcd_init:474: FIQ ASM at 0xc030f1c0 length 36
[ 1.882170] WARN::hcd_init:500: MPHI regs_base at 0xdc806000
[ 1.889500] dwc_otg bcm2708_usb: DWC OTG Controller
[ 1.896069] dwc_otg bcm2708_usb: new USB bus registered, assigned bus number 1
[ 1.905065] dwc_otg bcm2708_usb: irq 32, io mem 0x00000000
[ 1.912311] Init: Port Power? op_state=1
[ 1.917913] Init: Power Port (0)
[ 1.923012] usb usb1: New USB device found, idVendor=1d6b, idProduct=0002
[ 1.931518] usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1
[ 1.940436] usb usb1: Product: DWC OTG Controller
[ 1.946764] usb usb1: Manufacturer: Linux 3.12.26 dwc_otg_hcd
[ 1.954169] usb usb1: SerialNumber: bcm2708_usb
[ 1.961211] hub 1-0:1.0: USB hub found
[ 1.966667] hub 1-0:1.0: 1 port detected
[ 1.973198] usbcore: registered new interface driver usb-storage
[ 1.981333] mousedev: PS/2 mouse device common for all mice
[ 1.989331] bcm2835-cpufreq: min=700000 max=700000 cur=700000
[ 1.996831] bcm2835-cpufreq: switching to governor powersave
[ 2.004153] bcm2835-cpufreq: switching to governor powersave
[ 2.011401] sdhci: Secure Digital Host Controller Interface driver
[ 2.019096] sdhci: Copyright(c) Pierre Ossman
[ 2.025014] sdhci: Enable low-latency mode
[ 2.030754] bcm2708_sdhci bcm2708_sdhci.0: couldn't allocate a DMA channel
[ 2.039273] bcm2708_sdhci bcm2708_sdhci.0: probe failed, err -12
[ 2.046814] bcm2708_sdhci: probe of bcm2708_sdhci.0 failed with error -12
[ 2.055247] sdhci-pltfm: SDHCI platform and OF driver helper
[ 2.062587] ledtrig-cpu: registered to indicate activity on CPUs
[ 2.070557] hidraw: raw HID events driver (C) Jiri Kosina
[ 2.077830] usbcore: registered new interface driver usbhid
[ 2.084970] usbhid: USB HID core driver
[ 2.090882] TCP: cubic registered
[ 2.095761] Initializing XFRM netlink socket
[ 2.101625] NET: Registered protocol family 17
[ 2.107788] Key type dns_resolver registered
[ 2.114574] registered taskstats version 1
[ 2.120305] vc-sm: Videocore shared memory driver
[ 2.126500] [vc_sm_connected_init]: start
[ 2.132918] [vc_sm_connected_init]: end - returning 0
[ 2.140681] Waiting for root device /dev/mmcblk0p2...
[ 2.167709] Indeed it is in host mode hprt0 = 00021501
[ 2.347624] usb 1-1: new high-speed USB device number 2 using dwc_otg
[ 2.355791] Indeed it is in host mode hprt0 = 00001101
[ 2.557909] usb 1-1: New USB device found, idVendor=0424, idProduct=9514
[ 2.566304] usb 1-1: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[ 2.575993] hub 1-1:1.0: USB hub found
[ 2.581643] hub 1-1:1.0: 5 ports detected
[ 2.867721] usb 1-1.1: new high-speed USB device number 3 using dwc_otg
[ 2.987909] usb 1-1.1: New USB device found, idVendor=0424, idProduct=ec00
[ 2.996460] usb 1-1.1: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[ 3.008314] smsc95xx v1.0.4
[ 3.071254] smsc95xx 1-1.1:1.0 eth0: register 'smsc95xx' at usb-bcm2708_usb-1.1, smsc95xx USB 2.0 Ethernet, e2:ab:f7:8d:98:c9
[ 3.177655] usb 1-1.3: new high-speed USB device number 4 using dwc_otg
[ 3.299183] usb 1-1.3: New USB device found, idVendor=0bda, idProduct=8176
[ 3.307930] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 3.317080] usb 1-1.3: Manufacturer: Realtek
[ 3.323137] usb 1-1.3: SerialNumber: 00e04c000001
[ 3.567730] usb 1-1.5: new full-speed USB device number 5 using dwc_otg
[ 3.691209] usb 1-1.5: New USB device found, idVendor=1d57, idProduct=5a66
[ 3.700009] usb 1-1.5: New USB device strings: Mfr=0, Product=2, SerialNumber=0
[ 3.709173] usb 1-1.5: Product: 2.4G Receiver
[ 3.731831] input: 2.4G Receiver as /devices/platform/bcm2708_usb/usb1/1-1/1-1.5/1-1.5:1.0/input/input0
[ 3.746148] hid-generic 0003:1D57:5A66.0001: input,hiddev0,hidraw0: USB HID v1.10 Mouse [2.4G Receiver] on usb-bcm2708_usb-1.5/input0
[ 3.770481] input: 2.4G Receiver as /devices/platform/bcm2708_usb/usb1/1-1/1-1.5/1-1.5:1.1/input/input1
[ 3.784566] hid-generic 0003:1D57:5A66.0002: input,hidraw1: USB HID v1.10 Keyboard [2.4G Receiver] on usb-bcm2708_usb-1.5/input1
这个问题在以下几个文件有做改动:
文件地址: http://people.freebsd.org/~gonzo/arm/patches/rpi-sdhci.diff
Index: dev/mmc/mmc.c
===================================================================
--- dev/mmc/mmc.c (revision 246573)
+++ dev/mmc/mmc.c (working copy)
@@ -578,6 +578,8 @@
mmcbr_update_ios(dev);
mmc_ms_delay(1);
+ printf("mmcbr_set_clock %d == %d\n", __LINE__,
+ mmcbr_get_f_min(sc->dev));
mmcbr_set_clock(dev, mmcbr_get_f_min(sc->dev));
mmcbr_set_timing(dev, bus_timing_normal);
mmcbr_set_power_mode(dev, power_on);
@@ -651,6 +653,8 @@
data.flags = MMC_DATA_READ;
err = mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES);
+ if (err != MMC_ERR_NONE)
+ device_printf(sc->dev, "SWITCH command failed\n");
return (err);
}
@@ -1067,7 +1071,8 @@
cmd.flags = MMC_RSP_R2 | MMC_CMD_BCR;
cmd.data = NULL;
err = mmc_wait_for_cmd(sc, &cmd, 0);
- memcpy(rawcsd, cmd.resp, 4 * sizeof(uint32_t));
+ if (err == MMC_ERR_NONE)
+ memcpy(rawcsd, cmd.resp, 4 * sizeof(uint32_t));
return (err);
}
@@ -1092,8 +1097,11 @@
data.flags = MMC_DATA_READ;
err = mmc_wait_for_app_cmd(sc, rca, &cmd, CMD_RETRIES);
- rawscr[0] = be32toh(rawscr[0]);
- rawscr[1] = be32toh(rawscr[1]);
+ if (err == MMC_ERR_NONE) {
+ rawscr[0] = be32toh(rawscr[0]);
+ rawscr[1] = be32toh(rawscr[1]);
+ }
+
return (err);
}
@@ -1274,7 +1282,11 @@
mmc_send_relative_addr(sc, &resp);
ivar->rca = resp >> 16;
/* Get card CSD. */
- mmc_send_csd(sc, ivar->rca, ivar->raw_csd);
+ err = mmc_send_csd(sc, ivar->rca, ivar->raw_csd);
+ if (err != MMC_ERR_NONE) {
+ device_printf(sc->dev, "Error reading CSD %d\n", err);
+ break;
+ }
if (bootverbose || mmc_debug)
device_printf(sc->dev,
"%sard detected (CSD %08x%08x%08x%08x)\n",
@@ -1303,7 +1315,13 @@
/* Get card SCR. Card must be selected to fetch it. */
mmc_select_card(sc, ivar->rca);
- mmc_app_send_scr(sc, ivar->rca, ivar->raw_scr);
+ err = mmc_app_send_scr(sc, ivar->rca, ivar->raw_scr);
+ if (err != MMC_ERR_NONE) {
+ device_printf(sc->dev,
+ "Error reading card SCR %d\n", err);
+ break;
+ }
+
mmc_app_decode_scr(ivar->raw_scr, &ivar->scr);
/* Get card switch capabilities (command class 10). */
if ((ivar->scr.sda_vsn >= 1) &&
@@ -1357,7 +1375,11 @@
ivar->rca = rca++;
mmc_set_relative_addr(sc, ivar->rca);
/* Get card CSD. */
- mmc_send_csd(sc, ivar->rca, ivar->raw_csd);
+ err = mmc_send_csd(sc, ivar->rca, ivar->raw_csd);
+ if (err != MMC_ERR_NONE) {
+ device_printf(sc->dev, "Error reading CSD %d\n", err);
+ break;
+ }
if (bootverbose || mmc_debug)
device_printf(sc->dev,
"%sard detected (CSD %08x%08x%08x%08x)\n",
@@ -1533,6 +1555,8 @@
mmc_idle_cards(sc);
} else {
mmcbr_set_bus_mode(dev, opendrain);
+ printf("mmcbr_set_clock %d == %d\n", __LINE__,
+ mmcbr_get_f_min(dev));
mmcbr_set_clock(dev, mmcbr_get_f_min(dev));
mmcbr_update_ios(dev);
/* XXX recompute vdd based on new cards? */
@@ -1604,7 +1628,7 @@
free(kids, M_TEMP);
if (max_timing == bus_timing_hs)
max_dtr = max_hs_dtr;
- if (bootverbose || mmc_debug) {
+ if (1) {
device_printf(sc->dev,
"setting transfer rate to %d.%03dMHz%s\n",
max_dtr / 1000000, (max_dtr / 1000) % 1000,
Index: dev/sdhci/sdhci.h
===================================================================
--- dev/sdhci/sdhci.h (revision 246573)
+++ dev/sdhci/sdhci.h (working copy)
@@ -266,5 +266,6 @@
int sdhci_generic_acquire_host(device_t brdev, device_t reqdev);
int sdhci_generic_release_host(device_t brdev, device_t reqdev);
void sdhci_generic_intr(struct sdhci_slot *slot);
+uint32_t sdhci_generic_min_freq(device_t brdev, struct sdhci_slot *slot);
#endif /* __SDHCI_H__ */
Index: dev/sdhci/sdhci_if.m
===================================================================
--- dev/sdhci/sdhci_if.m (revision 246573)
+++ dev/sdhci/sdhci_if.m (working copy)
@@ -58,7 +58,18 @@
# that mmc/sd card drivers call to make requests.
#
+#include
+#include
+#include
+#include
+#include
+
#include
+
+#include
+#include
+#include
+
CODE {
struct sdhci_slot;
}
@@ -119,3 +130,8 @@
uint32_t *data;
bus_size_t count;
}
+
+METHOD uint32_t min_freq {
+ device_t brdev;
+ struct sdhci_slot *slot;
+} DEFAULT sdhci_generic_min_freq;
Index: dev/sdhci/sdhci.c
===================================================================
--- dev/sdhci/sdhci.c (revision 246573)
+++ dev/sdhci/sdhci.c (working copy)
@@ -65,7 +65,7 @@
static SYSCTL_NODE(_hw, OID_AUTO, sdhci, CTLFLAG_RD, 0, "sdhci driver");
-int sdhci_debug = 0;
+int sdhci_debug = 1;
TUNABLE_INT("hw.sdhci.debug", &sdhci_debug);
SYSCTL_INT(_hw_sdhci, OID_AUTO, debug, CTLFLAG_RW, &sdhci_debug, 0, "Debug level");
@@ -98,6 +98,9 @@
#define SDHCI_DEFAULT_MAX_FREQ 50
+#define SDHCI_200_MAX_DIVIDER 256
+#define SDHCI_300_MAX_DIVIDER 2046
+
static void
sdhci_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
{
@@ -238,7 +241,7 @@
if (slot->version < SDHCI_SPEC_300) {
/* Looking for highest freq <= clock. */
res = slot->max_clk;
- for (div = 1; div < 256; div <<= 1) {
+ for (div = 1; div < SDHCI_200_MAX_DIVIDER; div <<= 1) {
if (res <= clock)
break;
res >>= 1;
@@ -248,10 +251,10 @@
}
else {
/* Version 3.0 divisors are multiples of two up to 1023*2 */
- if (clock > slot->max_clk)
- div = 2;
+ if (clock >= slot->max_clk)
+ div = 0;
else {
- for (div = 2; div < 1023*2; div += 2) {
+ for (div = 2; div < SDHCI_300_MAX_DIVIDER; div += 2) {
if ((slot->max_clk / div) <= clock)
break;
}
@@ -545,7 +548,7 @@
"frequency.\n");
}
- slot->host.f_min = slot->max_clk / 256;
+ slot->host.f_min = SDHCI_MIN_FREQ(slot->bus, slot);
slot->host.f_max = slot->max_clk;
slot->host.host_ocr = 0;
if (caps & SDHCI_CAN_VDD_330)
@@ -635,6 +638,15 @@
return (0);
}
+uint32_t
+sdhci_generic_min_freq(device_t brdev, struct sdhci_slot *slot)
+{
+ if (slot->version >= SDHCI_SPEC_300)
+ return (slot->max_clk / SDHCI_300_MAX_DIVIDER);
+ else
+ return (slot->max_clk / SDHCI_200_MAX_DIVIDER);
+}
+
int
sdhci_generic_update_ios(device_t brdev, device_t reqdev)
{
@@ -1078,8 +1090,12 @@
}
if (intmask & SDHCI_INT_DATA_TIMEOUT)
slot->curcmd->error = MMC_ERR_TIMEOUT;
- else if (intmask & (SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_END_BIT))
+ else if (intmask & (SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_END_BIT)) {
+ if (intmask & SDHCI_INT_DATA_CRC) {
+ panic("DATA CRC error\n");
+ }
slot->curcmd->error = MMC_ERR_BADCRC;
+ }
if (slot->curcmd->data == NULL &&
(intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL |
SDHCI_INT_DMA_END))) {
@@ -1299,14 +1315,30 @@
break;
case MMCBR_IVAR_CLOCK:
if (value > 0) {
- uint32_t clock = slot->max_clk;
+ uint32_t max_clock;
+ uint32_t clock;
int i;
- for (i = 0; i < 8; i++) {
- if (clock <= value)
- break;
- clock >>= 1;
+ max_clock = slot->max_clk;
+ clock = max_clock;
+
+ if (slot->version < SDHCI_SPEC_300) {
+ for (i = 0; i < SDHCI_200_MAX_DIVIDER;
+ i <<= 1) {
+ if (clock <= value)
+ break;
+ clock >>= 1;
+ }
}
+ else {
+ for (i = 0; i < SDHCI_300_MAX_DIVIDER;
+ i += 2) {
+ if (clock <= value)
+ break;
+ clock = max_clock / (i + 2);
+ }
+ }
+
slot->host.ios.clock = clock;
} else
slot->host.ios.clock = 0;
Index: arm/broadcom/bcm2835/bcm2835_sdhci.c
===================================================================
--- arm/broadcom/bcm2835/bcm2835_sdhci.c (revision 246573)
+++ arm/broadcom/bcm2835/bcm2835_sdhci.c (working copy)
@@ -334,6 +334,18 @@
bus_space_write_multi_4(sc->sc_bst, sc->sc_bsh, off, data, count);
}
+static uint32_t
+bcm_sdhci_min_freq(device_t dev, struct sdhci_slot *slot)
+{
+
+ /*
+ * Arasan HC seems to have problem with
+ * Data CRC on lower frequencies. Cap minimum
+ * frequncy at 8MHz to work around this issue
+ */
+ return (8*1000*1000);
+}
+
static device_method_t bcm_sdhci_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, bcm_sdhci_probe),
@@ -353,6 +365,7 @@
DEVMETHOD(mmcbr_release_host, sdhci_generic_release_host),
/* SDHCI registers accessors */
+ DEVMETHOD(sdhci_min_freq, bcm_sdhci_min_freq),
DEVMETHOD(sdhci_read_1, bcm_sdhci_read_1),
DEVMETHOD(sdhci_read_2, bcm_sdhci_read_2),
DEVMETHOD(sdhci_read_4, bcm_sdhci_read_4),
@@ -375,3 +388,4 @@
DRIVER_MODULE(sdhci_bcm, simplebus, bcm_sdhci_driver, bcm_sdhci_devclass, 0, 0);
MODULE_DEPEND(sdhci_bcm, sdhci, 1, 1, 1);
+MODULE_DEPEND(sdhci_bcm, mbox, 1, 1, 1);
下一个文件: http://people.freebsd.org/~gonzo/arm/patches/rpi_dma.diff
Index: boot/fdt/dts/bcm2835-rpi-b.dts
===================================================================
--- boot/fdt/dts/bcm2835-rpi-b.dts (revision 245119)
+++ boot/fdt/dts/bcm2835-rpi-b.dts (working copy)
@@ -98,10 +98,7 @@
dma: dma {
compatible = "broadcom,bcm2835-dma", "broadcom,bcm2708-dma";
reg = <0x7000 0x1000>, <0xE05000 0x1000>;
- interrupts = <
- 26 /* 2 */
- 27 /* 3 */
- >;
+ interrupts = <24 25 26 27 28 29 30 31 32 33 34 35 36>;
interrupt-parent = <&intc>;
broadcom,channels = <0>; /* Set by VideoCore */
Index: dev/fdt/fdt_common.h
===================================================================
--- dev/fdt/fdt_common.h (revision 245119)
+++ dev/fdt/fdt_common.h (working copy)
@@ -39,7 +39,7 @@
#define FDT_MEM_REGIONS 8
-#define DI_MAX_INTR_NUM 8
+#define DI_MAX_INTR_NUM 16
struct fdt_pci_range {
u_long base_pci;
Index: arm/broadcom/bcm2835/files.bcm2835
===================================================================
--- arm/broadcom/bcm2835/files.bcm2835 (revision 245119)
+++ arm/broadcom/bcm2835/files.bcm2835 (working copy)
@@ -1,5 +1,6 @@
# $FreeBSD$
+arm/broadcom/bcm2835/bcm2835_dma.c standard
arm/broadcom/bcm2835/bcm2835_fb.c optional sc
arm/broadcom/bcm2835/bcm2835_gpio.c optional gpio
arm/broadcom/bcm2835/bcm2835_intr.c standard
Index: arm/broadcom/bcm2835/bcm2835_dma.c
===================================================================
--- arm/broadcom/bcm2835/bcm2835_dma.c (revision 0)
+++ arm/broadcom/bcm2835/bcm2835_dma.c (working copy)
@@ -0,0 +1,625 @@
+/*
+ * Copyright (c) 2013 Daisuke Aoyama
+ * Copyright (c) 2013 Oleksandr Tymoshenko
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include
+__FBSDID("$FreeBSD$");
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "bcm2835_dma.h"
+#include "bcm2835_vcbus.h"
+
+#define MAX_REG 9
+
+/* private flags */
+#define BCM_DMA_CH_USED 0x00000001
+#define BCM_DMA_CH_FREE 0x40000000
+#define BCM_DMA_CH_UNMAP 0x80000000
+
+/* Register Map (4.2.1.2) */
+#define BCM_DMA_CS(n) (0x100*(n) + 0x00)
+#define CS_ACTIVE (1 << 0)
+#define CS_END (1 << 1)
+#define CS_INT (1 << 2)
+#define CS_DREQ (1 << 3)
+#define CS_ISPAUSED (1 << 4)
+#define CS_ISHELD (1 << 5)
+#define CS_ISWAIT (1 << 6)
+#define CS_ERR (1 << 8)
+#define CS_WAITWRT (1 << 28)
+#define CS_DISDBG (1 << 29)
+#define CS_ABORT (1 << 30)
+#define CS_RESET (1 << 31)
+#define BCM_DMA_CBADDR(n) (0x100*(n) + 0x04)
+#define BCM_DMA_INFO(n) (0x100*(n) + 0x08)
+#define INFO_INT_EN (1 << 0)
+#define INFO_TDMODE (1 << 1)
+#define INFO_WAIT_RESP (1 << 3)
+#define INFO_D_INC (1 << 4)
+#define INFO_D_WIDTH (1 << 5)
+#define INFO_D_DREQ (1 << 6)
+#define INFO_S_INC (1 << 8)
+#define INFO_S_WIDTH (1 << 9)
+#define INFO_S_DREQ (1 << 10)
+#define INFO_WAITS_SHIFT (21)
+#define INFO_PERMAP_SHIFT (16)
+#define INFO_PERMAP_MASK (0x1f << INFO_PERMAP_SHIFT)
+
+#define BCM_DMA_SRC(n) (0x100*(n) + 0x0C)
+#define BCM_DMA_DST(n) (0x100*(n) + 0x10)
+#define BCM_DMA_LEN(n) (0x100*(n) + 0x14)
+#define BCM_DMA_STRIDE(n) (0x100*(n) + 0x18)
+#define BCM_DMA_CBNEXT(n) (0x100*(n) + 0x1C)
+#define BCM_DMA_DEBUG(n) (0x100*(n) + 0x20)
+#define DEBUG_ERROR_MASK (7)
+
+#define BCM_DMA_INT_STATUS 0xfe0
+#define BCM_DMA_ENABLE 0xff0
+
+/* relative offset from BCM_VC_DMA0_BASE (p.39) */
+#define BCM_DMA_CH(n) (0x100*(n))
+
+/* DMA Control Block - 256bit aligned (p.40) */
+struct bcm_dma_cb {
+ uint32_t info; /* Transfer Information */
+ uint32_t src; /* Source Address */
+ uint32_t dst; /* Destination Address */
+ uint32_t len; /* Transfer Length */
+ uint32_t stride; /* 2D Mode Stride */
+ uint32_t next; /* Next Control Block Address */
+ uint32_t rsvd1; /* Reserved */
+ uint32_t rsvd2; /* Reserved */
+};
+
+#ifdef DEBUG
+static void bcm_dma_cb_dump(struct bcm_dma_cb *cb);
+static void bcm_dma_reg_dump(int ch);
+#endif
+
+/* DMA channel private info */
+struct bcm_dma_ch {
+ int ch;
+ uint32_t flags;
+ struct bcm_dma_cb * cb;
+ uint32_t vc_cb;
+ bus_dmamap_t dma_map;
+ void (*intr_func)(int, void *);
+ void * intr_arg;
+};
+
+struct bcm_dma_softc {
+ device_t sc_dev;
+ struct mtx sc_mtx;
+ struct resource * sc_mem;
+ struct resource * sc_irq[BCM_DMA_CH_MAX];
+ void * sc_intrhand[BCM_DMA_CH_MAX];
+ struct bcm_dma_ch sc_dma_ch[BCM_DMA_CH_MAX];
+ bus_dma_tag_t sc_dma_tag;
+};
+
+static struct bcm_dma_softc *bcm_dma_sc = NULL;
+
+static void
+bcm_dmamap_cb(void *arg, bus_dma_segment_t *segs,
+ int nseg, int err)
+{
+ bus_addr_t *addr;
+
+ if (err)
+ return;
+
+ addr = (bus_addr_t*)arg;
+ *addr = PHYS_TO_VCBUS(segs[0].ds_addr);
+}
+
+static void
+bcm_dma_reset(device_t dev, int ch)
+{
+ struct bcm_dma_softc *sc = device_get_softc(dev);
+ struct bcm_dma_cb *cb;
+ uint32_t cs;
+ int count;
+
+ if (ch < 0 || ch >= BCM_DMA_CH_MAX)
+ return;
+
+ cs = bus_read_4(sc->sc_mem, BCM_DMA_CS(ch));
+
+ if (cs & CS_ACTIVE) {
+ /* pause current task */
+ bus_write_4(sc->sc_mem, BCM_DMA_CS(ch), 0);
+
+ count = 1000;
+ do {
+ cs = bus_read_4(sc->sc_mem, BCM_DMA_CS(ch));
+ } while (!(cs & CS_ISPAUSED) && (count-- > 0));
+
+ if (!(cs & CS_ISPAUSED)) {
+ device_printf(dev,
+ "Can't abort DMA transfer at channel %d\n", ch);
+ }
+
+ bus_write_4(sc->sc_mem, BCM_DMA_CBNEXT(ch), 0);
+
+ /* Complete everything, clear interrupt */
+ bus_write_4(sc->sc_mem, BCM_DMA_CS(ch),
+ CS_ABORT | CS_INT | CS_END| CS_ACTIVE);
+ }
+
+ /* clear control blocks */
+ bus_write_4(sc->sc_mem, BCM_DMA_CBADDR(ch), 0);
+ bus_write_4(sc->sc_mem, BCM_DMA_CBNEXT(ch), 0);
+
+ /* Reset control block */
+ cb = sc->sc_dma_ch[ch].cb;
+ bzero(cb, sizeof(cb));
+}
+
+static int
+bcm_dma_init(device_t dev)
+{
+ struct bcm_dma_softc *sc = device_get_softc(dev);
+ uint32_t mask;
+ struct bcm_dma_ch *ch;
+ void *cb_virt;
+ vm_paddr_t cb_phys;
+ int err;
+ int i;
+
+ /* disable and clear interrupt status */
+ bus_write_4(sc->sc_mem, BCM_DMA_ENABLE, 0);
+ bus_write_4(sc->sc_mem, BCM_DMA_INT_STATUS, 0);
+
+ /* Allocate DMA chunks contorl blocks */
+ /* p.40 of spec - control block should be 32-bit aligned */
+ err = bus_dma_tag_create(bus_get_dma_tag(dev),
+ 32, 0, BUS_SPACE_MAXADDR_32BIT,
+ BUS_SPACE_MAXADDR, NULL, NULL,
+ sizeof(struct bcm_dma_cb), 1,
+ sizeof(struct bcm_dma_cb),
+ BUS_DMA_ALLOCNOW, NULL, NULL,
+ &sc->sc_dma_tag);
+
+ if (err) {
+ device_printf(dev, "failed allocate DMA tag");
+ return (err);
+ }
+
+ /* setup initial settings */
+ for (i = 0; i < BCM_DMA_CH_MAX; i++) {
+ ch = &sc->sc_dma_ch[i];
+
+ err = bus_dmamem_alloc(sc->sc_dma_tag, &cb_virt,
+ BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO,
+ &ch->dma_map);
+ if (err) {
+ device_printf(dev, "cannot allocate DMA memory\n");
+ break;
+ }
+
+ err = bus_dmamap_load(sc->sc_dma_tag, ch->dma_map, cb_virt,
+ sizeof(struct bcm_dma_cb), bcm_dmamap_cb, &cb_phys,
+ BUS_DMA_WAITOK);
+ if (err) {
+ device_printf(dev, "cannot load DMA memory\n");
+ break;
+ }
+
+ bzero(ch, sizeof(struct bcm_dma_ch));
+ ch->ch = i;
+ ch->cb = cb_virt;
+ ch->vc_cb = cb_phys;
+ ch->intr_func = NULL;
+ ch->intr_arg = NULL;
+ ch->flags = BCM_DMA_CH_UNMAP;
+
+ /* reset DMA engine */
+ bcm_dma_reset(dev, i);
+ }
+
+ /* now use DMA2/DMA3 only */
+ sc->sc_dma_ch[2].flags = BCM_DMA_CH_FREE;
+ sc->sc_dma_ch[3].flags = BCM_DMA_CH_FREE;
+
+ /* enable DMAs */
+ mask = 0;
+
+ for (i = 0; i < BCM_DMA_CH_MAX; i++)
+ if (sc->sc_dma_ch[i].flags & BCM_DMA_CH_FREE)
+ mask |= (1 << i);
+
+ bus_write_4(sc->sc_mem, BCM_DMA_ENABLE, mask);
+
+ return (0);
+}
+
+int
+bcm_dma_allocate(int req_ch)
+{
+ struct bcm_dma_softc *sc = bcm_dma_sc;
+ int ch = -1;
+ int i;
+
+ if (req_ch >= BCM_DMA_CH_MAX)
+ return (-1);
+
+ /* Auto(req_ch < 0) or CH specified */
+ mtx_lock(&sc->sc_mtx);
+
+ if (req_ch < 0) {
+ for (i = 0; i < BCM_DMA_CH_MAX; i++) {
+ if (sc->sc_dma_ch[i].flags & BCM_DMA_CH_FREE) {
+ ch = i;
+ sc->sc_dma_ch[ch].flags &= ~BCM_DMA_CH_FREE;
+ sc->sc_dma_ch[ch].flags |= BCM_DMA_CH_USED;
+ break;
+ }
+ }
+ }
+ else {
+ if (sc->sc_dma_ch[req_ch].flags & BCM_DMA_CH_FREE) {
+ ch = req_ch;
+ sc->sc_dma_ch[ch].flags &= ~BCM_DMA_CH_FREE;
+ sc->sc_dma_ch[ch].flags |= BCM_DMA_CH_USED;
+ }
+ }
+
+ mtx_unlock(&sc->sc_mtx);
+ return (ch);
+}
+
+int
+bcm_dma_free(int ch)
+{
+ struct bcm_dma_softc *sc = bcm_dma_sc;
+
+ if (ch < 0 || ch >= BCM_DMA_CH_MAX)
+ return (-1);
+
+ mtx_lock(&sc->sc_mtx);
+ if (sc->sc_dma_ch[ch].flags & BCM_DMA_CH_USED) {
+ sc->sc_dma_ch[ch].flags |= BCM_DMA_CH_FREE;
+ sc->sc_dma_ch[ch].flags &= ~BCM_DMA_CH_USED;
+ sc->sc_dma_ch[ch].intr_func = NULL;
+ sc->sc_dma_ch[ch].intr_arg = NULL;
+
+ /* reset DMA engine */
+ bcm_dma_reset(sc->sc_dev, ch);
+ }
+
+ mtx_unlock(&sc->sc_mtx);
+ return (0);
+}
+
+int
+bcm_dma_setup_intr(int ch, void (*func)(int, void *), void *arg)
+{
+ struct bcm_dma_softc *sc = bcm_dma_sc;
+ struct bcm_dma_cb *cb;
+
+ if (ch < 0 || ch >= BCM_DMA_CH_MAX)
+ return (-1);
+
+ if (!(sc->sc_dma_ch[ch].flags & BCM_DMA_CH_USED))
+ return (-1);
+
+ sc->sc_dma_ch[ch].intr_func = func;
+ sc->sc_dma_ch[ch].intr_arg = arg;
+ cb = sc->sc_dma_ch[ch].cb;
+ cb->info |= INFO_INT_EN;
+
+ return (0);
+}
+
+int
+bcm_dma_setup_src(int ch, int dreq, int increase_addr)
+{
+ struct bcm_dma_softc *sc = bcm_dma_sc;
+ uint32_t info;
+
+ if (ch < 0 || ch >= BCM_DMA_CH_MAX)
+ return (-1);
+
+ if (!(sc->sc_dma_ch[ch].flags & BCM_DMA_CH_USED))
+ return (-1);
+
+ info = sc->sc_dma_ch[ch].cb->info;
+ info &= ~INFO_PERMAP_MASK;
+ info &= ~INFO_S_DREQ;
+ info |= (dreq << INFO_PERMAP_SHIFT) & INFO_PERMAP_MASK;
+ if (dreq)
+ info |= INFO_S_DREQ;
+
+ if (increase_addr)
+ info |= INFO_S_INC;
+ else
+ info &= ~INFO_S_INC;
+
+ sc->sc_dma_ch[ch].cb->info = info;
+
+ return (0);
+}
+
+int
+bcm_dma_setup_dst(int ch, int dreq, int increase_addr)
+{
+ struct bcm_dma_softc *sc = bcm_dma_sc;
+ uint32_t info;
+
+ if (ch < 0 || ch >= BCM_DMA_CH_MAX)
+ return (-1);
+
+ if (!(sc->sc_dma_ch[ch].flags & BCM_DMA_CH_USED))
+ return (-1);
+
+ info = sc->sc_dma_ch[ch].cb->info;
+ info &= ~INFO_PERMAP_MASK;
+ info &= ~INFO_D_DREQ;
+ info |= (dreq << INFO_PERMAP_SHIFT) & INFO_PERMAP_MASK;
+ if (dreq)
+ info |= INFO_D_DREQ;
+
+ if (increase_addr)
+ info |= INFO_D_INC;
+ else
+ info &= ~INFO_D_INC;
+
+ sc->sc_dma_ch[ch].cb->info = info;
+
+ return (0);
+}
+
+#ifdef DEBUG
+void
+bcm_dma_cb_dump(struct bcm_dma_cb *cb)
+{
+
+ printf("DMA CB ");
+ printf("INFO: %8.8x ", cb->info);
+ printf("SRC: %8.8x ", cb->src);
+ printf("DST: %8.8x ", cb->dst);
+ printf("LEN: %8.8x ", cb->len);
+ printf("\n");
+ printf("STRIDE: %8.8x ", cb->stride);
+ printf("NEXT: %8.8x ", cb->next);
+ printf("RSVD1: %8.8x ", cb->rsvd1);
+ printf("RSVD2: %8.8x ", cb->rsvd2);
+ printf("\n");
+}
+
+void
+bcm_dma_reg_dump(int ch)
+{
+ struct bcm_dma_softc *sc = bcm_dma_sc;
+ int i;
+ uint32_t reg;
+
+ if (ch < 0 || ch >= BCM_DMA_CH_MAX)
+ return;
+
+ printf("DMA%d: ", ch);
+ for (i = 0; i < MAX_REG; i++) {
+ reg = bus_read_4(sc->sc_mem, BCM_DMA_CH(ch) + i*4);
+ printf("%8.8x ", reg);
+ }
+ printf("\n");
+}
+#endif
+
+int
+bcm_dma_start(int ch, vm_paddr_t src, vm_paddr_t dst, int len)
+{
+ struct bcm_dma_softc *sc = bcm_dma_sc;
+ struct bcm_dma_cb *cb;
+
+ if (ch < 0 || ch >= BCM_DMA_CH_MAX)
+ return (-1);
+
+ if (!(sc->sc_dma_ch[ch].flags & BCM_DMA_CH_USED))
+ return (-1);
+
+ cb = sc->sc_dma_ch[ch].cb;
+ cb->src = PHYS_TO_VCBUS(src);
+ cb->dst = PHYS_TO_VCBUS(dst);
+ cb->len = len;
+
+ bus_write_4(sc->sc_mem, BCM_DMA_CBADDR(ch),
+ sc->sc_dma_ch[ch].vc_cb);
+ bus_write_4(sc->sc_mem, BCM_DMA_CS(ch), CS_ACTIVE);
+
+#ifdef DEBUG
+ bcm_dma_cb_dump(sc->sc_dma_ch[ch].cb);
+ bcm_dma_reg_dump(ch);
+#endif
+
+ return (0);
+}
+
+int
+bcm_dma_restart(int ch)
+{
+ if (ch < 0 || ch >= BCM_DMA_CH_MAX)
+ return (-1);
+
+ printf("Restart with CS\n");
+ return (0);
+}
+
+static void
+bcm_dma_intr(void *arg)
+{
+ struct bcm_dma_softc *sc = bcm_dma_sc;
+ struct bcm_dma_ch *ch = (struct bcm_dma_ch *)arg;
+ uint32_t cs, debug;
+
+ /* my interrupt? */
+ cs = bus_read_4(sc->sc_mem, BCM_DMA_CS(ch->ch));
+
+ if (!(cs & (CS_INT | CS_ERR)))
+ return;
+
+ /* running? */
+ if (!(ch->flags & BCM_DMA_CH_USED)) {
+ device_printf(sc->sc_dev,
+ "unused DMA intr CH=%d, CS=%x\n", ch->ch, cs);
+ return;
+ }
+
+ if (cs & CS_ERR) {
+ debug = bus_read_4(sc->sc_mem, BCM_DMA_DEBUG(ch->ch));
+ device_printf(sc->sc_dev, "DMA error %d on CH%d\n",
+ debug & DEBUG_ERROR_MASK, ch->ch);
+ bus_write_4(sc->sc_mem, BCM_DMA_DEBUG(ch->ch),
+ debug & DEBUG_ERROR_MASK);
+ }
+
+ if (cs & CS_INT) {
+ /* acknowledge interrupt */
+ bus_write_4(sc->sc_mem, BCM_DMA_CS(ch->ch),
+ CS_INT | CS_END);
+
+ /* save callback function and argument */
+ if (ch->intr_func)
+ ch->intr_func(ch->ch, ch->intr_arg);
+ }
+}
+
+static int
+bcm_dma_probe(device_t dev)
+{
+
+ if (!ofw_bus_is_compatible(dev, "broadcom,bcm2835-dma"))
+ return (ENXIO);
+
+ device_set_desc(dev, "BCM2835 DMA Controller");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+bcm_dma_attach(device_t dev)
+{
+ struct bcm_dma_softc *sc = device_get_softc(dev);
+ int rid, err = 0;
+ int i;
+
+ sc->sc_dev = dev;
+
+ if (bcm_dma_sc)
+ return (ENXIO);
+
+ for (i = 0; i < BCM_DMA_CH_MAX; i++) {
+ sc->sc_irq[i] = NULL;
+ sc->sc_intrhand[i] = NULL;
+ }
+
+ /* DMA0 - DMA14 */
+ rid = 0;
+ sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
+ if (sc->sc_mem == NULL) {
+ device_printf(dev, "could not allocate memory resource\n");
+ return (ENXIO);
+ }
+
+ /* IRQ DMA0 - DMA11 XXX NOT USE DMA12(spurious?) */
+ for (rid = 0; rid < BCM_DMA_CH_MAX; rid++) {
+ sc->sc_irq[rid] = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE);
+ if (sc->sc_irq[rid] == NULL) {
+ device_printf(dev, "cannot allocate interrupt\n");
+ err = ENXIO;
+ goto fail;
+ }
+ if (bus_setup_intr(dev, sc->sc_irq[rid], INTR_TYPE_MISC | INTR_MPSAFE,
+ NULL, bcm_dma_intr, &sc->sc_dma_ch[rid],
+ &sc->sc_intrhand[rid])) {
+ device_printf(dev, "cannot setup interrupt handler\n");
+ err = ENXIO;
+ goto fail;
+ }
+ }
+
+ mtx_init(&sc->sc_mtx, "bcmdma", "bcmdma", MTX_DEF);
+ bcm_dma_sc = sc;
+
+ err = bcm_dma_init(dev);
+ if (err)
+ goto fail;
+
+ return (err);
+
+fail:
+ if (sc->sc_mem)
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem);
+
+ for (i = 0; i < BCM_DMA_CH_MAX; i++) {
+ if (sc->sc_intrhand[i])
+ bus_teardown_intr(dev, sc->sc_irq[i], sc->sc_intrhand[i]);
+ if (sc->sc_irq[i])
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq[i]);
+ }
+
+ return (err);
+}
+
+static device_method_t bcm_dma_methods[] = {
+ DEVMETHOD(device_probe, bcm_dma_probe),
+ DEVMETHOD(device_attach, bcm_dma_attach),
+ { 0, 0 }
+};
+
+static driver_t bcm_dma_driver = {
+ "bcm_dma",
+ bcm_dma_methods,
+ sizeof(struct bcm_dma_softc),
+};
+
+static devclass_t bcm_dma_devclass;
+
+DRIVER_MODULE(bcm_dma, simplebus, bcm_dma_driver, bcm_dma_devclass, 0, 0);
+MODULE_VERSION(bcm_dma, 1);
Property changes on: arm/broadcom/bcm2835/bcm2835_dma.c
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
Added: svn:eol-style
## -0,0 +1 ##
+native
Index: arm/broadcom/bcm2835/bcm2835_dma.h
===================================================================
--- arm/broadcom/bcm2835/bcm2835_dma.h (revision 0)
+++ arm/broadcom/bcm2835/bcm2835_dma.h (working copy)
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2013 Daisuke Aoyama
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _BCM2835_DMA_H_
+#define _BCM2835_DMA_H_
+
+/* DMA0-DMA15 but DMA15 is special */
+#define BCM_DMA_CH_MAX 12
+
+/* request CH for any nubmer */
+#define BCM_DMA_CH_ANY (-1)
+
+/* Peripheral DREQ Signals (4.2.1.3) */
+#define BCM_DMA_DREQ_EMMC 11
+#define BCM_DMA_DREQ_SDHOST 13
+
+int bcm_dma_allocate(int req_ch);
+int bcm_dma_free(int ch);
+int bcm_dma_setup_intr(int ch, void (*func)(int, void *), void *arg);
+int bcm_dma_setup_src(int ch, int dreq, int increase_addr);
+int bcm_dma_setup_dst(int ch, int dreq, int increase_addr);
+int bcm_dma_start(int ch, vm_paddr_t src, vm_paddr_t dst, int len);
+int bcm_dma_restart(int ch);
+
+#endif /* _BCM2835_DMA_H_ */
Property changes on: arm/broadcom/bcm2835/bcm2835_dma.h
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
Added: svn:eol-style
## -0,0 +1 ##
+native
以上两个文件我没有加到kernel中。这里算烂尾了。开了坑啥时候填都不知道。