diff --git a/lib/rob b/lib/rob index 6da79ed6d..6c0725a56 100644 --- a/lib/rob +++ b/lib/rob @@ -399,3 +399,4 @@ Over time, everything gets better but also worse and always bigger and more comp Nice to see Egreg again. It wasn't my intention. The Blit was nice. +Sockets are just so unpleasant, and the endless nonsense around network configuration doubly so. diff --git a/sys/include/ndb.h b/sys/include/ndb.h index b44da0539..1a9ab7742 100644 --- a/sys/include/ndb.h +++ b/sys/include/ndb.h @@ -27,7 +27,7 @@ struct Ndb Ndb *next; Biobufhdr b; /* buffered input file */ - uchar buf[256]; /* and its buffer */ + uchar buf[8192]; /* and its buffer */ ulong mtime; /* mtime of db file */ Qid qid; /* qid of db file */ diff --git a/sys/lib/dist/mkfile b/sys/lib/dist/mkfile index 581ca2989..ac9118ab3 100644 --- a/sys/lib/dist/mkfile +++ b/sys/lib/dist/mkfile @@ -77,7 +77,7 @@ cd:V: /tmp/9front.386.iso.gz mv $target.$pid.disk $target } -%.zynq.img: +%.zynq.img:D: @{ objtype=arm kernel=/n/src9/$objtype/9zynq @@ -88,6 +88,16 @@ cd:V: /tmp/9front.386.iso.gz mv $target.$pid.disk $target } +%.reform.img:D: /n/src9/sys/src/boot/reform/flash.bin /n/src9/sys/src/boot/reform/boot.scr + @{ + objtype=arm64 + kernel=/n/src9/$objtype/9reform.u + fatfiles=(/n/src9/sys/src/boot/reform/boot.scr $kernel) + mb=1885 # storage vendors idea of 2GB + mk $target.$pid.disk + mv $target.$pid.disk $target && dd -trunc 0 -bs 1024 -oseek 33 -if /n/src9/sys/src/boot/reform/flash.bin -of $target + } + %.pc.iso:D: $proto /n/src9/sys/lib/sysconfig/proto/9bootproto $kernel @{rfork n mk binds @@ -142,6 +152,20 @@ cd:V: /tmp/9front.386.iso.gz disk/prep -bw -a^(nvram fs) $d/plan9 disk/format -d $d/dos $fatfiles } + if not if(~ $target *.reform.img.*){ + { + echo 'a p1 4M 100M' + echo 't p1 FAT32' + echo 'a p2 . $' + echo 't p2 PLAN9' + echo 'A p1' + echo 'p' + echo 'w' + echo 'q' + } | disk/fdisk -b $d/data + disk/prep -bw -a^(nvram fs) $d/plan9 + disk/format -d $d/dos $fatfiles + } if not { disk/fdisk -baw $d/data disk/prep -bw -a^(9fat nvram fs) $d/plan9 diff --git a/sys/man/1/patch b/sys/man/1/patch new file mode 100644 index 000000000..9178d0c02 --- /dev/null +++ b/sys/man/1/patch @@ -0,0 +1,86 @@ +.TH PATCH 1 +.SH NAME +patch \- apply patches +.SH SYNOPSIS +.B patch +[ +.B -R +] +[ +.B -p +.I nstrip +] +[ +.I patch ... +] +.SH DESCRIPTION +.I Patch +scans its input for a sequence of patches, and applies them, printing the list of changed files. +When an applied patch does not match precisely, +.I patch +will scan the input file for matching context, applying the patch up to 250 lines away from +its original location. +If a hunk does not apply, then the file is left untouched. +.PP +The following options are supported: +.TP +.B -R +Reverse direction of the patch. Additions become removals, +and the new and old file names are swapped. +.TP +.BI -p \ nstrip +Remove the prefix containing +.I nstrip +leading slashes from each file path in the diff file. +.SH INPUT FORMAT +A patch begins with a patch header, and is followed by a sequence of one or more hunks. +All lines before a patch header or after the last hunk of a patch are comments, +and are ignored by patch. A patch header is a sequence of 2 lines in the following +format: +.IP +.EX +--- oldfile [trailing text] ++++ newfile [trailing text] +.EE +.PP +A hunk must immediately follow a patch header or another hunk. +It begins with a header line in the following format: +.IP +.EX +@@ -count,addr +count,addr @@ +.EE +.PP +And contains a sequence of lines beginning with a +.LR - , +.LR + , +or space characters. +A +.L - +indicates that the line is to be removed from the old file. +A +.L + +indicates that the line is to be inserted into the new file. +A space indicates that the line is context. +It will be copied unchanged from the old file to the new file. +.PP +If the old file is +.LR /dev/null , +the patch indicates a file creation. +If the new file is +.LR /dev/null , +the patch indicates a file deletion. +In this case, the file printed is the file being removed. +.SH SEE ALSO +.IR diff (1), +.IR git/export (1) +.SH BUGS +.PP +The output of +.B diff -c +is not handled. +.PP +Reject files and backups are not supported. +.PP +All files are processed in memory, limiting the maximum file size to available RAM. + + diff --git a/sys/man/3/srv b/sys/man/3/srv index 820c849db..b68f00887 100644 --- a/sys/man/3/srv +++ b/sys/man/3/srv @@ -5,6 +5,8 @@ srv \- server registry .nf .B bind #s /srv +.BI #s/ clone +.BI #s/ n .BI #s/ service1 .BI #s/ service2 ... @@ -12,7 +14,7 @@ srv \- server registry .SH DESCRIPTION The .I srv -device provides a one-level directory holding +device provides a tree of directories holding already-open channels to services. In effect, .I srv @@ -40,6 +42,18 @@ releases that reference. .PP It is an error to write more than one number into a server file, or to create a file with a name that is already being used. +.PP +Opening the +.I clone +file allocates a new service directory. Reading +.I clone +returns the id of the new directory. This new service +directory can then be accessed at +.BR /srv/id . +Directories are recursable; each new service directory +contains its own +.I clone +file. .SH EXAMPLE To drop one end of a pipe into .BR /srv , diff --git a/sys/man/4/skelfs b/sys/man/4/skelfs new file mode 100644 index 000000000..7168c92f3 --- /dev/null +++ b/sys/man/4/skelfs @@ -0,0 +1,65 @@ +.TH SKELFS 4 +.SH NAME +skelfs \- build directory skeletons +.SH SYNOPSIS +.B skelfs +[ +.B -i +] +[ +.B -t +.I mode +] +[ +.B -s +.I service +] +[ +.I mnt +] +.SH DESCRIPTION +.I Skelfs +generates directory skeletons +to assist in building namespaces. +Skeletons are generated on demand +by walking through the root directory. +A skeleon is a directory containing a single empty child. +The name of this child is defined by the first walk taken +away from the root. For example the hierarchy for a skeleton +named 'echo' would be: +.PP +.EX + / + /echo/ + /echo/echo +.EE +.PP +The +.I mode +dictates what form the innermost child file takes. The +.B file +and +.B dir +modes cause the child to be an empty file or directory +respecively. The +.B empty +mode instead serves no skeletons, causing the root +directory to always be empty. +A client may override the mode by providing +its own selection as an attach option. If a +mode is not provided, +.B file +is assumed. +.PP +The skeletons generated by +.I skelfs +are anonmyous. Clients will never see the +skeletons of other clients, nor can a client revisit +a previous skeleton. +.PP +.SH "SEE ALSO" +.B auth/box +in +.IR auth (8). +.SH SOURCE +.B /sys/src/cmd/skelfs.c diff --git a/sys/man/8/auth b/sys/man/8/auth index 1d7eca1cf..e31730a30 100644 --- a/sys/man/8/auth +++ b/sys/man/8/auth @@ -60,6 +60,20 @@ changeuser, convkeys, printnetkey, status, enable, disable, authsrv, guard.srv, .I arg \&... .PP +.B auth/box +[ +.B -d +] [ +.B -rc +.I file +] [ +.B -e +.I devs +] +.I command +.I arg +\&... +.PP .B auth/as [ .B -d @@ -264,6 +278,26 @@ If there are no arguments, it It's an easy way to run a command as .IR none . .PP +.I Box +executes its arguments in a minimal namespace. +This namespace is derived by binding in the specified +program to the same name within a new hierarchy. +The same is done with the paths +provided as arguments. Paths provided with the +.B -r +flag are bound with +.IR MREPL , +and those provided with the +.B -c +flag are bound with +.IR MCREATE . +.I Box +removes access to all kernel drivers from +the child namespace; the +.B -e +flag specifies a string of driver +characters to keep. +.PP .I As executes .I command @@ -299,5 +333,3 @@ in .IR authsrv (2), .IR keyfs (4), .IR securenet (8) -.SH BUGS -Only CPU kernels permit changing userid. diff --git a/sys/man/8/plan9.ini b/sys/man/8/plan9.ini index 8be2e4f47..8d9ad93a5 100644 --- a/sys/man/8/plan9.ini +++ b/sys/man/8/plan9.ini @@ -712,6 +712,12 @@ Suppress the prompt and use .I value as the answer instead. +.SS \fLbootloop=\fIvalue\fP +Always use +.I value +as the answer to the +.L bootargs +prompt, retrying if unsuccessful. .SS \fLrootdir=\fB/root/\fIdir\fP .SS \fLrootspec=\fIspec\fP Changes the mount arguments for the root file server diff --git a/sys/src/9/boot/bootrc b/sys/src/9/boot/bootrc index c0823e6f4..49a936381 100755 --- a/sys/src/9/boot/bootrc +++ b/sys/src/9/boot/bootrc @@ -68,6 +68,11 @@ mt=() fn main{ mp=() while(~ $#mp 0){ + if(! ~ $#bootloop 0){ + nobootprompt=$bootloop + # 'flatten' for the next boot + echo -n $bootloop > '#ec/bootloop' + } if(~ $#nobootprompt 0){ echo showlocaldevs diff --git a/sys/src/9/boot/reboot.rc b/sys/src/9/boot/reboot.rc index 536ac2009..e2521b768 100755 --- a/sys/src/9/boot/reboot.rc +++ b/sys/src/9/boot/reboot.rc @@ -32,6 +32,7 @@ fn connectreboot { # set new kernel parameters echo -n $bootargs > '#ec/bootargs' + rm -f '#ec/bootloop' # remove part of our temporary root /mnt/broot/$cputype/bin/unmount /$cputype/bin /bin diff --git a/sys/src/9/imx8/ccm.c b/sys/src/9/imx8/ccm.c new file mode 100644 index 000000000..ffec22d52 --- /dev/null +++ b/sys/src/9/imx8/ccm.c @@ -0,0 +1,1357 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" + +static u32int *regs = (u32int*)(VIRTIO + 0x380000); +static u32int *anatop = (u32int*)(VIRTIO + 0x360000); + +enum { + /* input clocks */ + ARM_PLL_CLK = 12, + GPU_PLL_CLK, + VPU_PLL_CLK, + DRAM_PLL1_CLK, + SYSTEM_PLL1_CLK, + SYSTEM_PLL1_DIV2, + SYSTEM_PLL1_DIV3, + SYSTEM_PLL1_DIV4, + SYSTEM_PLL1_DIV5, + SYSTEM_PLL1_DIV6, + SYSTEM_PLL1_DIV8, + SYSTEM_PLL1_DIV10, + SYSTEM_PLL1_DIV20, + SYSTEM_PLL2_CLK, + SYSTEM_PLL2_DIV2, + SYSTEM_PLL2_DIV3, + SYSTEM_PLL2_DIV4, + SYSTEM_PLL2_DIV5, + SYSTEM_PLL2_DIV6, + SYSTEM_PLL2_DIV8, + SYSTEM_PLL2_DIV10, + SYSTEM_PLL2_DIV20, + SYSTEM_PLL3_CLK, + AUDIO_PLL1_CLK, + AUDIO_PLL2_CLK, + VIDEO_PLL1_CLK, + VIDEO_PLL2_CLK, + + OSC_32K_REF_CLK, + OSC_25M_REF_CLK, + OSC_27M_REF_CLK, + EXT_CLK_1, + EXT_CLK_2, + EXT_CLK_3, + EXT_CLK_4, + + /* root clocks (slices) */ + ARM_A53_CLK_ROOT = 0, + ARM_M4_CLK_ROOT = 1, + VPU_A53_CLK_ROOT = 2, + GPU_CORE_CLK_ROOT = 3, + GPU_SHADER_CLK_ROOT = 4, + + MAIN_AXI_CLK_ROOT = 16, + ENET_AXI_CLK_ROOT = 17, + NAND_USDHC_BUS_CLK_ROOT = 18, + VPU_BUS_CLK_ROOT = 19, + DISPLAY_AXI_CLK_ROOT = 20, + DISPLAY_APB_CLK_ROOT = 21, + DISPLAY_RTRM_CLK_ROOT = 22, + USB_BUS_CLK_ROOT = 23, + GPU_AXI_CLK_ROOT = 24, + GPU_AHB_CLK_ROOT = 25, + NOC_CLK_ROOT = 26, + NOC_APB_CLK_ROOT = 27, + + AHB_CLK_ROOT = 32, + IPG_CLK_ROOT = 33, + AUDIO_AHB_CLK_ROOT = 34, + AUDIO_IPG_CLK_ROOT = 35, + MIPI_DSI_ESC_RX_CLK_ROOT = 36, + MIPI_DSI_ESC_CLK_ROOT = 37, + + DRAM_ALT_CLK_ROOT = 64, + DRAM_APB_CLK_ROOT = 65, + VPU_G1_CLK_ROOT = 66, + VPU_G2_CLK_ROOT = 67, + DISPLAY_DTRC_CLK_ROOT = 68, + DISPLAY_DC8000_CLK_ROOT = 69, + PCIE1_CTRL_CLK_ROOT = 70, + PCIE1_PHY_CLK_ROOT = 71, + PCIE1_AUX_CLK_ROOT = 72, + DC_PIXEL_CLK_ROOT = 73, + LCDIF_PIXEL_CLK_ROOT = 74, + SAI1_CLK_ROOT = 75, + SAI2_CLK_ROOT = 76, + SAI3_CLK_ROOT = 77, + SAI4_CLK_ROOT = 78, + SAI5_CLK_ROOT = 79, + SAI6_CLK_ROOT = 80, + SPDIF1_CLK_ROOT = 81, + SPDIF2_CLK_ROOT = 82, + ENET_REF_CLK_ROOT = 83, + ENET_TIMER_CLK_ROOT = 84, + ENET_PHY_REF_CLK_ROOT = 85, + NAND_CLK_ROOT = 86, + QSPI_CLK_ROOT = 87, + USDHC1_CLK_ROOT = 88, + USDHC2_CLK_ROOT = 89, + I2C1_CLK_ROOT = 90, + I2C2_CLK_ROOT = 91, + I2C3_CLK_ROOT = 92, + I2C4_CLK_ROOT = 93, + UART1_CLK_ROOT = 94, + UART2_CLK_ROOT = 95, + UART3_CLK_ROOT = 96, + UART4_CLK_ROOT = 97, + USB_CORE_REF_CLK_ROOT = 98, + USB_PHY_REF_CLK_ROOT = 99, + GIC_CLK_ROOT = 100, + ECSPI1_CLK_ROOT = 101, + ECSPI2_CLK_ROOT = 102, + PWM1_CLK_ROOT = 103, + PWM2_CLK_ROOT = 104, + PWM3_CLK_ROOT = 105, + PWM4_CLK_ROOT = 106, + GPT1_CLK_ROOT = 107, + GPT2_CLK_ROOT = 108, + GPT3_CLK_ROOT = 109, + GPT4_CLK_ROOT = 110, + GPT5_CLK_ROOT = 111, + GPT6_CLK_ROOT = 112, + TRACE_CLK_ROOT = 113, + WDOG_CLK_ROOT = 114, + WRCLK_CLK_ROOT = 115, + IPP_DO_CLKO1 = 116, + IPP_DO_CLKO2 = 117, + MIPI_DSI_CORE_CLK_ROOT = 118, + MIPI_DSI_PHY_REF_CLK_ROOT = 119, + MIPI_DSI_DBI_CLK_ROOT = 120, + OLD_MIPI_DSI_ESC_CLK_ROOT = 121, + MIPI_CSI1_CORE_CLK_ROOT = 122, + MIPI_CSI1_PHY_REF_CLK_ROOT = 123, + MIPI_CSI1_ESC_CLK_ROOT = 124, + MIPI_CSI2_CORE_CLK_ROOT = 125, + MIPI_CSI2_PHY_REF_CLK_ROOT = 126, + MIPI_CSI2_ESC_CLK_ROOT = 127, + PCIE2_CTRL_CLK_ROOT = 128, + PCIE2_PHY_CLK_ROOT = 129, + PCIE2_AUX_CLK_ROOT = 130, + ECSPI3_CLK_ROOT = 131, + OLD_MIPI_DSI_ESC_RX_CLK_ROOT = 132, + DISPLAY_HDMI_CLK_ROOT = 133, +}; + +static int input_clk_freq[] = { + [ARM_PLL_CLK] 1600*Mhz, + [GPU_PLL_CLK] 1600*Mhz, + [VPU_PLL_CLK] 800*Mhz, + [DRAM_PLL1_CLK] 800*Mhz, + [SYSTEM_PLL1_CLK] 800*Mhz, + [SYSTEM_PLL1_DIV2] 400*Mhz, + [SYSTEM_PLL1_DIV3] 266*Mhz, + [SYSTEM_PLL1_DIV4] 200*Mhz, + [SYSTEM_PLL1_DIV5] 160*Mhz, + [SYSTEM_PLL1_DIV6] 133*Mhz, + [SYSTEM_PLL1_DIV8] 100*Mhz, + [SYSTEM_PLL1_DIV10] 80*Mhz, + [SYSTEM_PLL1_DIV20] 40*Mhz, + [SYSTEM_PLL2_CLK] 1000*Mhz, + [SYSTEM_PLL2_DIV2] 500*Mhz, + [SYSTEM_PLL2_DIV3] 333*Mhz, + [SYSTEM_PLL2_DIV4] 250*Mhz, + [SYSTEM_PLL2_DIV5] 200*Mhz, + [SYSTEM_PLL2_DIV6] 166*Mhz, + [SYSTEM_PLL2_DIV8] 125*Mhz, + [SYSTEM_PLL2_DIV10] 100*Mhz, + [SYSTEM_PLL2_DIV20] 50*Mhz, + [SYSTEM_PLL3_CLK] 1000*Mhz, + [AUDIO_PLL1_CLK] 650*Mhz, + [AUDIO_PLL2_CLK] 650*Mhz, + [VIDEO_PLL1_CLK] 594*Mhz, + [VIDEO_PLL2_CLK] 600*Mhz, + [OSC_32K_REF_CLK] 32000, + [OSC_25M_REF_CLK] 25*Mhz, + [OSC_27M_REF_CLK] 27*Mhz, + [EXT_CLK_1] 133*Mhz, + [EXT_CLK_2] 133*Mhz, + [EXT_CLK_3] 133*Mhz, + [EXT_CLK_4] 133*Mhz, +}; + +static char *input_clk_name[] = { + [ARM_PLL_CLK] "arm_pll_clk", + [GPU_PLL_CLK] "gpu_pll_clk", + [VPU_PLL_CLK] "vpu_pll_clk", + [DRAM_PLL1_CLK] "dram_pll1_clk", + [SYSTEM_PLL1_CLK] "system_pll1_clk", + [SYSTEM_PLL1_DIV2] "system_pll1_div2", + [SYSTEM_PLL1_DIV3] "system_pll1_div3", + [SYSTEM_PLL1_DIV4] "system_pll1_div4", + [SYSTEM_PLL1_DIV5] "system_pll1_div5", + [SYSTEM_PLL1_DIV6] "system_pll1_div6", + [SYSTEM_PLL1_DIV8] "system_pll1_div8", + [SYSTEM_PLL1_DIV10] "system_pll1_div10", + [SYSTEM_PLL1_DIV20] "system_pll1_div20", + [SYSTEM_PLL2_CLK] "system_pll2_clk", + [SYSTEM_PLL2_DIV2] "system_pll2_div2", + [SYSTEM_PLL2_DIV3] "system_pll2_div3", + [SYSTEM_PLL2_DIV4] "system_pll2_div4", + [SYSTEM_PLL2_DIV5] "system_pll2_div5", + [SYSTEM_PLL2_DIV6] "system_pll2_div6", + [SYSTEM_PLL2_DIV8] "system_pll2_div8", + [SYSTEM_PLL2_DIV10] "system_pll2_div10", + [SYSTEM_PLL2_DIV20] "system_pll2_div20", + [SYSTEM_PLL3_CLK] "system_pll3_clk", + [AUDIO_PLL1_CLK] "audio_pll1_clk", + [AUDIO_PLL2_CLK] "audio_pll2_clk", + [VIDEO_PLL1_CLK] "video_pll1_clk", + [VIDEO_PLL2_CLK] "video_pll2_clk", + [OSC_32K_REF_CLK] "osc_32k_ref_clk", + [OSC_25M_REF_CLK] "osc_25m_ref_clk", + [OSC_27M_REF_CLK] "osc_27m_ref_clk", + [EXT_CLK_1] "ext_clk_1", + [EXT_CLK_2] "ext_clk_2", + [EXT_CLK_3] "ext_clk_3", + [EXT_CLK_4] "ext_clk_4", +}; + +static char *root_clk_name[] = { + [ARM_A53_CLK_ROOT] "ccm_arm_a53_clk_root", + [ARM_M4_CLK_ROOT] "ccm_arm_m4_clk_root", + [VPU_A53_CLK_ROOT] "ccm_vpu_a53_clk_root", + [GPU_CORE_CLK_ROOT] "ccm_gpu_core_clk_root", + [GPU_SHADER_CLK_ROOT] "ccm_gpu_shader_clk_root", + [MAIN_AXI_CLK_ROOT] "ccm_main_axi_clk_root", + [ENET_AXI_CLK_ROOT] "ccm_enet_axi_clk_root", + [NAND_USDHC_BUS_CLK_ROOT] "ccm_nand_usdhc_bus_clk_root", + [VPU_BUS_CLK_ROOT] "ccm_vpu_bus_clk_root", + [DISPLAY_AXI_CLK_ROOT] "ccm_display_axi_clk_root", + [DISPLAY_APB_CLK_ROOT] "ccm_display_apb_clk_root", + [DISPLAY_RTRM_CLK_ROOT] "ccm_display_rtrm_clk_root", + [USB_BUS_CLK_ROOT] "ccm_usb_bus_clk_root", + [GPU_AXI_CLK_ROOT] "ccm_gpu_axi_clk_root", + [GPU_AHB_CLK_ROOT] "ccm_gpu_ahb_clk_root", + [NOC_CLK_ROOT] "ccm_noc_clk_root", + [NOC_APB_CLK_ROOT] "ccm_noc_apb_clk_root", + [AHB_CLK_ROOT] "ccm_ahb_clk_root", + [IPG_CLK_ROOT] "ccm_ipg_clk_root", + [AUDIO_AHB_CLK_ROOT] "ccm_audio_ahb_clk_root", + [AUDIO_IPG_CLK_ROOT] "ccm_audio_ipg_clk_root", + [MIPI_DSI_ESC_RX_CLK_ROOT] "ccm_mipi_dsi_esc_rx_clk_root", + [MIPI_DSI_ESC_CLK_ROOT] "ccm_mipi_dsi_esc_clk_root", + [DRAM_ALT_CLK_ROOT] "ccm_dram_alt_clk_root", + [DRAM_APB_CLK_ROOT] "ccm_dram_apb_clk_root", + [VPU_G1_CLK_ROOT] "ccm_vpu_g1_clk_root", + [VPU_G2_CLK_ROOT] "ccm_vpu_g2_clk_root", + [DISPLAY_DTRC_CLK_ROOT] "ccm_display_dtrc_clk_root", + [DISPLAY_DC8000_CLK_ROOT] "ccm_display_dc8000_clk_root", + [PCIE1_CTRL_CLK_ROOT] "ccm_pcie1_ctrl_clk_root", + [PCIE1_PHY_CLK_ROOT] "ccm_pcie1_phy_clk_root", + [PCIE1_AUX_CLK_ROOT] "ccm_pcie1_aux_clk_root", + [DC_PIXEL_CLK_ROOT] "ccm_dc_pixel_clk_root", + [LCDIF_PIXEL_CLK_ROOT] "ccm_lcdif_pixel_clk_root", + [SAI1_CLK_ROOT] "ccm_sai1_clk_root", + [SAI2_CLK_ROOT] "ccm_sai2_clk_root", + [SAI3_CLK_ROOT] "ccm_sai3_clk_root", + [SAI4_CLK_ROOT] "ccm_sai4_clk_root", + [SAI5_CLK_ROOT] "ccm_sai5_clk_root", + [SAI6_CLK_ROOT] "ccm_sai6_clk_root", + [SPDIF1_CLK_ROOT] "ccm_spdif1_clk_root", + [SPDIF2_CLK_ROOT] "ccm_spdif2_clk_root", + [ENET_REF_CLK_ROOT] "ccm_enet_ref_clk_root", + [ENET_TIMER_CLK_ROOT] "ccm_enet_timer_clk_root", + [ENET_PHY_REF_CLK_ROOT] "ccm_enet_phy_ref_clk_root", + [NAND_CLK_ROOT] "ccm_nand_clk_root", + [QSPI_CLK_ROOT] "ccm_qspi_clk_root", + [USDHC1_CLK_ROOT] "ccm_usdhc1_clk_root", + [USDHC2_CLK_ROOT] "ccm_usdhc2_clk_root", + [I2C1_CLK_ROOT] "ccm_i2c1_clk_root", + [I2C2_CLK_ROOT] "ccm_i2c2_clk_root", + [I2C3_CLK_ROOT] "ccm_i2c3_clk_root", + [I2C4_CLK_ROOT] "ccm_i2c4_clk_root", + [UART1_CLK_ROOT] "ccm_uart1_clk_root", + [UART2_CLK_ROOT] "ccm_uart2_clk_root", + [UART3_CLK_ROOT] "ccm_uart3_clk_root", + [UART4_CLK_ROOT] "ccm_uart4_clk_root", + [USB_CORE_REF_CLK_ROOT] "ccm_usb_core_ref_clk_root", + [USB_PHY_REF_CLK_ROOT] "ccm_usb_phy_ref_clk_root", + [GIC_CLK_ROOT] "ccm_gic_clk_root", + [ECSPI1_CLK_ROOT] "ccm_ecspi1_clk_root", + [ECSPI2_CLK_ROOT] "ccm_ecspi2_clk_root", + [PWM1_CLK_ROOT] "ccm_pwm1_clk_root", + [PWM2_CLK_ROOT] "ccm_pwm2_clk_root", + [PWM3_CLK_ROOT] "ccm_pwm3_clk_root", + [PWM4_CLK_ROOT] "ccm_pwm4_clk_root", + [GPT1_CLK_ROOT] "ccm_gpt1_clk_root", + [GPT2_CLK_ROOT] "ccm_gpt2_clk_root", + [GPT3_CLK_ROOT] "ccm_gpt3_clk_root", + [GPT4_CLK_ROOT] "ccm_gpt4_clk_root", + [GPT5_CLK_ROOT] "ccm_gpt5_clk_root", + [GPT6_CLK_ROOT] "ccm_gpt6_clk_root", + [TRACE_CLK_ROOT] "ccm_trace_clk_root", + [WDOG_CLK_ROOT] "ccm_wdog_clk_root", + [WRCLK_CLK_ROOT] "ccm_wrclk_clk_root", + [IPP_DO_CLKO1] "ccm_ipp_do_clko1", + [IPP_DO_CLKO2] "ccm_ipp_do_clko2", + [MIPI_DSI_CORE_CLK_ROOT] "ccm_mipi_dsi_core_clk_root", + [MIPI_DSI_PHY_REF_CLK_ROOT] "ccm_mipi_dsi_phy_ref_clk_root", + [MIPI_DSI_DBI_CLK_ROOT] "ccm_mipi_dsi_dbi_clk_root", + [OLD_MIPI_DSI_ESC_CLK_ROOT] "ccm_old_mipi_dsi_esc_clk_root", + [MIPI_CSI1_CORE_CLK_ROOT] "ccm_mipi_csi1_core_clk_root", + [MIPI_CSI1_PHY_REF_CLK_ROOT] "ccm_mipi_csi1_phy_ref_clk_root", + [MIPI_CSI1_ESC_CLK_ROOT] "ccm_mipi_csi1_esc_clk_root", + [MIPI_CSI2_CORE_CLK_ROOT] "ccm_mipi_csi2_core_clk_root", + [MIPI_CSI2_PHY_REF_CLK_ROOT] "ccm_mipi_csi2_phy_ref_clk_root", + [MIPI_CSI2_ESC_CLK_ROOT] "ccm_mipi_csi2_esc_clk_root", + [PCIE2_CTRL_CLK_ROOT] "ccm_pcie2_ctrl_clk_root", + [PCIE2_PHY_CLK_ROOT] "ccm_pcie2_phy_clk_root", + [PCIE2_AUX_CLK_ROOT] "ccm_pcie2_aux_clk_root", + [ECSPI3_CLK_ROOT] "ccm_ecspi3_clk_root", + [OLD_MIPI_DSI_ESC_RX_CLK_ROOT] "ccm_old_mipi_dsi_esc_rx_clk_root", + [DISPLAY_HDMI_CLK_ROOT] "ccm_display_hdmi_clk_root", +}; + +static uchar root_clk_input_mux[] = { +[ARM_A53_CLK_ROOT*8] + OSC_25M_REF_CLK, ARM_PLL_CLK, SYSTEM_PLL2_DIV2, SYSTEM_PLL2_CLK, + SYSTEM_PLL1_CLK, SYSTEM_PLL1_DIV2, AUDIO_PLL1_CLK, SYSTEM_PLL3_CLK, +[ARM_M4_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV5, SYSTEM_PLL2_DIV4, SYSTEM_PLL1_DIV3, + SYSTEM_PLL1_CLK, AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, SYSTEM_PLL3_CLK, +[VPU_A53_CLK_ROOT*8] + OSC_25M_REF_CLK, ARM_PLL_CLK, SYSTEM_PLL2_DIV2, SYSTEM_PLL2_CLK, + SYSTEM_PLL1_CLK, SYSTEM_PLL1_DIV2, AUDIO_PLL1_CLK, VPU_PLL_CLK, +[GPU_CORE_CLK_ROOT*8] + OSC_25M_REF_CLK, GPU_PLL_CLK, SYSTEM_PLL1_CLK, SYSTEM_PLL3_CLK, + SYSTEM_PLL2_CLK, AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, AUDIO_PLL2_CLK, +[GPU_SHADER_CLK_ROOT*8] + OSC_25M_REF_CLK, GPU_PLL_CLK, SYSTEM_PLL1_CLK, SYSTEM_PLL3_CLK, + SYSTEM_PLL2_CLK, AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, AUDIO_PLL2_CLK, +[MAIN_AXI_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV3, SYSTEM_PLL1_CLK, SYSTEM_PLL2_DIV4, + SYSTEM_PLL2_CLK, AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, SYSTEM_PLL1_DIV8, +[ENET_AXI_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV3, SYSTEM_PLL1_CLK, SYSTEM_PLL2_DIV4, + SYSTEM_PLL2_DIV5, AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, SYSTEM_PLL3_CLK, +[NAND_USDHC_BUS_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV3, SYSTEM_PLL1_CLK, SYSTEM_PLL2_DIV5, + SYSTEM_PLL1_DIV6, SYSTEM_PLL3_CLK, SYSTEM_PLL2_DIV4, AUDIO_PLL1_CLK, +[VPU_BUS_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_CLK, VPU_PLL_CLK, AUDIO_PLL2_CLK, + SYSTEM_PLL3_CLK, SYSTEM_PLL2_CLK, SYSTEM_PLL2_DIV5, SYSTEM_PLL1_DIV8, +[DISPLAY_AXI_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV8, SYSTEM_PLL1_CLK, SYSTEM_PLL3_CLK, + SYSTEM_PLL1_DIV20, AUDIO_PLL2_CLK, EXT_CLK_1, EXT_CLK_4, +[DISPLAY_APB_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV8, SYSTEM_PLL1_CLK, SYSTEM_PLL3_CLK, + SYSTEM_PLL1_DIV20, AUDIO_PLL2_CLK, EXT_CLK_1, EXT_CLK_3, +[DISPLAY_RTRM_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_CLK, SYSTEM_PLL2_DIV5, SYSTEM_PLL1_DIV2, + AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, EXT_CLK_2, EXT_CLK_3, +[USB_BUS_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV2, SYSTEM_PLL1_CLK, SYSTEM_PLL2_DIV10, + SYSTEM_PLL2_DIV5, EXT_CLK_2, EXT_CLK_4, AUDIO_PLL2_CLK, +[GPU_AXI_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_CLK, GPU_PLL_CLK, SYSTEM_PLL3_CLK, + SYSTEM_PLL2_CLK, AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, AUDIO_PLL2_CLK, +[GPU_AHB_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_CLK, GPU_PLL_CLK, SYSTEM_PLL3_CLK, + SYSTEM_PLL2_CLK, AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, AUDIO_PLL2_CLK, +[NOC_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_CLK, SYSTEM_PLL3_CLK, SYSTEM_PLL2_CLK, + SYSTEM_PLL2_DIV2, AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, AUDIO_PLL2_CLK, +[NOC_APB_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV2, SYSTEM_PLL3_CLK, SYSTEM_PLL2_DIV3, + SYSTEM_PLL2_DIV5, SYSTEM_PLL1_CLK, AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, +[AHB_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV6, SYSTEM_PLL1_CLK, SYSTEM_PLL1_DIV2, + SYSTEM_PLL2_DIV8, SYSTEM_PLL3_CLK, AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, +[AUDIO_AHB_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV2, SYSTEM_PLL1_CLK, SYSTEM_PLL2_CLK, + SYSTEM_PLL2_DIV6, SYSTEM_PLL3_CLK, AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, +[MIPI_DSI_ESC_RX_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV10, SYSTEM_PLL1_CLK, + SYSTEM_PLL2_CLK, SYSTEM_PLL3_CLK, EXT_CLK_3, AUDIO_PLL2_CLK, +[DRAM_ALT_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_CLK, SYSTEM_PLL1_DIV8, SYSTEM_PLL2_DIV2, + SYSTEM_PLL2_DIV4, SYSTEM_PLL1_DIV2, AUDIO_PLL1_CLK, SYSTEM_PLL1_DIV3, +[DRAM_APB_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV5, SYSTEM_PLL1_DIV20, SYSTEM_PLL1_DIV5, + SYSTEM_PLL1_CLK, SYSTEM_PLL3_CLK, SYSTEM_PLL2_DIV4, AUDIO_PLL2_CLK, +[VPU_G1_CLK_ROOT*8] + OSC_25M_REF_CLK, VPU_PLL_CLK, SYSTEM_PLL1_CLK, SYSTEM_PLL2_CLK, + SYSTEM_PLL1_DIV8, SYSTEM_PLL2_DIV8, SYSTEM_PLL3_CLK, AUDIO_PLL1_CLK, +[VPU_G2_CLK_ROOT*8] + OSC_25M_REF_CLK, VPU_PLL_CLK, SYSTEM_PLL1_CLK, SYSTEM_PLL2_CLK, + SYSTEM_PLL1_DIV8, SYSTEM_PLL2_DIV8, SYSTEM_PLL3_CLK, AUDIO_PLL1_CLK, +[DISPLAY_DTRC_CLK_ROOT*8] + OSC_25M_REF_CLK, VIDEO_PLL2_CLK, SYSTEM_PLL1_CLK, SYSTEM_PLL2_CLK, + SYSTEM_PLL1_DIV5, VIDEO_PLL1_CLK, SYSTEM_PLL3_CLK, AUDIO_PLL2_CLK, +[DISPLAY_DC8000_CLK_ROOT*8] + OSC_25M_REF_CLK, VIDEO_PLL2_CLK, SYSTEM_PLL1_CLK, SYSTEM_PLL2_CLK, + SYSTEM_PLL1_DIV5, VIDEO_PLL1_CLK, SYSTEM_PLL3_CLK, AUDIO_PLL2_CLK, +[PCIE1_CTRL_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV4, SYSTEM_PLL2_DIV5, SYSTEM_PLL1_DIV3, + SYSTEM_PLL1_CLK, SYSTEM_PLL2_DIV2, SYSTEM_PLL2_DIV3, SYSTEM_PLL3_CLK, +[PCIE1_PHY_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL2_DIV2, EXT_CLK_1, + EXT_CLK_2, EXT_CLK_3, EXT_CLK_4, SYSTEM_PLL1_DIV2, +[PCIE1_AUX_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV5, SYSTEM_PLL2_DIV20, SYSTEM_PLL3_CLK, + SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV10, SYSTEM_PLL1_DIV5, SYSTEM_PLL1_DIV4, +[DC_PIXEL_CLK_ROOT*8] + OSC_25M_REF_CLK, VIDEO_PLL1_CLK, AUDIO_PLL2_CLK, AUDIO_PLL1_CLK, + SYSTEM_PLL1_CLK, SYSTEM_PLL2_CLK, SYSTEM_PLL3_CLK, EXT_CLK_4, +[LCDIF_PIXEL_CLK_ROOT*8] + OSC_25M_REF_CLK, VIDEO_PLL1_CLK, AUDIO_PLL2_CLK, AUDIO_PLL1_CLK, + SYSTEM_PLL1_CLK, SYSTEM_PLL2_CLK, SYSTEM_PLL3_CLK, EXT_CLK_4, +[SAI1_CLK_ROOT*8] + OSC_25M_REF_CLK, AUDIO_PLL1_CLK, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, + SYSTEM_PLL1_DIV6, OSC_27M_REF_CLK, EXT_CLK_1, EXT_CLK_2, +[SAI2_CLK_ROOT*8] + OSC_25M_REF_CLK, AUDIO_PLL1_CLK, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, + SYSTEM_PLL1_DIV6, OSC_27M_REF_CLK, EXT_CLK_2, EXT_CLK_3, +[SAI3_CLK_ROOT*8] + OSC_25M_REF_CLK, AUDIO_PLL1_CLK, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, + SYSTEM_PLL1_DIV6, OSC_27M_REF_CLK, EXT_CLK_3, EXT_CLK_4, +[SAI4_CLK_ROOT*8] + OSC_25M_REF_CLK, AUDIO_PLL1_CLK, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, + SYSTEM_PLL1_DIV6, OSC_27M_REF_CLK, EXT_CLK_1, EXT_CLK_2, +[SAI5_CLK_ROOT*8] + OSC_25M_REF_CLK, AUDIO_PLL1_CLK, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, + SYSTEM_PLL1_DIV6, OSC_27M_REF_CLK, EXT_CLK_2, EXT_CLK_3, +[SAI6_CLK_ROOT*8] + OSC_25M_REF_CLK, AUDIO_PLL1_CLK, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, + SYSTEM_PLL1_DIV6, OSC_27M_REF_CLK, EXT_CLK_3, EXT_CLK_4, +[SPDIF1_CLK_ROOT*8] + OSC_25M_REF_CLK, AUDIO_PLL1_CLK, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, + SYSTEM_PLL1_DIV6, OSC_27M_REF_CLK, EXT_CLK_2, EXT_CLK_3, +[SPDIF2_CLK_ROOT*8] + OSC_25M_REF_CLK, AUDIO_PLL1_CLK, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, + SYSTEM_PLL1_DIV6, OSC_27M_REF_CLK, EXT_CLK_3, EXT_CLK_4, +[ENET_REF_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV8, SYSTEM_PLL2_DIV20, SYSTEM_PLL2_DIV10, + SYSTEM_PLL1_DIV5, AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, EXT_CLK_4, +[ENET_TIMER_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, AUDIO_PLL1_CLK, EXT_CLK_1, + EXT_CLK_2, EXT_CLK_3, EXT_CLK_4, VIDEO_PLL1_CLK, +[ENET_PHY_REF_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV20, SYSTEM_PLL2_DIV8, SYSTEM_PLL2_DIV5, + SYSTEM_PLL2_DIV2, AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, AUDIO_PLL2_CLK, +[NAND_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV2, AUDIO_PLL1_CLK, SYSTEM_PLL1_DIV2, + AUDIO_PLL2_CLK, SYSTEM_PLL3_CLK, SYSTEM_PLL2_DIV4, VIDEO_PLL1_CLK, +[QSPI_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV2, SYSTEM_PLL1_CLK, SYSTEM_PLL2_DIV2, + AUDIO_PLL2_CLK, SYSTEM_PLL1_DIV3, SYSTEM_PLL3_CLK, SYSTEM_PLL1_DIV8, +[USDHC1_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV2, SYSTEM_PLL1_CLK, SYSTEM_PLL2_DIV2, + SYSTEM_PLL3_CLK, SYSTEM_PLL1_DIV3, AUDIO_PLL2_CLK, SYSTEM_PLL1_DIV8, +[USDHC2_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV2, SYSTEM_PLL1_CLK, SYSTEM_PLL2_DIV2, + SYSTEM_PLL3_CLK, SYSTEM_PLL1_DIV3, AUDIO_PLL2_CLK, SYSTEM_PLL1_DIV8, +[I2C1_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV5, SYSTEM_PLL2_DIV20, SYSTEM_PLL3_CLK, + AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, AUDIO_PLL2_CLK, SYSTEM_PLL1_DIV6, +[I2C2_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV5, SYSTEM_PLL2_DIV20, SYSTEM_PLL3_CLK, + AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, AUDIO_PLL2_CLK, SYSTEM_PLL1_DIV6, +[I2C3_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV5, SYSTEM_PLL2_DIV20, SYSTEM_PLL3_CLK, + AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, AUDIO_PLL2_CLK, SYSTEM_PLL1_DIV6, +[I2C4_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV5, SYSTEM_PLL2_DIV20, SYSTEM_PLL3_CLK, + AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, AUDIO_PLL2_CLK, SYSTEM_PLL1_DIV6, +[UART1_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV10, SYSTEM_PLL2_DIV5, SYSTEM_PLL2_DIV10, + SYSTEM_PLL3_CLK, EXT_CLK_2, EXT_CLK_4, AUDIO_PLL2_CLK, +[UART2_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV10, SYSTEM_PLL2_DIV5, SYSTEM_PLL2_DIV10, + SYSTEM_PLL3_CLK, EXT_CLK_2, EXT_CLK_3, AUDIO_PLL2_CLK, +[UART3_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV10, SYSTEM_PLL2_DIV5, SYSTEM_PLL2_DIV10, + SYSTEM_PLL3_CLK, EXT_CLK_2, EXT_CLK_4, AUDIO_PLL2_CLK, +[UART4_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV10, SYSTEM_PLL2_DIV5, SYSTEM_PLL2_DIV10, + SYSTEM_PLL3_CLK, EXT_CLK_2, EXT_CLK_3, AUDIO_PLL2_CLK, +[USB_CORE_REF_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV8, SYSTEM_PLL1_DIV20, SYSTEM_PLL2_DIV10, + SYSTEM_PLL2_DIV5, EXT_CLK_2, EXT_CLK_3, AUDIO_PLL2_CLK, +[USB_PHY_REF_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV8, SYSTEM_PLL1_DIV20, SYSTEM_PLL2_DIV10, + SYSTEM_PLL2_DIV5, EXT_CLK_2, EXT_CLK_3, AUDIO_PLL2_CLK, +[GIC_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV5, SYSTEM_PLL1_DIV20, SYSTEM_PLL2_DIV10, + SYSTEM_PLL1_CLK, EXT_CLK_2, EXT_CLK_4, AUDIO_PLL2_CLK, +[ECSPI1_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV5, SYSTEM_PLL1_DIV20, SYSTEM_PLL1_DIV5, + SYSTEM_PLL1_CLK, SYSTEM_PLL3_CLK, SYSTEM_PLL2_DIV4, AUDIO_PLL2_CLK, +[ECSPI2_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV5, SYSTEM_PLL1_DIV20, SYSTEM_PLL1_DIV5, + SYSTEM_PLL1_CLK, SYSTEM_PLL3_CLK, SYSTEM_PLL2_DIV4, AUDIO_PLL2_CLK, +[PWM1_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV5, SYSTEM_PLL1_DIV20, + SYSTEM_PLL3_CLK, EXT_CLK_1, SYSTEM_PLL1_DIV10, VIDEO_PLL1_CLK, +[PWM2_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV5, SYSTEM_PLL1_DIV20, + SYSTEM_PLL3_CLK, EXT_CLK_1, SYSTEM_PLL1_DIV10, VIDEO_PLL1_CLK, +[PWM3_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV5, SYSTEM_PLL1_DIV20, + SYSTEM_PLL3_CLK, EXT_CLK_2, SYSTEM_PLL1_DIV10, VIDEO_PLL1_CLK, +[PWM4_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV5, SYSTEM_PLL1_DIV20, + SYSTEM_PLL3_CLK, EXT_CLK_2, SYSTEM_PLL1_DIV10, VIDEO_PLL1_CLK, +[GPT1_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV2, SYSTEM_PLL1_DIV20, + VIDEO_PLL1_CLK, SYSTEM_PLL1_DIV10, AUDIO_PLL1_CLK, EXT_CLK_1, +[GPT2_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV2, SYSTEM_PLL1_DIV20, + VIDEO_PLL1_CLK, SYSTEM_PLL1_DIV10, AUDIO_PLL1_CLK, EXT_CLK_2, +[GPT3_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV2, SYSTEM_PLL1_DIV20, + VIDEO_PLL1_CLK, SYSTEM_PLL1_DIV10, AUDIO_PLL1_CLK, EXT_CLK_3, +[GPT4_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV2, SYSTEM_PLL1_DIV20, + VIDEO_PLL1_CLK, SYSTEM_PLL1_DIV10, AUDIO_PLL1_CLK, EXT_CLK_1, +[GPT5_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV2, SYSTEM_PLL1_DIV20, + VIDEO_PLL1_CLK, SYSTEM_PLL1_DIV10, AUDIO_PLL1_CLK, EXT_CLK_2, +[GPT6_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV2, SYSTEM_PLL1_DIV20, + VIDEO_PLL1_CLK, SYSTEM_PLL1_DIV10, AUDIO_PLL1_CLK, EXT_CLK_3, +[TRACE_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV6, SYSTEM_PLL1_DIV5, VPU_PLL_CLK, + SYSTEM_PLL2_DIV8, SYSTEM_PLL3_CLK, EXT_CLK_1, EXT_CLK_3, +[WDOG_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV6, SYSTEM_PLL1_DIV5, VPU_PLL_CLK, + SYSTEM_PLL2_DIV8, SYSTEM_PLL3_CLK, SYSTEM_PLL1_DIV10, SYSTEM_PLL2_DIV6, +[WRCLK_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV20, VPU_PLL_CLK, SYSTEM_PLL3_CLK, + SYSTEM_PLL2_DIV5, SYSTEM_PLL1_DIV3, SYSTEM_PLL2_DIV2, SYSTEM_PLL1_DIV8, +[IPP_DO_CLKO1*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_CLK, OSC_27M_REF_CLK, SYSTEM_PLL1_DIV4, + AUDIO_PLL2_CLK, SYSTEM_PLL2_DIV2, VPU_PLL_CLK, SYSTEM_PLL1_DIV10, +[IPP_DO_CLKO2*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV5, SYSTEM_PLL1_DIV2, SYSTEM_PLL2_DIV6, + SYSTEM_PLL3_CLK, AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, OSC_32K_REF_CLK, +[MIPI_DSI_CORE_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV3, SYSTEM_PLL2_DIV4, SYSTEM_PLL1_CLK, + SYSTEM_PLL2_CLK, SYSTEM_PLL3_CLK, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, +[MIPI_DSI_PHY_REF_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV8, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_CLK, + SYSTEM_PLL2_CLK, EXT_CLK_2, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, +[MIPI_DSI_DBI_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV3, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_CLK, + SYSTEM_PLL2_CLK, SYSTEM_PLL3_CLK, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, +[MIPI_CSI1_CORE_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV3, SYSTEM_PLL2_DIV4, SYSTEM_PLL1_CLK, + SYSTEM_PLL2_CLK, SYSTEM_PLL3_CLK, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, +[MIPI_CSI1_PHY_REF_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV3, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_CLK, + SYSTEM_PLL2_CLK, EXT_CLK_2, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, +[MIPI_CSI1_ESC_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV10, SYSTEM_PLL1_CLK, + SYSTEM_PLL2_CLK, SYSTEM_PLL3_CLK, EXT_CLK_3, AUDIO_PLL2_CLK, +[MIPI_CSI2_CORE_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV3, SYSTEM_PLL2_DIV4, SYSTEM_PLL1_CLK, + SYSTEM_PLL2_CLK, SYSTEM_PLL3_CLK, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, +[MIPI_CSI2_PHY_REF_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV3, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_CLK, + SYSTEM_PLL2_CLK, EXT_CLK_2, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, +[MIPI_CSI2_ESC_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV10, SYSTEM_PLL1_CLK, + SYSTEM_PLL2_CLK, SYSTEM_PLL3_CLK, EXT_CLK_3, AUDIO_PLL2_CLK, +[PCIE2_CTRL_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV4, SYSTEM_PLL2_DIV5, SYSTEM_PLL1_DIV3, + SYSTEM_PLL1_CLK, SYSTEM_PLL2_DIV2, SYSTEM_PLL2_DIV3, SYSTEM_PLL3_CLK, +[PCIE2_PHY_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL2_DIV2, EXT_CLK_1, + EXT_CLK_2, EXT_CLK_3, EXT_CLK_4, SYSTEM_PLL1_DIV2, +[PCIE2_AUX_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV5, SYSTEM_PLL2_DIV20, SYSTEM_PLL3_CLK, + SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV10, SYSTEM_PLL1_DIV5, SYSTEM_PLL1_DIV4, +[ECSPI3_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV5, SYSTEM_PLL1_DIV20, SYSTEM_PLL1_DIV5, + SYSTEM_PLL1_CLK, SYSTEM_PLL3_CLK, SYSTEM_PLL2_DIV4, AUDIO_PLL2_CLK, +[OLD_MIPI_DSI_ESC_RX_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV10, SYSTEM_PLL1_CLK, + SYSTEM_PLL2_CLK, SYSTEM_PLL3_CLK, EXT_CLK_3, AUDIO_PLL2_CLK, +[DISPLAY_HDMI_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV4, SYSTEM_PLL2_DIV5, VPU_PLL_CLK, + SYSTEM_PLL1_CLK, SYSTEM_PLL2_CLK, SYSTEM_PLL3_CLK, EXT_CLK_4, +}; + +typedef struct Clock Clock; +struct Clock { + char *name; /* clock instance name */ + int root; /* root clock slice */ + int ccgr; /* clock gating register */ +}; + +static Clock clocks[] = { + { "aips_tz1.hclk", AHB_CLK_ROOT, 28 }, + { "ipmux1.master_clk", AHB_CLK_ROOT, 28 }, + { "ipmux1.slave_clk", IPG_CLK_ROOT, 28 }, + + { "aips_tz2.hclk", AHB_CLK_ROOT, 29 }, + { "ipmux2.master_clk", AHB_CLK_ROOT, 29 }, + { "ipmux2.slave_clk", AHB_CLK_ROOT, 29 }, + + { "aips_tz3.hclk", AHB_CLK_ROOT, 30 }, + { "ipmux3.master_clk", AHB_CLK_ROOT, 30 }, + { "ipmux3.slave_clk", IPG_CLK_ROOT, 30 }, + + { "apbhdma.hclk", NAND_USDHC_BUS_CLK_ROOT, 48 }, + { "apdhdma_sec.mst_hclk", NAND_USDHC_BUS_CLK_ROOT, 48 }, + { "rawnand.u_bch_input_apb_clk", NAND_USDHC_BUS_CLK_ROOT, 48 }, + { "u_bch_input_apb_clk", NAND_USDHC_BUS_CLK_ROOT, 48 }, + { "rawnand.u_gpmi_bch_input_gpmi_io_clk", NAND_CLK_ROOT, 48 }, + { "rawnand.U_gpmi_input_apb_clk", NAND_USDHC_BUS_CLK_ROOT, 48 }, + + { "caam.aclk", AHB_CLK_ROOT }, + { "caam.ipg_clk", IPG_CLK_ROOT }, + { "caam.ipg_clk_s", IPG_CLK_ROOT }, + { "caam_exsc.aclk_exsc", AHB_CLK_ROOT }, + { "caam_mem.clk", AHB_CLK_ROOT }, + + { "cm4.cm4_cti_clk", ARM_M4_CLK_ROOT }, + { "cm4.cm4_fclk", ARM_M4_CLK_ROOT }, + { "cm4.cm4_hclk", ARM_M4_CLK_ROOT }, + { "cm4.dap_clk", AHB_CLK_ROOT }, + { "cm4.ipg_clk_nic", ARM_M4_CLK_ROOT }, + { "cm4.tcmc_hclk", ARM_M4_CLK_ROOT }, + { "cm4_mem.tcmc_hclk", ARM_M4_CLK_ROOT }, + { "cm4_sec.ipg_clk", IPG_CLK_ROOT }, + { "cm4_sec.ipg_clk_s", IPG_CLK_ROOT }, + { "cm4_sec.mst_hclk", ARM_M4_CLK_ROOT }, + + { "csi2_1.clk_vid", MIPI_CSI1_PHY_REF_CLK_ROOT }, + { "csi2_1.clk", MIPI_CSI1_CORE_CLK_ROOT, 101}, + { "csi2_1.clk_esc", MIPI_CSI1_ESC_CLK_ROOT, 101}, + { "csi2_1.pclk", MIPI_CSI1_CORE_CLK_ROOT }, + { "csi2_1.clk_ui", MIPI_CSI1_PHY_REF_CLK_ROOT, 101}, + + { "csi2_2.clk_vid", MIPI_CSI2_PHY_REF_CLK_ROOT }, + { "csi2_2.clk", MIPI_CSI2_CORE_CLK_ROOT, 102 }, + { "csi2_2.clk_esc", MIPI_CSI2_ESC_CLK_ROOT, 102 }, + { "csi2_2.pclk", MIPI_CSI2_CORE_CLK_ROOT }, + { "csi2_2.clk_ui", MIPI_CSI2_PHY_REF_CLK_ROOT, 102 }, + + { "csu.ipg_clk_s", IPG_CLK_ROOT, 3}, + + { "dap.dapclk_2_2", AHB_CLK_ROOT, 4}, + + { "ecspi1.ipg_clk", IPG_CLK_ROOT, 7}, + { "ecspi1.ipg_clk_per", ECSPI1_CLK_ROOT, 7}, + { "ecspi1.ipg_clk_s", IPG_CLK_ROOT, 7}, + + { "ecspi2.ipg_clk", IPG_CLK_ROOT, 8}, + { "ecspi2.ipg_clk_per", ECSPI2_CLK_ROOT, 8}, + { "ecspi2.ipg_clk_s", IPG_CLK_ROOT, 8}, + + { "ecspi2.ipg_clk", IPG_CLK_ROOT, 8}, + { "ecspi2.ipg_clk_per", ECSPI2_CLK_ROOT, 8}, + { "ecspi2.ipg_clk_s", IPG_CLK_ROOT, 8}, + + { "ecspi3.ipg_clk", IPG_CLK_ROOT, 9}, + { "ecspi3.ipg_clk_per", ECSPI3_CLK_ROOT, 9}, + { "ecspi3.ipg_clk_s", IPG_CLK_ROOT, 9}, + + { "enet1.ipp_ind_mac0_txclk", ENET_REF_CLK_ROOT, 10 }, + { "enet1.ipg_clk", ENET_AXI_CLK_ROOT, 10 }, + { "enet1.ipg_clk_mac0", ENET_AXI_CLK_ROOT, 10 }, + { "enet1.ipg_clk_mac0_s", ENET_AXI_CLK_ROOT, 10 }, + { "enet1.ipg_clk_s", ENET_AXI_CLK_ROOT, 10 }, + { "enet1.ipg_clk_time", ENET_TIMER_CLK_ROOT, 10 }, + { "enet1.mem.mac0_rxmem_clk", ENET_AXI_CLK_ROOT, 10 }, + { "enet1.mem.mac0_txmem_clk", ENET_AXI_CLK_ROOT, 10 }, + + { "gpio1.ipg_clk_s", IPG_CLK_ROOT, 11 }, + { "gpio2.ipg_clk_s", IPG_CLK_ROOT, 12 }, + { "gpio3.ipg_clk_s", IPG_CLK_ROOT, 13 }, + { "gpio4.ipg_clk_s", IPG_CLK_ROOT, 14 }, + { "gpio5.ipg_clk_s", IPG_CLK_ROOT, 15 }, + + { "gpt1.ipg_clk", GPT1_CLK_ROOT, 16 }, + { "gpt1.ipg_clk_highfreq", GPT1_CLK_ROOT, 16 }, + { "gpt1.ipg_clk_s", GPT1_CLK_ROOT, 16 }, + + { "gpt2.ipg_clk", GPT2_CLK_ROOT, 17 }, + { "gpt2.ipg_clk_highfreq", GPT2_CLK_ROOT, 17 }, + { "gpt2.ipg_clk_s", GPT2_CLK_ROOT, 17 }, + + { "gpt3.ipg_clk", GPT3_CLK_ROOT, 18 }, + { "gpt3.ipg_clk_highfreq", GPT3_CLK_ROOT, 18 }, + { "gpt3.ipg_clk_s", GPT3_CLK_ROOT, 18 }, + + { "gpt4.ipg_clk", GPT4_CLK_ROOT, 19 }, + { "gpt4.ipg_clk_highfreq", GPT4_CLK_ROOT, 19 }, + { "gpt4.ipg_clk_s", GPT4_CLK_ROOT, 19 }, + + { "gpt5.ipg_clk", GPT5_CLK_ROOT, 20 }, + { "gpt5.ipg_clk_highfreq", GPT5_CLK_ROOT, 20 }, + { "gpt5.ipg_clk_s", GPT5_CLK_ROOT, 20 }, + + { "gpt6.ipg_clk", GPT6_CLK_ROOT, 21 }, + { "gpt6.ipg_clk_highfreq", GPT6_CLK_ROOT, 21 }, + { "gpt6.ipg_clk_s", GPT6_CLK_ROOT, 21 }, + + { "i2c1.ipg_clk_patref", I2C1_CLK_ROOT, 23 }, + { "i2c1.iph_clk_s", I2C1_CLK_ROOT, 23 }, + + { "i2c2.ipg_clk_patref", I2C2_CLK_ROOT, 24 }, + { "i2c2.iph_clk_s", I2C2_CLK_ROOT, 24 }, + + { "i2c3.ipg_clk_patref", I2C3_CLK_ROOT, 25 }, + { "i2c3.iph_clk_s", I2C3_CLK_ROOT, 25 }, + + { "i2c4.ipg_clk_patref", I2C4_CLK_ROOT, 26 }, + { "i2c4.iph_clk_s", I2C4_CLK_ROOT, 26 }, + + { "iomuxc.ipg_clk_s", IPG_CLK_ROOT, 27 }, + { "iomuxc_gpr.ipg_clk_s", IPG_CLK_ROOT, 27 }, + { "iomux.ipt_clk_io", IPG_CLK_ROOT, 27 }, + + { "lcdif.pix_clk", LCDIF_PIXEL_CLK_ROOT }, + { "lcdif.apb_clk", MAIN_AXI_CLK_ROOT }, + + { "disp.apb_clk", DISPLAY_APB_CLK_ROOT, 93 }, + { "disp.axi_clk", DISPLAY_AXI_CLK_ROOT, 93 }, + { "disp.rtrm_clk", DISPLAY_RTRM_CLK_ROOT, 93 }, + { "disp.dc8000_clk", DISPLAY_DC8000_CLK_ROOT, 93 }, + { "disp.dtrc_clk", DISPLAY_DTRC_CLK_ROOT }, + + { "mipi.CLKREF", MIPI_DSI_PHY_REF_CLK_ROOT }, + { "mipi.pclk", MAIN_AXI_CLK_ROOT }, + { "mipi.RxClkEsc", MIPI_DSI_ESC_RX_CLK_ROOT }, + { "mipi.TxClkEsc", MIPI_DSI_ESC_CLK_ROOT }, + { "mipi.core", MIPI_DSI_CORE_CLK_ROOT }, + { "mipi.ahb", MIPI_DSI_ESC_RX_CLK_ROOT }, + + { "mu.ipg_clk_dsp", IPG_CLK_ROOT, 33 }, + { "mu.ipg_clk_mcu", IPG_CLK_ROOT, 33 }, + { "mu.ipg_clk_s_dsp", IPG_CLK_ROOT, 33 }, + { "mu.ipg_clk_s_mcu", IPG_CLK_ROOT, 33 }, + + { "ocotp.ipg_clk", IPG_CLK_ROOT, 34 }, + { "ocotp.ipg_clk_s", IPG_CLK_ROOT, 34 }, + + { "ocram_ctrl.clk", MAIN_AXI_CLK_ROOT, 35 }, + { "ocram_excs.aclk_exsc", MAIN_AXI_CLK_ROOT, 35 }, + { "ocram_exsc.ipg_clk", IPG_CLK_ROOT, 35 }, + { "ocram_mem.clk", MAIN_AXI_CLK_ROOT, 35 }, + + { "ocram_ctrl_s.clk", AHB_CLK_ROOT, 36 }, + { "ocram_s_exsc.aclk_exsc", AHB_CLK_ROOT, 36 }, + { "ocram_s_exsc.ipg_clk", IPG_CLK_ROOT, 36 }, + { "ocram_s.mem_clk", AHB_CLK_ROOT, 36 }, + + { "pcie_clk_rst.auxclk", PCIE1_AUX_CLK_ROOT, 37 }, + { "pcie_clk_rst.mstr_axi_clk", MAIN_AXI_CLK_ROOT, 37 }, + { "pcie_clk_rst.slv_axi_clk", MAIN_AXI_CLK_ROOT, 37 }, + { "pcie_ctrl.mstr_aclk", MAIN_AXI_CLK_ROOT, 37 }, + { "pcie_ctrl.slv_aclk", MAIN_AXI_CLK_ROOT, 37 }, + { "pcie_exsc.aclk_exsc", MAIN_AXI_CLK_ROOT, 37 }, + { "pcie_exsc.ipg_clk", IPG_CLK_ROOT, 37 }, + { "pcie_mem.mstr_axi_clk", MAIN_AXI_CLK_ROOT, 37 }, + { "pcie_mem.slv_axi_clk", MAIN_AXI_CLK_ROOT, 37 }, + + { "pcie2_clk_rst.auxclk", PCIE2_AUX_CLK_ROOT, 100 }, + { "pcie2_clk_rst.mstr_axi_clk", MAIN_AXI_CLK_ROOT, 100 }, + { "pcie2_clk_rst.slv_axi_clk", MAIN_AXI_CLK_ROOT, 100 }, + { "pcie2_ctrl.mstr_aclk", MAIN_AXI_CLK_ROOT, 100 }, + { "pcie2_ctrl.slv_aclk", MAIN_AXI_CLK_ROOT, 100 }, + { "pcie2_exsc.aclk_exsc", MAIN_AXI_CLK_ROOT, 100 }, + { "pcie2_exsc.ipg_clk", IPG_CLK_ROOT, 100 }, + { "pcie2_mem.mstr_axi_clk", MAIN_AXI_CLK_ROOT, 100 }, + { "pcie2_mem.slv_axi_clk", MAIN_AXI_CLK_ROOT, 100 }, + + { "pcie_phy.ref_alt_clk_p", PCIE1_PHY_CLK_ROOT }, + { "pcie2_phy.ref_alt_clk_p", PCIE2_PHY_CLK_ROOT }, + + { "perfmon1.apb_clk", IPG_CLK_ROOT, 38 }, + { "perfmon1.axi0_ACLK", MAIN_AXI_CLK_ROOT, 38 }, + + { "perfmon2.apb_clk", IPG_CLK_ROOT, 39 }, + { "perfmon1.axi0_ACLK", MAIN_AXI_CLK_ROOT, 39 }, + + { "pwm1.ipg_clk", PWM1_CLK_ROOT, 40 }, + { "pwm1.ipg_clk_high_freq", PWM1_CLK_ROOT, 40 }, + { "pwm1.ipg_clk_s", PWM1_CLK_ROOT, 40 }, + + { "pwm2.ipg_clk", PWM2_CLK_ROOT, 41 }, + { "pwm2.ipg_clk_high_freq", PWM2_CLK_ROOT, 41 }, + { "pwm2.ipg_clk_s", PWM2_CLK_ROOT, 41 }, + + { "pwm3.ipg_clk", PWM3_CLK_ROOT, 42 }, + { "pwm3.ipg_clk_high_freq", PWM3_CLK_ROOT, 42 }, + { "pwm3.ipg_clk_s", PWM3_CLK_ROOT, 42 }, + + { "pwm4.ipg_clk", PWM4_CLK_ROOT, 43 }, + { "pwm4.ipg_clk_high_freq", PWM4_CLK_ROOT, 43 }, + { "pwm4.ipg_clk_s", PWM4_CLK_ROOT, 43 }, + + { "qspi.ahb_clk", AHB_CLK_ROOT, 47 }, + { "qspi.ipg_clk", IPG_CLK_ROOT, 47 }, + { "qspi.ipg_clk_4xsfif", QSPI_CLK_ROOT, 47 }, + { "qspi.ipg_clk_s", IPG_CLK_ROOT, 47 }, + { "qspi_sec.ipg_clk", IPG_CLK_ROOT, 47 }, + { "qspi_sec.ipg_clk_s", IPG_CLK_ROOT, 47 }, + { "qspi_sec.mst_hclk", AHB_CLK_ROOT, 47 }, + + { "rdc.ipg_clk_s", IPG_CLK_ROOT, 49 }, + { "rdc.ipg_clk", IPG_CLK_ROOT, 49 }, + { "rdc_mem.ipg_clk", IPG_CLK_ROOT, 49 }, + + { "romcp.hclk", AHB_CLK_ROOT, 50 }, + { "romcp.hclk_reg", IPG_CLK_ROOT, 50 }, + { "romcp_mem.rom_CLK", AHB_CLK_ROOT, 50 }, + { "romcp_sec.mst_hclk", AHB_CLK_ROOT, 50 }, + + { "sai1.ipg_clk", AUDIO_IPG_CLK_ROOT, 51 }, + { "sai1.ipg_clk_s", AUDIO_IPG_CLK_ROOT, 51 }, + { "sai1.ipg_clk_sai_mclk_1", SAI1_CLK_ROOT, 51 }, + { "sai1.ipt_clk_sai_bclk", SAI1_CLK_ROOT, 51 }, + { "sai1.ipt_clk_sai_bclk_b", SAI1_CLK_ROOT, 51 }, + + { "sai2.ipg_clk", AUDIO_IPG_CLK_ROOT, 52 }, + { "sai2.ipg_clk_s", AUDIO_IPG_CLK_ROOT, 52 }, + { "sai2.ipg_clk_sai_mclk_1", SAI2_CLK_ROOT, 52 }, + { "sai2.ipt_clk_sai_bclk", SAI2_CLK_ROOT, 52 }, + { "sai2.ipt_clk_sai_bclk_b", SAI1_CLK_ROOT, 52 }, + + { "sai3.ipg_clk", AUDIO_IPG_CLK_ROOT, 53 }, + { "sai3.ipg_clk_s", AUDIO_IPG_CLK_ROOT, 53 }, + { "sai3.ipg_clk_sai_mclk_1", SAI3_CLK_ROOT, 53 }, + { "sai3.ipt_clk_sai_bclk", SAI3_CLK_ROOT, 53 }, + { "sai3.ipt_clk_sai_bclk_b", SAI1_CLK_ROOT, 53 }, + + { "sai4.ipg_clk", AUDIO_IPG_CLK_ROOT, 54 }, + { "sai4.ipg_clk_s", AUDIO_IPG_CLK_ROOT, 54 }, + { "sai4.ipg_clk_sai_mclk_1", SAI4_CLK_ROOT, 54 }, + { "sai4.ipt_clk_sai_bclk", SAI4_CLK_ROOT, 54 }, + { "sai4.ipt_clk_sai_bclk_b", SAI1_CLK_ROOT, 54 }, + + { "sai5.ipg_clk", AUDIO_IPG_CLK_ROOT, 55 }, + { "sai5.ipg_clk_s", AUDIO_IPG_CLK_ROOT, 55 }, + { "sai5.ipg_clk_sai_mclk_1", SAI5_CLK_ROOT, 55 }, + { "sai5.ipt_clk_sai_bclk", SAI5_CLK_ROOT, 55 }, + { "sai5.ipt_clk_sai_bclk_b", SAI1_CLK_ROOT, 55 }, + + { "sai6.ipg_clk", AUDIO_IPG_CLK_ROOT, 56 }, + { "sai6.ipg_clk_s", AUDIO_IPG_CLK_ROOT, 56 }, + { "sai6.ipg_clk_sai_mclk_1", SAI6_CLK_ROOT, 56 }, + { "sai6.ipt_clk_sai_bclk", SAI6_CLK_ROOT, 56 }, + { "sai6.ipt_clk_sai_bclk_b", SAI1_CLK_ROOT, 56 }, + + { "sctr.ipg_clk", IPG_CLK_ROOT, 57 }, + { "sctr.ipg_clk_s", IPG_CLK_ROOT, 57 }, + + { "sdma1.ips_hostctrl_clk", IPG_CLK_ROOT, 58 }, + { "sdma1.sdma_ap_ahb_clk", AHB_CLK_ROOT, 58 }, + { "sdma1.sdma_core_clk", IPG_CLK_ROOT, 58 }, + + { "sdma2.ips_hostctrl_clk", AUDIO_IPG_CLK_ROOT, 59 }, + { "sdma2.sdma_ap_ahb_clk", AUDIO_AHB_CLK_ROOT, 59 }, + { "sdma2.sdma_core_clk", AUDIO_IPG_CLK_ROOT, 59 }, + + { "sec_wrapper.clk", IPG_CLK_ROOT, 60 }, + + { "sema1.clk", IPG_CLK_ROOT, 61 }, + { "sema2.clk", IPG_CLK_ROOT, 62 }, + + { "sim_display.cm4clk", ARM_M4_CLK_ROOT }, + { "sim_display.mainclk", MAIN_AXI_CLK_ROOT, 63 }, + { "sim_display.mainclk_r", MAIN_AXI_CLK_ROOT, 63 }, + { "sim_enet.mainclk", ENET_AXI_CLK_ROOT, 64 }, + { "sim_enet.mainclk_r", ENET_AXI_CLK_ROOT, 64 }, + { "sim_m.mainclk", AHB_CLK_ROOT, 65 }, + { "sim_m.mainclk_r", AHB_CLK_ROOT, 65 }, + { "sim_m.usdhcclk", NAND_USDHC_BUS_CLK_ROOT, 65 }, + { "sim_m.usdhcclk_r", NAND_USDHC_BUS_CLK_ROOT, 65 }, + { "sim_main.cm4clk", ARM_M4_CLK_ROOT }, + { "sim_main.enetclk", ENET_AXI_CLK_ROOT, 64 }, + { "sim_main.mainclk", MAIN_AXI_CLK_ROOT, 66 }, + { "sim_main,mainclk_r", MAIN_AXI_CLK_ROOT, 66 }, + { "sim_main.per_mclk", AHB_CLK_ROOT, 65 }, + { "sim_main.per_sclk", AHB_CLK_ROOT, 67 }, + { "sim_main.usdhcclk", NAND_USDHC_BUS_CLK_ROOT, 65 }, + { "sim_main.wakeupclk", AHB_CLK_ROOT, 68 }, + { "sim_s.apbhdmaclk", NAND_USDHC_BUS_CLK_ROOT, 48 }, + { "sim_s.gpv4clk", ENET_AXI_CLK_ROOT, 64 }, + { "sim_s.mainclk", AHB_CLK_ROOT, 67 }, + { "sim_s.mainclk_r", AHB_CLK_ROOT, 67 }, + { "sim_s.weimclk", AHB_CLK_ROOT }, + { "sim_wakeup.mainclk", AHB_CLK_ROOT, 68 }, + { "sim_wakeup.mainclk_r", AHB_CLK_ROOT, 68 }, + { "pl301_audio.displayclk", MAIN_AXI_CLK_ROOT, 63 }, + + { "snvs_hs_wrapper.ipg_clk", IPG_CLK_ROOT, 71 }, + { "snvs_hs.wrapper.ipg_clk_s", IPG_CLK_ROOT, 71 }, + { "snvsmix.ipg_clk_root", IPG_CLK_ROOT }, + + { "spba1.ipg_clk", IPG_CLK_ROOT, 30 }, + { "spba1.ipg_clk_s", IPG_CLK_ROOT, 30 }, + + { "spba2.ipg_clk", AUDIO_IPG_CLK_ROOT }, + { "spba2.ipg_clk_s", AUDIO_IPG_CLK_ROOT }, + + { "spdif1.gclkw_t0", SPDIF1_CLK_ROOT}, + { "spdif1.ipg_clk_s", IPG_CLK_ROOT}, + { "spdif1.tx_clk", SPDIF1_CLK_ROOT}, + { "spdif1.tx_clk1", SPDIF1_CLK_ROOT}, + { "spdif1.tx_clk3", SPDIF1_CLK_ROOT}, + { "spdif1.tx_clk4", SPDIF1_CLK_ROOT}, + { "spdif1.tx_clk5", SPDIF1_CLK_ROOT}, + + { "spdif2.gclkw_t0", SPDIF2_CLK_ROOT}, + { "spdif2.ipg_clk_s", IPG_CLK_ROOT}, + { "spdif2.tx_clk", SPDIF2_CLK_ROOT}, + { "spdif2.tx_clk1", SPDIF2_CLK_ROOT}, + { "spdif2.tx_clk3", SPDIF2_CLK_ROOT}, + { "spdif2.tx_clk4", SPDIF2_CLK_ROOT}, + { "spdif2.tx_clk5", SPDIF2_CLK_ROOT}, + + { "coresight.DBGCLK", MAIN_AXI_CLK_ROOT, 72 }, + { "coresight.traceclkin", TRACE_CLK_ROOT, 72 }, + { "coresight_mem.cs_etf_clk", MAIN_AXI_CLK_ROOT, 72 }, + + { "uart1.ipg_clk", IPG_CLK_ROOT, 73 }, + { "uart1.ipg_clk_s", IPG_CLK_ROOT, 73 }, + { "uart1.ipg_perclk", UART1_CLK_ROOT, 73 }, + + { "uart2.ipg_clk", IPG_CLK_ROOT, 74 }, + { "uart2.ipg_clk_s", IPG_CLK_ROOT, 74 }, + { "uart2.ipg_perclk", UART2_CLK_ROOT, 74 }, + + { "uart3.ipg_clk", IPG_CLK_ROOT, 75 }, + { "uart3.ipg_clk_s", IPG_CLK_ROOT, 75 }, + { "uart3.ipg_perclk", UART3_CLK_ROOT, 75 }, + + { "uart4.ipg_clk", IPG_CLK_ROOT, 76 }, + { "uart4.ipg_clk_s", IPG_CLK_ROOT, 76 }, + { "uart4.ipg_perclk", UART4_CLK_ROOT, 76 }, + + { "usb.clk", IPG_CLK_ROOT, 22 }, /* HS */ + + { "usb1.ctrl", IPG_CLK_ROOT, 77 }, /* what is the root clock? */ + { "usb2.ctrl", IPG_CLK_ROOT, 78 }, + { "usb1.phy", IPG_CLK_ROOT, 79 }, /* what is the root clock? */ + { "usb2.phy", IPG_CLK_ROOT, 80 }, + + { "usdhc1.hclk", NAND_USDHC_BUS_CLK_ROOT, 81 }, + { "usdhc1.ipg_clk", IPG_CLK_ROOT, 81 }, + { "usdhc1.ipg_clk_s", IPG_CLK_ROOT, 81 }, + { "usdhc1.ipg_clk_perclk", USDHC1_CLK_ROOT, 81 }, + + { "usdhc2.hclk", NAND_USDHC_BUS_CLK_ROOT, 82 }, + { "usdhc2.ipg_clk", IPG_CLK_ROOT, 82 }, + { "usdhc2.ipg_clk_s", IPG_CLK_ROOT, 82 }, + { "usdhc2.ipg_clk_perclk", USDHC2_CLK_ROOT, 82 }, + + { "wdog1.ipg_clk", WDOG_CLK_ROOT, 83 }, + { "wdog1.ipg_clk_s", WDOG_CLK_ROOT, 83 }, + + { "wdog2.ipg_clk", WDOG_CLK_ROOT, 84 }, + { "wdog2.ipg_clk_s", WDOG_CLK_ROOT, 84 }, + + { "wdog3.ipg_clk", WDOG_CLK_ROOT, 85 }, + { "wdog3.ipg_clk_s", WDOG_CLK_ROOT, 85 }, + + { 0 } +}; + +static void +enablefracpll(u32int *reg, int ref_sel, int ref_freq, int freq) +{ + int divq, divr, ref, divfi, divff, pllout, error; + u32int cfg0, cfg1; + vlong v; + + cfg0 = reg[0]; + cfg1 = reg[1]; + + error = freq; + for(divq = 2; divq <= 64; divq += 2){ + for(divr = 1; divr <= 64; divr++){ + ref = ref_freq/divr; + if(ref < 10*Mhz || ref > 300*Mhz) + continue; + + ref *= 8; + divfi = ((vlong)freq*divq) / ref; + if(divfi < 1 || divfi > 32) + continue; + + v = ((vlong)freq*divq) - (vlong)ref*divfi; + divff = (v<<24) / ref; + if(divff < 1 || divff > (1<<24)) + continue; + + v = (vlong)ref*(vlong)divff; + pllout = (ref*divfi + (v>>24))/divq; + if(pllout < 30*Mhz || pllout > 2000*Mhz) + continue; + + if(pllout > freq) + continue; + + if(freq - pllout > error) + continue; + +// iprint("%p enablefracpll: freq=%d (actual %d)\n", PADDR(reg), freq, pllout); + + cfg0 = 1<<21 | ref_sel<<16 | 1<<15 | (divr-1)<<5 | (divq/2)-1; + cfg1 = divff<<7 | divfi-1; + + error = freq - pllout; + if(error == 0) + goto Found; + } + } + +Found: + /* skip if nothing has changed */ + if(((reg[0] ^ cfg0) & (1<<21 | 3<<16 | 1<<15 | 0x3F<<5 | 0x1F)) == 0 + && ((reg[1] ^ cfg1) & ~(1<<31)) == 0) + return; + + reg[0] |= 1<<14; /* bypass */ + +// iprint("%p cfg1=%.8ux\n", PADDR(reg), cfg1); + reg[1] = cfg1; + +// iprint("%p cfg0=%.8ux\n", PADDR(reg), cfg0); + reg[0] = cfg0 | (1<<14) | (1<<12); + + /* unbypass */ + reg[0] &= ~(1<<14); + +// iprint("%p wait for lock...", PADDR(reg)); + while((reg[0] & (1<<31)) == 0) + ; +// iprint("locked!\n"); + reg[0] &= ~(1<<12); +} + +static void +enablepll(int input) +{ + u32int old, val = 2; + + if(input < 0 || input > 38 || input_clk_freq[input] <= 0) + return; + + /* CCM_PLL_CTRL */ + old = regs[(0x800/4) + (16/4)*input] & 3; + if(old < val){ +// iprint("ccm: %s PLL_CTRL%d %.ux->%.ux\n", input_clk_name[input], input, old, val); + regs[(0x800/4) + (16/4)*input] = val; + } + + switch(input){ + case AUDIO_PLL1_CLK: + enablefracpll(&anatop[0x00/4], 0, 25*Mhz, input_clk_freq[input]); + break; + case AUDIO_PLL2_CLK: + enablefracpll(&anatop[0x08/4], 0, 25*Mhz, input_clk_freq[input]); + break; + case VIDEO_PLL1_CLK: + enablefracpll(&anatop[0x10/4], 0, 25*Mhz, input_clk_freq[input]); + break; + case GPU_PLL_CLK: + enablefracpll(&anatop[0x18/4], 0, 25*Mhz, input_clk_freq[input]); + break; + case VPU_PLL_CLK: + enablefracpll(&anatop[0x20/4], 0, 25*Mhz, input_clk_freq[input]); + break; + case ARM_PLL_CLK: + enablefracpll(&anatop[0x28/4], 0, 25*Mhz, input_clk_freq[input]); + break; + } +} + +static u32int +clkgate(Clock *gate, u32int val) +{ + u32int old; + + if(gate == nil || gate->ccgr == 0) + return 0; + + /* CCM_CCGR */ + old = regs[(0x4000/4) + (16/4)*gate->ccgr] & 3; + if(old != val){ +// if(gate->ccgr != 73) iprint("ccm: %s CCGR%d %.ux->%.ux\n", gate->name, gate->ccgr, old, val); + regs[(0x4000/4) + (16/4)*gate->ccgr] = val; + } + return old; +} + +static int +rootclkisipg(int root) +{ + switch(root){ + case IPG_CLK_ROOT: + case AUDIO_IPG_CLK_ROOT: + case MIPI_DSI_ESC_CLK_ROOT: + return 1; + } + return 0; +} + +static u32int +gettarget(int root) +{ + u32int val = regs[(0x8000/4) + (128/4)*root]; +// if(root != UART1_CLK_ROOT) iprint("ccm: %s TARGET_ROOT%d -> %.8ux\n", root_clk_name[root], root, val); + return val; +} + +static void +settarget(int root, Clock *gate, u32int val) +{ + if(gate != nil){ + for(; gate->name != nil; gate++){ + u32int old; + + if(gate->root != root) + continue; + + old = clkgate(gate, 0); + if(old == 0) + continue; + + /* skip restore when root is being disabled */ + if((val & (1<<28)) == 0) + continue; + + /* now change the root clock target */ + settarget(root, gate+1, val); + + /* restore gate */ + clkgate(gate, old); + return; + } + } + + if(rootclkisipg(root)) + val &= ~(1<<28); +// if(root != UART1_CLK_ROOT) iprint("ccm: %s TARGET_ROOT%d <- %.8ux\n", root_clk_name[root], root, val); + regs[(0x8000/4) + (128/4)*root] = val; +} + +static int +rootclkgetcfg(int root, int *input) +{ + u32int t = gettarget(root); + int freq = input_clk_freq[*input = root_clk_input_mux[root*8 + ((t >> 24)&7)]]; + int pre_podf = (t >> 16)&7; + int post_podf = (t >> 0)&0x3F; + + /* return negative frequency if disabled */ + if((t & (1<<28)) == 0) + freq = -freq; + + switch(root){ + case ARM_A53_CLK_ROOT: + case ARM_M4_CLK_ROOT: + case VPU_A53_CLK_ROOT: + case GPU_CORE_CLK_ROOT: + case GPU_SHADER_CLK_ROOT: + post_podf &= 7; + /* wet floor */ + case GPU_AXI_CLK_ROOT: + case GPU_AHB_CLK_ROOT: + case NOC_CLK_ROOT: + pre_podf = 0; + break; + case IPG_CLK_ROOT: + case AUDIO_IPG_CLK_ROOT: + post_podf &= 1; + case MIPI_DSI_ESC_CLK_ROOT: + freq = rootclkgetcfg(root-1, input); + /* wet floor */ + case AHB_CLK_ROOT: + case AUDIO_AHB_CLK_ROOT: + case MIPI_DSI_ESC_RX_CLK_ROOT: + pre_podf = 0; + break; + } + freq /= pre_podf+1; + freq /= post_podf+1; + + return freq; +} + +static void +rootclksetcfg(int root, int input, int freq) +{ + u32int t = gettarget(root); + + if(!rootclkisipg(root)){ + int mux; + + for(mux = 0; mux < 8; mux++){ + if(root_clk_input_mux[root*8 + mux] == input){ + t = (t & ~(7<<24)) | (mux << 24); + goto Muxok; + } + } + panic("rootclksetcfg: invalid input clock %d for TARGET_ROOT%d\n", input, root); +Muxok:; + } + /* disable by default */ + t &= ~(1 << 28); + + if(freq){ + int pre_mask, pre_podf, post_mask, post_podf; + int error, input_freq = input_clk_freq[input]; + + if(freq < 0) { + /* set dividers but keep disabled */ + freq = -freq; + } else { + /* set dividers and enable */ + t |= (1 << 28); + } + + pre_mask = 7; + post_mask = 0x3F; + + switch(root){ + case ARM_A53_CLK_ROOT: + case ARM_M4_CLK_ROOT: + case VPU_A53_CLK_ROOT: + case GPU_CORE_CLK_ROOT: + case GPU_SHADER_CLK_ROOT: + post_mask = 7; + /* wet floor */ + case GPU_AXI_CLK_ROOT: + case GPU_AHB_CLK_ROOT: + case NOC_CLK_ROOT: + pre_mask = 0; + break; + case IPG_CLK_ROOT: + case AUDIO_IPG_CLK_ROOT: + post_mask = 1; + case MIPI_DSI_ESC_CLK_ROOT: + input_freq = rootclkgetcfg(root-1, &input); + /* wet floor */ + case AHB_CLK_ROOT: + case AUDIO_AHB_CLK_ROOT: + case MIPI_DSI_ESC_RX_CLK_ROOT: + pre_mask = 0; + break; + } + if(input_freq < 0) input_freq = -input_freq; + + + error = freq; + for(pre_podf = 0; pre_podf <= pre_mask; pre_podf++){ + for(post_podf = 0; post_podf <= post_mask; post_podf++){ + int f = input_freq; + f /= pre_podf+1; + f /= post_podf+1; + if(f <= freq && (freq - f) < error){ + t = (t & ~(7<<16)) | (pre_podf << 16); + t = (t & ~0x3F) | post_podf; + error = freq - f; + if(error == 0) + break; + } + } + } + if(error >= freq) + panic("rootclksetcfg: frequency %d invalid for TARGET_ROOT%d\n", freq, root); + if(t & (1<<28)) + enablepll(input); + } + settarget(root, clocks, t); +} + +static int +lookinputclk(char *name) +{ + int i; + + for(i = 0; i < nelem(input_clk_name); i++){ + if(input_clk_name[i] != nil + && cistrcmp(name, input_clk_name[i]) == 0) + return i; + } + + return -1; +} + +static Clock* +lookmodclk(char *name) +{ + Clock *clk; + + for(clk = clocks; clk->name != nil; clk++){ + if(cistrcmp(name, clk->name) == 0) + return clk; + } + + return nil; +} + +static int +lookrootclk(char *name) +{ + Clock *clk; + int i; + + for(i = 0; i < nelem(root_clk_name); i++){ + if(root_clk_name[i] != nil + && cistrcmp(name, root_clk_name[i]) == 0) + return i; + } + + if((clk = lookmodclk(name)) != nil) + return clk->root; + + return -1; +} + +void +setclkgate(char *name, int on) +{ + clkgate(lookmodclk(name), on ? 3 : 0); +} + +void +setclkrate(char *name, char *source, int freq) +{ + int root, input; + + if((root = lookrootclk(name)) < 0) + panic("setclkrate: clock %s not defined", name); + if(source == nil) + rootclkgetcfg(root, &input); + else { + if((input = lookinputclk(source)) < 0) + panic("setclkrate: input clock %s not defined", source); + } + rootclksetcfg(root, input, freq); +} + +int +getclkrate(char *name) +{ + int root, input; + + if((root = lookrootclk(name)) >= 0) + return rootclkgetcfg(root, &input); + + if((input = lookinputclk(name)) > 0) + return input_clk_freq[input]; + + panic("getclkrate: clock %s not defined", name); + return -1; +} diff --git a/sys/src/9/imx8/etherimx.c b/sys/src/9/imx8/etherimx.c index 7a78c4c9d..9b816920f 100644 --- a/sys/src/9/imx8/etherimx.c +++ b/sys/src/9/imx8/etherimx.c @@ -9,7 +9,10 @@ #include "../port/ethermii.h" enum { - Moduleclk = 125000000, /* 125Mhz */ + Ptpclk = 100*Mhz, + Busclk = 266*Mhz, + Txclk = 125*Mhz, + Maxtu = 1518, R_BUF_SIZE = ((Maxtu+BLOCKALIGN-1)&~BLOCKALIGN), @@ -231,6 +234,7 @@ struct Ctlr struct { Mii; + int done; Rendez; } mii[1]; @@ -245,7 +249,7 @@ static int mdiodone(void *arg) { Ctlr *ctlr = arg; - return rr(ctlr, ENET_EIR) & INT_MII; + return ctlr->mii->done || (rr(ctlr, ENET_EIR) & INT_MII) != 0; } static int mdiowait(Ctlr *ctlr) @@ -265,9 +269,13 @@ mdiow(Mii* mii, int phy, int addr, int data) Ctlr *ctlr = mii->ctlr; data &= 0xFFFF; + wr(ctlr, ENET_EIR, INT_MII); + ctlr->mii->done = 0; + wr(ctlr, ENET_MMFR, MMFR_WR | MMFR_ST | MMFR_TA | phy<ctlr; wr(ctlr, ENET_EIR, INT_MII); + ctlr->mii->done = 0; + wr(ctlr, ENET_MMFR, MMFR_RD | MMFR_ST | MMFR_TA | phy<rx); if(e & INT_TXF) wakeup(ctlr->tx); - if(e & INT_MII) wakeup(ctlr->mii); + if(e & INT_MII) { + ctlr->mii->done = 1; + wakeup(ctlr->mii); + } + wr(ctlr, ENET_EIR, e); } static void @@ -450,13 +463,11 @@ linkproc(void *arg) Ether *edev = arg; Ctlr *ctlr = edev->ctlr; MiiPhy *phy; - int link = -1; + int link = 0; while(waserror()) ; - - miiane(ctlr->mii, ~0, AnaAP|AnaP, ~0); - + miiane(ctlr->mii, ~0, ~0, ~0); for(;;){ miistatus(ctlr->mii); phy = ctlr->mii->curphy; @@ -505,7 +516,7 @@ linkproc(void *arg) edev->mbps = phy->speed; wr(ctlr, ENET_RDAR, RDAR_ACTIVE); - } + } edev->link = link; print("#l%d: link %d speed %d\n", edev->ctlrno, edev->link, edev->mbps); } @@ -532,7 +543,7 @@ attach(Ether *edev) wr(ctlr, ENET_RCR, RCR_MII_MODE | RCR_RGMII_EN | Maxtu<intmask |= INT_MII; wr(ctlr, ENET_EIMR, ctlr->intmask); @@ -586,8 +597,8 @@ attach(Ether *edev) wr(ctlr, ENET_TFWR, TFWR_STRFWD); /* interrupt coalescing: 200 pkts, 1000 µs */ - wr(ctlr, ENET_RXIC0, IC_EN | 200<intmask |= INT_TXF | INT_RXF; wr(ctlr, ENET_EIMR, ctlr->intmask); @@ -688,6 +699,33 @@ pnp(Ether *edev) edev->mbps = 1000; edev->maxmtu = Maxtu; + iomuxpad("pad_enet_mdc", "enet1_mdc", "~LVTTL ~HYS ~PUE ~ODE SLOW 75_OHM"); + iomuxpad("pad_enet_mdio", "enet1_mdio", "~LVTTL ~HYS ~PUE ODE SLOW 75_OHM"); + + iomuxpad("pad_enet_td3", "enet1_rgmii_td3", "~LVTTL ~HYS ~PUE ~ODE MAX 40_OHM"); + iomuxpad("pad_enet_td2", "enet1_rgmii_td2", "~LVTTL ~HYS ~PUE ~ODE MAX 40_OHM"); + iomuxpad("pad_enet_td1", "enet1_rgmii_td1", "~LVTTL ~HYS ~PUE ~ODE MAX 40_OHM"); + iomuxpad("pad_enet_td0", "enet1_rgmii_td0", "~LVTTL ~HYS ~PUE ~ODE MAX 40_OHM"); + iomuxpad("pad_enet_tx_ctl", "enet1_rgmii_tx_ctl", "~LVTTL ~HYS ~PUE ~ODE MAX 40_OHM VSEL_0"); + iomuxpad("pad_enet_txc", "enet1_rgmii_txc", "~LVTTL ~HYS ~PUE ~ODE MAX 40_OHM"); + + iomuxpad("pad_enet_rxc", "enet1_rgmii_rxc", "~LVTTL HYS ~PUE ~ODE FAST 255_OHM"); + iomuxpad("pad_enet_rx_ctl", "enet1_rgmii_rx_ctl", "~LVTTL HYS ~PUE ~ODE FAST 255_OHM"); + iomuxpad("pad_enet_rd0", "enet1_rgmii_rd0", "~LVTTL HYS ~PUE ~ODE FAST 255_OHM"); + iomuxpad("pad_enet_rd1", "enet1_rgmii_rd1", "~LVTTL HYS ~PUE ~ODE FAST 255_OHM"); + iomuxpad("pad_enet_rd2", "enet1_rgmii_rd2", "~LVTTL HYS ~PUE ~ODE FAST 255_OHM"); + iomuxpad("pad_enet_rd3", "enet1_rgmii_rd3", "~LVTTL HYS ~PUE ~ODE FAST 255_OHM"); + + setclkgate("enet1.ipp_ind_mac0_txclk", 0); + setclkgate("sim_enet.mainclk", 0); + + setclkrate("enet1.ipg_clk", "system_pll1_div3", Busclk); + setclkrate("enet1.ipp_ind_mac0_txclk", "system_pll2_div8", Txclk); + setclkrate("enet1.ipg_clk_time", "system_pll2_div10", Ptpclk); + + setclkgate("enet1.ipp_ind_mac0_txclk", 1); + setclkgate("sim_enet.mainclk", 1); + if(reset(edev) < 0) return -1; diff --git a/sys/src/9/imx8/fns.h b/sys/src/9/imx8/fns.h index 146216073..735225372 100644 --- a/sys/src/9/imx8/fns.h +++ b/sys/src/9/imx8/fns.h @@ -80,6 +80,7 @@ extern void meminit(void); extern void putasid(Proc*); extern void* ucalloc(usize); +extern void* fbmemalloc(usize); /* clock */ extern void clockinit(void); @@ -138,3 +139,23 @@ extern void writeconf(void); extern int isaconfig(char*, int, ISAConf*); extern void links(void); + +/* ccm */ +extern void setclkgate(char *name, int on); +extern void setclkrate(char *name, char *source, int freq); +extern int getclkrate(char *name); + +/* gpc */ +extern void powerup(char *dom); + +/* lcd */ +extern void lcdinit(void); + +/* iomux */ +extern void iomuxpad(char *pads, char *sel, char *cfg); +extern uint iomuxgpr(int gpr, uint set, uint mask); + +/* gpio */ +#define GPIO_PIN(n, m) ((n)<<5 | (m)) +extern void gpioout(uint pin, int set); +extern int gpioin(uint pin); diff --git a/sys/src/9/imx8/gpc.c b/sys/src/9/imx8/gpc.c new file mode 100644 index 000000000..5b3ef8794 --- /dev/null +++ b/sys/src/9/imx8/gpc.c @@ -0,0 +1,63 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" + +/* power gating controller registers */ +enum { + GPC_PGC_CPU_0_1_MAPPING = 0xEC/4, + GPC_PGC_PU_PGC_SW_PUP_REQ = 0xF8/4, + GPC_PGC_PU_PGC_SW_PDN_REQ = 0x104/4, +}; + +static u32int *gpc = (u32int*)(VIRTIO + 0x3A0000); + +typedef struct Tab Tab; +struct Tab { + char *dom; + uint mask; +}; + +static Tab pu_tab[] = { + "mipi", 1<<0, + "pcie", 1<<1, + "usb_otg1", 1<<2, + "usb_otg2", 1<<3, + "ddr1", 1<<5, + "ddr2", 1<<6, + "gpu", 1<<7, + "vpu", 1<<8, + "hdmi", 1<<9, + "disp", 1<<10, + "mipi_csi1", 1<<11, + "mipi_csi2", 1<<12, + "pcie2", 1<<13, + + nil, +}; + +void +powerup(char *dom) +{ + Tab *t; + + if(dom == nil) + return; + + for(t = pu_tab; t->dom != nil; t++) + if(cistrcmp(dom, t->dom) == 0) + goto Found; + + panic("powerup: domain %s not defined", dom); + +Found: + gpc[GPC_PGC_CPU_0_1_MAPPING] = 0x0000FFFF; + + gpc[GPC_PGC_PU_PGC_SW_PUP_REQ] |= t->mask; + while(gpc[GPC_PGC_PU_PGC_SW_PUP_REQ] & t->mask) + ; + + gpc[GPC_PGC_CPU_0_1_MAPPING] = 0; +} diff --git a/sys/src/9/imx8/gpio.c b/sys/src/9/imx8/gpio.c new file mode 100644 index 000000000..0fdb3aefd --- /dev/null +++ b/sys/src/9/imx8/gpio.c @@ -0,0 +1,82 @@ +#include "u.h" +#include "../port/lib.h" +#include "../port/error.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" + +/* gpio registers */ +enum { + GPIO_DR = 0x00/4, + GPIO_GDIR = 0x04/4, + GPIO_PSR = 0x08/4, + GPIO_ICR1 = 0x0C/4, + GPIO_ICR2 = 0x10/4, + GPIO_IMR = 0x14/4, + GPIO_ISR = 0x18/4, + GPIO_EDGE_SEL = 0x1C/4, +}; + +typedef struct Ctlr Ctlr; +struct Ctlr +{ + u32int *reg; + char *clk; + u32int dir; + int enabled; +}; + +static Ctlr ctlrs[5] = { + {(u32int*)(VIRTIO + 0x200000), "gpio1.ipg_clk_s" }, + {(u32int*)(VIRTIO + 0x210000), "gpio2.ipg_clk_s" }, + {(u32int*)(VIRTIO + 0x220000), "gpio3.ipg_clk_s" }, + {(u32int*)(VIRTIO + 0x230000), "gpio4.ipg_clk_s" }, + {(u32int*)(VIRTIO + 0x240000), "gpio5.ipg_clk_s" }, +}; + +static Ctlr* +enable(uint pin) +{ + Ctlr *ctlr; + + pin /= 32; + if(pin < 1 || pin > nelem(ctlrs)) + return nil; + + ctlr = &ctlrs[pin-1]; + if(!ctlr->enabled){ + setclkgate(ctlr->clk, 1); + ctlr->reg[GPIO_IMR] = 0; + ctlr->dir = ctlr->reg[GPIO_GDIR]; + ctlr->enabled = 1; + } + return ctlr; +} + +void +gpioout(uint pin, int set) +{ + u32int bit = 1 << (pin % 32); + Ctlr *ctlr = enable(pin); + if(ctlr == nil) + return; + if((ctlr->dir & bit) == 0) + ctlr->reg[GPIO_GDIR] = ctlr->dir |= bit; + if(set) + ctlr->reg[GPIO_DR] |= bit; + else + ctlr->reg[GPIO_DR] &= ~bit; +} + +int +gpioin(uint pin) +{ + u32int bit = 1 << (pin % 32); + Ctlr *ctlr = enable(pin); + if(ctlr == nil) + return -1; + if(ctlr->dir & bit) + ctlr->reg[GPIO_GDIR] = ctlr->dir &= ~bit; + return (ctlr->reg[GPIO_DR] & bit) != 0; +} diff --git a/sys/src/9/imx8/i2cimx.c b/sys/src/9/imx8/i2cimx.c new file mode 100644 index 000000000..41e297697 --- /dev/null +++ b/sys/src/9/imx8/i2cimx.c @@ -0,0 +1,270 @@ +#include "u.h" +#include "../port/lib.h" +#include "../port/error.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "../port/i2c.h" + +enum { + Moduleclk = 25*Mhz, + + I2C_IADR = 0x00, + I2C_IFDR = 0x04, + I2C_I2CR = 0x08, + I2CR_IEN = 1<<7, + I2CR_IIEN = 1<<6, + I2CR_MSTA = 1<<5, + I2CR_MTX = 1<<4, + I2CR_TXAK = 1<<3, + I2CR_RSTA = 1<<2, + I2C_I2SR = 0x0C, + I2SR_ICF = 1<<7, + I2SR_IAAS = 1<<6, + I2SR_IBB = 1<<5, + I2SR_IAL = 1<<4, + I2SR_SRW = 1<<2, + I2SR_IIF = 1<<1, + I2SR_RXAK = 1<<0, + I2C_I2DR = 0x10, +}; + +typedef struct Ctlr Ctlr; +struct Ctlr +{ + void *regs; + int irq; + + Rendez; +}; + +static void +interrupt(Ureg*, void *arg) +{ + I2Cbus *bus = arg; + Ctlr *ctlr = bus->ctlr; + wakeup(ctlr); +} + +static int +haveirq(void *arg) +{ + uchar *regs = arg; + return regs[I2C_I2SR] & (I2SR_IAL|I2SR_IIF); +} + +static int +waitsr(Ctlr *ctlr, int inv, int mask) +{ + uchar *regs = ctlr->regs; + int sr; + + for(;;){ + sr = regs[I2C_I2SR]; + if(sr & I2SR_IAL){ + regs[I2C_I2SR] = sr & ~(I2SR_IAL|I2SR_IIF); + break; + } + if(sr & I2SR_IIF) + regs[I2C_I2SR] = sr & ~I2SR_IIF; + if((sr ^ inv) & mask) + break; + + /* polling mode */ + if(up == nil || !islo()) + continue; + + tsleep(ctlr, haveirq, regs, 1); + } + return sr ^ inv; +} + +static uchar dummy; + +static int +io(I2Cbus *bus, uchar *pkt, int olen, int ilen) +{ + Ctlr *ctlr = bus->ctlr; + uchar *regs = ctlr->regs; + int cr, sr, alen, o, i; + + cr = regs[I2C_I2CR]; + if((cr & I2CR_IEN) == 0) + return -1; + + o = 0; + if(olen <= 0) + goto Stop; + + alen = 1; + if((pkt[0] & 0xF8) == 0xF0 && olen > alen) + alen++; + + regs[I2C_IADR] = (pkt[0]&0xFE)^0xFE; /* make sure doesnt match */ + + /* wait for bus idle */ + waitsr(ctlr, I2SR_IBB, I2SR_IBB); + + /* start */ + cr |= I2CR_MSTA | I2CR_MTX | I2CR_TXAK | I2CR_IIEN; + regs[I2C_I2CR] = cr; + + /* wait for bus busy */ + if(waitsr(ctlr, 0, I2SR_IBB) & I2SR_IAL) + goto Err; + + if(olen > alen) + pkt[0] &= ~1; + + for(o=0; octlr; + uchar *regs = ctlr->regs; + + clkenable(bus->name, 1); + + regs[I2C_IFDR] = divindex(Moduleclk / bus->speed); + regs[I2C_IADR] = 0; + + regs[I2C_I2CR] = I2CR_IEN; + delay(1); + + intrenable(ctlr->irq, interrupt, bus, BUSUNKNOWN, bus->name); + + return 0; +} + +static Ctlr ctlr1 = { + .regs = (void*)(VIRTIO + 0xA20000), + .irq = IRQi2c1, +}; +static Ctlr ctlr2 = { + .regs = (void*)(VIRTIO + 0xA30000), + .irq = IRQi2c2, +}; +static Ctlr ctlr3 = { + .regs = (void*)(VIRTIO + 0xA40000), + .irq = IRQi2c3, +}; +static Ctlr ctlr4 = { + .regs = (void*)(VIRTIO + 0xA50000), + .irq = IRQi2c4, +}; + +void +i2cimxlink(void) +{ + static I2Cbus i2c1 = { "i2c1", 400000, &ctlr1, init, io }; + static I2Cbus i2c3 = { "i2c3", 400000, &ctlr3, init, io }; + static I2Cbus i2c4 = { "i2c4", 400000, &ctlr4, init, io }; + + iomuxpad("pad_i2c1_sda", "i2c1_sda", "SION ~LVTTL ~HYS PUE ODE MAX 40_OHM"); + iomuxpad("pad_i2c1_scl", "i2c1_scl", "SION ~LVTTL ~HYS PUE ODE MAX 40_OHM"); + addi2cbus(&i2c1); + + iomuxpad("pad_i2c3_sda", "i2c3_sda", "SION ~LVTTL ~HYS PUE ODE MAX 40_OHM"); + iomuxpad("pad_i2c3_scl", "i2c3_scl", "SION ~LVTTL ~HYS PUE ODE MAX 40_OHM VSEL_0"); + addi2cbus(&i2c3); + + iomuxpad("pad_i2c4_sda", "i2c4_sda", "SION ~LVTTL ~HYS PUE ODE MAX 40_OHM"); + iomuxpad("pad_i2c4_scl", "i2c4_scl", "SION ~LVTTL ~HYS PUE ODE MAX 40_OHM"); + addi2cbus(&i2c4); +} diff --git a/sys/src/9/imx8/io.h b/sys/src/9/imx8/io.h index ddd558ad9..38a1ce0f3 100644 --- a/sys/src/9/imx8/io.h +++ b/sys/src/9/imx8/io.h @@ -7,6 +7,9 @@ enum { IRQcntps = PPI+13, IRQcntpns = PPI+14, + IRQusdhc1 = SPI+22, + IRQusdhc2 = SPI+23, + IRQuart1 = SPI+26, IRQuart2 = SPI+27, IRQuart3 = SPI+28, diff --git a/sys/src/9/imx8/iomux.c b/sys/src/9/imx8/iomux.c new file mode 100644 index 000000000..9aed7562c --- /dev/null +++ b/sys/src/9/imx8/iomux.c @@ -0,0 +1,1139 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" + +static u32int *iomuxc = (u32int*)(VIRTIO + 0x330000); + +enum { + IOMUXC_SW_MUX_CTL_PAD_PMIC_STBY_REQ = 0x014/4, + SION = 1<<4, + MUX_MODE = 7, + + IOMUXC_SW_PAD_CTL_PAD_TEST_MODE = 0x254/4, + + IOMUXC_CCM_PMIC_READY_SELECT_INPUT = 0x4BC/4, + + IOMUXC_GPR_GPR0 = 0x10000/4, +}; + +enum { + /* pads without muxes */ + PAD_TEST_MODE = 0, + + PAD_BOOT_MODE0, PAD_BOOT_MODE1, + + PAD_JTAG_MOD, PAD_JTAG_TRST_B, PAD_JTAG_TDI, PAD_JTAG_TMS, + PAD_JTAG_TCK, PAD_JTAG_TDO, + + PAD_RTC, + + PAD_PMIC_STBY_REQ, PAD_PMIC_ON_REQ, + PAD_ONOFF, PAD_POR_B, PAD_RTC_RESET_B, + + /* pads with muxes */ + PAD_GPIO1_IO00, PAD_GPIO1_IO01, PAD_GPIO1_IO02, PAD_GPIO1_IO03, + PAD_GPIO1_IO04, PAD_GPIO1_IO05, PAD_GPIO1_IO06, PAD_GPIO1_IO07, + PAD_GPIO1_IO08, PAD_GPIO1_IO09, PAD_GPIO1_IO10, PAD_GPIO1_IO11, + PAD_GPIO1_IO12, PAD_GPIO1_IO13, PAD_GPIO1_IO14, PAD_GPIO1_IO15, + + PAD_ENET_MDC, PAD_ENET_MDIO, + PAD_ENET_TD3, PAD_ENET_TD2, PAD_ENET_TD1, PAD_ENET_TD0, + PAD_ENET_TX_CTL, PAD_ENET_TXC, PAD_ENET_RX_CTL, PAD_ENET_RXC, + PAD_ENET_RD0, PAD_ENET_RD1, PAD_ENET_RD2, PAD_ENET_RD3, + + PAD_SD1_CLK, PAD_SD1_CMD, PAD_SD1_DATA0, PAD_SD1_DATA1, + PAD_SD1_DATA2, PAD_SD1_DATA3, PAD_SD1_DATA4, PAD_SD1_DATA5, + PAD_SD1_DATA6, PAD_SD1_DATA7, PAD_SD1_RESET_B, PAD_SD1_STROBE, + + PAD_SD2_CD_B, PAD_SD2_CLK, PAD_SD2_CMD, PAD_SD2_DATA0, + PAD_SD2_DATA1, PAD_SD2_DATA2, PAD_SD2_DATA3, + PAD_SD2_RESET_B, PAD_SD2_WP, + + PAD_NAND_ALE, PAD_NAND_CE0_B, PAD_NAND_CE1_B, PAD_NAND_CE2_B, + PAD_NAND_CE3_B, PAD_NAND_CLE, PAD_NAND_DATA0, PAD_NAND_DATA1, + PAD_NAND_DATA2, PAD_NAND_DATA3, PAD_NAND_DATA4, + PAD_NAND_DATA5, PAD_NAND_DATA6, PAD_NAND_DATA7, PAD_NAND_DQS, + PAD_NAND_RE_B, PAD_NAND_READY_B, PAD_NAND_WE_B, PAD_NAND_WP_B, + + PAD_SAI5_RXFS, PAD_SAI5_RXC, PAD_SAI5_RXD0, PAD_SAI5_RXD1, + PAD_SAI5_RXD2, PAD_SAI5_RXD3, PAD_SAI5_MCLK, + + PAD_SAI1_RXFS, PAD_SAI1_RXC, PAD_SAI1_RXD0, PAD_SAI1_RXD1, + PAD_SAI1_RXD2, PAD_SAI1_RXD3, PAD_SAI1_RXD4, PAD_SAI1_RXD5, + PAD_SAI1_RXD6, PAD_SAI1_RXD7, PAD_SAI1_TXFS, PAD_SAI1_TXC, + PAD_SAI1_TXD0, PAD_SAI1_TXD1, PAD_SAI1_TXD2, PAD_SAI1_TXD3, + PAD_SAI1_TXD4, PAD_SAI1_TXD5, PAD_SAI1_TXD6, PAD_SAI1_TXD7, + PAD_SAI1_MCLK, + + PAD_SAI2_RXFS, PAD_SAI2_RXC, PAD_SAI2_RXD0, PAD_SAI2_TXFS, + PAD_SAI2_TXC, PAD_SAI2_TXD0, PAD_SAI2_MCLK, + + PAD_SAI3_RXFS, PAD_SAI3_RXC, PAD_SAI3_RXD, PAD_SAI3_TXFS, + PAD_SAI3_TXC, PAD_SAI3_TXD, PAD_SAI3_MCLK, + + PAD_SPDIF_TX, PAD_SPDIF_RX, PAD_SPDIF_EXT_CLK, + + PAD_ECSPI1_SCLK, PAD_ECSPI1_MOSI, PAD_ECSPI1_MISO, PAD_ECSPI1_SS0, + PAD_ECSPI2_SCLK, PAD_ECSPI2_MOSI, PAD_ECSPI2_MISO, PAD_ECSPI2_SS0, + + PAD_I2C1_SCL, PAD_I2C1_SDA, + PAD_I2C2_SCL, PAD_I2C2_SDA, + PAD_I2C3_SCL, PAD_I2C3_SDA, + PAD_I2C4_SCL, PAD_I2C4_SDA, + + PAD_UART1_RXD, PAD_UART1_TXD, + PAD_UART2_RXD, PAD_UART2_TXD, + PAD_UART3_RXD, PAD_UART3_TXD, + PAD_UART4_RXD, PAD_UART4_TXD, +}; + +enum { + /* signals with input muxes (must be first for daisytab) */ + CCM_PMIC_READY = 0, + ENET1_MDIO, + PCIE1_CLKREQ_B, PCIE2_CLKREQ_B, + SAI1_RX_BCLK, SAI1_RX_SYNC, SAI1_TX_SYNC, + SAI5_MCLK, SAI5_RXD0, SAI5_RXD1, SAI5_RXD2, SAI5_RXD3, + SAI5_RX_BCLK, SAI5_RX_SYNC, SAI5_TX_BLCK, SAI5_TX_SYNC, + SAI6_MCLK, SAI6_RXD0, SAI6_RX_BCLK, SAI6_RX_SYNC, + SAI6_TX_BCLK, SAY6_TX_SYNC, + UART1_RTS_B, UART1_RXD, + UART2_RTS_B, UART2_RXD, + UART3_RTS_B, UART3_RXD, + UART4_RTS_B, UART4_RXD, + + /* signals without input muxes */ + ANAMIX_REF_CLK_25M, + ANAMIX_REF_CLK_32K, + CCM_CLKO1, + CCM_CLKO2, + CCM_ENET_PHY_REF_CLK_ROOT, + CCM_EXT_CLK1, + CCM_EXT_CLK2, + CCM_EXT_CLK3, + CCM_EXT_CLK4, + + CORESIGHT_EVENTI, CORESIGHT_EVENTO, CORESIGHT_TRACE0, + CORESIGHT_TRACE1, CORESIGHT_TRACE10, CORESIGHT_TRACE11, + CORESIGHT_TRACE12, CORESIGHT_TRACE13, CORESIGHT_TRACE14, + CORESIGHT_TRACE15, CORESIGHT_TRACE2, CORESIGHT_TRACE3, + CORESIGHT_TRACE4, CORESIGHT_TRACE5, CORESIGHT_TRACE6, + CORESIGHT_TRACE7, CORESIGHT_TRACE8, CORESIGHT_TRACE9, + CORESIGHT_TRACE_CLK, CORESIGHT_TRACE_CTL, + + ECSPI1_MISO, ECSPI1_MOSI, ECSPI1_SCLK, ECSPI1_SS0, + ECSPI2_MISO, ECSPI2_MOSI, ECSPI2_SCLK, ECSPI2_SS0, + ECSPI3_MISO, ECSPI3_MOSI, ECSPI3_SCLK, ECSPI3_SS0, + ENET1_1588_EVENT0_IN, ENET1_1588_EVENT0_OUT, + ENET1_1588_EVENT1_IN, ENET1_1588_EVENT1_OUT, + ENET1_MDC, ENET1_RGMII_RD0, ENET1_RGMII_RD1, ENET1_RGMII_RD2, + ENET1_RGMII_RD3, ENET1_RGMII_RXC, ENET1_RGMII_RX_CTL, + ENET1_RGMII_TD0, ENET1_RGMII_TD1, ENET1_RGMII_TD2, + ENET1_RGMII_TD3, ENET1_RGMII_TXC, ENET1_RGMII_TX_CTL, + ENET1_RX_ER, ENET1_TX_CLK, ENET1_TX_ER, + + GPIO1_IO00, GPIO1_IO01, GPIO1_IO02, GPIO1_IO03, GPIO1_IO04, + GPIO1_IO05, GPIO1_IO06, GPIO1_IO07, GPIO1_IO08, GPIO1_IO09, + GPIO1_IO10, GPIO1_IO11, GPIO1_IO12, GPIO1_IO13, GPIO1_IO14, + GPIO1_IO15, GPIO1_IO16, GPIO1_IO17, GPIO1_IO18, GPIO1_IO19, + GPIO1_IO20, GPIO1_IO21, GPIO1_IO22, GPIO1_IO23, GPIO1_IO24, + GPIO1_IO25, GPIO1_IO26, GPIO1_IO27, GPIO1_IO28, GPIO1_IO29, + + GPIO2_IO00, GPIO2_IO01, GPIO2_IO02, GPIO2_IO03, GPIO2_IO04, + GPIO2_IO05, GPIO2_IO06, GPIO2_IO07, GPIO2_IO08, GPIO2_IO09, + GPIO2_IO10, GPIO2_IO11, GPIO2_IO12, GPIO2_IO13, GPIO2_IO14, + GPIO2_IO15, GPIO2_IO16, GPIO2_IO17, GPIO2_IO18, GPIO2_IO19, + GPIO2_IO20, + + GPIO3_IO00, GPIO3_IO01, GPIO3_IO02, GPIO3_IO03, GPIO3_IO04, + GPIO3_IO05, GPIO3_IO06, GPIO3_IO07, GPIO3_IO08, GPIO3_IO09, + GPIO3_IO10, GPIO3_IO11, GPIO3_IO12, GPIO3_IO13, GPIO3_IO14, + GPIO3_IO15, GPIO3_IO16, GPIO3_IO17, GPIO3_IO18, GPIO3_IO19, + GPIO3_IO20, GPIO3_IO21, GPIO3_IO22, GPIO3_IO23, GPIO3_IO24, + GPIO3_IO25, + + GPIO4_IO00, GPIO4_IO01, GPIO4_IO02, GPIO4_IO03, GPIO4_IO04, + GPIO4_IO05, GPIO4_IO06, GPIO4_IO07, GPIO4_IO08, GPIO4_IO09, + GPIO4_IO10, GPIO4_IO11, GPIO4_IO12, GPIO4_IO13, GPIO4_IO14, + GPIO4_IO15, GPIO4_IO16, GPIO4_IO17, GPIO4_IO18, GPIO4_IO19, + GPIO4_IO20, GPIO4_IO21, GPIO4_IO22, GPIO4_IO23, GPIO4_IO24, + GPIO4_IO25, GPIO4_IO26, GPIO4_IO27, GPIO4_IO28, GPIO4_IO29, + GPIO4_IO31, + + GPIO5_IO00, GPIO5_IO01, GPIO5_IO02, GPIO5_IO03, GPIO5_IO04, + GPIO5_IO05, GPIO5_IO06, GPIO5_IO07, GPIO5_IO08, GPIO5_IO09, + GPIO5_IO10, GPIO5_IO11, GPIO5_IO12, GPIO5_IO13, GPIO5_IO14, + GPIO5_IO15, GPIO5_IO16, GPIO5_IO17, GPIO5_IO18, GPIO5_IO19, + GPIO5_IO20, GPIO5_IO21, GPIO5_IO22, GPIO5_IO23, GPIO5_IO24, + GPIO5_IO25, GPIO5_IO26, GPIO5_IO27, GPIO5_IO28, GPIO5_IO29, + + GPT1_CAPTURE1, GPT1_CAPTURE2, GPT1_COMPARE1, GPT1_COMPARE2, + GPT1_COMPARE3, GPT1_CLK, GPT2_CLK, GPT3_CLK, + + I2C1_SCL, I2C1_SDA, + I2C2_SCL, I2C2_SDA, + I2C3_SCL, I2C3_SDA, + I2C4_SCL, I2C4_SDA, + M4_NMI, + PCIE_CLKREQ_B, + PWM1_OUT, PWM2_OUT, PWM3_OUT, PWM4_OUT, + + QSPI_A_DATA0, QSPI_A_DATA1, QSPI_A_DATA2, QSPI_A_DATA3, + QSPI_A_DQS, QSPI_A_SCLK, QSPI_A_SS0_B, QSPI_A_SS1_B, + + QSPI_B_DATA0, QSPI_B_DATA1, QSPI_B_DATA2, QSPI_B_DATA3, + QSPI_B_DQS, QSPI_B_SCLK, QSPI_B_SS0_B, QSPI_B_SS1_B, + + RAWNAND_ALE, RAWNAND_CE0_B, RAWNAND_CE1_B, RAWNAND_CE2_B, + RAWNAND_CE3_B, RAWNAND_CLE, RAWNAND_DATA00, RAWNAND_DATA01, + RAWNAND_DATA02, RAWNAND_DATA03, RANWNAD_DATA04, + RAWNAND_DATA05, RAWNAND_DATA06, RAWNAND_DATA07, RAWNAND_DQS, + RAWNAND_READY_B, RAWNAND_RE_B, RAWNAND_WE_B, RAWNAND_WP_B, + + SAI1_MCLK, SAI1_RX_DATA0, SAI1_RX_DATA1, SAI1_RX_DATA2, + SAI1_RX_DATA3, SAI1_RX_DATA4, SAI1_RX_DATA5, SAI1_RX_DATA6, + SAI1_RX_DATA7, SAI1_TX_BCLK, SAI1_TX_DATA0, SAI1_TX_DATA1, + SAI1_TX_DATA2, SAI1_TX_DATA3, SAI1_TX_DATA4, SAI1_TX_DATA5, + SAI1_TX_DATA6, SAI1_TX_DATA7, + + SAI2_MCLK, SAI2_RX_BCLK, SAI2_RX_DATA0, SAI2_RX_SYNC, + SAI2_TX_BCLK, SAI2_TX_DATA0, SAI2_TX_SYNC, + SAI3_MCLK, SAI3_RX_BCLK, SAI3_RX_DATA0, SAI3_RX_SYNC, + SAI3_TX_BCLK, SAI3_TX_DATA0, SAI3_TX_SYNC, + + SAI4_MCLK, + + SAI5_RX_DATA0, SAI5_RX_DATA1, SAI5_RX_DATA2, SAI5_RX_DATA3, + SAI5_TX_BCLK, SAI5_TX_DATA0, SAI5_TX_DATA1, SAI5_TX_DATA2, + SAI5_TX_DATA3, + + SAI6_RC_BCLK, SAI6_RX_DATA0, SAI6_TX_DATA0, SAI6_TX_SYNC, + + SDMA1_EXT_EVENT0, SDMA1_EXT_EVENT1, + SDMA2_EXT_EVENT0, SDMA2_EXT_EVENT1, + + SJC_DE_B, + + SPDIF1_EXT_CLK, SPDIF1_IN, SPDIF1_OUT, + + SRC_BOOT_CFG0, SRC_BOOT_CFG1, SRC_BOOT_CFG2, SRC_BOOT_CFG3, + SRC_BOOT_CFG4, SRC_BOOT_CFG5, SRC_BOOT_CFG6, SRC_BOOT_CFG7, + SRC_BOOT_CFG8, SRC_BOOT_CFG9, SRC_BOOT_CFG10, SRC_BOOT_CFG11, + SRC_BOOT_CFG12, SRC_BOOT_CFG13, SRC_BOOT_CFG14, SRC_BOOT_CFG15, + + UART1_CTS_B, UART1_RX, UART1_TX, + UART2_CTS_B, UART2_RX, UART2_TX, + UART3_CTS_B, UART3_RX, UART3_TX, + UART4_CTS_B, UART4_RX, UART4_TX, + + USB1_OTG_ID, USB1_OTG_OC, USB1_OTG_PWR, + USB2_OTG_ID, USB2_OTG_OC, USB2_OTG_PWR, + + USDHC1_CD_B, USDHC1_CLK, USDHC1_CMD, USDHC1_DATA0, + USDHC1_DATA1, USDHC1_DATA2, USDHC1_DATA3, USDHC1_DATA4, + USDHC1_DATA5, USDHC1_DATA6, USDHC1_DATA7, USDHC1_RESET_B, + USDHC1_STROBE, USDHC1_VSELECT, USDHC1_WP, + + USDHC2_CD_B, USDHC2_CLK, USDHC2_CMD, USDHC2_DATA0, + USDHC2_DATA1, USDHC2_DATA2, USDHC2_DATA3, USDHC2_RESET_B, + USDHC2_VSELECT, USDHC2_WP, + + WDOG1_WDOG_ANY, WDOG1_WDOG_B, +}; + +#define DAISY(x) (0x8000|(((x)&7)<<12)) +#define DAISY_VAL(x) (((x)>>12)&7) +#define DAISY_ID(x) ((x) & ~DAISY(7)) + +static ushort daisytab[] = { + [CCM_PMIC_READY] 0 | DAISY(1), + [ENET1_MDIO] 1 | DAISY(3), + [PCIE1_CLKREQ_B] 26 | DAISY(1), + [PCIE2_CLKREQ_B] 27 | DAISY(1), + [SAI1_RX_BCLK] 3 | DAISY(3), + [SAI1_RX_SYNC] 2 | DAISY(1), + [SAI1_TX_SYNC] 4 | DAISY(7), + [SAI5_MCLK] 28 | DAISY(3), + [SAI5_RXD0] 6 | DAISY(3), + [SAI5_RXD1] 7 | DAISY(3), + [SAI5_RXD2] 8 | DAISY(3), + [SAI5_RXD3] 9 | DAISY(3), + [SAI5_RX_BCLK] 5 | DAISY(3), + [SAI5_RX_SYNC] 10 | DAISY(3), + [SAI5_TX_BLCK] 11 | DAISY(3), + [SAI5_TX_SYNC] 12 | DAISY(3), + [SAI6_MCLK] 29 | DAISY(1), + [SAI6_RXD0] 22 | DAISY(1), + [SAI6_RX_BCLK] 21 | DAISY(1), + [SAI6_RX_SYNC] 23 | DAISY(1), + [SAI6_TX_BCLK] 24 | DAISY(1), + [SAY6_TX_SYNC] 25 | DAISY(1), + [UART1_RTS_B] 13 | DAISY(1), + [UART1_RXD] 14 | DAISY(1), + [UART2_RTS_B] 15 | DAISY(1), + [UART2_RXD] 16 | DAISY(1), + [UART3_RTS_B] 17 | DAISY(1), + [UART3_RXD] 18 | DAISY(3), + [UART4_RTS_B] 19 | DAISY(1), + [UART4_RXD] 20 | DAISY(3), +}; + +static ushort padmux[] = { + [PAD_GPIO1_IO00*8] GPIO1_IO00, CCM_ENET_PHY_REF_CLK_ROOT, 0, 0, 0, ANAMIX_REF_CLK_32K, CCM_EXT_CLK1, 0, + [PAD_GPIO1_IO01*8] GPIO1_IO01, PWM1_OUT, 0, 0, 0, ANAMIX_REF_CLK_25M, CCM_EXT_CLK2, 0, + [PAD_GPIO1_IO02*8] GPIO1_IO02, WDOG1_WDOG_B, 0, 0, 0, WDOG1_WDOG_ANY, 0, SJC_DE_B, + [PAD_GPIO1_IO03*8] GPIO1_IO03, USDHC1_VSELECT, 0, 0, 0, SDMA1_EXT_EVENT0, 0, 0, + [PAD_GPIO1_IO04*8] GPIO1_IO04, USDHC2_VSELECT, 0, 0, 0, SDMA1_EXT_EVENT1, 0, 0, + [PAD_GPIO1_IO05*8] GPIO1_IO05, M4_NMI, 0, 0, 0, CCM_PMIC_READY|DAISY(0), 0, 0, + [PAD_GPIO1_IO06*8] GPIO1_IO06, ENET1_MDC, 0, 0, 0, USDHC1_CD_B, CCM_EXT_CLK3, 0, + [PAD_GPIO1_IO07*8] GPIO1_IO07, ENET1_MDIO|DAISY(0), 0, 0, 0, USDHC1_WP, CCM_EXT_CLK4, 0, + [PAD_GPIO1_IO08*8] GPIO1_IO08, ENET1_1588_EVENT0_IN, 0, 0, 0, USDHC2_RESET_B, 0, 0, + [PAD_GPIO1_IO09*8] GPIO1_IO09, ENET1_1588_EVENT0_OUT, 0, 0, 0, SDMA2_EXT_EVENT0, 0, 0, + [PAD_GPIO1_IO10*8] GPIO1_IO10, USB1_OTG_ID, 0, 0, 0, 0, 0, 0, + [PAD_GPIO1_IO11*8] GPIO1_IO11, USB2_OTG_ID, 0, 0, 0, CCM_PMIC_READY|DAISY(1), 0, 0, + [PAD_GPIO1_IO12*8] GPIO1_IO12, USB1_OTG_PWR, 0, 0, 0, SDMA2_EXT_EVENT1, 0, 0, + [PAD_GPIO1_IO13*8] GPIO1_IO13, USB1_OTG_OC, 0, 0, 0, PWM2_OUT, 0, 0, + [PAD_GPIO1_IO14*8] GPIO1_IO14, USB2_OTG_PWR, 0, 0, 0, PWM3_OUT, CCM_CLKO1, 0, + [PAD_GPIO1_IO15*8] GPIO1_IO15, USB2_OTG_OC, 0, 0, 0, PWM4_OUT, CCM_CLKO2, 0, + [PAD_ENET_MDC*8] ENET1_MDC, 0, 0, 0, 0, GPIO1_IO16, 0, 0, + [PAD_ENET_MDIO*8] ENET1_MDIO|DAISY(1), 0, 0, 0, 0, GPIO1_IO17, 0, 0, + [PAD_ENET_TD3*8] ENET1_RGMII_TD3, 0, 0, 0, 0, GPIO1_IO18, 0, 0, + [PAD_ENET_TD2*8] ENET1_RGMII_TD2, ENET1_TX_CLK, 0, 0, 0, GPIO1_IO19, 0, 0, + [PAD_ENET_TD1*8] ENET1_RGMII_TD1, 0, 0, 0, 0, GPIO1_IO20, 0, 0, + [PAD_ENET_TD0*8] ENET1_RGMII_TD0, 0, 0, 0, 0, GPIO1_IO21, 0, 0, + [PAD_ENET_TX_CTL*8] ENET1_RGMII_TX_CTL, 0, 0, 0, 0, GPIO1_IO22, 0, 0, + [PAD_ENET_TXC*8] ENET1_RGMII_TXC, ENET1_TX_ER, 0, 0, 0, GPIO1_IO23, 0, 0, + [PAD_ENET_RX_CTL*8] ENET1_RGMII_RX_CTL, 0, 0, 0, 0, GPIO1_IO24, 0, 0, + [PAD_ENET_RXC*8] ENET1_RGMII_RXC, ENET1_RX_ER, 0, 0, 0, GPIO1_IO25, 0, 0, + [PAD_ENET_RD0*8] ENET1_RGMII_RD0, 0, 0, 0, 0, GPIO1_IO26, 0, 0, + [PAD_ENET_RD1*8] ENET1_RGMII_RD1, 0, 0, 0, 0, GPIO1_IO27, 0, 0, + [PAD_ENET_RD2*8] ENET1_RGMII_RD2, 0, 0, 0, 0, GPIO1_IO28, 0, 0, + [PAD_ENET_RD3*8] ENET1_RGMII_RD3, 0, 0, 0, 0, GPIO1_IO29, 0, 0, + [PAD_SD1_CLK*8] USDHC1_CLK, 0, 0, 0, 0, GPIO2_IO00, 0, 0, + [PAD_SD1_CMD*8] USDHC1_CMD, 0, 0, 0, 0, GPIO2_IO01, 0, 0, + [PAD_SD1_DATA0*8] USDHC1_DATA0, 0, 0, 0, 0, GPIO2_IO02, 0, 0, + [PAD_SD1_DATA1*8] USDHC1_DATA1, 0, 0, 0, 0, GPIO2_IO03, 0, 0, + [PAD_SD1_DATA2*8] USDHC1_DATA2, 0, 0, 0, 0, GPIO2_IO04, 0, 0, + [PAD_SD1_DATA3*8] USDHC1_DATA3, 0, 0, 0, 0, GPIO2_IO05, 0, 0, + [PAD_SD1_DATA4*8] USDHC1_DATA4, 0, 0, 0, 0, GPIO2_IO06, 0, 0, + [PAD_SD1_DATA5*8] USDHC1_DATA5, 0, 0, 0, 0, GPIO2_IO07, 0, 0, + [PAD_SD1_DATA6*8] USDHC1_DATA6, 0, 0, 0, 0, GPIO2_IO08, 0, 0, + [PAD_SD1_DATA7*8] USDHC1_DATA7, 0, 0, 0, 0, GPIO2_IO09, 0, 0, + [PAD_SD1_RESET_B*8] USDHC1_RESET_B, 0, 0, 0, 0, GPIO2_IO10, 0, 0, + [PAD_SD1_STROBE*8] USDHC1_STROBE, 0, 0, 0, 0, GPIO2_IO11, 0, 0, + [PAD_SD2_CD_B*8] USDHC2_CD_B, 0, 0, 0, 0, GPIO2_IO12, 0, 0, + [PAD_SD2_CLK*8] USDHC2_CLK, 0, 0, 0, 0, GPIO2_IO13, 0, 0, + [PAD_SD2_CMD*8] USDHC2_CMD, 0, 0, 0, 0, GPIO2_IO14, 0, 0, + [PAD_SD2_DATA0*8] USDHC2_DATA0, 0, 0, 0, 0, GPIO2_IO15, 0, 0, + [PAD_SD2_DATA1*8] USDHC2_DATA1, 0, 0, 0, 0, GPIO2_IO16, 0, 0, + [PAD_SD2_DATA2*8] USDHC2_DATA2, 0, 0, 0, 0, GPIO2_IO17, 0, 0, + [PAD_SD2_DATA3*8] USDHC2_DATA3, 0, 0, 0, 0, GPIO2_IO18, 0, 0, + [PAD_SD2_RESET_B*8] USDHC2_RESET_B, 0, 0, 0, 0, GPIO2_IO19, 0, 0, + [PAD_SD2_WP*8] USDHC2_WP, 0, 0, 0, 0, GPIO2_IO20, 0, 0, + [PAD_NAND_ALE*8] RAWNAND_ALE, QSPI_A_SCLK, 0, 0, 0, GPIO3_IO00, 0, 0, + [PAD_NAND_CE0_B*8] RAWNAND_CE0_B, QSPI_A_SS0_B, 0, 0, 0, GPIO3_IO01, 0, 0, + [PAD_NAND_CE1_B*8] RAWNAND_CE1_B, QSPI_A_SS1_B, 0, 0, 0, GPIO3_IO02, 0, 0, + [PAD_NAND_CE2_B*8] RAWNAND_CE2_B, QSPI_B_SS0_B, 0, 0, 0, GPIO3_IO03, 0, 0, + [PAD_NAND_CE3_B*8] RAWNAND_CE3_B, QSPI_B_SS1_B, 0, 0, 0, GPIO3_IO04, 0, 0, + [PAD_NAND_CLE*8] RAWNAND_CLE, QSPI_B_SCLK, 0, 0, 0, GPIO3_IO05, 0, 0, + [PAD_NAND_DATA0*8] RAWNAND_DATA00, QSPI_A_DATA0, 0, 0, 0, GPIO3_IO06, 0, 0, + [PAD_NAND_DATA1*8] RAWNAND_DATA01, QSPI_A_DATA1, 0, 0, 0, GPIO3_IO07, 0, 0, + [PAD_NAND_DATA2*8] RAWNAND_DATA02, QSPI_A_DATA2, 0, 0, 0, GPIO3_IO08, 0, 0, + [PAD_NAND_DATA3*8] RAWNAND_DATA03, QSPI_A_DATA3, 0, 0, 0, GPIO3_IO09, 0, 0, + [PAD_NAND_DATA4*8] RANWNAD_DATA04, QSPI_B_DATA0, 0, 0, 0, GPIO3_IO10, 0, 0, + [PAD_NAND_DATA5*8] RAWNAND_DATA05, QSPI_B_DATA1, 0, 0, 0, GPIO3_IO11, 0, 0, + [PAD_NAND_DATA6*8] RAWNAND_DATA06, QSPI_B_DATA2, 0, 0, 0, GPIO3_IO12, 0, 0, + [PAD_NAND_DATA7*8] RAWNAND_DATA07, QSPI_B_DATA3, 0, 0, 0, GPIO3_IO13, 0, 0, + [PAD_NAND_DQS*8] RAWNAND_DQS, QSPI_A_DQS, 0, 0, 0, GPIO3_IO14, 0, 0, + [PAD_NAND_RE_B*8] RAWNAND_RE_B, QSPI_B_DQS, 0, 0, 0, GPIO3_IO15, 0, 0, + [PAD_NAND_READY_B*8] RAWNAND_READY_B, 0, 0, 0, 0, GPIO3_IO16, 0, 0, + [PAD_NAND_WE_B*8] RAWNAND_WE_B, 0, 0, 0, 0, GPIO3_IO17, 0, 0, + [PAD_NAND_WP_B*8] RAWNAND_WP_B, 0, 0, 0, 0, GPIO3_IO18, 0, 0, + [PAD_SAI5_RXFS*8] SAI5_RX_SYNC|DAISY(0), SAI1_TX_DATA0, 0, 0, 0, GPIO3_IO19, 0, 0, + [PAD_SAI5_RXC*8] SAI5_RX_BCLK|DAISY(0), SAI1_TX_DATA1, 0, 0, 0, GPIO3_IO20, 0, 0, + [PAD_SAI5_RXD0*8] SAI5_RX_DATA0, SAI1_TX_DATA2, 0, 0, 0, GPIO3_IO21, 0, 0, + [PAD_SAI5_RXD1*8] SAI5_RX_DATA1, SAI1_TX_DATA3, SAI1_TX_SYNC|DAISY(0), SAI5_TX_SYNC|DAISY(0), 0, GPIO3_IO22, 0, 0, + [PAD_SAI5_RXD2*8] SAI5_RX_DATA2, SAI1_TX_DATA4, SAI1_TX_SYNC|DAISY(1), SAI5_TX_BCLK, 0, GPIO3_IO23, 0, 0, + [PAD_SAI5_RXD3*8] SAI5_RX_DATA3, SAI1_TX_DATA5, 0, SAI5_TX_DATA0, 0, GPIO3_IO24, 0, 0, + [PAD_SAI5_MCLK*8] SAI5_MCLK|DAISY(0), SAI1_TX_BCLK, SAI4_MCLK, 0, 0, GPIO3_IO25, 0, 0, + [PAD_SAI1_RXFS*8] SAI1_RX_SYNC|DAISY(0), SAI5_RX_SYNC|DAISY(1), 0, 0, CORESIGHT_TRACE_CLK, GPIO4_IO00, 0, 0, + [PAD_SAI1_RXC*8] SAI1_RX_BCLK, SAI5_RX_BCLK|DAISY(1), 0, 0, CORESIGHT_TRACE_CTL, GPIO4_IO01, 0, 0, + [PAD_SAI1_RXD0*8] SAI1_RX_DATA0, SAI5_RX_DATA0, 0, 0, CORESIGHT_TRACE0, GPIO4_IO02, SRC_BOOT_CFG0, 0, + [PAD_SAI1_RXD1*8] SAI1_RX_DATA1, SAI5_RX_DATA1, 0, 0, CORESIGHT_TRACE1, GPIO4_IO03, SRC_BOOT_CFG1, 0, + [PAD_SAI1_RXD2*8] SAI1_RX_DATA2, SAI5_RX_DATA2, 0, 0, CORESIGHT_TRACE2, GPIO4_IO04, SRC_BOOT_CFG2, 0, + [PAD_SAI1_RXD3*8] SAI1_RX_DATA3, SAI5_RX_DATA3, 0, 0, CORESIGHT_TRACE3, GPIO4_IO05, SRC_BOOT_CFG3, 0, + [PAD_SAI1_RXD4*8] SAI1_RX_DATA4, SAI6_TX_BCLK|DAISY(0), SAI6_RX_BCLK|DAISY(0), 0, CORESIGHT_TRACE4, GPIO4_IO06, SRC_BOOT_CFG4, 0, + [PAD_SAI1_RXD5*8] SAI1_RX_DATA5, SAI6_TX_DATA0, SAI6_RX_DATA0, SAI1_RX_SYNC|DAISY(1), CORESIGHT_TRACE5, GPIO4_IO07, SRC_BOOT_CFG5, 0, + [PAD_SAI1_RXD6*8] SAI1_RX_DATA6, SAI6_TX_SYNC, SAI6_RX_SYNC|DAISY(0), 0, CORESIGHT_TRACE6, GPIO4_IO08, SRC_BOOT_CFG6, 0, + [PAD_SAI1_RXD7*8] SAI1_RX_DATA7, SAI6_MCLK|DAISY(0), SAI1_TX_SYNC|DAISY(4), SAI1_TX_DATA4, CORESIGHT_TRACE7, GPIO4_IO09, SRC_BOOT_CFG7, 0, + [PAD_SAI1_TXFS*8] SAI1_TX_SYNC|DAISY(3), SAI5_TX_SYNC|DAISY(1), 0, 0, CORESIGHT_EVENTO, GPIO4_IO10, 0, 0, + [PAD_SAI1_TXC*8] SAI1_TX_BCLK, SAI5_TX_BCLK, 0, 0, CORESIGHT_EVENTI, GPIO4_IO11, 0, 0, + [PAD_SAI1_TXD0*8] SAI1_TX_DATA0, SAI5_TX_DATA0, 0, 0, CORESIGHT_TRACE8, GPIO4_IO12, SRC_BOOT_CFG8, 0, + [PAD_SAI1_TXD1*8] SAI1_TX_DATA1, SAI5_TX_DATA1, 0, 0, CORESIGHT_TRACE9, GPIO4_IO13, SRC_BOOT_CFG9, 0, + [PAD_SAI1_TXD2*8] SAI1_TX_DATA2, SAI5_TX_DATA2, 0, 0, CORESIGHT_TRACE10, GPIO4_IO14, SRC_BOOT_CFG10, 0, + [PAD_SAI1_TXD3*8] SAI1_TX_DATA3, SAI5_TX_DATA3, 0, 0, CORESIGHT_TRACE11, GPIO4_IO15, SRC_BOOT_CFG11, 0, + [PAD_SAI1_TXD4*8] SAI1_TX_DATA4, SAI6_RC_BCLK, SAI6_TX_BCLK|DAISY(1), 0, CORESIGHT_TRACE12, GPIO4_IO16, SRC_BOOT_CFG12, 0, + [PAD_SAI1_TXD5*8] SAI1_TX_DATA5, SAI6_RX_DATA0, SAI6_TX_DATA0, 0, CORESIGHT_TRACE13, GPIO4_IO17, SRC_BOOT_CFG13, 0, + [PAD_SAI1_TXD6*8] SAI1_TX_DATA6, SAI6_RX_SYNC|DAISY(1), SAI6_TX_SYNC, 0, CORESIGHT_TRACE14, GPIO4_IO18, SRC_BOOT_CFG14, 0, + [PAD_SAI1_TXD7*8] SAI1_TX_DATA7, SAI6_MCLK|DAISY(1), 0, 0, CORESIGHT_TRACE15, GPIO4_IO19, SRC_BOOT_CFG15, 0, + [PAD_SAI1_MCLK*8] SAI1_MCLK, SAI5_MCLK|DAISY(1), SAI1_TX_BCLK, 0, 0, GPIO4_IO20, 0, 0, + [PAD_SAI2_RXFS*8] SAI2_RX_SYNC, SAI5_TX_SYNC|DAISY(2), 0, 0, 0, GPIO4_IO21, 0, 0, + [PAD_SAI2_RXC*8] SAI2_RX_BCLK, SAI5_TX_BCLK, 0, 0, 0, GPIO4_IO22, 0, 0, + [PAD_SAI2_RXD0*8] SAI2_RX_DATA0, SAI5_TX_DATA0, 0, 0, 0, GPIO4_IO23, 0, 0, + [PAD_SAI2_TXFS*8] SAI2_TX_SYNC, SAI5_TX_DATA1, 0, 0, 0, GPIO4_IO24, 0, 0, + [PAD_SAI2_TXC*8] SAI2_TX_BCLK, SAI5_TX_DATA2, 0, 0, 0, GPIO4_IO25, 0, 0, + [PAD_SAI2_TXD0*8] SAI2_TX_DATA0, SAI5_TX_DATA3, 0, 0, 0, GPIO4_IO26, 0, 0, + [PAD_SAI2_MCLK*8] SAI2_MCLK, SAI5_MCLK|DAISY(2), 0, 0, 0, GPIO4_IO27, 0, 0, + [PAD_SAI3_RXFS*8] SAI3_RX_SYNC, GPT1_CAPTURE1, SAI5_RX_SYNC|DAISY(2), 0, 0, GPIO4_IO28, 0, 0, + [PAD_SAI3_RXC*8] SAI3_RX_BCLK, GPT1_CAPTURE2, SAI5_RX_BCLK|DAISY(2), 0, 0, GPIO4_IO29, 0, 0, + [PAD_SAI3_RXD*8] SAI3_RX_DATA0, GPT1_COMPARE1, 0, 0, 0, 0, 0, 0, + [PAD_SAI3_TXFS*8] SAI3_TX_SYNC, GPT1_CLK, SAI5_RX_DATA1, 0, 0, GPIO4_IO31, 0, 0, + [PAD_SAI3_TXC*8] SAI3_TX_BCLK, GPT1_COMPARE2, SAI5_RX_DATA2, 0, 0, GPIO5_IO00, 0, 0, + [PAD_SAI3_TXD*8] SAI3_TX_DATA0, GPT1_COMPARE3, SAI5_RX_DATA3, 0, 0, GPIO5_IO01, 0, 0, + [PAD_SAI3_MCLK*8] SAI3_MCLK, PWM4_OUT, SAI5_MCLK|DAISY(3), 0, 0, GPIO5_IO02, 0, 0, + [PAD_SPDIF_TX*8] SPDIF1_OUT, PWM3_OUT, 0, 0, 0, GPIO5_IO03, 0, 0, + [PAD_SPDIF_RX*8] SPDIF1_IN, PWM2_OUT, 0, 0, 0, GPIO5_IO04, 0, 0, + [PAD_SPDIF_EXT_CLK*8] SPDIF1_EXT_CLK, PWM1_OUT, 0, 0, 0, GPIO5_IO05, 0, 0, + [PAD_ECSPI1_SCLK*8] ECSPI1_SCLK, UART3_RX, 0, 0, 0, GPIO5_IO06, 0, 0, + [PAD_ECSPI1_MOSI*8] ECSPI1_MOSI, UART3_TX, 0, 0, 0, GPIO5_IO07, 0, 0, + [PAD_ECSPI1_MISO*8] ECSPI1_MISO, UART3_CTS_B, 0, 0, 0, GPIO5_IO08, 0, 0, + [PAD_ECSPI1_SS0*8] ECSPI1_SS0, UART3_RTS_B|DAISY(1), 0, 0, 0, GPIO5_IO09, 0, 0, + [PAD_ECSPI2_SCLK*8] ECSPI2_SCLK, UART4_RX, 0, 0, 0, GPIO5_IO10, 0, 0, + [PAD_ECSPI2_MOSI*8] ECSPI2_MOSI, UART4_TX, 0, 0, 0, GPIO5_IO11, 0, 0, + [PAD_ECSPI2_MISO*8] ECSPI2_MISO, UART4_CTS_B, 0, 0, 0, GPIO5_IO12, 0, 0, + [PAD_ECSPI2_SS0*8] ECSPI2_SS0, UART4_RTS_B|DAISY(1), 0, 0, 0, GPIO5_IO13, 0, 0, + [PAD_I2C1_SCL*8] I2C1_SCL, ENET1_MDC, 0, 0, 0, GPIO5_IO14, 0, 0, + [PAD_I2C1_SDA*8] I2C1_SDA, ENET1_MDIO|DAISY(2), 0, 0, 0, GPIO5_IO15, 0, 0, + [PAD_I2C2_SCL*8] I2C2_SCL, ENET1_1588_EVENT1_IN, 0, 0, 0, GPIO5_IO16, 0, 0, + [PAD_I2C2_SDA*8] I2C2_SDA, ENET1_1588_EVENT1_OUT, 0, 0, 0, GPIO5_IO17, 0, 0, + [PAD_I2C3_SCL*8] I2C3_SCL, PWM4_OUT, GPT2_CLK, 0, 0, GPIO5_IO18, 0, 0, + [PAD_I2C3_SDA*8] I2C3_SDA, PWM3_OUT, GPT3_CLK, 0, 0, GPIO5_IO19, 0, 0, + [PAD_I2C4_SCL*8] I2C4_SCL, PWM2_OUT, PCIE_CLKREQ_B, 0, 0, GPIO5_IO20, 0, 0, + [PAD_I2C4_SDA*8] I2C4_SDA, PWM1_OUT, PCIE2_CLKREQ_B|DAISY(0), 0, 0, GPIO5_IO21, 0, 0, + [PAD_UART1_RXD*8] UART1_RX, ECSPI3_SCLK, 0, 0, 0, GPIO5_IO22, 0, 0, + [PAD_UART1_TXD*8] UART1_TX, ECSPI3_MOSI, 0, 0, 0, GPIO5_IO23, 0, 0, + [PAD_UART2_RXD*8] UART2_RX, ECSPI3_MISO, 0, 0, 0, GPIO5_IO24, 0, 0, + [PAD_UART2_TXD*8] UART2_TX, ECSPI3_SS0, 0, 0, 0, GPIO5_IO25, 0, 0, + [PAD_UART3_RXD*8] UART3_RX, UART1_CTS_B, 0, 0, 0, GPIO5_IO26, 0, 0, + [PAD_UART3_TXD*8] UART3_TX, UART1_RTS_B|DAISY(1), 0, 0, 0, GPIO5_IO27, 0, 0, + [PAD_UART4_RXD*8] UART4_RX, UART2_CTS_B, PCIE1_CLKREQ_B|DAISY(1), 0, 0, GPIO5_IO28, 0, 0, + [PAD_UART4_TXD*8] UART4_TX, UART2_RTS_B|DAISY(1), PCIE2_CLKREQ_B|DAISY(1), 0, 0, GPIO5_IO29, 0, 0, +}; + +static char *padname[] = { + [PAD_TEST_MODE] "pad_test_mode", + [PAD_BOOT_MODE0] "pad_boot_mode0", + [PAD_BOOT_MODE1] "pad_boot_mode1", + [PAD_JTAG_MOD] "pad_jtag_mod", + [PAD_JTAG_TRST_B] "pad_jtag_trst_b", + [PAD_JTAG_TDI] "pad_jtag_tdi", + [PAD_JTAG_TMS] "pad_jtag_tms", + [PAD_JTAG_TCK] "pad_jtag_tck", + [PAD_JTAG_TDO] "pad_jtag_tdo", + [PAD_RTC] "pad_rtc", + [PAD_PMIC_STBY_REQ] "pad_pmic_stby_req", + [PAD_PMIC_ON_REQ] "pad_pmic_on_req", + [PAD_ONOFF] "pad_onoff", + [PAD_POR_B] "pad_por_b", + [PAD_RTC_RESET_B] "pad_rtc_reset_b", + [PAD_GPIO1_IO00] "pad_gpio1_io00", + [PAD_GPIO1_IO01] "pad_gpio1_io01", + [PAD_GPIO1_IO02] "pad_gpio1_io02", + [PAD_GPIO1_IO03] "pad_gpio1_io03", + [PAD_GPIO1_IO04] "pad_gpio1_io04", + [PAD_GPIO1_IO05] "pad_gpio1_io05", + [PAD_GPIO1_IO06] "pad_gpio1_io06", + [PAD_GPIO1_IO07] "pad_gpio1_io07", + [PAD_GPIO1_IO08] "pad_gpio1_io08", + [PAD_GPIO1_IO09] "pad_gpio1_io09", + [PAD_GPIO1_IO10] "pad_gpio1_io10", + [PAD_GPIO1_IO11] "pad_gpio1_io11", + [PAD_GPIO1_IO12] "pad_gpio1_io12", + [PAD_GPIO1_IO13] "pad_gpio1_io13", + [PAD_GPIO1_IO14] "pad_gpio1_io14", + [PAD_GPIO1_IO15] "pad_gpio1_io15", + [PAD_ENET_MDC] "pad_enet_mdc", + [PAD_ENET_MDIO] "pad_enet_mdio", + [PAD_ENET_TD3] "pad_enet_td3", + [PAD_ENET_TD2] "pad_enet_td2", + [PAD_ENET_TD1] "pad_enet_td1", + [PAD_ENET_TD0] "pad_enet_td0", + [PAD_ENET_TX_CTL] "pad_enet_tx_ctl", + [PAD_ENET_TXC] "pad_enet_txc", + [PAD_ENET_RX_CTL] "pad_enet_rx_ctl", + [PAD_ENET_RXC] "pad_enet_rxc", + [PAD_ENET_RD0] "pad_enet_rd0", + [PAD_ENET_RD1] "pad_enet_rd1", + [PAD_ENET_RD2] "pad_enet_rd2", + [PAD_ENET_RD3] "pad_enet_rd3", + [PAD_SD1_CLK] "pad_sd1_clk", + [PAD_SD1_CMD] "pad_sd1_cmd", + [PAD_SD1_DATA0] "pad_sd1_data0", + [PAD_SD1_DATA1] "pad_sd1_data1", + [PAD_SD1_DATA2] "pad_sd1_data2", + [PAD_SD1_DATA3] "pad_sd1_data3", + [PAD_SD1_DATA4] "pad_sd1_data4", + [PAD_SD1_DATA5] "pad_sd1_data5", + [PAD_SD1_DATA6] "pad_sd1_data6", + [PAD_SD1_DATA7] "pad_sd1_data7", + [PAD_SD1_RESET_B] "pad_sd1_reset_b", + [PAD_SD1_STROBE] "pad_sd1_strobe", + [PAD_SD2_CD_B] "pad_sd2_cd_b", + [PAD_SD2_CLK] "pad_sd2_clk", + [PAD_SD2_CMD] "pad_sd2_cmd", + [PAD_SD2_DATA0] "pad_sd2_data0", + [PAD_SD2_DATA1] "pad_sd2_data1", + [PAD_SD2_DATA2] "pad_sd2_data2", + [PAD_SD2_DATA3] "pad_sd2_data3", + [PAD_SD2_RESET_B] "pad_sd2_reset_b", + [PAD_SD2_WP] "pad_sd2_wp", + [PAD_NAND_ALE] "pad_nand_ale", + [PAD_NAND_CE0_B] "pad_nand_ce0_b", + [PAD_NAND_CE1_B] "pad_nand_ce1_b", + [PAD_NAND_CE2_B] "pad_nand_ce2_b", + [PAD_NAND_CE3_B] "pad_nand_ce3_b", + [PAD_NAND_CLE] "pad_nand_cle", + [PAD_NAND_DATA0] "pad_nand_data0", + [PAD_NAND_DATA1] "pad_nand_data1", + [PAD_NAND_DATA2] "pad_nand_data2", + [PAD_NAND_DATA3] "pad_nand_data3", + [PAD_NAND_DATA4] "pad_nand_data4", + [PAD_NAND_DATA5] "pad_nand_data5", + [PAD_NAND_DATA6] "pad_nand_data6", + [PAD_NAND_DATA7] "pad_nand_data7", + [PAD_NAND_DQS] "pad_nand_dqs", + [PAD_NAND_RE_B] "pad_nand_re_b", + [PAD_NAND_READY_B] "pad_nand_ready_b", + [PAD_NAND_WE_B] "pad_nand_we_b", + [PAD_NAND_WP_B] "pad_nand_wp_b", + [PAD_SAI5_RXFS] "pad_sai5_rxfs", + [PAD_SAI5_RXC] "pad_sai5_rxc", + [PAD_SAI5_RXD0] "pad_sai5_rxd0", + [PAD_SAI5_RXD1] "pad_sai5_rxd1", + [PAD_SAI5_RXD2] "pad_sai5_rxd2", + [PAD_SAI5_RXD3] "pad_sai5_rxd3", + [PAD_SAI5_MCLK] "pad_sai5_mclk", + [PAD_SAI1_RXFS] "pad_sai1_rxfs", + [PAD_SAI1_RXC] "pad_sai1_rxc", + [PAD_SAI1_RXD0] "pad_sai1_rxd0", + [PAD_SAI1_RXD1] "pad_sai1_rxd1", + [PAD_SAI1_RXD2] "pad_sai1_rxd2", + [PAD_SAI1_RXD3] "pad_sai1_rxd3", + [PAD_SAI1_RXD4] "pad_sai1_rxd4", + [PAD_SAI1_RXD5] "pad_sai1_rxd5", + [PAD_SAI1_RXD6] "pad_sai1_rxd6", + [PAD_SAI1_RXD7] "pad_sai1_rxd7", + [PAD_SAI1_TXFS] "pad_sai1_txfs", + [PAD_SAI1_TXC] "pad_sai1_txc", + [PAD_SAI1_TXD0] "pad_sai1_txd0", + [PAD_SAI1_TXD1] "pad_sai1_txd1", + [PAD_SAI1_TXD2] "pad_sai1_txd2", + [PAD_SAI1_TXD3] "pad_sai1_txd3", + [PAD_SAI1_TXD4] "pad_sai1_txd4", + [PAD_SAI1_TXD5] "pad_sai1_txd5", + [PAD_SAI1_TXD6] "pad_sai1_txd6", + [PAD_SAI1_TXD7] "pad_sai1_txd7", + [PAD_SAI1_MCLK] "pad_sai1_mclk", + [PAD_SAI2_RXFS] "pad_sai2_rxfs", + [PAD_SAI2_RXC] "pad_sai2_rxc", + [PAD_SAI2_RXD0] "pad_sai2_rxd0", + [PAD_SAI2_TXFS] "pad_sai2_txfs", + [PAD_SAI2_TXC] "pad_sai2_txc", + [PAD_SAI2_TXD0] "pad_sai2_txd0", + [PAD_SAI2_MCLK] "pad_sai2_mclk", + [PAD_SAI3_RXFS] "pad_sai3_rxfs", + [PAD_SAI3_RXC] "pad_sai3_rxc", + [PAD_SAI3_RXD] "pad_sai3_rxd", + [PAD_SAI3_TXFS] "pad_sai3_txfs", + [PAD_SAI3_TXC] "pad_sai3_txc", + [PAD_SAI3_TXD] "pad_sai3_txd", + [PAD_SAI3_MCLK] "pad_sai3_mclk", + [PAD_SPDIF_TX] "pad_spdif_tx", + [PAD_SPDIF_RX] "pad_spdif_rx", + [PAD_SPDIF_EXT_CLK] "pad_spdif_ext_clk", + [PAD_ECSPI1_SCLK] "pad_ecspi1_sclk", + [PAD_ECSPI1_MOSI] "pad_ecspi1_mosi", + [PAD_ECSPI1_MISO] "pad_ecspi1_miso", + [PAD_ECSPI1_SS0] "pad_ecspi1_ss0", + [PAD_ECSPI2_SCLK] "pad_ecspi2_sclk", + [PAD_ECSPI2_MOSI] "pad_ecspi2_mosi", + [PAD_ECSPI2_MISO] "pad_ecspi2_miso", + [PAD_ECSPI2_SS0] "pad_ecspi2_ss0", + [PAD_I2C1_SCL] "pad_i2c1_scl", + [PAD_I2C1_SDA] "pad_i2c1_sda", + [PAD_I2C2_SCL] "pad_i2c2_scl", + [PAD_I2C2_SDA] "pad_i2c2_sda", + [PAD_I2C3_SCL] "pad_i2c3_scl", + [PAD_I2C3_SDA] "pad_i2c3_sda", + [PAD_I2C4_SCL] "pad_i2c4_scl", + [PAD_I2C4_SDA] "pad_i2c4_sda", + [PAD_UART1_RXD] "pad_uart1_rxd", + [PAD_UART1_TXD] "pad_uart1_txd", + [PAD_UART2_RXD] "pad_uart2_rxd", + [PAD_UART2_TXD] "pad_uart2_txd", + [PAD_UART3_RXD] "pad_uart3_rxd", + [PAD_UART3_TXD] "pad_uart3_txd", + [PAD_UART4_RXD] "pad_uart4_rxd", + [PAD_UART4_TXD] "pad_uart4_txd", +}; + +static char *signame[] = { + [CCM_PMIC_READY] "ccm_pmic_ready", + [ENET1_MDIO] "enet1_mdio", + [PCIE1_CLKREQ_B] "pcie1_clkreq_b", + [PCIE2_CLKREQ_B] "pcie2_clkreq_b", + [SAI1_RX_BCLK] "sai1_rx_bclk", + [SAI1_RX_SYNC] "sai1_rx_sync", + [SAI1_TX_SYNC] "sai1_tx_sync", + [SAI5_MCLK] "sai5_mclk", + [SAI5_RXD0] "sai5_rxd0", + [SAI5_RXD1] "sai5_rxd1", + [SAI5_RXD2] "sai5_rxd2", + [SAI5_RXD3] "sai5_rxd3", + [SAI5_RX_BCLK] "sai5_rx_bclk", + [SAI5_RX_SYNC] "sai5_rx_sync", + [SAI5_TX_BLCK] "sai5_tx_blck", + [SAI5_TX_SYNC] "sai5_tx_sync", + [SAI6_MCLK] "sai6_mclk", + [SAI6_RXD0] "sai6_rxd0", + [SAI6_RX_BCLK] "sai6_rx_bclk", + [SAI6_RX_SYNC] "sai6_rx_sync", + [SAI6_TX_BCLK] "sai6_tx_bclk", + [SAY6_TX_SYNC] "say6_tx_sync", + [UART1_RTS_B] "uart1_rts_b", + [UART1_RXD] "uart1_rxd", + [UART2_RTS_B] "uart2_rts_b", + [UART2_RXD] "uart2_rxd", + [UART3_RTS_B] "uart3_rts_b", + [UART3_RXD] "uart3_rxd", + [UART4_RTS_B] "uart4_rts_b", + [UART4_RXD] "uart4_rxd", + [ANAMIX_REF_CLK_25M] "anamix_ref_clk_25m", + [ANAMIX_REF_CLK_32K] "anamix_ref_clk_32k", + [CCM_CLKO1] "ccm_clko1", + [CCM_CLKO2] "ccm_clko2", + [CCM_ENET_PHY_REF_CLK_ROOT] "ccm_enet_phy_ref_clk_root", + [CCM_EXT_CLK1] "ccm_ext_clk1", + [CCM_EXT_CLK2] "ccm_ext_clk2", + [CCM_EXT_CLK3] "ccm_ext_clk3", + [CCM_EXT_CLK4] "ccm_ext_clk4", + [CORESIGHT_EVENTI] "coresight_eventi", + [CORESIGHT_EVENTO] "coresight_evento", + [CORESIGHT_TRACE0] "coresight_trace0", + [CORESIGHT_TRACE1] "coresight_trace1", + [CORESIGHT_TRACE10] "coresight_trace10", + [CORESIGHT_TRACE11] "coresight_trace11", + [CORESIGHT_TRACE12] "coresight_trace12", + [CORESIGHT_TRACE13] "coresight_trace13", + [CORESIGHT_TRACE14] "coresight_trace14", + [CORESIGHT_TRACE15] "coresight_trace15", + [CORESIGHT_TRACE2] "coresight_trace2", + [CORESIGHT_TRACE3] "coresight_trace3", + [CORESIGHT_TRACE4] "coresight_trace4", + [CORESIGHT_TRACE5] "coresight_trace5", + [CORESIGHT_TRACE6] "coresight_trace6", + [CORESIGHT_TRACE7] "coresight_trace7", + [CORESIGHT_TRACE8] "coresight_trace8", + [CORESIGHT_TRACE9] "coresight_trace9", + [CORESIGHT_TRACE_CLK] "coresight_trace_clk", + [CORESIGHT_TRACE_CTL] "coresight_trace_ctl", + [ECSPI1_MISO] "ecspi1_miso", + [ECSPI1_MOSI] "ecspi1_mosi", + [ECSPI1_SCLK] "ecspi1_sclk", + [ECSPI1_SS0] "ecspi1_ss0", + [ECSPI2_MISO] "ecspi2_miso", + [ECSPI2_MOSI] "ecspi2_mosi", + [ECSPI2_SCLK] "ecspi2_sclk", + [ECSPI2_SS0] "ecspi2_ss0", + [ECSPI3_MISO] "ecspi3_miso", + [ECSPI3_MOSI] "ecspi3_mosi", + [ECSPI3_SCLK] "ecspi3_sclk", + [ECSPI3_SS0] "ecspi3_ss0", + [ENET1_1588_EVENT0_IN] "enet1_1588_event0_in", + [ENET1_1588_EVENT0_OUT] "enet1_1588_event0_out", + [ENET1_1588_EVENT1_IN] "enet1_1588_event1_in", + [ENET1_1588_EVENT1_OUT] "enet1_1588_event1_out", + [ENET1_MDC] "enet1_mdc", + [ENET1_RGMII_RD0] "enet1_rgmii_rd0", + [ENET1_RGMII_RD1] "enet1_rgmii_rd1", + [ENET1_RGMII_RD2] "enet1_rgmii_rd2", + [ENET1_RGMII_RD3] "enet1_rgmii_rd3", + [ENET1_RGMII_RXC] "enet1_rgmii_rxc", + [ENET1_RGMII_RX_CTL] "enet1_rgmii_rx_ctl", + [ENET1_RGMII_TD0] "enet1_rgmii_td0", + [ENET1_RGMII_TD1] "enet1_rgmii_td1", + [ENET1_RGMII_TD2] "enet1_rgmii_td2", + [ENET1_RGMII_TD3] "enet1_rgmii_td3", + [ENET1_RGMII_TXC] "enet1_rgmii_txc", + [ENET1_RGMII_TX_CTL] "enet1_rgmii_tx_ctl", + [ENET1_RX_ER] "enet1_rx_er", + [ENET1_TX_CLK] "enet1_tx_clk", + [ENET1_TX_ER] "enet1_tx_er", + [GPIO1_IO00] "gpio1_io00", + [GPIO1_IO01] "gpio1_io01", + [GPIO1_IO02] "gpio1_io02", + [GPIO1_IO03] "gpio1_io03", + [GPIO1_IO04] "gpio1_io04", + [GPIO1_IO05] "gpio1_io05", + [GPIO1_IO06] "gpio1_io06", + [GPIO1_IO07] "gpio1_io07", + [GPIO1_IO08] "gpio1_io08", + [GPIO1_IO09] "gpio1_io09", + [GPIO1_IO10] "gpio1_io10", + [GPIO1_IO11] "gpio1_io11", + [GPIO1_IO12] "gpio1_io12", + [GPIO1_IO13] "gpio1_io13", + [GPIO1_IO14] "gpio1_io14", + [GPIO1_IO15] "gpio1_io15", + [GPIO1_IO16] "gpio1_io16", + [GPIO1_IO17] "gpio1_io17", + [GPIO1_IO18] "gpio1_io18", + [GPIO1_IO19] "gpio1_io19", + [GPIO1_IO20] "gpio1_io20", + [GPIO1_IO21] "gpio1_io21", + [GPIO1_IO22] "gpio1_io22", + [GPIO1_IO23] "gpio1_io23", + [GPIO1_IO24] "gpio1_io24", + [GPIO1_IO25] "gpio1_io25", + [GPIO1_IO26] "gpio1_io26", + [GPIO1_IO27] "gpio1_io27", + [GPIO1_IO28] "gpio1_io28", + [GPIO1_IO29] "gpio1_io29", + [GPIO2_IO00] "gpio2_io00", + [GPIO2_IO01] "gpio2_io01", + [GPIO2_IO02] "gpio2_io02", + [GPIO2_IO03] "gpio2_io03", + [GPIO2_IO04] "gpio2_io04", + [GPIO2_IO05] "gpio2_io05", + [GPIO2_IO06] "gpio2_io06", + [GPIO2_IO07] "gpio2_io07", + [GPIO2_IO08] "gpio2_io08", + [GPIO2_IO09] "gpio2_io09", + [GPIO2_IO10] "gpio2_io10", + [GPIO2_IO11] "gpio2_io11", + [GPIO2_IO12] "gpio2_io12", + [GPIO2_IO13] "gpio2_io13", + [GPIO2_IO14] "gpio2_io14", + [GPIO2_IO15] "gpio2_io15", + [GPIO2_IO16] "gpio2_io16", + [GPIO2_IO17] "gpio2_io17", + [GPIO2_IO18] "gpio2_io18", + [GPIO2_IO19] "gpio2_io19", + [GPIO2_IO20] "gpio2_io20", + [GPIO3_IO00] "gpio3_io00", + [GPIO3_IO01] "gpio3_io01", + [GPIO3_IO02] "gpio3_io02", + [GPIO3_IO03] "gpio3_io03", + [GPIO3_IO04] "gpio3_io04", + [GPIO3_IO05] "gpio3_io05", + [GPIO3_IO06] "gpio3_io06", + [GPIO3_IO07] "gpio3_io07", + [GPIO3_IO08] "gpio3_io08", + [GPIO3_IO09] "gpio3_io09", + [GPIO3_IO10] "gpio3_io10", + [GPIO3_IO11] "gpio3_io11", + [GPIO3_IO12] "gpio3_io12", + [GPIO3_IO13] "gpio3_io13", + [GPIO3_IO14] "gpio3_io14", + [GPIO3_IO15] "gpio3_io15", + [GPIO3_IO16] "gpio3_io16", + [GPIO3_IO17] "gpio3_io17", + [GPIO3_IO18] "gpio3_io18", + [GPIO3_IO19] "gpio3_io19", + [GPIO3_IO20] "gpio3_io20", + [GPIO3_IO21] "gpio3_io21", + [GPIO3_IO22] "gpio3_io22", + [GPIO3_IO23] "gpio3_io23", + [GPIO3_IO24] "gpio3_io24", + [GPIO3_IO25] "gpio3_io25", + [GPIO4_IO00] "gpio4_io00", + [GPIO4_IO01] "gpio4_io01", + [GPIO4_IO02] "gpio4_io02", + [GPIO4_IO03] "gpio4_io03", + [GPIO4_IO04] "gpio4_io04", + [GPIO4_IO05] "gpio4_io05", + [GPIO4_IO06] "gpio4_io06", + [GPIO4_IO07] "gpio4_io07", + [GPIO4_IO08] "gpio4_io08", + [GPIO4_IO09] "gpio4_io09", + [GPIO4_IO10] "gpio4_io10", + [GPIO4_IO11] "gpio4_io11", + [GPIO4_IO12] "gpio4_io12", + [GPIO4_IO13] "gpio4_io13", + [GPIO4_IO14] "gpio4_io14", + [GPIO4_IO15] "gpio4_io15", + [GPIO4_IO16] "gpio4_io16", + [GPIO4_IO17] "gpio4_io17", + [GPIO4_IO18] "gpio4_io18", + [GPIO4_IO19] "gpio4_io19", + [GPIO4_IO20] "gpio4_io20", + [GPIO4_IO21] "gpio4_io21", + [GPIO4_IO22] "gpio4_io22", + [GPIO4_IO23] "gpio4_io23", + [GPIO4_IO24] "gpio4_io24", + [GPIO4_IO25] "gpio4_io25", + [GPIO4_IO26] "gpio4_io26", + [GPIO4_IO27] "gpio4_io27", + [GPIO4_IO28] "gpio4_io28", + [GPIO4_IO29] "gpio4_io29", + [GPIO4_IO31] "gpio4_io31", + [GPIO5_IO00] "gpio5_io00", + [GPIO5_IO01] "gpio5_io01", + [GPIO5_IO02] "gpio5_io02", + [GPIO5_IO03] "gpio5_io03", + [GPIO5_IO04] "gpio5_io04", + [GPIO5_IO05] "gpio5_io05", + [GPIO5_IO06] "gpio5_io06", + [GPIO5_IO07] "gpio5_io07", + [GPIO5_IO08] "gpio5_io08", + [GPIO5_IO09] "gpio5_io09", + [GPIO5_IO10] "gpio5_io10", + [GPIO5_IO11] "gpio5_io11", + [GPIO5_IO12] "gpio5_io12", + [GPIO5_IO13] "gpio5_io13", + [GPIO5_IO14] "gpio5_io14", + [GPIO5_IO15] "gpio5_io15", + [GPIO5_IO16] "gpio5_io16", + [GPIO5_IO17] "gpio5_io17", + [GPIO5_IO18] "gpio5_io18", + [GPIO5_IO19] "gpio5_io19", + [GPIO5_IO20] "gpio5_io20", + [GPIO5_IO21] "gpio5_io21", + [GPIO5_IO22] "gpio5_io22", + [GPIO5_IO23] "gpio5_io23", + [GPIO5_IO24] "gpio5_io24", + [GPIO5_IO25] "gpio5_io25", + [GPIO5_IO26] "gpio5_io26", + [GPIO5_IO27] "gpio5_io27", + [GPIO5_IO28] "gpio5_io28", + [GPIO5_IO29] "gpio5_io29", + [GPT1_CAPTURE1] "gpt1_capture1", + [GPT1_CAPTURE2] "gpt1_capture2", + [GPT1_COMPARE1] "gpt1_compare1", + [GPT1_COMPARE2] "gpt1_compare2", + [GPT1_COMPARE3] "gpt1_compare3", + [GPT1_CLK] "gpt1_clk", + [GPT2_CLK] "gpt2_clk", + [GPT3_CLK] "gpt3_clk", + [I2C1_SCL] "i2c1_scl", + [I2C1_SDA] "i2c1_sda", + [I2C2_SCL] "i2c2_scl", + [I2C2_SDA] "i2c2_sda", + [I2C3_SCL] "i2c3_scl", + [I2C3_SDA] "i2c3_sda", + [I2C4_SCL] "i2c4_scl", + [I2C4_SDA] "i2c4_sda", + [M4_NMI] "m4_nmi", + [PCIE_CLKREQ_B] "pcie_clkreq_b", + [PWM1_OUT] "pwm1_out", + [PWM2_OUT] "pwm2_out", + [PWM3_OUT] "pwm3_out", + [PWM4_OUT] "pwm4_out", + [QSPI_A_DATA0] "qspi_a_data0", + [QSPI_A_DATA1] "qspi_a_data1", + [QSPI_A_DATA2] "qspi_a_data2", + [QSPI_A_DATA3] "qspi_a_data3", + [QSPI_A_DQS] "qspi_a_dqs", + [QSPI_A_SCLK] "qspi_a_sclk", + [QSPI_A_SS0_B] "qspi_a_ss0_b", + [QSPI_A_SS1_B] "qspi_a_ss1_b", + [QSPI_B_DATA0] "qspi_b_data0", + [QSPI_B_DATA1] "qspi_b_data1", + [QSPI_B_DATA2] "qspi_b_data2", + [QSPI_B_DATA3] "qspi_b_data3", + [QSPI_B_DQS] "qspi_b_dqs", + [QSPI_B_SCLK] "qspi_b_sclk", + [QSPI_B_SS0_B] "qspi_b_ss0_b", + [QSPI_B_SS1_B] "qspi_b_ss1_b", + [RAWNAND_ALE] "rawnand_ale", + [RAWNAND_CE0_B] "rawnand_ce0_b", + [RAWNAND_CE1_B] "rawnand_ce1_b", + [RAWNAND_CE2_B] "rawnand_ce2_b", + [RAWNAND_CE3_B] "rawnand_ce3_b", + [RAWNAND_CLE] "rawnand_cle", + [RAWNAND_DATA00] "rawnand_data00", + [RAWNAND_DATA01] "rawnand_data01", + [RAWNAND_DATA02] "rawnand_data02", + [RAWNAND_DATA03] "rawnand_data03", + [RANWNAD_DATA04] "ranwnad_data04", + [RAWNAND_DATA05] "rawnand_data05", + [RAWNAND_DATA06] "rawnand_data06", + [RAWNAND_DATA07] "rawnand_data07", + [RAWNAND_DQS] "rawnand_dqs", + [RAWNAND_READY_B] "rawnand_ready_b", + [RAWNAND_RE_B] "rawnand_re_b", + [RAWNAND_WE_B] "rawnand_we_b", + [RAWNAND_WP_B] "rawnand_wp_b", + [SAI1_MCLK] "sai1_mclk", + [SAI1_RX_DATA0] "sai1_rx_data0", + [SAI1_RX_DATA1] "sai1_rx_data1", + [SAI1_RX_DATA2] "sai1_rx_data2", + [SAI1_RX_DATA3] "sai1_rx_data3", + [SAI1_RX_DATA4] "sai1_rx_data4", + [SAI1_RX_DATA5] "sai1_rx_data5", + [SAI1_RX_DATA6] "sai1_rx_data6", + [SAI1_RX_DATA7] "sai1_rx_data7", + [SAI1_TX_BCLK] "sai1_tx_bclk", + [SAI1_TX_DATA0] "sai1_tx_data0", + [SAI1_TX_DATA1] "sai1_tx_data1", + [SAI1_TX_DATA2] "sai1_tx_data2", + [SAI1_TX_DATA3] "sai1_tx_data3", + [SAI1_TX_DATA4] "sai1_tx_data4", + [SAI1_TX_DATA5] "sai1_tx_data5", + [SAI1_TX_DATA6] "sai1_tx_data6", + [SAI1_TX_DATA7] "sai1_tx_data7", + [SAI2_MCLK] "sai2_mclk", + [SAI2_RX_BCLK] "sai2_rx_bclk", + [SAI2_RX_DATA0] "sai2_rx_data0", + [SAI2_RX_SYNC] "sai2_rx_sync", + [SAI2_TX_BCLK] "sai2_tx_bclk", + [SAI2_TX_DATA0] "sai2_tx_data0", + [SAI2_TX_SYNC] "sai2_tx_sync", + [SAI3_MCLK] "sai3_mclk", + [SAI3_RX_BCLK] "sai3_rx_bclk", + [SAI3_RX_DATA0] "sai3_rx_data0", + [SAI3_RX_SYNC] "sai3_rx_sync", + [SAI3_TX_BCLK] "sai3_tx_bclk", + [SAI3_TX_DATA0] "sai3_tx_data0", + [SAI3_TX_SYNC] "sai3_tx_sync", + [SAI4_MCLK] "sai4_mclk", + [SAI5_RX_DATA0] "sai5_rx_data0", + [SAI5_RX_DATA1] "sai5_rx_data1", + [SAI5_RX_DATA2] "sai5_rx_data2", + [SAI5_RX_DATA3] "sai5_rx_data3", + [SAI5_TX_BCLK] "sai5_tx_bclk", + [SAI5_TX_DATA0] "sai5_tx_data0", + [SAI5_TX_DATA1] "sai5_tx_data1", + [SAI5_TX_DATA2] "sai5_tx_data2", + [SAI5_TX_DATA3] "sai5_tx_data3", + [SAI6_RC_BCLK] "sai6_rc_bclk", + [SAI6_RX_DATA0] "sai6_rx_data0", + [SAI6_TX_DATA0] "sai6_tx_data0", + [SAI6_TX_SYNC] "sai6_tx_sync", + [SDMA1_EXT_EVENT0] "sdma1_ext_event0", + [SDMA1_EXT_EVENT1] "sdma1_ext_event1", + [SDMA2_EXT_EVENT0] "sdma2_ext_event0", + [SDMA2_EXT_EVENT1] "sdma2_ext_event1", + [SJC_DE_B] "sjc_de_b", + [SPDIF1_EXT_CLK] "spdif1_ext_clk", + [SPDIF1_IN] "spdif1_in", + [SPDIF1_OUT] "spdif1_out", + [SRC_BOOT_CFG0] "src_boot_cfg0", + [SRC_BOOT_CFG1] "src_boot_cfg1", + [SRC_BOOT_CFG2] "src_boot_cfg2", + [SRC_BOOT_CFG3] "src_boot_cfg3", + [SRC_BOOT_CFG4] "src_boot_cfg4", + [SRC_BOOT_CFG5] "src_boot_cfg5", + [SRC_BOOT_CFG6] "src_boot_cfg6", + [SRC_BOOT_CFG7] "src_boot_cfg7", + [SRC_BOOT_CFG8] "src_boot_cfg8", + [SRC_BOOT_CFG9] "src_boot_cfg9", + [SRC_BOOT_CFG10] "src_boot_cfg10", + [SRC_BOOT_CFG11] "src_boot_cfg11", + [SRC_BOOT_CFG12] "src_boot_cfg12", + [SRC_BOOT_CFG13] "src_boot_cfg13", + [SRC_BOOT_CFG14] "src_boot_cfg14", + [SRC_BOOT_CFG15] "src_boot_cfg15", + [UART1_CTS_B] "uart1_cts_b", + [UART1_RX] "uart1_rx", + [UART1_TX] "uart1_tx", + [UART2_CTS_B] "uart2_cts_b", + [UART2_RX] "uart2_rx", + [UART2_TX] "uart2_tx", + [UART3_CTS_B] "uart3_cts_b", + [UART3_RX] "uart3_rx", + [UART3_TX] "uart3_tx", + [UART4_CTS_B] "uart4_cts_b", + [UART4_RX] "uart4_rx", + [UART4_TX] "uart4_tx", + [USB1_OTG_ID] "usb1_otg_id", + [USB1_OTG_OC] "usb1_otg_oc", + [USB1_OTG_PWR] "usb1_otg_pwr", + [USB2_OTG_ID] "usb2_otg_id", + [USB2_OTG_OC] "usb2_otg_oc", + [USB2_OTG_PWR] "usb2_otg_pwr", + [USDHC1_CD_B] "usdhc1_cd_b", + [USDHC1_CLK] "usdhc1_clk", + [USDHC1_CMD] "usdhc1_cmd", + [USDHC1_DATA0] "usdhc1_data0", + [USDHC1_DATA1] "usdhc1_data1", + [USDHC1_DATA2] "usdhc1_data2", + [USDHC1_DATA3] "usdhc1_data3", + [USDHC1_DATA4] "usdhc1_data4", + [USDHC1_DATA5] "usdhc1_data5", + [USDHC1_DATA6] "usdhc1_data6", + [USDHC1_DATA7] "usdhc1_data7", + [USDHC1_RESET_B] "usdhc1_reset_b", + [USDHC1_STROBE] "usdhc1_strobe", + [USDHC1_VSELECT] "usdhc1_vselect", + [USDHC1_WP] "usdhc1_wp", + [USDHC2_CD_B] "usdhc2_cd_b", + [USDHC2_CLK] "usdhc2_clk", + [USDHC2_CMD] "usdhc2_cmd", + [USDHC2_DATA0] "usdhc2_data0", + [USDHC2_DATA1] "usdhc2_data1", + [USDHC2_DATA2] "usdhc2_data2", + [USDHC2_DATA3] "usdhc2_data3", + [USDHC2_RESET_B] "usdhc2_reset_b", + [USDHC2_VSELECT] "usdhc2_vselect", + [USDHC2_WP] "usdhc2_wp", + [WDOG1_WDOG_ANY] "wdog1_wdog_any", + [WDOG1_WDOG_B] "wdog1_wdog_b", +}; + +struct padopt { + char *s; + u32int m; + u32int v; +}; + +static struct padopt padopts[] = { + "VSEL_0", 7<<11, 0<<11, + "VSEL_1", 7<<11, 1<<11, + "VSEL_2", 7<<11, 2<<11, + "VSEL_3", 7<<11, 3<<11, + "VSEL_4", 7<<11, 4<<11, + "VSEL_5", 7<<11, 5<<11, + "VSEL_6", 7<<11, 6<<11, + "VSEL_7", 7<<11, 7<<11, + + "LVTTL", 1<<8, 1<<8, + + "HYS", 1<<7, 1<<7, + + "PUE", 1<<6, 1<<6, + + "ODE", 1<<5, 1<<5, + + "SLOW", 3<<3, 0<<3, + "MEDIUM", 3<<3, 1<<3, + "FAST", 3<<3, 2<<3, + "MAX", 3<<3, 3<<3, + + "HI-Z", 7, 0, + "255_OHM", 7, 1, + "105_OHM", 7, 2, + "75_OHM", 7, 3, + "85_OHM", 7, 4, + "65_OHM", 7, 5, + "45_OHM", 7, 6, + "40_OHM", 7, 7, + + nil, +}; + +void +iomuxpad(char *pads, char *sel, char *cfg) +{ + int pad, sig, mux, alt, daisy; + u32int val, mask, *reg; + + for(pad = 0; pad < nelem(padname); pad++) + if(padname[pad] != nil && cistrcmp(pads, padname[pad]) == 0) + goto Padok; + + panic("iomuxpad: %s not defined", pads); + return; +Padok: + val = 0; + mask = 0; + mux = 0; + sig = 0; + + if(cfg != nil){ + struct padopt *o; + char *x; + + for(o = padopts; o->s != nil; o++) { + x = strstr(cfg, o->s); + if(x != nil){ + if(x > cfg && x[-1] == '~') + val &= ~o->v; + else + val |= o->v; + mask |= o->m; + } + } + if(mask != 0){ + reg = &iomuxc[IOMUXC_SW_PAD_CTL_PAD_TEST_MODE + pad]; +// iprint("iomuxpad: pad_ctl_%s %p <= %.8ux & %.8ux\n", padname[pad], PADDR(reg), val, mask); + *reg = (*reg & ~mask) | val; + } + + val = 0; + mask = 0; + x = strstr(cfg, "SION"); + if(x != nil){ + if(x > cfg && x[-1] == '~') + val &= ~SION; + else + val |= SION; + mask |= SION; + } + } + + if(sel != nil){ + if(pad < PAD_GPIO1_IO00 || pad >= nelem(padmux)/8) + panic("iomuxpad: %s is not muxed", pads); + + /* find the mux value for the signal */ + for(alt = 0; alt < 8; alt++){ + mux = padmux[pad*8 + alt]; + if(mux == 0) + continue; + + sig = mux & ~DAISY(7); + if(signame[sig] != nil && cistrcmp(sel, signame[sig]) == 0) + goto Muxok; + } + panic("iomuxpad: %s not muxable to %s", pads, sel); + return; +Muxok: + val = (val & ~MUX_MODE) | alt; + mask |= MUX_MODE; + } + + if(mask == 0) + return; + + if(pad < PAD_PMIC_STBY_REQ){ + panic("iomuxpad: %s has no mux control", pads); + return; + } + + reg = &iomuxc[IOMUXC_SW_MUX_CTL_PAD_PMIC_STBY_REQ + (pad - PAD_PMIC_STBY_REQ)]; +// iprint("iomuxpad: mux_ctl_%s %p <= %.8ux & %.8ux (%s)\n", padname[pad], PADDR(reg), val, mask, signame[sig]); + *reg = (*reg & ~mask) | val; + + if((mux & DAISY(0)) == 0) + return; + + val = DAISY_VAL(mux); + + /* configure daisy input mux */ + assert(sig < nelem(daisytab)); + daisy = daisytab[sig]; + assert(daisy != 0); + mask = DAISY_VAL(daisy); + assert((mask & (mask+1)) == 0); + daisy &= ~DAISY(7); + + reg = &iomuxc[IOMUXC_CCM_PMIC_READY_SELECT_INPUT + daisy]; +// iprint("iomuxpad: %s_input_select %p <= %.8ux & %.8ux\n", signame[sig], PADDR(reg), val, mask); + *reg = (*reg & ~mask) | val; +} + +uint +iomuxgpr(int gpr, uint set, uint mask) +{ + u32int *reg = &iomuxc[IOMUXC_GPR_GPR0 + gpr]; + + if(mask == 0) + return *reg; + +// iprint("iomuxgpr: gpr%d %p <= %.8ux & %.8ux\n", gpr, PADDR(reg), set, mask); + return *reg = (*reg & ~mask) | (set & mask); +} diff --git a/sys/src/9/imx8/lcd.c b/sys/src/9/imx8/lcd.c new file mode 100644 index 000000000..78549f036 --- /dev/null +++ b/sys/src/9/imx8/lcd.c @@ -0,0 +1,911 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "../port/i2c.h" + +#define Image IMAGE +#include +#include +#include +#include "screen.h" + +extern Memimage *gscreen; + +/* system reset controller registers */ +enum { + SRC_MIPIPHY_RCR = 0x28/4, + RCR_MIPI_DSI_PCLK_RESET_N = 1<<5, + RCR_MIPI_DSI_ESC_RESET_N = 1<<4, + RCR_MIPI_DSI_DPI_RESET_N = 1<<3, + RCR_MIPI_DSI_RESET_N = 1<<2, + RCR_MIPI_DSI_RESET_BYTE_N = 1<<1, + + SRC_DISP_RCR = 0x34/4, +}; + +/* pwm controller registers */ +enum { + Pwmsrcclk = 25*Mhz, + + PWMCR = 0x00/4, + CR_FWM_1 = 0<<26, + CR_FWM_2 = 1<<26, + CR_FWM_3 = 2<<26, + CR_FWM_4 = 3<<26, + + CR_STOPEN = 1<<25, + CR_DOZEN = 1<<24, + CR_WAITEN = 1<<23, + CR_DBGEN = 1<<22, + CR_BCTR = 1<<21, + CR_HCTR = 1<<20, + + CR_POUTC = 1<<18, + + CR_CLKSRC_OFF = 0<<16, + CR_CLKSRC_IPG = 1<<16, + CR_CLKSRC_HIGHFREQ = 2<<16, + CR_CLKSRC_32K = 3<<16, + + CR_PRESCALER_SHIFT = 4, + + CR_SWR = 1<<3, + + CR_REPEAT_1 = 0<<1, + CR_REPEAT_2 = 1<<1, + CR_REPEAT_4 = 2<<1, + CR_REPEAT_8 = 3<<1, + + CR_EN = 1<<0, + + PWMSR = 0x04/4, + PWMIR = 0x08/4, + PWMSAR = 0x0C/4, + SAR_MASK = 0xFFFF, + PWMPR = 0x10/4, + PR_MASK = 0xFFFF, + PWMCNR = 0x14/4, + CNR_MASK = 0xFFFF, +}; + +/* dphy registers */ +enum { + DPHY_PD_PHY = 0x0/4, + DPHY_M_PRG_HS_PREPARE = 0x4/4, + DPHY_MC_PRG_HS_PREPARE = 0x8/4, + DPHY_M_PRG_HS_ZERO = 0xc/4, + DPHY_MC_PRG_HS_ZERO = 0x10/4, + DPHY_M_PRG_HS_TRAIL = 0x14/4, + DPHY_MC_PRG_HS_TRAIL = 0x18/4, + DPHY_PD_PLL = 0x1c/4, + DPHY_TST = 0x20/4, + DPHY_CN = 0x24/4, + DPHY_CM = 0x28/4, + DPHY_CO = 0x2c/4, + DPHY_LOCK = 0x30/4, + DPHY_LOCK_BYP = 0x34/4, + DPHY_RTERM_SEL = 0x38/4, + DPHY_AUTO_PD_EN = 0x3c/4, + DPHY_RXLPRP = 0x40/4, + DPHY_RXCDR = 0x44/4, + DPHY_RXHS_SETTLE = 0x48/4, /* undocumented */ +}; + +/* dsi-host registers */ +enum { + DSI_HOST_CFG_NUM_LANES = 0x0/4, + DSI_HOST_CFG_NONCONTINUOUS_CLK = 0x4/4, + DSI_HOST_CFG_AUTOINSERT_EOTP = 0x14/4, + DSI_HOST_CFG_T_PRE = 0x8/4, + DSI_HOST_CFG_T_POST = 0xc/4, + DSI_HOST_CFG_TX_GAP = 0x10/4, + DSI_HOST_CFG_EXTRA_CMDS_AFTER_EOTP = 0x18/4, + DSI_HOST_CFG_HTX_TO_COUNT = 0x1c/4, + DSI_HOST_CFG_LRX_H_TO_COUNT = 0x20/4, + DSI_HOST_CFG_BTA_H_TO_COUNT = 0x24/4, + DSI_HOST_CFG_TWAKEUP = 0x28/4, + + DSI_HOST_CFG_DPI_INTERFACE_COLOR_CODING = 0x208/4, + DSI_HOST_CFG_DPI_PIXEL_FORMAT = 0x20c/4, + DSI_HOST_CFG_DPI_VSYNC_POLARITY = 0x210/4, + DSI_HOST_CFG_DPI_HSYNC_POLARITY = 0x214/4, + DSI_HOST_CFG_DPI_VIDEO_MODE = 0x218/4, + DSI_HOST_CFG_DPI_PIXEL_FIFO_SEND_LEVEL = 0x204/4, + DSI_HOST_CFG_DPI_HFP = 0x21c/4, + DSI_HOST_CFG_DPI_HBP = 0x220/4, + DSI_HOST_CFG_DPI_HSA = 0x224/4, + DSI_HOST_CFG_DPI_ENA_BLE_MULT_PKTS = 0x228/4, + DSI_HOST_CFG_DPI_BLLP_MODE = 0x234/4, + DSI_HOST_CFG_DPI_USE_NULL_PKT_BLLP = 0x238/4, + DSI_HOST_CFG_DPI_VC = 0x240/4, + DSI_HOST_CFG_DPI_PIXEL_PAYLOAD_SIZE = 0x200/4, + DSI_HOST_CFG_DPI_VACTIVE = 0x23c/4, + DSI_HOST_CFG_DPI_VBP = 0x22c/4, + DSI_HOST_CFG_DPI_VFP = 0x230/4, +}; + +/* lcdif registers */ +enum { + LCDIF_CTRL = 0x00/4, + LCDIF_CTRL_SET = 0x04/4, + LCDIF_CTRL_CLR = 0x08/4, + LCDIF_CTRL_TOG = 0x0C/4, + CTRL_SFTRST = 1<<31, + CTRL_CLKGATE = 1<<30, + CTRL_YCBCR422_INPUT = 1<<29, + CTRL_READ_WEITEB = 1<<28, + CTRL_WAIT_FOR_VSYNC_EDGE = 1<<27, + CTRL_DATA_SHIFT_DIR = 1<<26, + CTRL_SHIFT_NUM_BITS = 0x1F<<21, + CTRL_DVI_MODE = 1<<20, + CTRL_BYPASS_COUNT = 1<<19, + CTRL_VSYNC_MODE = 1<<18, + CTRL_DOTCLK_MODE = 1<<17, + CTRL_DATA_SELECT = 1<<16, + + CTRL_INPUT_DATA_NO_SWAP = 0<<14, + CTRL_INPUT_DATA_LITTLE_ENDIAN = 0<<14, + CTRL_INPUT_DATA_BIG_ENDIAB = 1<<14, + CTRL_INPUT_DATA_SWAP_ALL_BYTES = 1<<14, + CTRL_INPUT_DATA_HWD_SWAP = 2<<14, + CTRL_INPUT_DATA_HWD_BYTE_SWAP = 3<<14, + + CTRL_CSC_DATA_NO_SWAP = 0<<12, + CTRL_CSC_DATA_LITTLE_ENDIAN = 0<<12, + CTRL_CSC_DATA_BIG_ENDIAB = 1<<12, + CTRL_CSC_DATA_SWAP_ALL_BYTES = 1<<12, + CTRL_CSC_DATA_HWD_SWAP = 2<<12, + CTRL_CSC_DATA_HWD_BYTE_SWAP = 3<<12, + + CTRL_LCD_DATABUS_WIDTH_16_BIT = 0<<10, + CTRL_LCD_DATABUS_WIDTH_8_BIT = 1<<10, + CTRL_LCD_DATABUS_WIDTH_18_BIT = 2<<10, + CTRL_LCD_DATABUS_WIDTH_24_BIT = 3<<10, + + CTRL_WORD_LENGTH_16_BIT = 0<<8, + CTRL_WORD_LENGTH_8_BIT = 1<<8, + CTRL_WORD_LENGTH_18_BIT = 2<<8, + CTRL_WORD_LENGTH_24_BIT = 3<<8, + + CTRL_RGB_TO_YCBCR422_CSC = 1<<7, + + CTRL_MASTER = 1<<5, + + CTRL_DATA_FORMAT_16_BIT = 1<<3, + CTRL_DATA_FORMAT_18_BIT = 1<<2, + CTRL_DATA_FORMAT_24_BIT = 1<<1, + + CTRL_RUN = 1<<0, + + LCDIF_CTRL1 = 0x10/4, + LCDIF_CTRL1_SET = 0x14/4, + LCDIF_CTRL1_CLR = 0x18/4, + LCDIF_CTRL1_TOG = 0x1C/4, + CTRL1_COMBINE_MPU_WR_STRB = 1<<27, + CTRL1_BM_ERROR_IRQ_EN = 1<<26, + CTRL1_BM_ERROR_IRQ = 1<<25, + CTRL1_RECOVER_ON_UNDERFLOW = 1<<24, + + CTRL1_INTERLACE_FIELDS = 1<<23, + CTRL1_START_INTERLACE_FROM_SECOND_FIELD = 1<<22, + + CTRL1_FIFO_CLEAR = 1<<21, + CTRL1_IRQ_ON_ALTERNATE_FIELDS = 1<<20, + + CTRL1_BYTE_PACKING_FORMAT = 0xF<<16, + + CTRL1_OVERFLOW_IRQ_EN = 1<<15, + CTRL1_UNDERFLOW_IRQ_EN = 1<<14, + CTRL1_CUR_FRAME_DONE_IRQ_EN = 1<<13, + CTRL1_VSYNC_EDGE_IRQ_EN = 1<<12, + CTRL1_OVERFLOW_IRQ = 1<<11, + CTRL1_UNDERFLOW_IRQ = 1<<10, + CTRL1_CUR_FRAME_DONE_IRQ = 1<<9, + CTRL1_VSYNC_EDGE_IRQ = 1<<8, + + CTRL1_BUSY_ENABLE = 1<<2, + CTRL1_MODE86 = 1<<1, + CTRL1_RESET = 1<<0, + + LCDIF_CTRL2 = 0x20/4, + LCDIF_CTRL2_SET = 0x24/4, + LCDIF_CTRL2_CLR = 0x28/4, + LCDIF_CTRL2_TOG = 0x2C/4, + CTRL2_OUTSTANDING_REQS_REQ_1 = 0<<21, + CTRL2_OUTSTANDING_REQS_REQ_2 = 1<<21, + CTRL2_OUTSTANDING_REQS_REQ_4 = 2<<21, + CTRL2_OUTSTANDING_REQS_REQ_8 = 3<<21, + CTRL2_OUTSTANDING_REQS_REQ_16 = 4<<21, + + CTRL2_BURST_LEN_8 = 1<<20, + + CTRL2_ODD_LINE_PATTERN_RGB = 0<<16, + CTRL2_ODD_LINE_PATTERN_RBG = 1<<16, + CTRL2_ODD_LINE_PATTERN_GBR = 2<<16, + CTRL2_ODD_LINE_PATTERN_GRB = 3<<16, + CTRL2_ODD_LINE_PATTERN_BRG = 4<<16, + CTRL2_ODD_LINE_PATTERN_BGR = 5<<16, + + CTRL2_EVEN_LINE_PATTERN_RGB = 0<<12, + CTRL2_EVEN_LINE_PATTERN_RBG = 1<<12, + CTRL2_EVEN_LINE_PATTERN_GBR = 2<<12, + CTRL2_EVEN_LINE_PATTERN_GRB = 3<<12, + CTRL2_EVEN_LINE_PATTERN_BRG = 4<<12, + CTRL2_EVEN_LINE_PATTERN_BGR = 5<<12, + + CTRL2_READ_PACK_DIR = 1<<10, + + CTRL2_READ_MODE_OUTPUT_IN_RGB_FORMAT = 1<<9, + CTRL2_READ_MODE_6_BIT_INPUT = 1<<8, + CTRL2_READ_MODE_NUM_PACKED_SUBWORDS = 7<<4, + CTRL2_INITIAL_DUMMY_READS = 7<<1, + + LCDIF_TRANSFER_COUNT= 0x30/4, + TRANSFER_COUNT_V_COUNT = 0xFFFF<<16, + TRANSFER_COUNT_H_COUNT = 0xFFFF, + + LCDIF_CUR_BUF = 0x40/4, + LCDIF_NEXT_BUF = 0x50/4, + + LCDIF_TIMING = 0x60/4, + TIMING_CMD_HOLD = 0xFF<<24, + TIMING_CMD_SETUP = 0xFF<<16, + TIMING_DATA_HOLD = 0xFF<<8, + TIMING_DATA_SETUP = 0xFF<<0, + + LCDIF_VDCTRL0 = 0x70/4, + VDCTRL0_VSYNC_OEB = 1<<29, + VDCTRL0_ENABLE_PRESENT = 1<<28, + + VDCTRL0_VSYNC_POL = 1<<27, + VDCTRL0_HSYNC_POL = 1<<26, + VDCTRL0_DOTCLK_POL = 1<<25, + VDCTRL0_ENABLE_POL = 1<<24, + + VDCTRL0_VSYNC_PERIOD_UNIT = 1<<21, + VDCTRL0_VSYNC_PULSE_WIDTH_UNIT = 1<<20, + VDCTRL0_HALF_LINE = 1<<19, + VDCTRL0_HALF_LINE_MODE = 1<<18, + + VDCTRL0_VSYNC_PULSE_WIDTH = 0x3FFFF, + + LCDIF_VDCTRL1 = 0x80/4, + VDCTRL1_VSYNC_PERIOD = 0xFFFFFFFF, + + LCDIF_VDCTRL2 = 0x90/4, + VDCTRL2_HSYNC_PERIOD = 0x3FFFF, + VDCTRL2_HSYNC_PULSE_WIDTH = 0x3FFF<<18, + + LCDIF_VDCTRL3 = 0xA0/4, + VDCTRL3_VERTICAL_WAIT_CNT = 0xFFFF, + VDCTRL3_HORIZONTAL_WAIT_CNT = 0xFFF<<16, + VDCTRL3_VSYNC_ONLY = 1<<28, + VDCTRL3_MUX_SYNC_SIGNALS = 1<<29, + + LCDIF_VDCTRL4 = 0xB0/4, + VDCTRL4_DOTCLK_H_VALID_DATA_CNT = 0x3FFFF, + VDCTRL4_SYNC_SIGNALS_ON = 1<<18, + + VDCTRL4_DOTCLK_DLY_2NS = 0<<29, + VDCTRL4_DOTCLK_DLY_4NS = 1<<29, + VDCTRL4_DOTCLK_DLY_6NS = 2<<29, + VDCTRL4_DOTCLK_DLY_8NS = 3<<29, + + LCDIF_DATA = 0x180/4, + + LCDIF_STAT = 0x1B0/4, + + LCDIF_AS_CTRL = 0x210/4, +}; + +struct video_mode { + int pixclk; + int hactive; + int vactive; + int hblank; + int vblank; + int hso; + int vso; + int hspw; + int vspw; + + char vsync_pol; + char hsync_pol; +}; + +struct dsi_cfg { + int lanes; + + int ref_clk; + int hs_clk; + int ui_ps; + + int byte_clk; + int byte_t_ps; + + int tx_esc_clk; + int tx_esc_t_ps; + + int rx_esc_clk; + + int clk_pre_ps; + int clk_prepare_ps; + int clk_zero_ps; + + int hs_prepare_ps; + int hs_zero_ps; + int hs_trail_ps; + int hs_exit_ps; + + int lpx_ps; + + vlong wakeup_ps; +}; + +/* base addresses, VIRTIO is at 0x30000000 physical */ + +static u32int *pwm2 = (u32int*)(VIRTIO + 0x670000); + +static u32int *resetc= (u32int*)(VIRTIO + 0x390000); + +static u32int *dsi = (u32int*)(VIRTIO + 0xA00000); +static u32int *dphy = (u32int*)(VIRTIO + 0xA00300); + +static u32int *lcdif = (u32int*)(VIRTIO + 0x320000); + +/* shift and mask */ +static u32int +sm(u32int v, u32int m) +{ + int s; + + if(m == 0) + return 0; + + s = 0; + while((m & 1) == 0){ + m >>= 1; + s++; + } + + return (v & m) << s; +} + +static u32int +rr(u32int *base, int reg) +{ + u32int val = base[reg]; +// iprint("%#p+%#.4x -> %#.8ux\n", PADDR(base), reg*4, val); + return val; +} +static void +wr(u32int *base, int reg, u32int val) +{ +// iprint("%#p+%#.4x <- %#.8ux\n", PADDR(base), reg*4, val); + base[reg] = val; +} +static void +mr(u32int *base, int reg, u32int val, u32int mask) +{ + wr(base, reg, (rr(base, reg) & ~mask) | (val & mask)); +} + +static void +dsiparams(struct dsi_cfg *cfg, int lanes, int hs_clk, int ref_clk, int tx_esc_clk, int rx_esc_clk) +{ + cfg->lanes = lanes; + cfg->ref_clk = ref_clk; + + cfg->hs_clk = hs_clk; + cfg->ui_ps = (1000000000000LL + (cfg->hs_clk-1)) / cfg->hs_clk; + + cfg->byte_clk = cfg->hs_clk / 8; + cfg->byte_t_ps = cfg->ui_ps * 8; + + cfg->tx_esc_clk = tx_esc_clk; + cfg->tx_esc_t_ps = (1000000000000LL + (cfg->tx_esc_clk-1)) / cfg->tx_esc_clk; + + cfg->rx_esc_clk = rx_esc_clk; + + /* min 8*ui */ + cfg->clk_pre_ps = 8*cfg->ui_ps; + + /* min 38ns, max 95ns */ + cfg->clk_prepare_ps = 38*1000; + + /* clk_prepare + clk_zero >= 300ns */ + cfg->clk_zero_ps = 300*1000 - cfg->clk_prepare_ps; + + /* min 40ns + 4*ui, max 85ns + 6*ui */ + cfg->hs_prepare_ps = 40*1000 + 4*cfg->ui_ps; + + /* hs_prepae + hs_zero >= 145ns + 10*ui */ + cfg->hs_zero_ps = (145*1000 + 10*cfg->ui_ps) - cfg->hs_prepare_ps; + + /* min max(n*8*ui, 60ns + n*4*ui); n=1 */ + cfg->hs_trail_ps = 60*1000 + 1*4*cfg->ui_ps; + if(cfg->hs_trail_ps < 1*8*cfg->ui_ps) + cfg->hs_trail_ps = 1*8*cfg->ui_ps; + + /* min 100ns */ + cfg->hs_exit_ps = 100*1000; + + /* min 50ns */ + cfg->lpx_ps = 50*1000; + + /* min 1ms */ + cfg->wakeup_ps = 1000000000000LL; +} + +static void +lcdifinit(struct video_mode *mode) +{ + wr(lcdif, LCDIF_CTRL_CLR, CTRL_SFTRST); + while(rr(lcdif, LCDIF_CTRL) & CTRL_SFTRST) + ; + wr(lcdif, LCDIF_CTRL_CLR, CTRL_CLKGATE); + while(rr(lcdif, LCDIF_CTRL) & (CTRL_SFTRST|CTRL_CLKGATE)) + ; + + wr(lcdif, LCDIF_CTRL1_SET, CTRL1_FIFO_CLEAR); + wr(lcdif, LCDIF_AS_CTRL, 0); + + wr(lcdif, LCDIF_CTRL1, sm(7, CTRL1_BYTE_PACKING_FORMAT)); + + wr(lcdif, LCDIF_CTRL, + CTRL_BYPASS_COUNT | + CTRL_MASTER | + CTRL_LCD_DATABUS_WIDTH_24_BIT | + CTRL_WORD_LENGTH_24_BIT); + + wr(lcdif, LCDIF_TRANSFER_COUNT, + sm(mode->vactive, TRANSFER_COUNT_V_COUNT) | + sm(mode->hactive, TRANSFER_COUNT_H_COUNT)); + + wr(lcdif, LCDIF_VDCTRL0, + VDCTRL0_ENABLE_PRESENT | + VDCTRL0_VSYNC_POL | VDCTRL0_HSYNC_POL | + VDCTRL0_VSYNC_PERIOD_UNIT | + VDCTRL0_VSYNC_PULSE_WIDTH_UNIT | + sm(mode->vspw, VDCTRL0_VSYNC_PULSE_WIDTH)); + + wr(lcdif, LCDIF_VDCTRL1, + sm(mode->vactive + mode->vblank, VDCTRL1_VSYNC_PERIOD)); + + wr(lcdif, LCDIF_VDCTRL2, + sm(mode->hactive + mode->hblank, VDCTRL2_HSYNC_PERIOD) | + sm(mode->hspw, VDCTRL2_HSYNC_PULSE_WIDTH)); + + wr(lcdif, LCDIF_VDCTRL3, + sm(mode->vblank - mode->vso, VDCTRL3_VERTICAL_WAIT_CNT) | + sm(mode->hblank - mode->hso, VDCTRL3_HORIZONTAL_WAIT_CNT)); + + wr(lcdif, LCDIF_VDCTRL4, + sm(mode->hactive, VDCTRL4_DOTCLK_H_VALID_DATA_CNT)); + + wr(lcdif, LCDIF_CUR_BUF, PADDR(gscreen->data->bdata)); + wr(lcdif, LCDIF_NEXT_BUF, PADDR(gscreen->data->bdata)); + + wr(lcdif, LCDIF_CTRL_SET, CTRL_DOTCLK_MODE); + + mr(lcdif, LCDIF_VDCTRL4, VDCTRL4_SYNC_SIGNALS_ON, VDCTRL4_SYNC_SIGNALS_ON); + + wr(lcdif, LCDIF_CTRL_SET, CTRL_RUN); +} + +static void +bridgeinit(I2Cdev *dev, struct video_mode *mode, struct dsi_cfg *cfg) +{ + int n; + + // clock derived from dsi clock + switch(cfg->hs_clk/2000000){ + case 384: + default: n = 1 << 1; break; + case 416: n = 2 << 1; break; + case 468: n = 0 << 1; break; + case 486: n = 3 << 1; break; + case 461: n = 4 << 1; break; + } + i2cwritebyte(dev, 0x0a, n); + + // single channel A + n = 1<<5 | (cfg->lanes-4)<<3 | 3<<1; + i2cwritebyte(dev, 0x10, n); + + // Enhanced framing and ASSR + i2cwritebyte(dev, 0x5a, 0x05); + + // 2 DP lanes w/o SSC + i2cwritebyte(dev, 0x93, 0x20); + + // 2.7Gbps DP data rate + i2cwritebyte(dev, 0x94, 0x80); + + // Enable PLL and confirm PLL is locked + i2cwritebyte(dev, 0x0d, 0x01); + + // wait for PLL to lock + while((i2creadbyte(dev, 0x0a) & 0x80) == 0) + ; + + // Enable ASSR on display + i2cwritebyte(dev, 0x64, 0x01); + i2cwritebyte(dev, 0x75, 0x01); + i2cwritebyte(dev, 0x76, 0x0a); + i2cwritebyte(dev, 0x77, 0x01); + i2cwritebyte(dev, 0x78, 0x81); + + // Train link and confirm trained + i2cwritebyte(dev, 0x96, 0x0a); + while(i2creadbyte(dev, 0x96) != 1) + ; + + // video timings + i2cwritebyte(dev, 0x20, mode->hactive & 0xFF); + i2cwritebyte(dev, 0x21, mode->hactive >> 8); + i2cwritebyte(dev, 0x24, mode->vactive & 0xFF); + i2cwritebyte(dev, 0x25, mode->vactive >> 8); + i2cwritebyte(dev, 0x2c, mode->hspw); + i2cwritebyte(dev, 0x2d, mode->hspw>>8 | (mode->hsync_pol=='-')<<7); + i2cwritebyte(dev, 0x30, mode->vspw); + i2cwritebyte(dev, 0x31, mode->vspw>>8 | (mode->vsync_pol=='-')<<7); + i2cwritebyte(dev, 0x34, mode->hblank - mode->hspw - mode->hso); + i2cwritebyte(dev, 0x36, mode->vblank - mode->vspw - mode->vso); + i2cwritebyte(dev, 0x38, mode->hso); + i2cwritebyte(dev, 0x3a, mode->vso); + + // Enable video stream, ASSR, enhanced framing + i2cwritebyte(dev, 0x5a, 0x0d); +} + +static char* +parseedid128(struct video_mode *mode, uchar edid[128]) +{ + static uchar magic[8] = { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00 }; + uchar *p, sum; + int i; + + if(memcmp(edid, magic, 8) != 0) + return "bad edid magic"; + + sum = 0; + for(i=0; i<128; i++) + sum += edid[i]; + if(sum != 0) + return "bad edid checksum"; + + /* + * Detailed Timings + */ + p = edid+8+10+2+5+10+3+16; + for(i=0; i<4; i++, p+=18){ + if((p[0]|p[1])==0) + continue; + + memset(mode, 0, sizeof(*mode)); + + mode->pixclk = ((p[1]<<8) | p[0]) * 10000; + + mode->hactive = ((p[4] & 0xF0)<<4) | p[2]; /* horizontal active */ + mode->hblank = ((p[4] & 0x0F)<<8) | p[3]; /* horizontal blanking */ + mode->vactive = ((p[7] & 0xF0)<<4) | p[5]; /* vertical active */ + mode->vblank = ((p[7] & 0x0F)<<8) | p[6]; /* vertical blanking */ + mode->hso = ((p[11] & 0xC0)<<2) | p[8]; /* horizontal sync offset */ + mode->hspw = ((p[11] & 0x30)<<4) | p[9]; /* horizontal sync pulse width */ + mode->vso = ((p[11] & 0x0C)<<2) | ((p[10] & 0xF0)>>4); /* vertical sync offset */ + mode->vspw = ((p[11] & 0x03)<<4) | (p[10] & 0x0F); /* vertical sync pulse width */ + + switch((p[17] & 0x18)>>3) { + case 3: /* digital separate sync signal; the norm */ + mode->vsync_pol = (p[17] & 0x04) ? '+' : '-'; + mode->hsync_pol = (p[17] & 0x02) ? '+' : '-'; + break; + } + + return nil; + } + + return "no edid timings available"; +} + +static char* +getmode(I2Cdev *dev, struct video_mode *mode) +{ + static uchar edid[128]; + static I2Cdev aux; + + aux.bus = dev->bus; + aux.addr = 0x50; + aux.subaddr = 1; + aux.size = sizeof(edid); + + /* enable passthru mode for address 0x50 (EDID) */ + i2cwritebyte(dev, 0x60, aux.addr<<1 | 1); + addi2cdev(&aux); + + if(i2crecv(&aux, edid, sizeof(edid), 0) != sizeof(edid)) + return "i2crecv failed to get edid bytes"; + + return parseedid128(mode, edid); +} + +static void +dphyinit(struct dsi_cfg *cfg) +{ + int n; + + /* powerdown */ + wr(dphy, DPHY_PD_PLL, 1); + wr(dphy, DPHY_PD_PHY, 1); + + /* magic */ + wr(dphy, DPHY_LOCK_BYP, 0); + wr(dphy, DPHY_RTERM_SEL, 1); + wr(dphy, DPHY_AUTO_PD_EN, 0); + wr(dphy, DPHY_RXLPRP, 2); + wr(dphy, DPHY_RXCDR, 2); + wr(dphy, DPHY_TST, 0x25); + + /* hs timings */ + n = (2*cfg->hs_prepare_ps - cfg->tx_esc_t_ps) / cfg->tx_esc_t_ps; + if(n < 0) + n = 0; + else if(n > 3) + n = 3; + wr(dphy, DPHY_M_PRG_HS_PREPARE, n); + + n = (2*cfg->clk_prepare_ps - cfg->tx_esc_t_ps) / cfg->tx_esc_t_ps; + if(n < 0) + n = 0; + else if(n > 1) + n = 1; + wr(dphy, DPHY_MC_PRG_HS_PREPARE, n); + + n = ((cfg->hs_zero_ps + (cfg->byte_t_ps-1)) / cfg->byte_t_ps) - 6; + if(n < 1) + n = 1; + wr(dphy, DPHY_M_PRG_HS_ZERO, n); + + n = ((cfg->clk_zero_ps + (cfg->byte_t_ps-1)) / cfg->byte_t_ps) - 3; + if(n < 1) + n = 1; + wr(dphy, DPHY_MC_PRG_HS_ZERO, n); + + n = (cfg->hs_trail_ps + (cfg->byte_t_ps-1)) / cfg->byte_t_ps; + if(n < 1) + n = 1; + else if(n > 15) + n = 15; + wr(dphy, DPHY_M_PRG_HS_TRAIL, n); + wr(dphy, DPHY_MC_PRG_HS_TRAIL, n); + + if(cfg->hs_clk < 80*Mhz) + n = 0xD; + else if(cfg->hs_clk < 90*Mhz) + n = 0xC; + else if(cfg->hs_clk < 125*Mhz) + n = 0xB; + else if(cfg->hs_clk < 150*Mhz) + n = 0xA; + else if(cfg->hs_clk < 225*Mhz) + n = 0x9; + else if(cfg->hs_clk < 500*Mhz) + n = 0x8; + else + n = 0x7; + wr(dphy, DPHY_RXHS_SETTLE, n); + + /* hs_clk = ref_clk * (CM / (CN*CO)); just set CN=CO=1 */ + n = (cfg->hs_clk + cfg->ref_clk-1) / cfg->ref_clk; + + /* strange encoding for CM */ + if(n < 32) + n = 0xE0 | (n - 16); + else if(n < 64) + n = 0xC0 | (n - 32); + else if(n < 128) + n = 0x80 | (n - 64); + else + n = n - 128; + wr(dphy, DPHY_CM, n); + + wr(dphy, DPHY_CN, 0x1F); /* CN==1 */ + wr(dphy, DPHY_CO, 0x00); /* CO==1 */ +} + +static void +dphypowerup(void) +{ + wr(dphy, DPHY_PD_PLL, 0); + while((rr(dphy, DPHY_LOCK) & 1) == 0) + ; + wr(dphy, DPHY_PD_PHY, 0); +} + +static void +dsiinit(struct dsi_cfg *cfg) +{ + int n; + + wr(dsi, DSI_HOST_CFG_NUM_LANES, cfg->lanes-1); + + wr(dsi, DSI_HOST_CFG_NONCONTINUOUS_CLK, 0x0); + wr(dsi, DSI_HOST_CFG_AUTOINSERT_EOTP, 0x0); + + n = (cfg->clk_pre_ps + cfg->byte_t_ps-1) / cfg->byte_t_ps; + wr(dsi, DSI_HOST_CFG_T_PRE, n); + + n = (cfg->clk_pre_ps + cfg->lpx_ps + cfg->clk_prepare_ps + cfg->clk_zero_ps + cfg->byte_t_ps-1) / cfg->byte_t_ps; + wr(dsi, DSI_HOST_CFG_T_POST, n); + + n = (cfg->hs_exit_ps + cfg->byte_t_ps-1) / cfg->byte_t_ps; + wr(dsi, DSI_HOST_CFG_TX_GAP, n); + + wr(dsi, DSI_HOST_CFG_EXTRA_CMDS_AFTER_EOTP, 0x1); + + wr(dsi, DSI_HOST_CFG_HTX_TO_COUNT, 0x0); + wr(dsi, DSI_HOST_CFG_LRX_H_TO_COUNT, 0x0); + wr(dsi, DSI_HOST_CFG_BTA_H_TO_COUNT, 0x0); + + n = (cfg->wakeup_ps + cfg->tx_esc_t_ps-1) / cfg->tx_esc_t_ps; + wr(dsi, DSI_HOST_CFG_TWAKEUP, n); +} + +static void +dpiinit(struct video_mode *mode) +{ + wr(dsi, DSI_HOST_CFG_DPI_INTERFACE_COLOR_CODING, 0x5); // 24-bit + + wr(dsi, DSI_HOST_CFG_DPI_PIXEL_FORMAT, 0x3); // 24-bit + + /* this seems wrong */ + wr(dsi, DSI_HOST_CFG_DPI_VSYNC_POLARITY, 0); + wr(dsi, DSI_HOST_CFG_DPI_HSYNC_POLARITY, 0); + + wr(dsi, DSI_HOST_CFG_DPI_VIDEO_MODE, 0x1); // non-burst mode with sync events + + wr(dsi, DSI_HOST_CFG_DPI_PIXEL_FIFO_SEND_LEVEL, mode->hactive); + + wr(dsi, DSI_HOST_CFG_DPI_HFP, mode->hso); + wr(dsi, DSI_HOST_CFG_DPI_HBP, mode->hblank - mode->hspw - mode->hso); + wr(dsi, DSI_HOST_CFG_DPI_HSA, mode->hspw); + + wr(dsi, DSI_HOST_CFG_DPI_ENA_BLE_MULT_PKTS, 0x0); + + wr(dsi, DSI_HOST_CFG_DPI_BLLP_MODE, 0x1); + + wr(dsi, DSI_HOST_CFG_DPI_USE_NULL_PKT_BLLP, 0x0); + + wr(dsi, DSI_HOST_CFG_DPI_VC, 0x0); + wr(dsi, DSI_HOST_CFG_DPI_PIXEL_PAYLOAD_SIZE, mode->hactive); + wr(dsi, DSI_HOST_CFG_DPI_VACTIVE, mode->vactive - 1); + wr(dsi, DSI_HOST_CFG_DPI_VBP, mode->vblank - mode->vspw - mode->vso); + wr(dsi, DSI_HOST_CFG_DPI_VFP, mode->vso); +} + +static void +backlighton(void) +{ + /* gpio1_io10: for panel backlight enable */ + iomuxpad("pad_gpio1_io10", "gpio1_io10", "~LVTTL ~HYS ~PUE ~ODE FAST 45_OHM"); + + /* gpio1_io10 low: panel backlight off */ + gpioout(GPIO_PIN(1, 10), 0); + + /* pwm2_out: for panel backlight */ + iomuxpad("pad_spdif_rx", "pwm2_out", "~LVTTL ~HYS ~PUE ~ODE FAST 45_OHM"); + + setclkrate("pwm2.ipg_clk_high_freq", "osc_25m_ref_clk", Pwmsrcclk); + setclkgate("pwm2.ipg_clk_high_freq", 1); + + wr(pwm2, PWMIR, 0); + wr(pwm2, PWMCR, CR_STOPEN | CR_DOZEN | CR_WAITEN | CR_DBGEN | CR_CLKSRC_HIGHFREQ | 0<subaddr = 1; + + /* power on mipi dsi */ + powerup("mipi"); + + mr(resetc, SRC_MIPIPHY_RCR, 0, RCR_MIPI_DSI_RESET_N); + mr(resetc, SRC_MIPIPHY_RCR, 0, RCR_MIPI_DSI_PCLK_RESET_N); + mr(resetc, SRC_MIPIPHY_RCR, 0, RCR_MIPI_DSI_ESC_RESET_N); + mr(resetc, SRC_MIPIPHY_RCR, 0, RCR_MIPI_DSI_RESET_BYTE_N); + mr(resetc, SRC_MIPIPHY_RCR, 0, RCR_MIPI_DSI_DPI_RESET_N); + + setclkgate("sim_display.mainclk", 0); + setclkgate("disp.axi_clk", 0); + setclkrate("disp.axi_clk", "system_pll1_clk", 800*Mhz); + setclkrate("disp.rtrm_clk", "system_pll1_clk", 400*Mhz); + setclkgate("disp.axi_clk", 1); + setclkgate("sim_display.mainclk", 1); + + setclkrate("mipi.core", "system_pll1_div3", 266*Mhz); + setclkrate("mipi.CLKREF", "system_pll2_clk", 25*Mhz); + setclkrate("mipi.RxClkEsc", "system_pll1_clk", 80*Mhz); + setclkrate("mipi.TxClkEsc", nil, 20*Mhz); + + /* dsi parameters are fixed for the bridge */ + dsiparams(&dsi_cfg, 4, 2*486*Mhz, + getclkrate("mipi.CLKREF"), + getclkrate("mipi.TxClkEsc"), + getclkrate("mipi.RxClkEsc")); + + /* release dphy reset */ + mr(resetc, SRC_MIPIPHY_RCR, RCR_MIPI_DSI_PCLK_RESET_N, RCR_MIPI_DSI_PCLK_RESET_N); + + dphyinit(&dsi_cfg); + dsiinit(&dsi_cfg); + dphypowerup(); + + /* release mipi clock resets (generated by the dphy) */ + mr(resetc, SRC_MIPIPHY_RCR, RCR_MIPI_DSI_ESC_RESET_N, RCR_MIPI_DSI_ESC_RESET_N); + mr(resetc, SRC_MIPIPHY_RCR, RCR_MIPI_DSI_RESET_BYTE_N, RCR_MIPI_DSI_RESET_BYTE_N); + + /* + * get mode information from EDID, this can only be done after the clocks + * are generated by the DPHY and the clock resets have been released. + */ + err = getmode(bridge, &mode); + if(err != nil) + goto out; + + /* allocates the framebuffer (gscreen->data->bdata) */ + if(screeninit(mode.hactive, mode.vactive, 32) < 0){ + err = "screeninit failed"; + goto out; + } + + /* + * start the pixel clock. running at the actual pixel clock + * causes the screen to shift horizontally after a while. + * using 80% seems to fix it - for now. + */ + setclkrate("lcdif.pix_clk", "system_pll1_clk", (mode.pixclk*8)/10); + dpiinit(&mode); + + /* release dpi reset */ + mr(resetc, SRC_MIPIPHY_RCR, RCR_MIPI_DSI_DPI_RESET_N, RCR_MIPI_DSI_DPI_RESET_N); + + /* enable display port bridge */ + bridgeinit(bridge, &mode, &dsi_cfg); + + /* send the pixels */ + lcdifinit(&mode); + return; + +out: + print("lcdinit: %s\n", err); +} diff --git a/sys/src/9/imx8/main.c b/sys/src/9/imx8/main.c index 01e4ce20c..b0494f682 100644 --- a/sys/src/9/imx8/main.c +++ b/sys/src/9/imx8/main.c @@ -32,6 +32,7 @@ init0(void) poperror(); } kproc("alarm", alarmkproc, 0); + sp = (char**)(USTKTOP-sizeof(Tos) - 8 - sizeof(sp[0])*4); sp[3] = sp[2] = sp[1] = nil; strcpy(sp[1] = (char*)&sp[4], "boot"); @@ -99,14 +100,7 @@ confinit(void) + conf.nswap + conf.nswppo*sizeof(Page*); mainmem->maxsize = kpages; - if(!cpuserver) - /* - * give terminals lots of image memory, too; the dynamic - * allocation will balance the load properly, hopefully. - * be careful with 32-bit overflow. - */ - imagmem->maxsize = kpages; - + imagmem->maxsize = kpages; } void @@ -149,7 +143,6 @@ main(void) fpuinit(); intrinit(); clockinit(); - print("cpu%d: UP!\n", m->machno); synccycles(); timersinit(); flushtlb(); @@ -175,6 +168,7 @@ main(void) initseg(); links(); chandevreset(); + lcdinit(); userinit(); mpinit(); mmu0clear((uintptr*)L1); diff --git a/sys/src/9/imx8/mem.h b/sys/src/9/imx8/mem.h index f20037bd9..0c92e9ae2 100644 --- a/sys/src/9/imx8/mem.h +++ b/sys/src/9/imx8/mem.h @@ -39,9 +39,9 @@ #define STACKALIGN(sp) ((sp) & ~7) /* bug: assure with alloc */ #define TRAPFRAMESIZE (38*8) -/* reserved dram for ucalloc() at the end of KZERO (physical) */ +/* reserved dram for ucalloc() and fbmemalloc() at the end of KZERO (physical) */ #define UCRAMBASE (-KZERO - UCRAMSIZE) -#define UCRAMSIZE (1*MiB) +#define UCRAMSIZE (8*MiB) #define VDRAM (0xFFFFFFFFC0000000ULL) /* 0x40000000 - 0x80000000 */ #define KTZERO (VDRAM + 0x100000) /* kernel text start */ @@ -54,7 +54,7 @@ #define VMAP (0xFFFFFFFF00000000ULL) /* 0x00000000 - 0x40000000 */ #define KMAPEND (0xFFFFFFFF00000000ULL) /* 0x140000000 */ -#define KMAP (0xFFFFFFFE00000000ULL) /* 0x40000000 */ +#define KMAP (0xFFFFFFFE00000000ULL) /* 0x40000000 */ #define KSEG0 (0xFFFFFFFE00000000ULL) diff --git a/sys/src/9/imx8/mkfile b/sys/src/9/imx8/mkfile index 2e37a5a8b..10d50f06b 100644 --- a/sys/src/9/imx8/mkfile +++ b/sys/src/9/imx8/mkfile @@ -58,12 +58,12 @@ OBJ=\ # HFILES= LIB=\ -# /$objtype/lib/libmemlayer.a\ -# /$objtype/lib/libmemdraw.a\ -# /$objtype/lib/libdraw.a\ + /$objtype/lib/libmemlayer.a\ + /$objtype/lib/libmemdraw.a\ + /$objtype/lib/libdraw.a\ /$objtype/lib/libip.a\ /$objtype/lib/libsec.a\ -# /$objtype/lib/libmp.a\ + /$objtype/lib/libmp.a\ /$objtype/lib/libc.a\ # /$objtype/lib/libdtracy.a\ @@ -80,7 +80,7 @@ $OBJ: $HFILES install:V: /$objtype/$p$CONF -/$objtype/$p$CONF:D: $p$CONF s$p$CONF +/$objtype/$p$CONF:D: $p$CONF $p$CONF.u cp -x $p$CONF $p$CONF.u /$objtype/ <../boot/bootmkfile diff --git a/sys/src/9/imx8/mmu.c b/sys/src/9/imx8/mmu.c index 5bec2ab05..c61ca7f01 100644 --- a/sys/src/9/imx8/mmu.c +++ b/sys/src/9/imx8/mmu.c @@ -472,21 +472,36 @@ checkmmu(uintptr, uintptr) { } -void* -ucalloc(usize size) +static void* +ucramalloc(usize size, uintptr align, uint attr) { static uintptr top = UCRAMBASE + UCRAMSIZE; static Lock lk; - uintptr va; - - size = PGROUND(size); + uintptr va, pg; lock(&lk); top -= size; + size += top & align-1; + top &= -align; if(top < UCRAMBASE) - panic("ucalloc: %p needs %zd bytes\n", getcallerpc(&size), size); + panic("ucramalloc: need %zd bytes", size); va = KZERO + top; + pg = va & -BY2PG; + if(pg != ((va+size) & -BY2PG)) + mmukmap(pg | attr, pg - KZERO, PGROUND(size)); unlock(&lk); - return (void*)mmukmap(va | PTEUNCACHED, PADDR(va), size); + return (void*)va; +} + +void* +ucalloc(usize size) +{ + return ucramalloc(size, 8, PTEUNCACHED); +} + +void* +fbmemalloc(usize size) +{ + return ucramalloc(PGROUND(size), BY2PG, PTEWT); } diff --git a/sys/src/9/imx8/reform b/sys/src/9/imx8/reform index ae88c1d99..747451665 100644 --- a/sys/src/9/imx8/reform +++ b/sys/src/9/imx8/reform @@ -14,14 +14,19 @@ dev fs ether netif ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium inferno + draw screen swcursor + mouse screen swcursor uart usb + i2c + sd link usbxhciimx etherimx ethermii ethermedium loopbackmedium + i2cimx devi2c ip tcp udp @@ -31,8 +36,14 @@ ip icmp6 ipmux misc + ccm gic + gpc + gpio + lcd uartimx + iomux + sdmmc usdhc port int cpuserver = 0; bootdir diff --git a/sys/src/9/imx8/screen.c b/sys/src/9/imx8/screen.c new file mode 100644 index 000000000..5be30fa79 --- /dev/null +++ b/sys/src/9/imx8/screen.c @@ -0,0 +1,341 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" + +#define Image IMAGE +#include +#include +#include +#include "screen.h" + +enum { + Tabstop = 4, + Scroll = 8, +}; + +Memimage *gscreen; + +static Memdata xgdata; +static Memimage xgscreen; +static Memimage *conscol; +static Memimage *back; +static Memsubfont *memdefont; + +static Lock screenlock; + +static Point curpos; +static int h, w; +static Rectangle window; + +static void myscreenputs(char *s, int n); +static void screenputc(char *buf); +static void screenwin(void); + +enum +{ + CMaccelerated, + CMlinear, +}; + +static Cmdtab mousectlmsg[] = +{ + CMaccelerated, "accelerated", 0, + CMlinear, "linear", 1, +}; + +void +mousectl(Cmdbuf *cb) +{ + Cmdtab *ct; + + ct = lookupcmd(cb, mousectlmsg, nelem(mousectlmsg)); + switch(ct->index){ + case CMaccelerated: + mouseaccelerate(cb->nf == 1? 1: atoi(cb->f[1])); + break; + case CMlinear: + mouseaccelerate(0); + break; + } +} + +void +cursoron(void) +{ + swcursorhide(0); + swcursordraw(mousexy()); +} + +void +cursoroff(void) +{ + swcursorhide(0); +} + +void +setcursor(Cursor* curs) +{ + swcursorload(curs); +} + +int +hwdraw(Memdrawparam *par) +{ + Memimage *dst, *src, *mask; + + if((dst = par->dst) == nil || dst->data == nil) + return 0; + if((src = par->src) && src->data == nil) + src = nil; + if((mask = par->mask) && mask->data == nil) + mask = nil; + + if(dst->data->bdata == xgdata.bdata) + swcursoravoid(par->r); + if(src && src->data->bdata == xgdata.bdata) + swcursoravoid(par->sr); + if(mask && mask->data->bdata == xgdata.bdata) + swcursoravoid(par->mr); + + return 0; +} + +int +screeninit(int width, int height, int depth) +{ + ulong chan; + + switch(depth){ + default: + return -1; + case 32: + chan = XRGB32; + break; + case 24: + chan = RGB24; + break; + case 16: + chan = RGB16; + break; + } + memsetchan(&xgscreen, chan); + xgscreen.r = Rect(0, 0, width, height); + xgscreen.clipr = xgscreen.r; + xgscreen.depth = depth; + xgscreen.width = wordsperline(xgscreen.r, xgscreen.depth); + xgdata.bdata = fbmemalloc(xgscreen.width*sizeof(ulong)*height); + xgdata.ref = 1; + + xgscreen.data = &xgdata; + + gscreen = &xgscreen; + + conf.monitor = 1; + + memimageinit(); + memdefont = getmemdefont(); + screenwin(); + myscreenputs(kmesg.buf, kmesg.n); + screenputs = myscreenputs; + swcursorinit(); + + return 0; +} + +void +flushmemscreen(Rectangle) +{ +} + +Memdata* +attachscreen(Rectangle *r, ulong *chan, int* d, int *width, int *softscreen) +{ + if(gscreen == nil) + return nil; + + *r = gscreen->r; + *d = gscreen->depth; + *chan = gscreen->chan; + *width = gscreen->width; + *softscreen = 0; + + gscreen->data->ref++; + return gscreen->data; +} + +void +getcolor(ulong p, ulong *pr, ulong *pg, ulong *pb) +{ + USED(p, pr, pg, pb); +} + +int +setcolor(ulong p, ulong r, ulong g, ulong b) +{ + USED(p, r, g, b); + return 0; +} + +void +blankscreen(int) +{ +} + +static void +myscreenputs(char *s, int n) +{ + int i; + Rune r; + char buf[4]; + + if(!islo()) { + /* don't deadlock trying to print in interrupt */ + if(!canlock(&screenlock)) + return; + } + else + lock(&screenlock); + + while(n > 0){ + i = chartorune(&r, s); + if(i == 0){ + s++; + --n; + continue; + } + memmove(buf, s, i); + buf[i] = 0; + n -= i; + s += i; + screenputc(buf); + } + unlock(&screenlock); +} + +static void +screenwin(void) +{ + char *greet; + Memimage *orange; + Point p, q; + Rectangle r; + + back = memblack; + conscol = memwhite; + + orange = allocmemimage(Rect(0, 0, 1, 1), RGB16); + orange->flags |= Frepl; + orange->clipr = gscreen->r; + orange->data->bdata[0] = 0x40; /* magic: colour? */ + orange->data->bdata[1] = 0xfd; /* magic: colour? */ + + w = memdefont->info[' '].width; + h = memdefont->height; + + r = gscreen->r; + memimagedraw(gscreen, r, memwhite, ZP, memopaque, ZP, S); + window = insetrect(r, 4); + memimagedraw(gscreen, window, memblack, ZP, memopaque, ZP, S); + + memimagedraw(gscreen, Rect(window.min.x, window.min.y, + window.max.x, window.min.y + h + 5 + 6), orange, ZP, nil, ZP, S); + + freememimage(orange); + window = insetrect(window, 5); + + greet = " Plan 9 Console "; + p = addpt(window.min, Pt(10, 0)); + q = memsubfontwidth(memdefont, greet); + memimagestring(gscreen, p, conscol, ZP, memdefont, greet); + flushmemscreen(r); + window.min.y += h + 6; + curpos = window.min; + window.max.y = window.min.y + ((window.max.y - window.min.y) / h) * h; +} + +static void +scroll(void) +{ + int o; + Point p; + Rectangle r; + + o = Scroll*h; + r = Rpt(window.min, Pt(window.max.x, window.max.y-o)); + p = Pt(window.min.x, window.min.y+o); + memimagedraw(gscreen, r, gscreen, p, nil, p, S); + flushmemscreen(r); + r = Rpt(Pt(window.min.x, window.max.y-o), window.max); + memimagedraw(gscreen, r, back, ZP, nil, ZP, S); + flushmemscreen(r); + + curpos.y -= o; +} + +static void +screenputc(char *buf) +{ + int w; + uint pos; + Point p; + Rectangle r; + static int *xp; + static int xbuf[256]; + + if (xp < xbuf || xp >= &xbuf[nelem(xbuf)]) + xp = xbuf; + + switch (buf[0]) { + case '\n': + if (curpos.y + h >= window.max.y) + scroll(); + curpos.y += h; + screenputc("\r"); + break; + case '\r': + xp = xbuf; + curpos.x = window.min.x; + break; + case '\t': + p = memsubfontwidth(memdefont, " "); + w = p.x; + if (curpos.x >= window.max.x - Tabstop * w) + screenputc("\n"); + + pos = (curpos.x - window.min.x) / w; + pos = Tabstop - pos % Tabstop; + *xp++ = curpos.x; + r = Rect(curpos.x, curpos.y, curpos.x + pos * w, curpos.y + h); + memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S); + flushmemscreen(r); + curpos.x += pos * w; + break; + case '\b': + if (xp <= xbuf) + break; + xp--; + r = Rect(*xp, curpos.y, curpos.x, curpos.y + h); + memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S); + flushmemscreen(r); + curpos.x = *xp; + break; + case '\0': + break; + default: + p = memsubfontwidth(memdefont, buf); + w = p.x; + + if (curpos.x >= window.max.x - w) + screenputc("\n"); + + *xp++ = curpos.x; + r = Rect(curpos.x, curpos.y, curpos.x + w, curpos.y + h); + memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S); + memimagestring(gscreen, curpos, conscol, ZP, memdefont, buf); + flushmemscreen(r); + curpos.x += w; + break; + } +} diff --git a/sys/src/9/imx8/screen.h b/sys/src/9/imx8/screen.h new file mode 100644 index 000000000..fc0b7f582 --- /dev/null +++ b/sys/src/9/imx8/screen.h @@ -0,0 +1,32 @@ +/* devmouse.c */ +typedef struct Cursor Cursor; +extern Cursor cursor; +extern void mousetrack(int, int, int, ulong); +extern void absmousetrack(int, int, int, ulong); +extern Point mousexy(void); +extern void mouseaccelerate(int); + +/* screen.c */ +extern int screeninit(int width, int hight, int depth); +extern void blankscreen(int); +extern void flushmemscreen(Rectangle); +extern Memdata* attachscreen(Rectangle*, ulong*, int*, int*, int*); +extern void cursoron(void); +extern void cursoroff(void); +extern void setcursor(Cursor*); + +extern void mousectl(Cmdbuf*); +extern void mouseresize(void); +extern void mouseredraw(void); + +/* devdraw.c */ +extern QLock drawlock; + +#define ishwimage(i) 1 /* for ../port/devdraw.c */ + +/* swcursor.c */ +void swcursorhide(int); +void swcursoravoid(Rectangle); +void swcursordraw(Point); +void swcursorload(Cursor *); +void swcursorinit(void); diff --git a/sys/src/9/imx8/uartimx.c b/sys/src/9/imx8/uartimx.c index 5d6e0d2f1..c7173f423 100644 --- a/sys/src/9/imx8/uartimx.c +++ b/sys/src/9/imx8/uartimx.c @@ -314,18 +314,36 @@ interrupt(Ureg*, void *arg) uartkick(uart); } +static void +clkenable(Uart *u, int on) +{ + char clk[32]; + + snprint(clk, sizeof(clk), "%s.ipg_perclk", u->name); + if(on) setclkrate(clk, "osc_25m_ref_clk", u->freq); + setclkgate(clk, on); +} + static void disable(Uart *u) { u32int *regs = u->regs; + + if(u->console) + return; /* avoid glitch */ + regs[UCR1] = 0; + clkenable(u, 0); } static void enable(Uart *u, int ie) { disable(u); + clkenable(u, 1); + if(ie) intrenable(IRQuart1, interrupt, u, BUSUNKNOWN, u->name); + config(u); } diff --git a/sys/src/9/imx8/usbxhciimx.c b/sys/src/9/imx8/usbxhciimx.c index e08b80b19..eed92b1a6 100644 --- a/sys/src/9/imx8/usbxhciimx.c +++ b/sys/src/9/imx8/usbxhciimx.c @@ -1774,9 +1774,64 @@ portreset(Hci *hp, int port, int on) return 0; } +static void +clkenable(int i, int on) +{ + char clk[32]; + + snprint(clk, sizeof(clk), "usb%d.ctrl", i+1); + setclkgate(clk, on); + snprint(clk, sizeof(clk), "usb%d.phy", i+1); + setclkgate(clk, on); +} + +static void +phyinit(u32int *reg) +{ + enum { + PHY_CTRL0 = 0x0/4, + CTRL0_REF_SSP_EN = 1<<2, + PHY_CTRL1 = 0x4/4, + CTRL1_RESET = 1<<0, + CTRL1_ATERESET = 1<<3, + CTRL1_VDATSRCENB0 = 1<<19, + CTRL1_VDATDETEBB0 = 1<<20, + PHY_CTRL2 = 0x8/4, + CTRL2_TXENABLEN0 = 1<<8, + }; + reg[PHY_CTRL1] = (reg[PHY_CTRL1] & ~(CTRL1_VDATSRCENB0 | CTRL1_VDATDETEBB0)) | CTRL1_RESET | CTRL1_ATERESET; + reg[PHY_CTRL0] |= CTRL0_REF_SSP_EN; + reg[PHY_CTRL2] |= CTRL2_TXENABLEN0; + reg[PHY_CTRL1] &= ~(CTRL1_RESET | CTRL1_ATERESET); +} + +static void +coreinit(u32int *reg) +{ + enum { + GCTL = 0xC110/4, + PWRDNSCALE_SHIFT = 19, + PWRDNSCALE_MASK = 0x3FFF << PWRDNSCALE_SHIFT, + PRTCAPDIR_SHIFT = 12, + PRTCAPDIR_MASK = 3 << PRTCAPDIR_SHIFT, + DISSCRAMBLE = 1<<3, + DSBLCLKGTNG = 1<<0, + + GFLADJ = 0xC630/4, + GFLADJ_30MHZ_SDBND_SEL = 1<<7, + GFLADJ_30MHZ_SHIFT = 0, + GFLADJ_30MHZ_MASK = 0x3F << GFLADJ_30MHZ_SHIFT, + + }; + reg[GCTL] &= ~(PWRDNSCALE_MASK | DISSCRAMBLE | DSBLCLKGTNG | PRTCAPDIR_MASK); + reg[GCTL] |= 2<mmio[0xF0040/4]); + coreinit(ctlr->mmio); + hp->init = init; hp->dump = dump; hp->interrupt = interrupt; diff --git a/sys/src/9/imx8/usdhc.c b/sys/src/9/imx8/usdhc.c new file mode 100644 index 000000000..8954ba8b9 --- /dev/null +++ b/sys/src/9/imx8/usdhc.c @@ -0,0 +1,532 @@ +#include "u.h" +#include "../port/lib.h" +#include "../port/error.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "../port/sd.h" + +enum { + Initfreq = 400000, /* initialisation frequency for MMC */ + SDfreq = 25*Mhz, /* standard SD frequency */ + SDfreqhs = 50*Mhz, /* highspeed frequency */ + DTO = 14, /* data timeout exponent (guesswork) */ + + GoIdle = 0, /* mmc/sdio go idle state */ + MMCSelect = 7, /* mmc/sd card select command */ + Setbuswidth = 6, /* mmc/sd set bus width command */ + Switchfunc = 6, /* mmc/sd switch function command */ + Voltageswitch = 11, /* md/sdio switch to 1.8V */ + IORWdirect = 52, /* sdio read/write direct command */ + IORWextended = 53, /* sdio read/write extended command */ + Appcmd = 55, /* mmc/sd application command prefix */ +}; + +enum { + /* Controller registers */ + SDMAaddr = 0x00>>2, + Blksizecnt = 0x04>>2, + Arg1 = 0x08>>2, + Cmdtm = 0x0c>>2, + Resp0 = 0x10>>2, + Resp1 = 0x14>>2, + Resp2 = 0x18>>2, + Resp3 = 0x1c>>2, + Data = 0x20>>2, + Status = 0x24>>2, + + Control0 = 0x28>>2, + Control1 = 0x2c>>2, + + Interrupt = 0x30>>2, + Irptmask = 0x34>>2, + Irpten = 0x38>>2, + + Control2 = 0x3c>>2, + Capability = 0x40>>2, + + Mixctrl = 0x48>>2, + + Forceirpt = 0x50>>2, + Dmadesc = 0x58>>2, + + Vendorspec = 0xC0>>2, + + /* Vendorspec */ + ClkEn = 1<<14, + PerEn = 1<<13, + HclkEn = 1<<12, + IpgEn = 1<<11, + Vsel = 1<<1, + + /* Control0 (PROT_CTRL) */ + Dmaselect = 3<<8, + DmaSDMA = 0<<8, + DmaADMA1 = 1<<8, + DmaADMA2 = 2<<8, + EMODE = 3<<4, + BE = 0<<4, + HBE = 1<<4, + LE = 2<<4, + DwidthMask = 3<<1, + Dwidth8 = 2<<1, + Dwidth4 = 1<<1, + Dwidth1 = 0<<1, + LED = 1<<0, + + /* Control1 (SYS_CTRL) */ + Srstdata = 1<<26, /* reset data circuit */ + Srstcmd = 1<<25, /* reset command circuit */ + Srsthc = 1<<24, /* reset complete host controller */ + Datatoshift = 16, /* data timeout unit exponent */ + Datatomask = 0xF0000, + SDCLKFSshift = 8, + DVSshift = 4, + + /* Cmdtm */ + Indexshift = 24, + Suspend = 1<<22, + Resume = 2<<22, + Abort = 3<<22, + Isdata = 1<<21, + Ixchken = 1<<20, + Crcchken = 1<<19, + Respmask = 3<<16, + Respnone = 0<<16, + Resp136 = 1<<16, + Resp48 = 2<<16, + Resp48busy = 3<<16, + + /* Mixctrl */ + Autocmd23 = 1<<7, + Multiblock = 1<<5, + Host2card = 0<<4, + Card2host = 1<<4, + DdrEn = 1<<3, + Autocmd12 = 1<<2, + Blkcnten = 1<<1, + Dmaen = 1<<0, + MixCmdMask = 0xFF ^ DdrEn, + + /* Interrupt */ + Admaerr = 1<<28, + Acmderr = 1<<24, + Denderr = 1<<22, + Dcrcerr = 1<<21, + Dtoerr = 1<<20, + Cbaderr = 1<<19, + Cenderr = 1<<18, + Ccrcerr = 1<<17, + Ctoerr = 1<<16, + Err = Admaerr|Acmderr|Denderr|Dcrcerr|Dtoerr|Cbaderr|Cenderr|Ccrcerr|Ctoerr, + + Cardintr = 1<<8, + Cardinsert = 1<<6, + Readrdy = 1<<5, + Writerdy = 1<<4, + Dmaintr = 1<<3, + Datadone = 1<<1, + Cmddone = 1<<0, + + /* Status */ + Bufread = 1<<11, + Bufwrite = 1<<10, + Readtrans = 1<<9, + Writetrans = 1<<8, + + Clkstable = 1<<3, + + Datactive = 1<<2, + Datinhibit = 1<<1, + Cmdinhibit = 1<<0, +}; + +static int cmdinfo[64] = { +[0] Ixchken, +[2] Resp136, +[3] Resp48 | Ixchken | Crcchken, +[5] Resp48, +[6] Resp48 | Ixchken | Crcchken, +[7] Resp48 | Ixchken | Crcchken, +[8] Resp48 | Ixchken | Crcchken, +[9] Resp136, +[11] Resp48 | Ixchken | Crcchken, +[13] Resp48 | Ixchken | Crcchken, +[16] Resp48, +[17] Resp48 | Isdata | Card2host | Ixchken | Crcchken, +[18] Resp48 | Isdata | Card2host | Multiblock | Blkcnten | Ixchken | Crcchken | Autocmd12, +[24] Resp48 | Isdata | Host2card | Ixchken | Crcchken, +[25] Resp48 | Isdata | Host2card | Multiblock | Blkcnten | Ixchken | Crcchken | Autocmd12, +[41] Resp48, +[52] Resp48 | Ixchken | Crcchken, +[53] Resp48 | Ixchken | Crcchken | Isdata, +[55] Resp48 | Ixchken | Crcchken, +}; + +typedef struct Adma Adma; +typedef struct Ctlr Ctlr; + +/* + * ADMA2 descriptor + * See SD Host Controller Simplified Specification Version 2.00 + */ +struct Adma { + u32int desc; + u32int addr; +}; + +enum { + /* desc fields */ + Valid = 1<<0, + End = 1<<1, + Int = 1<<2, + Nop = 0<<4, + Tran = 2<<4, + Link = 3<<4, + OLength = 16, + /* maximum value for Length field */ + Maxdma = 1<<12, +}; + +struct Ctlr { + Rendez r; + int fastclock; + uint extclk; + int appcmd; + Adma *dma; +}; + +static Ctlr usdhc; + +static void usdhcinterrupt(Ureg*, void*); + +static u32int *regs = (u32int*)(VIRTIO+0xB50000); /* USDHC2 */ +#define RR(reg) (regs[reg]) + +static void +WR(int reg, u32int val) +{ + if(0)print("WR %2.2ux %ux\n", reg<<2, val); + coherence(); + regs[reg] = val; +} + +static Adma* +dmaalloc(void *addr, int len) +{ + int n; + uintptr a; + Adma *adma, *p; + + a = PADDR(addr); + n = (len + Maxdma-1) / Maxdma; + adma = sdmalloc(n * sizeof(Adma)); + for(p = adma; len > 0; p++){ + if(n == 1) + p->desc = len<desc = Maxdma<addr = a; + a += Maxdma; + len -= Maxdma; + n--; + } + cachedwbse(adma, (char*)p - (char*)adma); + return adma; +} + +static void +usdhcclk(uint freq) +{ + uint pre_div = 1, post_div = 1, clk = usdhc.extclk; + + while(clk / (pre_div * 16) > freq && pre_div < 256) + pre_div <<= 1; + + while(clk / (pre_div * post_div) > freq && post_div < 16) + post_div++; + + WR(Vendorspec, RR(Vendorspec) & ~ClkEn); + WR(Control1, (pre_div>>1)<ticks; + while(((i=RR(Interrupt))&(Cmddone|Err)) == 0) + if(MACHP(0)->ticks - now > HZ) + break; + if((i&(Cmddone|Err)) != Cmddone){ + if((i&~(Err|Cardintr)) != Ctoerr) + print("usdhc: cmd %ux arg %ux error intr %ux stat %ux\n", c, arg, i, RR(Status)); + WR(Interrupt, i); + if(RR(Status)&Cmdinhibit){ + WR(Control1, RR(Control1)|Srstcmd); + while(RR(Control1)&Srstcmd) + ; + } + error(Eio); + } + WR(Interrupt, i & ~(Datadone|Readrdy|Writerdy)); + switch(c & Respmask){ + case Resp136: + resp[0] = RR(Resp0)<<8; + resp[1] = RR(Resp0)>>24 | RR(Resp1)<<8; + resp[2] = RR(Resp1)>>24 | RR(Resp2)<<8; + resp[3] = RR(Resp2)>>24 | RR(Resp3)<<8; + break; + case Resp48: + case Resp48busy: + resp[0] = RR(Resp0); + break; + case Respnone: + resp[0] = 0; + break; + } + if((c & Respmask) == Resp48busy){ + WR(Irpten, RR(Irpten)|Datadone|Err); + tsleep(&usdhc.r, datadone, 0, 1000); + i = RR(Interrupt); + if((i & Datadone) == 0) + print("usdhcio: no Datadone in %x after CMD%d\n", i, cmd); + if(i & Err) + print("usdhcio: CMD%d error interrupt %ux\n", + cmd, RR(Interrupt)); + if(i != 0) WR(Interrupt, i); + } + /* + * Once card is selected, use faster clock + */ + if(cmd == MMCSelect){ + usdhcclk(SDfreq); + usdhc.fastclock = 1; + } + if(cmd == Setbuswidth){ + if(usdhc.appcmd){ + /* + * If card bus width changes, change host bus width + */ + switch(arg){ + case 0: + WR(Control0, (RR(Control0) & ~DwidthMask) | Dwidth1); + break; + case 2: + WR(Control0, (RR(Control0) & ~DwidthMask) | Dwidth4); + break; + } + } else { + /* + * If card switched into high speed mode, increase clock speed + */ + if((arg&0x8000000F) == 0x80000001){ + delay(1); + usdhcclk(SDfreqhs); + delay(1); + } + } + }else if(cmd == IORWdirect && (arg & ~0xFF) == (1<<31|0<<28|7<<9)){ + switch(arg & 0x3){ + case 0: + WR(Control0, (RR(Control0) & ~DwidthMask) | Dwidth1); + break; + case 2: + WR(Control0, (RR(Control0) & ~DwidthMask) | Dwidth4); + break; + } + } + usdhc.appcmd = (cmd == Appcmd); + return 0; +} + +static void +usdhciosetup(int write, void *buf, int bsize, int bcount) +{ + int len = bsize * bcount; + assert(((uintptr)buf&3) == 0); + assert((len&3) == 0); + assert(bsize <= 2048); + WR(Blksizecnt, bcount<<16 | bsize); + if(usdhc.dma) + sdfree(usdhc.dma); + usdhc.dma = dmaalloc(buf, len); + if(write) + cachedwbse(buf, len); + else + cachedwbinvse(buf, len); + WR(Dmadesc, PADDR(usdhc.dma)); +} + +static void +usdhcio(int write, uchar *buf, int len) +{ + u32int i; + + WR(Irpten, RR(Irpten) | Datadone|Err); + tsleep(&usdhc.r, datadone, 0, 3000); + WR(Irpten, RR(Irpten) & ~(Datadone|Err)); + i = RR(Interrupt); + if((i & (Datadone|Err)) != Datadone){ + print("sdhc: %s error intr %ux stat %ux\n", + write? "write" : "read", i, RR(Status)); + WR(Interrupt, i); + error(Eio); + } + WR(Interrupt, i); + if(!write) + cachedinvse(buf, len); +} + +static void +usdhcinterrupt(Ureg*, void*) +{ + u32int i; + + i = RR(Interrupt); + if(i&(Datadone|Err)) + wakeup(&usdhc.r); + WR(Irpten, RR(Irpten) & ~i); +} + +SDio sdio = { + "usdhc", + usdhcinit, + usdhcenable, + usdhcinquiry, + usdhccmd, + usdhciosetup, + usdhcio, + .highspeed = 1, + .nomultiwrite = 1, +}; diff --git a/sys/src/9/pc/pc b/sys/src/9/pc/pc index 2cacee652..6ba1323ed 100644 --- a/sys/src/9/pc/pc +++ b/sys/src/9/pc/pc @@ -147,6 +147,7 @@ misc dtracysys dtracytimer + dtracydev ip tcp diff --git a/sys/src/9/pc64/pc64 b/sys/src/9/pc64/pc64 index bafda3d72..e385be7a6 100644 --- a/sys/src/9/pc64/pc64 +++ b/sys/src/9/pc64/pc64 @@ -144,6 +144,7 @@ misc dtracysys dtracytimer + dtracydev ip tcp diff --git a/sys/src/9/port/dev.c b/sys/src/9/port/dev.c index 185d7ffd0..6d6e157fc 100644 --- a/sys/src/9/port/dev.c +++ b/sys/src/9/port/dev.c @@ -262,7 +262,7 @@ devwalk(Chan *c, Chan *nc, char **name, int nname, Dirtab *tab, int ntab, Devgen if(strcmp(n, "..") == 0){ if((*gen)(nc, nil, tab, ntab, DEVDOTDOT, &dir) != 1){ print("devgen walk .. in dev%s %llux broken\n", - devtab[nc->type]->name, nc->qid.path); + devtab[c->type]->name, c->qid.path); error("broken devgen"); } nc->qid = dir.qid; diff --git a/sys/src/9/port/devi2c.c b/sys/src/9/port/devi2c.c new file mode 100644 index 000000000..568480ae7 --- /dev/null +++ b/sys/src/9/port/devi2c.c @@ -0,0 +1,597 @@ +/* I²C bus driver */ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "../port/error.h" +#include "../port/i2c.h" + +enum { + Qdir = 0, /* #J */ + Qbus, /* #J/bus */ + Qctl, /* #J/bus/i2c.n.ctl */ + Qdata, /* #J/bus/i2c.n.data */ +}; + +#define TYPE(q) ((ulong)(q).path & 0x0F) +#define BUS(q) (((ulong)(q).path>>4) & 0xFF) +#define DEV(q) (((ulong)(q).path>>12) & 0xFFF) +#define QID(d, b, t) (((d)<<12)|((b)<<4)|(t)) + +static I2Cbus *buses[16]; + +static I2Cdev *devs[1024]; +static Lock devslock; + +static void probebus(I2Cbus *bus); + +void +addi2cbus(I2Cbus *bus) +{ + int i; + + if(bus == nil) + return; + + for(i = 0; i < nelem(buses); i++){ + if(buses[i] == nil + || buses[i] == bus + || strcmp(bus->name, buses[i]->name) == 0){ + buses[i] = bus; + break; + } + } +} + +I2Cbus* +i2cbus(char *name) +{ + I2Cbus *bus; + int i; + + for(i = 0; i < nelem(buses); i++){ + bus = buses[i]; + if(bus == nil) + break; + if(strcmp(bus->name, name) == 0){ + probebus(bus); + return bus; + } + } + return nil; +} + +void +addi2cdev(I2Cdev *dev) +{ + int i; + + if(dev == nil || dev->bus == nil) + return; + + lock(&devslock); + for(i = 0; i < nelem(devs); i++){ + if(devs[i] == nil + || devs[i] == dev + || devs[i]->addr == dev->addr && devs[i]->bus == dev->bus){ + devs[i] = dev; + unlock(&devslock); + return; + } + } + unlock(&devslock); +} + +I2Cdev* +i2cdev(I2Cbus *bus, int addr) +{ + I2Cdev *dev; + int i; + + if(bus == nil || addr < 0 || addr >= 1<<10) + return nil; + + lock(&devslock); + for(i = 0; i < nelem(devs) && (dev = devs[i]) != nil; i++){ + if(dev->addr == addr && dev->bus == bus){ + unlock(&devslock); + return dev; + } + } + unlock(&devslock); + + return nil; +} + + +static int +enterbus(I2Cbus *bus) +{ + if(up != nil && islo()){ + eqlock(bus); + return 1; + } else { + while(!canqlock(bus)) + ; + return 0; + } +} + +static void +leavebus(I2Cbus *bus) +{ + qunlock(bus); +} + +int +i2cbusio(I2Cbus *bus, uchar *pkt, int olen, int ilen) +{ + int user, n; + + user = enterbus(bus); + if(!bus->probed){ + leavebus(bus); + return -1; + } + if(user && waserror()){ + (*bus->io)(bus, nil, 0, 0); + leavebus(bus); + nexterror(); + } +// iprint("%s: <- %.*H\n", bus->name, olen, pkt); + n = (*bus->io)(bus, pkt, olen, ilen); +// if(n > olen) iprint("%s: -> %.*H\n", bus->name, n - olen, pkt+olen); + + leavebus(bus); + if(user) poperror(); + + return n; +} + +static int +putaddr(I2Cdev *dev, int isread, uchar *pkt, vlong addr) +{ + int n, o = 0; + + if(dev->a10){ + pkt[o++] = 0xF0 | (dev->addr>>(8-1))&6 | (isread != 0); + pkt[o++] = dev->addr; + } else + pkt[o++] = dev->addr<<1 | (isread != 0); + + if(addr >= 0){ + for(n=0; nsubaddr; n++) + pkt[o++] = addr >> (n*8); + } + + return o; +} + +int +i2csend(I2Cdev *dev, void *data, int len, vlong addr) +{ + uchar pkt[138]; + int o; + + o = putaddr(dev, 0, pkt, addr); + if(o+len > sizeof(pkt)) + len = sizeof(pkt)-o; + + if(len > 0) + memmove(pkt+o, data, len); + + return i2cbusio(dev->bus, pkt, o + len, 0) - o; +} + +int +i2crecv(I2Cdev *dev, void *data, int len, vlong addr) +{ + uchar pkt[138]; + int o; + + o = putaddr(dev, 1, pkt, addr); + if(o+len > sizeof(pkt)) + len = sizeof(pkt)-o; + + len = i2cbusio(dev->bus, pkt, o, len) - o; + if(len > 0) + memmove(data, pkt+o, len); + + return len; +} + +int +i2cquick(I2Cdev *dev, int rw) +{ + uchar pkt[2]; + int o = putaddr(dev, rw, pkt, -1); + if(i2cbusio(dev->bus, pkt, o, 0) != o) + return -1; + return rw != 0; +} +int +i2crecvbyte(I2Cdev *dev) +{ + uchar pkt[2+1]; + int o = putaddr(dev, 1, pkt, -1); + if(i2cbusio(dev->bus, pkt, o, 1) - o != 1) + return -1; + return pkt[o]; +} +int +i2csendbyte(I2Cdev *dev, uchar b) +{ + uchar pkt[2+1]; + int o = putaddr(dev, 0, pkt, -1); + pkt[o] = b; + if(i2cbusio(dev->bus, pkt, o+1, 0) - o != 1) + return -1; + return b; +} +int +i2creadbyte(I2Cdev *dev, ulong addr) +{ + uchar pkt[2+4+1]; + int o = putaddr(dev, 1, pkt, addr); + if(i2cbusio(dev->bus, pkt, o, 1) - o != 1) + return -1; + return pkt[o]; +} +int +i2cwritebyte(I2Cdev *dev, ulong addr, uchar b) +{ + uchar pkt[2+4+1]; + int o = putaddr(dev, 0, pkt, addr); + pkt[o] = b; + if(i2cbusio(dev->bus, pkt, o+1, 0) - o != 1) + return -1; + return b; +} +int +i2creadword(I2Cdev *dev, ulong addr) +{ + uchar pkt[2+4+2]; + int o = putaddr(dev, 1, pkt, addr); + if(i2cbusio(dev->bus, pkt, o, 2) - o != 2) + return -1; + return pkt[o] | (ushort)pkt[o+1]<<8; +} +int +i2cwriteword(I2Cdev *dev, ulong addr, ushort w) +{ + uchar pkt[2+4+2]; + int o = putaddr(dev, 0, pkt, addr); + pkt[o+0] = w; + pkt[o+1] = w>>8; + if(i2cbusio(dev->bus, pkt, o+2, 0) - o != 2) + return -1; + return w; +} +vlong +i2cread32(I2Cdev *dev, ulong addr) +{ + uchar pkt[2+4+4]; + int o = putaddr(dev, 1, pkt, addr); + if(i2cbusio(dev->bus, pkt, o, 4) - o != 4) + return -1; + return pkt[o] | (ulong)pkt[o+1]<<8 | (ulong)pkt[o+2]<<16 | (ulong)pkt[o+3]<<24; +} +vlong +i2cwrite32(I2Cdev *dev, ulong addr, ulong u) +{ + uchar pkt[2+4+4]; + int o = putaddr(dev, 0, pkt, addr); + pkt[o+0] = u; + pkt[o+1] = u>>8; + pkt[o+2] = u>>16; + pkt[o+3] = u>>24; + if(i2cbusio(dev->bus, pkt, o+4, 0) - o != 4) + return -1; + return u; +} + +static void +probeddev(I2Cdev *dummy) +{ + I2Cdev *dev = smalloc(sizeof(I2Cdev)); + memmove(dev, dummy, sizeof(I2Cdev)); + addi2cdev(dev); +} + +static void +probebus(I2Cbus *bus) +{ + I2Cdev dummy; + uchar pkt[2]; + int user, n; + + if(bus->probed) + return; + + user = enterbus(bus); + if(bus->probed){ + leavebus(bus); + return; + } + if(user && waserror() + || (*bus->init)(bus)){ + leavebus(bus); + if(user) nexterror(); + return; + } + + memset(&dummy, 0, sizeof(dummy)); + dummy.bus = bus; + + dummy.a10 = 0; + for(dummy.addr = 8; dummy.addr < 0x78; dummy.addr++) { + if(i2cdev(bus, dummy.addr) != nil) + continue; + if(user && waserror()){ + (*bus->io)(bus, nil, 0, 0); + continue; + } + n = putaddr(&dummy, 0, pkt, -1); + if((*bus->io)(bus, pkt, n, 0) == n) + probeddev(&dummy); + if(user) poperror(); + } + + dummy.a10 = 1; + for(dummy.addr = 0; dummy.addr < (1<<10); dummy.addr++) { + if(i2cdev(bus, dummy.addr) != nil) + continue; + if(user && waserror()){ + (*bus->io)(bus, nil, 0, 0); + continue; + } + n = putaddr(&dummy, 0, pkt, -1); + if((*bus->io)(bus, pkt, n, 0) == n) + probeddev(&dummy); + if(user) poperror(); + } + + bus->probed = 1; + leavebus(bus); + if(user) poperror(); +} + +static int +i2cgen(Chan *c, char *, Dirtab*, int, int s, Dir *dp) +{ + I2Cbus *bus; + I2Cdev *dev; + + Qid q; + + switch(TYPE(c->qid)){ + case Qdir: + if(s == DEVDOTDOT){ + Gendir: + mkqid(&q, QID(0, 0, Qdir), 0, QTDIR); + snprint(up->genbuf, sizeof up->genbuf, "#J"); + devdir(c, q, up->genbuf, 0, eve, 0500, dp); + return 1; + } + if(s >= nelem(buses)) + return -1; + bus = buses[s]; + if(bus == nil) + return -1; + mkqid(&q, QID(0, s, Qbus), 0, QTDIR); + devdir(c, q, bus->name, 0, eve, 0500, dp); + return 1; + case Qbus: + if(s == DEVDOTDOT) + goto Gendir; + if((s/2) >= nelem(devs)) + return -1; + + bus = buses[BUS(c->qid)]; + probebus(bus); + + lock(&devslock); + dev = devs[s/2]; + unlock(&devslock); + + if(dev == nil) + return -1; + if(dev->bus != bus) + return 0; + if(s & 1){ + mkqid(&q, QID(dev->addr, BUS(c->qid), Qdata), 0, 0); + goto Gendata; + } + mkqid(&q, QID(dev->addr, BUS(c->qid), Qctl), 0, 0); + goto Genctl; + case Qctl: + q = c->qid; + Genctl: + snprint(up->genbuf, sizeof up->genbuf, "i2c.%lux.ctl", DEV(q)); + devdir(c, q, up->genbuf, 0, eve, 0600, dp); + return 1; + case Qdata: + q = c->qid; + bus = buses[BUS(q)]; + dev = i2cdev(bus, DEV(q)); + if(dev == nil) + return -1; + Gendata: + snprint(up->genbuf, sizeof up->genbuf, "i2c.%lux.data", DEV(q)); + devdir(c, q, up->genbuf, dev->size, eve, 0600, dp); + return 1; + } + return -1; +} + +static Chan* +i2cattach(char *spec) +{ + return devattach('J', spec); +} + +static Chan* +i2copen(Chan *c, int mode) +{ + c = devopen(c, mode, nil, 0, i2cgen); + switch(TYPE(c->qid)){ + case Qctl: + case Qdata: + c->aux = i2cdev(buses[BUS(c->qid)], DEV(c->qid)); + if(c->aux == nil) + error(Enonexist); + break; + } + return c; +} + +enum { + CMsize, + CMsubaddress, +}; + +static Cmdtab i2cctlmsg[] = +{ + CMsize, "size", 2, + CMsubaddress, "subaddress", 2, +}; + +static long +i2cwrctl(I2Cdev *dev, void *data, long len) +{ + Cmdbuf *cb; + Cmdtab *ct; + ulong u; + + cb = parsecmd(data, len); + if(waserror()){ + free(cb); + nexterror(); + } + ct = lookupcmd(cb, i2cctlmsg, nelem(i2cctlmsg)); + switch(ct->index){ + case CMsize: + dev->size = strtoul(cb->f[1], nil, 0); + break; + case CMsubaddress: + u = strtoul(cb->f[1], nil, 0); + if(u > 4) + cmderror(cb, Ebadarg); + dev->subaddr = u; + break; + default: + cmderror(cb, Ebadarg); + } + free(cb); + poperror(); + return len; +} + +static long +i2crdctl(I2Cdev *dev, void *data, long len, vlong offset) +{ + char cfg[64]; + + snprint(cfg, sizeof(cfg), "size %lud\nsubaddress %d\n", dev->size, dev->subaddr); + return readstr((ulong)offset, data, len, cfg); +} + +static long +i2cwrite(Chan *c, void *data, long len, vlong offset) +{ + I2Cdev *dev; + + switch(TYPE(c->qid)){ + default: + error(Egreg); + return -1; + case Qctl: + dev = c->aux; + return i2cwrctl(dev, data, len); + case Qdata: + break; + } + dev = c->aux; + if(dev->size){ + if(offset+len > dev->size){ + if(offset >= dev->size) + return 0; + len = dev->size - offset; + } + } + len = i2csend(dev, data, len, offset); + if(len < 0) + error(Eio); + return len; +} + +static long +i2cread(Chan *c, void *data, long len, vlong offset) +{ + I2Cdev *dev; + + if(c->qid.type == QTDIR) + return devdirread(c, data, len, nil, 0, i2cgen); + + switch(TYPE(c->qid)){ + default: + error(Egreg); + case Qctl: + dev = c->aux; + return i2crdctl(dev, data, len, offset); + case Qdata: + break; + } + dev = c->aux; + if(dev->size){ + if(offset+len > dev->size){ + if(offset >= dev->size) + return 0; + len = dev->size - offset; + } + } + len = i2crecv(dev, data, len, offset); + if(len < 0) + error(Eio); + return len; +} + +void +i2cclose(Chan*) +{ +} + +static Walkqid* +i2cwalk(Chan *c, Chan *nc, char **name, int nname) +{ + return devwalk(c, nc, name, nname, nil, 0, i2cgen); +} + +static int +i2cstat(Chan *c, uchar *dp, int n) +{ + return devstat(c, dp, n, nil, 0, i2cgen); +} + +Dev i2cdevtab = { + 'J', + "i2c", + + devreset, + devinit, + devshutdown, + i2cattach, + i2cwalk, + i2cstat, + i2copen, + devcreate, + i2cclose, + i2cread, + devbread, + i2cwrite, + devbwrite, + devremove, + devwstat, + devpower, +}; diff --git a/sys/src/9/port/devpipe.c b/sys/src/9/port/devpipe.c index 60c6edd13..8611681a4 100644 --- a/sys/src/9/port/devpipe.c +++ b/sys/src/9/port/devpipe.c @@ -11,9 +11,7 @@ typedef struct Pipe Pipe; struct Pipe { QLock; - Pipe *next; int ref; - ulong path; Queue *q[2]; int qref[2]; }; @@ -57,6 +55,7 @@ pipeattach(char *spec) { Pipe *p; Chan *c; + ulong path; c = devattach('|', spec); if(waserror()){ @@ -82,10 +81,10 @@ pipeattach(char *spec) poperror(); lock(&pipealloc); - p->path = ++pipealloc.path; + path = ++pipealloc.path; unlock(&pipealloc); - mkqid(&c->qid, NETQID(2*p->path, Qdir), 0, QTDIR); + mkqid(&c->qid, NETQID(path, Qdir), 0, QTDIR); c->aux = p; c->dev = 0; return c; diff --git a/sys/src/9/port/devsrv.c b/sys/src/9/port/devsrv.c index 8128569a1..e1b7856f9 100644 --- a/sys/src/9/port/devsrv.c +++ b/sys/src/9/port/devsrv.c @@ -5,80 +5,249 @@ #include "fns.h" #include "../port/error.h" +#include "netif.h" + +typedef struct Link Link; +struct Link +{ + void *link; + char *name; + ulong path; +}; typedef struct Srv Srv; struct Srv { - char *name; + Link; + char *owner; ulong perm; Chan *chan; - Srv *link; - ulong path; }; -static QLock srvlk; -static Srv *srv; -static int qidpath; - -static Srv* -srvlookup(char *name, ulong qidpath) +typedef struct Board Board; +struct Board { - Srv *sp; + Link; + RWlock; + Ref; - for(sp = srv; sp != nil; sp = sp->link) { - if(sp->path == qidpath || (name != nil && strcmp(sp->name, name) == 0)) - return sp; + Board *parent; + Board *child; + Srv *srv; + long id; + int qidpath; + int closed; +}; + +struct{ + QLock; + long path; +} boards; + +enum{ + Qroot, + Qclone, + Qlease, + + Qend, +}; + +Board root; + +static char Eexpired[] = "expired lease"; + +static void* +lookup(Link *l, char *name, ulong qidpath) +{ + Link *lp; + + if(qidpath != ~0UL) + qidpath = NETTYPE(qidpath); + for(lp = l; lp != nil; lp = lp->link){ + if(qidpath != ~0UL && lp->path == qidpath) + return lp; + if(name != nil && strcmp(lp->name, name) == 0) + return lp; } return nil; } +static void* +remove(Link **l, char *name, ulong qidpath) +{ + Link *lp; + Link **last; + + if(qidpath != ~0UL) + qidpath = NETTYPE(qidpath); + last = l; + for(lp = *l; lp != nil; lp = lp->link){ + if(qidpath != ~0UL && lp->path == qidpath) + break; + if(name != nil && strcmp(lp->name, name) == 0) + break; + last = &lp->link; + } + if(lp == nil) + return nil; + + *last = lp->link; + lp->link = nil; + return lp; +} + +static void +boardclunk(Board *b, int close) +{ + Srv *sp, *prv; + Board *ch; + long ref; + + /* caller holds a wlock */ + if(b == &root){ + wunlock(b); + return; + } + + if(close){ + assert(b->closed == 0); + b->closed++; + for(sp = b->srv; sp != nil; sp = prv){ + prv = sp->link; + free(sp->owner); + free(sp->name); + if(sp->chan != nil) + cclose(sp->chan); + free(sp); + } + b->srv = nil; + } + ref = decref(b); + + /* + * All boards must be walkable from root. So a board + * is allowed to sit at zero references as long as it + * still has active children. For leaf nodes we then + * have to walk up the tree to clear now empty parents. + */ + while(b->closed && b->child == nil && ref == 0){ + //Root should never be closed + assert(b->parent != nil); + wlock(b->parent); + ch = remove((Link**)&b->parent->child, b->name, b->path); + assert(ch == b); + + b = ch->parent; + free(ch->name); + wunlock(ch); + free(ch); + } + wunlock(b); +} + static int srvgen(Chan *c, char *name, Dirtab*, int, int s, Dir *dp) { Srv *sp; + Board *b, *ch; Qid q; - if(s == DEVDOTDOT){ - devdir(c, c->qid, "#s", 0, eve, 0555, dp); - return 1; - } + if(name != nil && strlen(name) >= sizeof(up->genbuf)) + return -1; - qlock(&srvlk); - if(name != nil) - sp = srvlookup(name, -1); - else { - for(sp = srv; sp != nil && s > 0; sp = sp->link) - s--; - } - if(sp == nil || (name != nil && (strlen(sp->name) >= sizeof(up->genbuf)))) { - qunlock(&srvlk); + b = c->aux; + ch = nil; + mkqid(&q, ~0L, 0, QTFILE); + rlock(b); + if(waserror()){ + runlock(b); return -1; } - mkqid(&q, sp->path, 0, QTFILE); - /* make sure name string continues to exist after we release lock */ - kstrcpy(up->genbuf, sp->name, sizeof up->genbuf); - devdir(c, q, up->genbuf, 0, sp->owner, sp->perm, dp); - qunlock(&srvlk); + if(s == DEVDOTDOT){ + ch = b->parent; + if(ch == nil) + ch = &root; + goto Child; + + } + if(name != nil){ + if(strcmp("clone", name) == 0) + goto Clone; + + sp = lookup(b->srv, name, ~0UL); + if(sp == nil) + ch = lookup(b->child, name, ~0UL); + } else { + if(s == 0) + goto Clone; + s--; + for(sp = b->srv; sp != nil && s > 0; sp = sp->link) + s--; + for(ch = b->child; ch != nil && s > 0; ch = ch->link) + s--; + } + if(sp != nil){ + kstrcpy(up->genbuf, sp->name, sizeof up->genbuf); + q.vers = NETID(c->qid.path); + q.path = NETQID(q.vers, sp->path); + devdir(c, q, up->genbuf, 0, sp->owner, sp->perm, dp); + } else if(ch != nil){ +Child: + kstrcpy(up->genbuf, ch->name, sizeof up->genbuf); + q.vers = ch->id; + q.path = NETQID(q.vers, ch->path); + q.type = QTDIR; + devdir(c, q, up->genbuf, 0, eve, 0555|DMDIR, dp); + /* dirread's and stats shouldn't alter c->aux */ + if(name != nil) + c->aux = ch; + } else if(0){ +Clone: + q.vers = NETID(c->qid.path); + q.path = NETQID(q.vers, Qclone); + devdir(c, q, "clone", 0, eve, 0444, dp); + } else + error(Enonexist); + + runlock(b); + poperror(); return 1; } static void srvinit(void) { - qidpath = 1; + root.qidpath = Qend; + root.name = "#s"; } static Chan* srvattach(char *spec) { - return devattach('s', spec); + Chan *c; + + c = devattach('s', spec); + c->aux = &root; + return c; } static Walkqid* srvwalk(Chan *c, Chan *nc, char **name, int nname) { - return devwalk(c, nc, name, nname, 0, 0, srvgen); + Board *b; + Walkqid *wq; + + wq = devwalk(c, nc, name, nname, 0, 0, srvgen); + if(wq == nil || wq->clone == nil) + return wq; + + b = wq->clone->aux; + if(b == &root) + return wq; + + incref(b); + return wq; } static int @@ -90,12 +259,14 @@ srvstat(Chan *c, uchar *db, int n) char* srvname(Chan *c) { + Board *b; Srv *sp; char *s; s = nil; - qlock(&srvlk); - for(sp = srv; sp != nil; sp = sp->link) { + b = &root; + rlock(b); + for(sp = b->srv; sp != nil; sp = sp->link) { if(sp->chan == c){ s = malloc(3+strlen(sp->name)+1); if(s != nil) @@ -103,15 +274,17 @@ srvname(Chan *c) break; } } - qunlock(&srvlk); + runlock(b); return s; } static Chan* srvopen(Chan *c, int omode) { + Board *b, *ch; Srv *sp; Chan *nc; + char buf[64]; if(c->qid.type == QTDIR){ if(omode & ORCLOSE) @@ -123,20 +296,53 @@ srvopen(Chan *c, int omode) c->offset = 0; return c; } - qlock(&srvlk); - if(waserror()){ - qunlock(&srvlk); - nexterror(); - } - - sp = srvlookup(nil, c->qid.path); - if(sp == nil || sp->chan == nil) - error(Eshutdown); - if(omode&OTRUNC) error(Eexist); if(omode&ORCLOSE) error(Eperm); + + b = c->aux; + if(NETTYPE(c->qid.path) == Qclone){; + wlock(b); + if(b->closed){ + wunlock(b); + error(Eexpired); + } + ch = smalloc(sizeof *ch); + ch->qidpath = Qend; + ch->ref = 1; + do { + qlock(&boards); + ch->id = ++boards.path; + qunlock(&boards); + snprint(buf, sizeof buf, "%ld", ch->id); + } while(lookup(b->srv, buf, ~0UL) != nil); + + ch->parent = b; + ch->path = b->qidpath++; + kstrdup(&ch->name, buf); + + ch->link = b->child; + b->child = ch; + c->aux = ch; + c->qid.vers = ch->id; + c->qid.path = NETQID(ch->id, Qlease); + boardclunk(b, 0); //unlock + return c; + } + + rlock(b); + if(waserror()){ + runlock(b); + nexterror(); + } + if(b->closed) + error(Eexpired); + + sp = lookup(b->srv, nil, c->qid.path); + if(sp == nil || sp->chan == nil) + error(Eshutdown); + if(openmode(omode)!=sp->chan->mode && sp->chan->mode!=ORDWR) error(Eperm); devpermcheck(sp->owner, sp->perm, omode); @@ -144,7 +350,7 @@ srvopen(Chan *c, int omode) nc = sp->chan; incref(nc); - qunlock(&srvlk); + runlock(b); poperror(); cclose(c); @@ -154,6 +360,7 @@ srvopen(Chan *c, int omode) static Chan* srvcreate(Chan *c, char *name, int omode, ulong perm) { + Board *b; Srv *sp; if(openmode(omode) != OWRITE) @@ -166,27 +373,33 @@ srvcreate(Chan *c, char *name, int omode, ulong perm) kstrdup(&sp->name, name); kstrdup(&sp->owner, up->user); - qlock(&srvlk); + b = c->aux; + wlock(b); if(waserror()){ - qunlock(&srvlk); + wunlock(b); free(sp->owner); free(sp->name); free(sp); nexterror(); } - if(srvlookup(name, -1) != nil) + if(b->closed) + error(Eexpired); + if(lookup(b->srv, name, ~0UL) != nil) + error(Eexist); + if(lookup(b->child, name, ~0UL) != nil) error(Eexist); sp->perm = perm&0777; - sp->path = qidpath++; + sp->path = b->qidpath++; - c->qid.path = sp->path; + c->qid.path = NETQID(b->id, sp->path); + c->qid.vers = b->id; c->qid.type = QTFILE; - sp->link = srv; - srv = sp; + sp->link = b->srv; + b->srv = sp; - qunlock(&srvlk); + wunlock(b); poperror(); c->flag |= COPEN; @@ -198,22 +411,24 @@ srvcreate(Chan *c, char *name, int omode, ulong perm) static void srvremove(Chan *c) { - Srv *sp, **l; + Board *b; + Srv *sp; if(c->qid.type == QTDIR) error(Eperm); + switch(NETTYPE(c->qid.path)){ + case Qlease: + case Qclone: + error(Eperm); + } - qlock(&srvlk); + b = c->aux; + wlock(b); if(waserror()){ - qunlock(&srvlk); + wunlock(b); nexterror(); } - l = &srv; - for(sp = *l; sp != nil; sp = *l) { - if(sp->path == c->qid.path) - break; - l = &sp->link; - } + sp = lookup(b->srv, nil, c->qid.path); if(sp == nil) error(Enonexist); @@ -229,10 +444,9 @@ srvremove(Chan *c) if((sp->perm&7) != 7 && strcmp(sp->owner, up->user) && !iseve()) error(Eperm); - *l = sp->link; - sp->link = nil; + remove((Link**)&b->srv, nil, c->qid.path); - qunlock(&srvlk); + boardclunk(b, 0); //unlock poperror(); if(sp->chan != nil) @@ -245,12 +459,18 @@ srvremove(Chan *c) static int srvwstat(Chan *c, uchar *dp, int n) { + Board *b; char *strs; Srv *sp; Dir d; if(c->qid.type & QTDIR) error(Eperm); + switch(NETTYPE(c->qid.path)){ + case Qlease: + case Qclone: + error(Eperm); + } strs = smalloc(n); if(waserror()){ @@ -261,13 +481,16 @@ srvwstat(Chan *c, uchar *dp, int n) if(n == 0) error(Eshortstat); - qlock(&srvlk); + b = c->aux; + wlock(b); if(waserror()){ - qunlock(&srvlk); + wunlock(b); nexterror(); } + if(b->closed) + error(Eexpired); - sp = srvlookup(nil, c->qid.path); + sp = lookup(b->srv, nil, c->qid.path); if(sp == nil) error(Enonexist); @@ -279,6 +502,10 @@ srvwstat(Chan *c, uchar *dp, int n) error(Ebadchar); if(strlen(d.name) >= sizeof(up->genbuf)) error(Etoolong); + if(lookup(b->srv, d.name, ~0UL) != nil) + error(Eexist); + if(lookup(b->child, d.name, ~0UL) != nil) + error(Eexist); kstrdup(&sp->name, d.name); } if(d.uid != nil && *d.uid) @@ -286,7 +513,7 @@ srvwstat(Chan *c, uchar *dp, int n) if(d.mode != ~0UL) sp->perm = d.mode & 0777; - qunlock(&srvlk); + wunlock(b); poperror(); free(strs); @@ -298,22 +525,47 @@ srvwstat(Chan *c, uchar *dp, int n) static void srvclose(Chan *c) { - /* - * in theory we need to override any changes in removability - * since open, but since all that's checked is the owner, - * which is immutable, all is well. - */ - if(c->flag & CRCLOSE){ + Board *b; + int expired; + + expired = 0; + if(NETTYPE(c->qid.path) == Qlease) + expired++; + else if(c->flag & CRCLOSE){ + /* + * in theory we need to override any changes in removability + * since open, but since all that's checked is the owner, + * which is immutable, all is well. + */ if(waserror()) - return; + goto Clunk; srvremove(c); poperror(); + return; } +Clunk: + b = c->aux; + wlock(b); + boardclunk(b, expired); //unlock } static long -srvread(Chan *c, void *va, long n, vlong) +srvread(Chan *c, void *va, long n, vlong off) { + Board *b; + + if(NETTYPE(c->qid.path) == Qlease){ + b = c->aux; + rlock(b); + if(waserror()){ + runlock(b); + nexterror(); + } + n = readstr((ulong)off, va, n, b->name); + runlock(b); + poperror(); + return n; + } isdir(c); return devdirread(c, va, n, 0, 0, srvgen); } @@ -321,11 +573,15 @@ srvread(Chan *c, void *va, long n, vlong) static long srvwrite(Chan *c, void *va, long n, vlong) { + Board *b; Srv *sp; Chan *c1; int fd; char buf[32]; + if(NETTYPE(c->qid.path) == Qlease) + error(Eperm); + if(n >= sizeof buf) error(Etoobig); memmove(buf, va, n); /* so we can NUL-terminate */ @@ -334,15 +590,18 @@ srvwrite(Chan *c, void *va, long n, vlong) c1 = fdtochan(fd, -1, 0, 1); /* error check and inc ref */ - qlock(&srvlk); + b = c->aux; + wlock(b); if(waserror()) { - qunlock(&srvlk); + wunlock(b); cclose(c1); nexterror(); } + if(b->closed) + error(Eexpired); if(c1->qid.type & QTAUTH) error("cannot post auth file in srv"); - sp = srvlookup(nil, c->qid.path); + sp = lookup(b->srv, nil, c->qid.path); if(sp == nil) error(Enonexist); @@ -351,7 +610,7 @@ srvwrite(Chan *c, void *va, long n, vlong) sp->chan = c1; - qunlock(&srvlk); + wunlock(b); poperror(); return n; } @@ -380,12 +639,14 @@ Dev srvdevtab = { void srvrenameuser(char *old, char *new) { + Board *b; Srv *sp; - qlock(&srvlk); - for(sp = srv; sp != nil; sp = sp->link) { + b = &root; + wlock(b); + for(sp = b->srv; sp != nil; sp = sp->link) { if(sp->owner != nil && strcmp(old, sp->owner) == 0) kstrdup(&sp->owner, new); } - qunlock(&srvlk); + wunlock(b); } diff --git a/sys/src/9/port/dtracydev.c b/sys/src/9/port/dtracydev.c new file mode 100644 index 000000000..b9a616cd0 --- /dev/null +++ b/sys/src/9/port/dtracydev.c @@ -0,0 +1,384 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "../port/error.h" + +#include + +enum{ + Dwalk, + Dstat, + Dopen, + Dcreate, + Dclose, + Dread, + Dbread, + Dwrite, + Dbwrite, + Dremove, + Dwstat, + + Dend +}; + +static char *optab[] = { + [Dwalk] "walk", + [Dstat] "stat", + [Dopen] "open", + [Dcreate] "create", + [Dclose] "close", + [Dread] "read", + [Dbread] "bread", + [Dwrite] "write", + [Dbwrite] "bwrite", + [Dremove] "remove", + [Dwstat] "wstat", +}; + +struct { + DTProbe *in[Dend]; + DTProbe *out[Dend]; + Dev clean; +} ledger[256]; + +static Walkqid* +wrapwalk(Chan *c, Chan *nc, char **names, int nname) +{ + DTTrigInfo info; + Walkqid *wq; + + + memset(&info, 0, sizeof info); + info.arg[0] = (uvlong)c; + info.arg[1] = (uvlong)nc; + info.arg[2] = (uvlong)names; + info.arg[3] = (uvlong)nname; + dtptrigger(ledger[c->type].in[Dwalk], &info); + + wq = ledger[c->type].clean.walk(c, nc, names, nname); + + memset(&info, 0, sizeof info); + info.arg[9] = (uvlong)wq; + dtptrigger(ledger[c->type].out[Dwalk], &info); + return wq; +} + +static int +wrapstat(Chan *c, uchar *b, int n) +{ + DTTrigInfo info; + + memset(&info, 0, sizeof info); + info.arg[0] = (uvlong)c; + info.arg[1] = (uvlong)b; + info.arg[2] = (uvlong)n; + dtptrigger(ledger[c->type].in[Dstat], &info); + + n = ledger[c->type].clean.stat(c, b, n); + + memset(&info, 0, sizeof info); + info.arg[9] = (uvlong)n; + dtptrigger(ledger[c->type].out[Dstat], &info); + return n; +} + +static Chan* +wrapopen(Chan *c, int mode) +{ + DTTrigInfo info; + + memset(&info, 0, sizeof info); + info.arg[0] = (uvlong)c; + info.arg[1] = (uvlong)mode; + dtptrigger(ledger[c->type].in[Dopen], &info); + + c = ledger[c->type].clean.open(c, mode); + + memset(&info, 0, sizeof info); + info.arg[9] = (uvlong)c; + dtptrigger(ledger[c->type].out[Dopen], &info); + return c; +} + +static Chan* +wrapcreate(Chan *c, char *name, int mode, ulong perm) +{ + DTTrigInfo info; + + memset(&info, 0, sizeof info); + info.arg[0] = (uvlong)c; + info.arg[1] = (uvlong)name; + info.arg[2] = (uvlong)mode; + info.arg[3] = (uvlong)perm; + dtptrigger(ledger[c->type].in[Dcreate], &info); + + c = ledger[c->type].clean.create(c, name, mode, perm); + + memset(&info, 0, sizeof info); + info.arg[9] = (uvlong)c; + dtptrigger(ledger[c->type].out[Dcreate], &info); + return c; +} + +static void +wrapclose(Chan *c) +{ + DTTrigInfo info; + + memset(&info, 0, sizeof info); + info.arg[0] = (uvlong)c; + dtptrigger(ledger[c->type].in[Dclose], &info); + + ledger[c->type].clean.close(c); + + memset(&info, 0, sizeof info); + dtptrigger(ledger[c->type].out[Dclose], &info); +} + +static long +wrapread(Chan *c, void *b, long n, vlong off) +{ + DTTrigInfo info; + + memset(&info, 0, sizeof info); + info.arg[0] = (uvlong)c; + info.arg[1] = (uvlong)b; + info.arg[2] = (uvlong)n; + info.arg[3] = (uvlong)off; + dtptrigger(ledger[c->type].in[Dread], &info); + + n = ledger[c->type].clean.read(c, b, n, off); + + memset(&info, 0, sizeof info); + info.arg[9] = (uvlong)n; + dtptrigger(ledger[c->type].out[Dread], &info); + return n; +} + +static Block* +wrapbread(Chan *c, long n, ulong off) +{ + Block *b; + DTTrigInfo info; + + memset(&info, 0, sizeof info); + info.arg[0] = (uvlong)c; + info.arg[1] = (uvlong)n; + info.arg[2] = (uvlong)off; + dtptrigger(ledger[c->type].in[Dbread], &info); + + b = ledger[c->type].clean.bread(c, n, off); + + memset(&info, 0, sizeof info); + info.arg[9] = (uvlong)b; + dtptrigger(ledger[c->type].out[Dbread], &info); + return b; +} + +static long +wrapwrite(Chan *c, void *b, long n, vlong off) +{ + DTTrigInfo info; + + memset(&info, 0, sizeof info); + info.arg[0] = (uvlong)c; + info.arg[1] = (uvlong)b; + info.arg[2] = (uvlong)n; + info.arg[3] = (uvlong)off; + dtptrigger(ledger[c->type].in[Dwrite], &info); + + n = ledger[c->type].clean.write(c, b, n, off); + + memset(&info, 0, sizeof info); + info.arg[9] = (uvlong)n; + dtptrigger(ledger[c->type].out[Dwrite], &info); + return n; +} + +static long +wrapbwrite(Chan *c, Block *b, ulong off) +{ + long n; + DTTrigInfo info; + + memset(&info, 0, sizeof info); + info.arg[0] = (uvlong)c; + info.arg[1] = (uvlong)b; + info.arg[2] = (uvlong)off; + dtptrigger(ledger[c->type].in[Dbwrite], &info); + + n = ledger[c->type].clean.bwrite(c, b, off); + + memset(&info, 0, sizeof info); + info.arg[9] = (uvlong)n; + dtptrigger(ledger[c->type].out[Dbwrite], &info); + return n; +} + +void +wrapremove(Chan *c) +{ + DTTrigInfo info; + + memset(&info, 0, sizeof info); + info.arg[0] = (uvlong)c; + dtptrigger(ledger[c->type].in[Dremove], &info); + + ledger[c->type].clean.remove(c); + + memset(&info, 0, sizeof info); + dtptrigger(ledger[c->type].out[Dremove], &info); +} + +int +wrapwstat(Chan *c, uchar *b, int n) +{ + DTTrigInfo info; + + memset(&info, 0, sizeof info); + info.arg[0] = (uvlong)c; + info.arg[1] = (uvlong)b; + info.arg[2] = (uvlong)n; + dtptrigger(ledger[c->type].in[Dwstat], &info); + + n = ledger[c->type].clean.wstat(c, b, n); + + memset(&info, 0, sizeof info); + info.arg[9] = (uvlong)n; + dtptrigger(ledger[c->type].out[Dwstat], &info); + return n; +} + +static void +devprovide(DTProvider *prov) +{ + uint i, j; + uint path; + char pname[32]; + char buf[32]; + + for(i = 0; devtab[i] != nil; i++){ + memmove(&ledger[i].clean, devtab[i], sizeof(Dev)); + for(j = 0; j < Dend; j++){ + path = (i<<16) | j; + snprint(buf, sizeof buf, "dev:%s:%s", devtab[i]->name, optab[j]); + snprint(pname, sizeof pname, "%s:entry", buf); + ledger[i].in[j] = dtpnew(pname, prov, (void *) path); + snprint(pname, sizeof pname, "%s:return", buf); + ledger[i].out[j] = dtpnew(pname, prov, (void *) path); + } + } +} + +static int +devenable(DTProbe *p) +{ + uint i, j; + uint path; + Dev *d; + + path = (uint)(uintptr)p->aux; + i = path>>16; + j = path & ((1<<16)-1); + assert(i < 256); + assert(j < Dend); + + d = devtab[i]; + switch(j){ + case Dwalk: + d->walk = wrapwalk; + break; + case Dstat: + d->stat = wrapstat; + break; + case Dopen: + d->open = wrapopen; + break; + case Dcreate: + d->create = wrapcreate; + break; + case Dclose: + d->close = wrapclose; + break; + case Dread: + d->read = wrapread; + break; + case Dbread: + d->bread = wrapbread; + break; + case Dwrite: + d->write = wrapwrite; + break; + case Dbwrite: + d->bwrite = wrapbwrite; + break; + case Dremove: + d->remove = wrapremove; + break; + case Dwstat: + d->wstat = wrapwstat; + break; + } + return 0; +} + +static void +devdisable(DTProbe *p) +{ + uint i, j; + uint path; + Dev *d, *clean; + + path = (uint)(uintptr)p->aux; + i = path>>16; + j = path & ((1<<16)-1); + assert(i < 256); + assert(j < Dend); + + d = devtab[i]; + clean = &ledger[i].clean; + switch(j){ + case Dwalk: + d->walk = clean->walk; + break; + case Dstat: + d->stat = clean->stat; + break; + case Dopen: + d->open = clean->open; + break; + case Dcreate: + d->create = clean->create; + break; + case Dclose: + d->close = clean->close; + break; + case Dread: + d->read = clean->read; + break; + case Dbread: + d->bread = clean->bread; + break; + case Dwrite: + d->write = clean->write; + break; + case Dbwrite: + d->bwrite = clean->bwrite; + break; + case Dremove: + d->remove = clean->remove; + break; + case Dwstat: + d->wstat = clean->wstat; + break; + } +} + +DTProvider dtracydevprov = { + .name = "dev", + .provide = devprovide, + .enable = devenable, + .disable = devdisable, +}; diff --git a/sys/src/9/port/ethermii.c b/sys/src/9/port/ethermii.c index d75c35072..dcb3915e2 100644 --- a/sys/src/9/port/ethermii.c +++ b/sys/src/9/port/ethermii.c @@ -87,6 +87,8 @@ miireset(Mii* mii) if(mii == nil || mii->ctlr == nil || mii->curphy == nil) return -1; bmcr = mii->mir(mii, mii->curphy->phyno, Bmcr); + if(bmcr == -1) + return -1; bmcr |= BmcrR; mii->miw(mii, mii->curphy->phyno, Bmcr, bmcr); microdelay(1); @@ -104,6 +106,8 @@ miiane(Mii* mii, int a, int p, int e) phyno = mii->curphy->phyno; bmsr = mii->mir(mii, phyno, Bmsr); + if(bmsr == -1) + return -1; if(!(bmsr & BmsrAna)) return -1; @@ -113,6 +117,8 @@ miiane(Mii* mii, int a, int p, int e) anar = mii->curphy->anar; else{ anar = mii->mir(mii, phyno, Anar); + if(anar == -1) + return -1; anar &= ~(AnaAP|AnaP|AnaT4|AnaTXFD|AnaTXHD|Ana10FD|Ana10HD); if(bmsr & Bmsr10THD) anar |= Ana10HD; @@ -133,6 +139,8 @@ miiane(Mii* mii, int a, int p, int e) if(bmsr & BmsrEs){ mscr = mii->mir(mii, phyno, Mscr); + if(mscr == -1) + return -1; mscr &= ~(Mscr1000TFD|Mscr1000THD); if(e != ~0) mscr |= (Mscr1000TFD|Mscr1000THD) & e; @@ -140,6 +148,8 @@ miiane(Mii* mii, int a, int p, int e) mscr = mii->curphy->mscr; else{ r = mii->mir(mii, phyno, Esr); + if(r == -1) + return -1; if(r & Esr1000THD) mscr |= Mscr1000THD; if(r & Esr1000TFD) @@ -148,9 +158,12 @@ miiane(Mii* mii, int a, int p, int e) mii->curphy->mscr = mscr; mii->miw(mii, phyno, Mscr, mscr); } - mii->miw(mii, phyno, Anar, anar); + if(mii->miw(mii, phyno, Anar, anar) == -1) + return -1; r = mii->mir(mii, phyno, Bmcr); + if(r == -1) + return -1; if(!(r & BmcrR)){ r |= BmcrAne|BmcrRan; mii->miw(mii, phyno, Bmcr, r); @@ -175,12 +188,16 @@ miistatus(Mii* mii) * (Read status twice as the Ls bit is sticky). */ bmsr = mii->mir(mii, phyno, Bmsr); + if(bmsr == -1) + return -1; if(!(bmsr & (BmsrAnc|BmsrAna))) { // print("miistatus: auto-neg incomplete\n"); return -1; } bmsr = mii->mir(mii, phyno, Bmsr); + if(bmsr == -1) + return -1; if(!(bmsr & BmsrLs)){ // print("miistatus: link down\n"); phy->link = 0; @@ -190,6 +207,8 @@ miistatus(Mii* mii) phy->speed = phy->fd = phy->rfc = phy->tfc = 0; if(phy->mscr){ r = mii->mir(mii, phyno, Mssr); + if(r == -1) + return -1; if((phy->mscr & Mscr1000TFD) && (r & Mssr1000TFD)){ phy->speed = 1000; phy->fd = 1; @@ -199,6 +218,8 @@ miistatus(Mii* mii) } anlpar = mii->mir(mii, phyno, Anlpar); + if(anlpar == -1) + return -1; if(phy->speed == 0){ r = phy->anar & anlpar; if(r & AnaTXFD){ diff --git a/sys/src/9/port/i2c.h b/sys/src/9/port/i2c.h new file mode 100644 index 000000000..eebff9569 --- /dev/null +++ b/sys/src/9/port/i2c.h @@ -0,0 +1,56 @@ +typedef struct I2Cbus I2Cbus; +struct I2Cbus +{ + char *name; + int speed; + + void *ctlr; + int (*init)(I2Cbus *bus); + int (*io)(I2Cbus *bus, uchar *pkt, int olen, int ilen); + + int probed; + QLock; +}; + +typedef struct I2Cdev I2Cdev; +struct I2Cdev +{ + I2Cbus *bus; + + int a10; + int addr; + int subaddr; + ulong size; +}; + +/* + * Register busses (controllers) and devices (addresses) + */ +extern void addi2cbus(I2Cbus *bus); +extern void addi2cdev(I2Cdev *dev); + +/* + * Look-up busses and devices by name and address + */ +extern I2Cbus* i2cbus(char *name); +extern I2Cdev* i2cdev(I2Cbus *bus, int addr); + +/* + * generic I/O + */ +extern int i2cbusio(I2Cbus *bus, uchar *pkt, int olen, int ilen); +extern int i2crecv(I2Cdev *dev, void *data, int len, vlong addr); +extern int i2csend(I2Cdev *dev, void *data, int len, vlong addr); + +/* + * common I/O for SMbus + */ +extern int i2cquick(I2Cdev *dev, int rw); +extern int i2crecvbyte(I2Cdev *dev); +extern int i2csendbyte(I2Cdev *dev, uchar b); +extern int i2creadbyte(I2Cdev *dev, ulong addr); +extern int i2cwritebyte(I2Cdev *dev, ulong addr, uchar b); +extern int i2creadword(I2Cdev *dev, ulong addr); +extern int i2cwriteword(I2Cdev *dev, ulong addr, ushort w); +extern vlong i2cread32(I2Cdev *dev, ulong addr); +extern vlong i2cwrite32(I2Cdev *dev, ulong addr, ulong u); diff --git a/sys/src/9/port/portmkfile b/sys/src/9/port/portmkfile index 119147e8e..aae30db94 100644 --- a/sys/src/9/port/portmkfile +++ b/sys/src/9/port/portmkfile @@ -88,7 +88,7 @@ devpipe.$O: ../port/netif.h netif.$O: ../port/netif.h devuart.$O: ../port/netif.h devbridge.$O: ../port/netif.h ../ip/ip.h ../ip/ipv6.h -devdtracy.$O dtracysys.$O dtracytimer.$O: /sys/include/dtracy.h +devdtracy.$O dtracysys.$O dtracytimer.$O dtracydev.$O: /sys/include/dtracy.h devdraw.$O: screen.h /sys/include/draw.h /sys/include/memdraw.h /sys/include/memlayer.h /sys/include/cursor.h devmouse.$O: screen.h /sys/include/draw.h /sys/include/memdraw.h /sys/include/cursor.h swcursor.$O: screen.h /sys/include/draw.h /sys/include/memdraw.h /sys/include/cursor.h diff --git a/sys/src/9/port/sd.h b/sys/src/9/port/sd.h index e4c567a17..0ef5dab33 100644 --- a/sys/src/9/port/sd.h +++ b/sys/src/9/port/sd.h @@ -162,6 +162,7 @@ struct SDio { void (*iosetup)(int, void*, int, int); void (*io)(int, uchar*, int); char highspeed; + char nomultiwrite; /* quirk for usdhc */ }; extern SDio sdio; diff --git a/sys/src/9/port/sdmmc.c b/sys/src/9/port/sdmmc.c index 34dbd046e..d7bd02d97 100644 --- a/sys/src/9/port/sdmmc.c +++ b/sys/src/9/port/sdmmc.c @@ -332,7 +332,7 @@ mmcbio(SDunit *unit, int lun, int write, void *data, long nb, uvlong bno) error(Echange); buf = data; len = unit->secsize; - if(Multiblock){ + if(Multiblock && (!write || !io->nomultiwrite)){ b = bno; tries = 0; while(waserror()) diff --git a/sys/src/boot/reform/boot.txt b/sys/src/boot/reform/boot.txt new file mode 100644 index 000000000..738fd305d --- /dev/null +++ b/sys/src/boot/reform/boot.txt @@ -0,0 +1,2 @@ +load ${devtype} ${devnum}:${bootpart} ${kernel_addr_r} ${prefix}9reform.u +bootm ${kernel_addr_r} diff --git a/sys/src/boot/reform/mkfile b/sys/src/boot/reform/mkfile new file mode 100644 index 000000000..52cd5058e --- /dev/null +++ b/sys/src/boot/reform/mkfile @@ -0,0 +1,12 @@ +FILES=flash.bin boot.scr + +all:V: $FILES + +clean:V: + rm -f $FILES + +flash.bin: + hget -o flash.bin 'https://source.mnt.re/reform/reform-boundary-uboot/-/jobs/artifacts/v3/raw/flash.bin?job=build' + +boot.scr: boot.txt + aux/txt2uimage -o $target $prereq diff --git a/sys/src/cmd/auth/box.c b/sys/src/cmd/auth/box.c new file mode 100644 index 000000000..4f01e43de --- /dev/null +++ b/sys/src/cmd/auth/box.c @@ -0,0 +1,214 @@ +#include +#include +#include + +static int debug; + +static void +binderr(char *new, char *old, int flag) +{ + char dash[4] = { '-' }; + + if(debug){ + if(flag & MCREATE){ + dash[2] = 'c'; + flag &= ~MCREATE; + } + switch(flag){ + case MREPL: + dash[0] = ' '; + if(dash[2] == 'c') + dash[1] = '-'; + else + dash[1] = ' '; + break; + case MBEFORE: + dash[1] = 'b'; + break; + case MAFTER: + dash[1] = 'a'; + break; + } + fprint(2, "bind %s %s %s\n", dash, new, old); + } + if(bind(new, old, flag) < 0) + sysfatal("bind: %r"); +} + +static void +resolvenames(char **names, int nname) +{ + int i; + char buf[8192]; + int fd; + + fd = open(".", OREAD|OCEXEC); + if(fd < 0) + sysfatal("could not open .: %r"); + fd2path(fd, buf, sizeof buf); + for(i = 0; i < nname; i++){ + if(names[i] == nil) + continue; + cleanname(names[i]); + switch(names[i][0]){ + case '#': + case '/': + break; + default: + names[i] = cleanname(smprint("%s/%s", buf, names[i])); + } + } + close(fd); +} + +static void +sandbox(char **names, int *flags, int nname) +{ + char *parts[32]; + char rootskel[128]; + char src[8192], targ[8192], dir[8192], skel[8192]; + char name[8192]; + char *newroot; + Dir *d; + int i, j, n; + + snprint(rootskel, sizeof rootskel, "/mnt/d/newroot.%d", getpid()); + binderr(rootskel, "/", MBEFORE); + + newroot = rootskel + strlen("/mnt/d"); + + for(j = 0; j < nname; j++){ + if(names[j] == nil) + continue; + utfecpy(name, &name[sizeof name-1], names[j]); + n = gettokens(name, parts, nelem(parts), "/"); + utfecpy(targ, &targ[sizeof targ-1], newroot); + memset(src, 0, sizeof src); + for(i = 0; i < n; i++){ + utfecpy(dir, &dir[sizeof dir-1], targ); + snprint(targ, sizeof targ, "%s/%s", targ, parts[i]); + snprint(src, sizeof src, "%s/%s", src, parts[i]); + d = dirstat(targ); + if(d != nil){ + free(d); + continue; + } + d = dirstat(src); + if(d == nil) + continue; + if(d->mode & DMDIR) + snprint(skel, sizeof skel, "/mnt/d/%s", parts[i]); + else + snprint(skel, sizeof skel, "/mnt/f/%s", parts[i]); + free(d); + binderr(skel, dir, MBEFORE); + } + binderr(names[j], targ, flags[j]); + } + binderr(newroot, "/", MREPL); +} + +void +skelfs(void) +{ + int p[2]; + int dfd; + + pipe(p); + switch(rfork(RFFDG|RFREND|RFPROC|RFNAMEG)){ + case -1: + sysfatal("fork"); + case 0: + close(p[1]); + dup(p[0], 0); + dup(p[0], 1); + execl("/bin/skelfs", "skelfs", debug > 1 ? "-Di" : "-i", nil); + sysfatal("exec /bin/skelfs: %r"); + } + close(p[0]); + dfd = dup(p[1], -1); + if(mount(p[1], -1, "/mnt/f", MREPL, "file") < 0) + sysfatal("/mnt/f mount setup: %r"); + if(mount(dfd, -1, "/mnt/d", MREPL, "dir") < 0) + sysfatal("/mnt/d mount setup: %r"); +} + +void +usage(void) +{ + fprint(2, "usage %s: [ -d ] [ -r file ] [ -c dir ] [ -e devs ] cmd args...\n", argv0); + exits("usage"); +} + +void +main(int argc, char **argv) +{ + char *b; + Dir *d; + char devs[1024]; + int dfd; + char *parts[256]; + int mflags[256]; + int nparts; + + nparts = 0; + memset(devs, 0, sizeof devs); + ARGBEGIN{ + case 'D': + debug++; + case 'd': + debug++; + break; + case 'r': + parts[nparts] = EARGF(usage()); + mflags[nparts++] = MREPL; + break; + case 'c': + parts[nparts] = EARGF(usage()); + mflags[nparts++] = MCREATE|MREPL; + break; + case 'e': + snprint(devs, sizeof devs, "%s%s", devs, EARGF(usage())); + break; + default: + usage(); + break; + }ARGEND + if(argc == 0) + usage(); + + b = argv[0]; + d = dirstat(b); + if(d == nil){ + b = smprint("/bin/%s", b); + d = dirstat(b); + if(d == nil) + sysfatal("could not stat %s %r", argv[0]); + } + free(d); + parts[nparts] = b; + mflags[nparts++] = MREPL; + argv[0] = b; + + rfork(RFNAMEG|RFFDG); + skelfs(); + dfd = open("/dev/drivers", OWRITE|OCEXEC); + if(dfd < 0) + sysfatal("could not /dev/drivers: %r"); + + resolvenames(parts, nparts); + sandbox(parts, mflags, nparts); + + if(debug) + fprint(2, "chdev %s\n", devs); + + if(devs[0] != '\0'){ + if(fprint(dfd, "chdev & %s", devs) <= 0) + sysfatal("could not write chdev: %r"); + } else { + if(fprint(dfd, "chdev ~") <= 0) + sysfatal("could not write chdev: %r"); + } + close(dfd); + exec(argv[0], argv); +} diff --git a/sys/src/cmd/auth/mkfile b/sys/src/cmd/auth/mkfile index f8f6ec829..1dbc46941 100644 --- a/sys/src/cmd/auth/mkfile +++ b/sys/src/cmd/auth/mkfile @@ -9,6 +9,7 @@ TARG=\ asn1dump\ asn12rsa\ authsrv\ + box\ changeuser\ convkeys\ cron\ diff --git a/sys/src/cmd/aux/mkfile b/sys/src/cmd/aux/mkfile index f38fda5d7..1ef302c45 100644 --- a/sys/src/cmd/aux/mkfile +++ b/sys/src/cmd/aux/mkfile @@ -43,6 +43,7 @@ TARG=\ tablet\ timesync\ trampoline\ + txt2uimage\ unbflz\ usage\ write\ diff --git a/sys/src/cmd/aux/txt2uimage.c b/sys/src/cmd/aux/txt2uimage.c new file mode 100644 index 000000000..5fec8c7c9 --- /dev/null +++ b/sys/src/cmd/aux/txt2uimage.c @@ -0,0 +1,108 @@ +#include +#include +#include + +int infd, outfd; +ulong dcrc; +ulong *tab; +uchar buf[65536]; + +enum { + IH_TYPE_SCRIPT = 6, +}; + +void +put(uchar *p, u32int v) +{ + *p++ = v >> 24; + *p++ = v >> 16; + *p++ = v >> 8; + *p = v; +} + +void +usage(void) +{ + fprint(2, "usage: %s a.out\n", argv0); + exits("usage"); +} + +void +block(int n) +{ + int rc; + + rc = readn(infd, buf, n); + if(rc < 0) sysfatal("read: %r"); + if(rc < n) sysfatal("input file truncated"); + if(write(outfd, buf, n) < 0) sysfatal("write: %r"); + dcrc = blockcrc(tab, dcrc, buf, n); +} + +void +copy(int n) +{ + int i; + + for(i = sizeof(buf) - 1; i < n; i += sizeof(buf)) + block(sizeof(buf)); + i = n & sizeof(buf) - 1; + if(i > 0) + block(i); +} + +void +main(int argc, char **argv) +{ + uchar header[64]; + char *ofile; + Dir *dir; + + ofile = nil; + ARGBEGIN { + case 'o': ofile = strdup(EARGF(usage())); break; + default: usage(); + } ARGEND; + + if(argc == 0) + infd = 0; + else { + if(argc != 1) usage(); + infd = open(argv[0], OREAD); + if(infd < 0) sysfatal("infd: %r"); + } + dir = dirfstat(infd); + if(dir == nil) sysfatal("stat: %r"); + if(dir->length > 0xFFFFFFFF-8) sysfatal("file too big"); + if(ofile == nil) ofile = smprint("%s.u", dir->name); + outfd = create(ofile, OWRITE|OTRUNC, 0666); + if(outfd < 0) sysfatal("create: %r"); + + tab = mkcrctab(0xEDB88320); + seek(outfd, sizeof(header), 0); + put(buf+0, dir->length); + put(buf+4, 0); + dcrc = blockcrc(tab, 0, buf, 8); + if(write(outfd, buf, 8) != 8) sysfatal("write: %r"); + copy(dir->length); + + memset(header, 0, sizeof(header)); + put(&header[0], 0x27051956); /* magic */ + put(&header[8], time(0)); /* time */ + put(&header[12], 8+dir->length); /* image size */ + put(&header[16], 0); /* load address */ + put(&header[20], 0); /* entry point */ + put(&header[24], dcrc); /* data crc */ + header[28] = 0; + header[29] = 0; + header[30] = IH_TYPE_SCRIPT; + header[31] = 0; /* compressed = no */ + + strncpy((char*)&header[32], dir->name, sizeof(header)-32); + put(&header[4], blockcrc(tab, 0, header, sizeof(header))); + + seek(outfd, 0, 0); + if(write(outfd, header, sizeof(header)) < sizeof(header)) sysfatal("write: %r"); + + exits(nil); +} diff --git a/sys/src/cmd/awk/lib.c b/sys/src/cmd/awk/lib.c index 2c5a60465..5044d3123 100644 --- a/sys/src/cmd/awk/lib.c +++ b/sys/src/cmd/awk/lib.c @@ -54,11 +54,13 @@ static Cell dollar1 = { OCELL, CFLD, nil, "", 0.0, FLD|STR|DONTFREE }; void recinit(unsigned int n) { + assert(n > 0); record = (char *) malloc(n); fields = (char *) malloc(n); fldtab = (Cell **) malloc((nfields+1) * sizeof(Cell *)); if (record == nil || fields == nil || fldtab == nil) FATAL("out of space for $0 and fields"); + record[0] = '\0'; fldtab[0] = (Cell *) malloc(sizeof (Cell)); *fldtab[0] = dollar0; fldtab[0]->sval = record; @@ -108,7 +110,7 @@ int getrec(char **pbuf, int *pbufsize, int isrecord) /* get next input record */ firsttime = 0; initgetrec(); } - dprint( ("RS=<%s>, FS=<%s>, AARGC=%g, FILENAME=%s\n", + dprint( ("RS=<%s>, FS=<%s>, AARGC=%g, FILENAME=%s\n", *RS, *FS, *AARGC, *FILENAME) ); if (isrecord) { donefld = 0; diff --git a/sys/src/cmd/awk/run.c b/sys/src/cmd/awk/run.c index 5e75c9d0a..090410314 100644 --- a/sys/src/cmd/awk/run.c +++ b/sys/src/cmd/awk/run.c @@ -1127,8 +1127,9 @@ Cell *assign(Node **a, int n) /* a[0] = a[1], a[0] += a[1], etc. */ if (x == y && !(x->tval & (FLD|REC))) /* self-assignment: */ goto Free; /* leave alone unless it's a field */ if ((y->tval & (STR|NUM)) == (STR|NUM)) { + yf = getfval(y); setsval(x, getsval(y)); - x->fval = getfval(y); + x->fval = yf; x->tval |= NUM; } else if (isstr(y)) diff --git a/sys/src/cmd/cwfs/9p2.c b/sys/src/cmd/cwfs/9p2.c index a4d129c97..3745fff76 100644 --- a/sys/src/cmd/cwfs/9p2.c +++ b/sys/src/cmd/cwfs/9p2.c @@ -1,7 +1,4 @@ #include "all.h" -#include - -enum { MSIZE = MAXDAT+MAXMSG }; static int mkmode9p1(ulong mode9p2) @@ -155,10 +152,10 @@ version(Chan* chan, Fcall* f, Fcall* r) if(chan->protocol != nil || f->msize < 256) return Eversion; - if(f->msize < MSIZE) + if(f->msize < MAXDAT+IOHDRSZ) r->msize = f->msize; else - r->msize = MSIZE; + r->msize = MAXDAT+IOHDRSZ; /* * Should check the '.' stuff here. @@ -1825,7 +1822,7 @@ serve9p2(Msgbuf* mb) * replies. */ if(convM2S(mb->data, mb->count, &f) != mb->count){ - fprint(2, "didn't like %d byte message\n", mb->count); + fprint(2, "didn't like %ld byte message\n", mb->count); return 0; } type = f.type; @@ -1921,7 +1918,7 @@ serve9p2(Msgbuf* mb) */ if(chan->msize == 0){ r.ename = "Tversion not seen"; - n = convS2M(&r, rmb->data, MAXMSG); + n = convS2M(&r, rmb->data, SMALLBUF); } else { snprint(ename, sizeof(ename), "9p2: convS2M: type %d", type); diff --git a/sys/src/cmd/cwfs/all.h b/sys/src/cmd/cwfs/all.h index 418d15f55..900113fbd 100644 --- a/sys/src/cmd/cwfs/all.h +++ b/sys/src/cmd/cwfs/all.h @@ -1,6 +1,7 @@ #include #include #include +#include #define Tfile Tfilescsi /* avoid name conflict */ #include #undef Tfile diff --git a/sys/src/cmd/cwfs/con.c b/sys/src/cmd/cwfs/con.c index 2b418d8c6..d604f9241 100644 --- a/sys/src/cmd/cwfs/con.c +++ b/sys/src/cmd/cwfs/con.c @@ -711,9 +711,9 @@ cmd_time(int argc, char *argv[]) { int i, len; char *cmd; - Timet t1, t2; + vlong t1, t2; - t1 = time(nil); + t1 = nsec(); len = 0; for(i=1; i /* 9p2 */ int version(Chan*, Fcall*, Fcall*); diff --git a/sys/src/cmd/cwfs/portdat.h b/sys/src/cmd/cwfs/portdat.h index 80af31044..3e025065c 100644 --- a/sys/src/cmd/cwfs/portdat.h +++ b/sys/src/cmd/cwfs/portdat.h @@ -20,18 +20,10 @@ typedef vlong Devsize; /* in bytes */ #define HOWMANY(x, y) (((x)+((y)-1)) / (y)) #define ROUNDUP(x, y) (HOWMANY((x), (y)) * (y)) -#define TK2MS(t) (((ulong)(t)*1000)/HZ) /* ticks to ms - beware rounding */ -#define MS2TK(t) (((ulong)(t)*HZ)/1000) /* ms to ticks - beware rounding */ -#define TK2SEC(t) ((t)/HZ) /* ticks to seconds */ - /* constants that don't affect disk layout */ enum { MAXDAT = 8192, /* max allowable data message */ - MAXMSG = 128, /* max protocol message sans data */ - MB = 1024*1024, - - HZ = 1, /* clock frequency */ }; /* @@ -152,8 +144,8 @@ enum { DIRPERBUF = BUFSIZE / sizeof(Dentry), INDPERBUF = BUFSIZE / sizeof(Off), FEPERBUF = (BUFSIZE-sizeof(Super1)-sizeof(Off)) / sizeof(Off), - SMALLBUF = MAXMSG, - LARGEBUF = MAXMSG+MAXDAT+256, + SMALLBUF = 128, + LARGEBUF = IOHDRSZ+MAXDAT+256, RAGAP = (300*1024)/BUFSIZE, /* readahead parameter */ BKPERBLK = 10, CEPERBK = (BUFSIZE - BKPERBLK*sizeof(Off)) / @@ -459,7 +451,7 @@ enum { struct Msgbuf { ulong magic; - short count; + ulong count; short flags; #define LARGE (1<<0) #define FREE (1<<1) diff --git a/sys/src/cmd/cwfs/srv.c b/sys/src/cmd/cwfs/srv.c index e022b9fbf..d745cdf8e 100644 --- a/sys/src/cmd/cwfs/srv.c +++ b/sys/src/cmd/cwfs/srv.c @@ -1,6 +1,5 @@ #include "all.h" #include "io.h" -#include /* 9p2000 */ #include enum { diff --git a/sys/src/cmd/cwfs/sub.c b/sys/src/cmd/cwfs/sub.c index d8befccb9..6a871b554 100644 --- a/sys/src/cmd/cwfs/sub.c +++ b/sys/src/cmd/cwfs/sub.c @@ -101,8 +101,6 @@ loop: unlock(&flock); } -enum { NOFID = (ulong)~0 }; - /* * returns a locked file structure */ diff --git a/sys/src/cmd/diff/diff.h b/sys/src/cmd/diff/diff.h index 8aca0439f..e1c8263d6 100644 --- a/sys/src/cmd/diff/diff.h +++ b/sys/src/cmd/diff/diff.h @@ -28,6 +28,5 @@ Biobuf *prepare(int, char *, char *); void panic(int, char *, ...); void check(Biobuf *, Biobuf *); void change(int, int, int, int); -void fileheader(void); void flushchanges(void); diff --git a/sys/src/cmd/diff/diffio.c b/sys/src/cmd/diff/diffio.c index b577b6d2a..1d4d4d6bb 100644 --- a/sys/src/cmd/diff/diffio.c +++ b/sys/src/cmd/diff/diffio.c @@ -329,24 +329,16 @@ changeset(int i) return nchanges; } -void -fileheader(void) -{ - if(mode != 'u') - return; - Bprint(&stdout, "--- %s\n", file1); - Bprint(&stdout, "+++ %s\n", file2); -} - void flushchanges(void) { - int a, b, c, d, at; + int a, b, c, d, at, hdr; int i, j; if(nchanges == 0) return; - + + hdr = 0; for(i=0; itype != GCommit) + return; + for(i = 0; i < o->commit->nparent; i++){ + if((p = readobject(o->commit->parent[i])) == nil) + continue; + qput(q, p, 0); + unref(p); + } +} + int fetchpack(Conn *c) { char buf[Pktmax], *sp[3], *ep; - char *packtmp, *idxtmp, **ref; + char *packtmp, *idxtmp, **ref, *caps; Hash h, *have, *want; - int nref, refsz, first; - int i, n, l, req, pfd; + int nref, refsz, first, nsent; + int i, l, n, req, pfd; vlong packsz; Objset hadobj; Object *o; + Objq haveq; + Qelt e; nref = 0; refsz = 16; @@ -234,6 +252,7 @@ fetchpack(Conn *c) if(writephase(c) == -1) sysfatal("write: %r"); req = 0; + caps = " multi_ack"; for(i = 0; i < nref; i++){ if(hasheq(&have[i], &want[i])) continue; @@ -241,30 +260,58 @@ fetchpack(Conn *c) unref(o); continue; } - n = snprint(buf, sizeof(buf), "want %H\n", want[i]); - if(writepkt(c, buf, n) == -1) + if(fmtpkt(c, "want %H%s\n", want[i], caps) == -1) sysfatal("could not send want for %H", want[i]); + caps = ""; req = 1; } flushpkt(c); + + nsent = 0; + qinit(&haveq); osinit(&hadobj); + /* + * We know we have these objects, and we want to make sure that + * they end up at the front of the queue. Send the 'have lines' + * first, and then enqueue their parents for a second round of + * sends. + */ for(i = 0; i < nref; i++){ if(hasheq(&have[i], &Zhash) || oshas(&hadobj, have[i])) continue; if((o = readobject(have[i])) == nil) sysfatal("missing object we should have: %H", have[i]); + if(fmtpkt(c, "have %H", o->hash) == -1) + sysfatal("write: %r"); + enqueueparent(&haveq, o); osadd(&hadobj, o); - unref(o); - n = snprint(buf, sizeof(buf), "have %H\n", have[i]); - if(writepkt(c, buf, n + 1) == -1) - sysfatal("could not send have for %H", have[i]); + unref(o); + } + /* + * While we could short circuit this and check if upstream has + * acked our objects, for the first 256 haves, this is simple + * enough. + * + * Also, doing multiple rounds of reference discovery breaks + * when using smart http. + */ + while(req && qpop(&haveq, &e) && nsent < 256){ + if(oshas(&hadobj, e.o->hash)) + continue; + if((o = readobject(e.o->hash)) == nil) + sysfatal("missing object we should have: %H", have[i]); + if(fmtpkt(c, "have %H", o->hash) == -1) + sysfatal("write: %r"); + enqueueparent(&haveq, o); + osadd(&hadobj, o); + unref(o); + nsent++; } osclear(&hadobj); + qclear(&haveq); if(!req) flushpkt(c); - - n = snprint(buf, sizeof(buf), "done\n"); - if(writepkt(c, buf, n) == -1) + if(fmtpkt(c, "done\n") == -1) sysfatal("write: %r"); if(!req) goto showrefs; @@ -298,9 +345,9 @@ fetchpack(Conn *c) if(strncmp(buf, "PACK", 4) == 0) break; l = strtol(buf, &ep, 16); - if(l == 0 || ep != buf + 4) + if(ep != buf + 4) sysfatal("fetch packfile: junk pktline"); - if(readn(c->rfd, buf, l) != l) + if(readn(c->rfd, buf, l-4) != l-4) sysfatal("fetch packfile: short read"); } if(write(pfd, "PACK", 4) != 4) diff --git a/sys/src/cmd/git/git.h b/sys/src/cmd/git/git.h index 88afcc1d7..c3ba7b7a9 100644 --- a/sys/src/cmd/git/git.h +++ b/sys/src/cmd/git/git.h @@ -313,6 +313,7 @@ Delta* deltify(Object*, Dtab*, int*); /* proto handling */ int readpkt(Conn*, char*, int); int writepkt(Conn*, char*, int); +int fmtpkt(Conn*, char*, ...); int flushpkt(Conn*); void initconn(Conn*, int, int); int gitconnect(Conn *, char *, char *); diff --git a/sys/src/cmd/git/import b/sys/src/cmd/git/import index 7ba7d0e48..0cc450bf8 100755 --- a/sys/src/cmd/git/import +++ b/sys/src/cmd/git/import @@ -78,7 +78,7 @@ fn apply @{ rc -c ' echo applying $msg | sed 1q date=`{seconds $date} - if(! files=`$nl{ape/patch -Ep1 < $diffpath | grep ''^patching file'' | sed ''s/^patching file `(.*)''''/\1/''}) + if(! files=`$nl{patch -p1 < $diffpath}) die ''patch failed'' for(f in $files){ if(test -e $f) diff --git a/sys/src/cmd/git/pack.c b/sys/src/cmd/git/pack.c index 41eac2262..05492e9f9 100644 --- a/sys/src/cmd/git/pack.c +++ b/sys/src/cmd/git/pack.c @@ -884,6 +884,7 @@ parsecommit(Object *o) }else if(strcmp(buf, "gpgsig") == 0){ /* just drop it */ if((t = strstr(p, "-----END PGP SIGNATURE-----")) == nil) + if((t = strstr(p, "-----END SSH SIGNATURE-----")) == nil) sysfatal("malformed gpg signature"); np -= t - p; p = t; diff --git a/sys/src/cmd/git/proto.c b/sys/src/cmd/git/proto.c index ddc2258f3..9af09ec19 100644 --- a/sys/src/cmd/git/proto.c +++ b/sys/src/cmd/git/proto.c @@ -93,6 +93,20 @@ writepkt(Conn *c, char *buf, int nbuf) return 0; } +int +fmtpkt(Conn *c, char *fmt, ...) +{ + char pkt[Pktmax]; + va_list ap; + int n; + + va_start(ap, fmt); + n = vsnprint(pkt, sizeof(pkt), fmt, ap); + n = writepkt(c, pkt, n); + va_end(ap); + return n; +} + int flushpkt(Conn *c) { diff --git a/sys/src/cmd/git/serve.c b/sys/src/cmd/git/serve.c index 895c6f5e0..da7cd56b0 100644 --- a/sys/src/cmd/git/serve.c +++ b/sys/src/cmd/git/serve.c @@ -8,20 +8,6 @@ char *pathpfx = nil; int allowwrite; -int -fmtpkt(Conn *c, char *fmt, ...) -{ - char pkt[Pktmax]; - va_list ap; - int n; - - va_start(ap, fmt); - n = vsnprint(pkt, sizeof(pkt), fmt, ap); - n = writepkt(c, pkt, n); - va_end(ap); - return n; -} - int showrefs(Conn *c) { diff --git a/sys/src/cmd/ip/dhcpd/dhcpd.c b/sys/src/cmd/ip/dhcpd/dhcpd.c index 93b83c8f8..387a3c77a 100644 --- a/sys/src/cmd/ip/dhcpd/dhcpd.c +++ b/sys/src/cmd/ip/dhcpd/dhcpd.c @@ -64,8 +64,6 @@ int mute, mutestat; int minlease = MinLease; int staticlease = StaticLease; -uvlong start; - static int v6opts; /* option magic */ @@ -196,15 +194,6 @@ void termopt(Req*); int validip(uchar*); void vectoropt(Req*, int, uchar*, int); -void -timestamp(char *tag) -{ - uvlong t; - - t = nsec()/1000; - syslog(0, blog, "%s %lludµs", tag, t - start); -} - void usage(void) { @@ -317,7 +306,6 @@ main(int argc, char **argv) n = readlast(r.fd, r.buf, sizeof(r.buf)); if(n < Udphdrsize) fatal("error reading requests: %r"); - start = nsec()/1000; op = optbuf; *op = 0; proto(&r, n); @@ -409,7 +397,6 @@ proto(Req *rp, int n) dhcp(rp); else bootp(rp); - timestamp("done"); } static void @@ -1477,6 +1464,7 @@ addrsopt(Req *rp, int t, uchar **ip, int i) while(i-- > 0){ if (!isv4(*ip)) { op = seprint(op, oe, " skipping %I ", *ip); + ip++; continue; } v6tov4(rp->p, *ip); @@ -1688,6 +1676,9 @@ logdhcp(Req *rp) char *p, *e; int i; + if(!debug) + return; + p = buf; e = buf + sizeof(buf); if(rp->dhcptype > 0 && rp->dhcptype <= Inform) @@ -1717,13 +1708,15 @@ logdhcp(Req *rp) p = seprint(p, e, ")"); USED(p); - syslog(0, blog, "%s", buf); + fprint(2, "%s\n", buf); } void logdhcpout(Req *rp, char *type) { - syslog(0, blog, "%s(%I->%I)id(%s)ci(%V)gi(%V)yi(%V)si(%V) %s", + if(!debug) + return; + fprint(2, "%s(%I->%I)id(%s)ci(%V)gi(%V)yi(%V)si(%V) %s\n", type, rp->up->laddr, rp->up->raddr, rp->id, rp->bp->ciaddr, rp->bp->giaddr, rp->bp->yiaddr, rp->bp->siaddr, optbuf); } diff --git a/sys/src/cmd/ip/ipconfig/dhcp.c b/sys/src/cmd/ip/ipconfig/dhcp.c index 44badcf8a..554a3e1a1 100644 --- a/sys/src/cmd/ip/ipconfig/dhcp.c +++ b/sys/src/cmd/ip/ipconfig/dhcp.c @@ -18,6 +18,7 @@ enum Tulong, Tvec, Tnames, + Tp9addrs, }; typedef struct Option Option; @@ -93,6 +94,7 @@ static Option option[256] = [OBircserver] { "irc", Taddrs }, [OBstserver] { "st", Taddrs }, [OBstdaserver] { "stdar", Taddrs }, +[OBvendorinfo] { "vendorinfo", Tvec }, [ODipaddr] { "ipaddr", Taddr }, [ODlease] { "lease", Tulong }, @@ -109,6 +111,14 @@ static Option option[256] = [ODtftpserver] { "tftp", Tstr }, [ODbootfile] { "bootfile", Tstr }, [ODdnsdomain] { "dnsdomain", Tnames }, + +[OP9authv4] { "p9authv4", Taddrs }, +[OP9fsv4] { "p9fsv4", Taddrs }, +[OP9fs] { "p9fs", Tp9addrs }, +[OP9auth] { "p9auth", Tp9addrs }, +[OP9ipaddr] { "p9ipaddr", Tp9addrs }, +[OP9ipmask] { "p9ipmask", Tp9addrs }, +[OP9ipgw] { "p9ipgw", Tp9addrs }, }; static uchar defrequested[] = { @@ -414,7 +424,7 @@ dhcprecv(void) int i, n, type; ulong lease; char err[ERRMAX]; - uchar buf[8000], vopts[256], taddr[IPaddrlen]; + uchar buf[8000], vopts[256], taddr[IPaddrlen*2]; Bootp *bp; memset(buf, 0, sizeof buf); @@ -544,39 +554,33 @@ dhcprecv(void) /* get plan9-specific options */ n = optgetvec(bp->optdata, OBvendorinfo, vopts, sizeof vopts-1); if(n > 0 && parseoptions(vopts, n) == 0){ - if(validip(conf.fs) && Oflag) - n = 1; - else { - n = optgetp9addrs(vopts, OP9fs, conf.fs, 2); - if (n == 0) - n = optgetaddrs(vopts, OP9fsv4, - conf.fs, 2); + if(!(Oflag && validip(conf.fs))){ + n = optgetp9addrs(vopts, OP9fs, taddr, 2); + if(n < 2) + n += optgetaddrs(vopts, OP9fsv4, taddr + (n * IPaddrlen), 2 - n); + memmove(conf.fs, taddr, n * IPaddrlen); } - for(i = 0; i < n; i++) - DEBUG("fs=%I ", conf.fs + i*IPaddrlen); - - if(validip(conf.auth) && Oflag) - n = 1; - else { - n = optgetp9addrs(vopts, OP9auth, conf.auth, 2); - if (n == 0) - n = optgetaddrs(vopts, OP9authv4, - conf.auth, 2); + if(!(Oflag && validip(conf.auth))){ + n = optgetp9addrs(vopts, OP9auth, taddr, 2); + if(n < 2) + n += optgetaddrs(vopts, OP9authv4, taddr + (n * IPaddrlen), 2 - n); + memmove(conf.auth, taddr, n * IPaddrlen); } - for(i = 0; i < n; i++) - DEBUG("auth=%I ", conf.auth + i*IPaddrlen); + DEBUG("fs=(%I %I) auth=(%I %I)", conf.fs, conf.fs + IPaddrlen, conf.auth , conf.auth + IPaddrlen); - n = optgetp9addrs(vopts, OP9ipaddr, taddr, 1); - if (n > 0) - ipmove(conf.laddr, taddr); - n = optgetp9addrs(vopts, OP9ipmask, taddr, 1); - if (n > 0) - ipmove(conf.mask, taddr); - n = optgetp9addrs(vopts, OP9ipgw, taddr, 1); - if (n > 0) - ipmove(conf.gaddr, taddr); - DEBUG("new ipaddr=%I new ipmask=%M new ipgw=%I", - conf.laddr, conf.mask, conf.gaddr); + if(!(Oflag && validip(conf.laddr))) + if(optgetp9addrs(vopts, OP9ipaddr, taddr, 1)) + ipmove(conf.laddr, taddr); + + if(!(Oflag && validip(conf.mask))) + if(optgetp9addrs(vopts, OP9ipmask, taddr, 1)) + ipmove(conf.mask, taddr); + + if(!(Oflag && validip(conf.gaddr))) + if(optgetp9addrs(vopts, OP9ipgw, taddr, 1)) + ipmove(conf.gaddr, taddr); + + DEBUG("p9 opt ipaddr=%I ipmask=%M ipgw=%I", conf.laddr, conf.mask, conf.gaddr); } conf.lease = lease; conf.state = Sbound; @@ -779,8 +783,8 @@ optgetp9addrs(uchar *ap, int op, uchar *ip, int n) slen = strlen(p) + 1; if (parseip(&ip[i*IPaddrlen], p) == -1) fprint(2, "%s: bad address %s\n", argv0, p); - DEBUG("got plan 9 option %d addr %I (%s)", - op, &ip[i*IPaddrlen], p); + DEBUG("got plan 9 option %s addr %I (%s)", + option[op].name, &ip[i*IPaddrlen], p); p += slen; len -= slen; } diff --git a/sys/src/cmd/nusb/usbd/hub.c b/sys/src/cmd/nusb/usbd/hub.c index 1a484625d..e04a4aedc 100644 --- a/sys/src/cmd/nusb/usbd/hub.c +++ b/sys/src/cmd/nusb/usbd/hub.c @@ -355,6 +355,7 @@ portattach(Hub *h, int p, u32int sts) char *sp; int mp; int nr; + int i; d = h->dev; pp = &h->port[p]; @@ -421,9 +422,13 @@ portattach(Hub *h, int p, u32int sts) nd->isusb3 = h->dev->isusb3; if(usbdebug > 2) devctl(nd, "debug 1"); - if(opendevdata(nd, ORDWR) < 0){ + for(i=0;; i++){ + if(opendevdata(nd, ORDWR) >= 0) + break; fprint(2, "%s: %s: opendevdata: %r\n", argv0, nd->dir); - goto Fail; + if(i >= 4) + goto Fail; + sleep(500); } if(usbcmd(nd, Rh2d|Rstd|Rdev, Rsetaddress, nd->id, 0, nil, 0) < 0){ dprint(2, "%s: %s: port %d: setaddress: %r\n", argv0, d->dir, p); diff --git a/sys/src/cmd/patch.c b/sys/src/cmd/patch.c new file mode 100644 index 000000000..3da0674ff --- /dev/null +++ b/sys/src/cmd/patch.c @@ -0,0 +1,611 @@ +#include +#include +#include +#include + +typedef struct Patch Patch; +typedef struct Hunk Hunk; +typedef struct Fbuf Fbuf; + +struct Patch { + char *name; + Hunk *hunk; + usize nhunk; +}; + +struct Hunk { + int lnum; + + char *oldpath; + int oldln; + int oldcnt; + int oldlen; + int oldsz; + char *old; + + char *newpath; + int newln; + int newcnt; + int newlen; + int newsz; + char *new; +}; + +struct Fbuf { + int *lines; + int nlines; + int lastln; + char *buf; + int len; +}; + +int strip; +int reverse; +void (*addnew)(Hunk*, char*); +void (*addold)(Hunk*, char*); + +char* +readline(Biobuf *f, int *lnum) +{ + char *ln; + + if((ln = Brdstr(f, '\n', 0)) == nil) + return nil; + *lnum += 1; + return ln; +} + +void * +emalloc(ulong n) +{ + void *v; + + v = mallocz(n, 1); + if(v == nil) + sysfatal("malloc: %r"); + setmalloctag(v, getcallerpc(&n)); + return v; +} + +void * +erealloc(void *v, ulong n) +{ + if(n == 0) + n++; + v = realloc(v, n); + if(v == nil) + sysfatal("malloc: %r"); + setmalloctag(v, getcallerpc(&n)); + return v; +} + +int +fileheader(char *s, char *pfx, char **name) +{ + int len, n, nnull; + char *e; + + if((strncmp(s, pfx, strlen(pfx))) != 0) + return -1; + for(s += strlen(pfx); *s; s++) + if(!isspace(*s)) + break; + for(e = s; *e; e++) + if(isspace(*e)) + break; + if(s == e) + return -1; + nnull = strlen("/dev/null"); + if((e - s) != nnull || strncmp(s, "/dev/null", nnull) != 0){ + n = strip; + while(s != e && n > 0){ + while(s != e && *s == '/') + s++; + while(s != e && *s != '/') + s++; + n--; + } + while(*s == '/') + s++; + if(*s == '\0') + sysfatal("too many components stripped"); + } + len = (e - s) + 1; + *name = emalloc(len); + strecpy(*name, *name + len, s); + return 0; +} + +int +hunkheader(Hunk *h, char *s, char *oldpath, char *newpath, int lnum) +{ + char *e; + + memset(h, 0, sizeof(*h)); + h->lnum = lnum; + h->oldpath = strdup(oldpath); + h->newpath = strdup(newpath); + h->oldlen = 0; + h->oldsz = 32; + h->old = emalloc(h->oldsz); + h->newlen = 0; + h->newsz = 32; + h->new = emalloc(h->newsz); + if(strncmp(s, "@@ -", 4) != 0) + return -1; + e = s + 4; + h->oldln = strtol(e, &e, 10); + h->oldcnt = 1; + if(*e == ','){ + e++; + h->oldcnt = strtol(e, &e, 10); + } + while(*e == ' ' || *e == '\t') + e++; + if(*e != '+') + return -1; + e++; + h->newln = strtol(e, &e, 10); + if(e == s) + return -1; + h->newcnt = 1; + if(*e == ','){ + e++; + h->newcnt = strtol(e, &e, 10); + } + if(e == s || *e != ' ') + return -1; + if(strncmp(e, " @@", 3) != 0) + return -1; + /* + * empty files have line number 0: keep that, + * otherwise adjust down. + */ + if(h->oldln > 0) + h->oldln--; + if(h->newln > 0) + h->newln--; + if(h->oldln < 0 || h->newln < 0 || h->oldcnt < 0 || h->newcnt < 0) + sysfatal("malformed hunk %s", s); + return 0; +} + +void +addnewfn(Hunk *h, char *ln) +{ + int n; + + ln++; + n = strlen(ln); + while(h->newlen + n >= h->newsz){ + h->newsz *= 2; + h->new = erealloc(h->new, h->newsz); + } + memcpy(h->new + h->newlen, ln, n); + h->newlen += n; +} + +void +addoldfn(Hunk *h, char *ln) +{ + int n; + + ln++; + n = strlen(ln); + while(h->oldlen + n >= h->oldsz){ + h->oldsz *= 2; + h->old = erealloc(h->old, h->oldsz); + } + memcpy(h->old + h->oldlen, ln, n); + h->oldlen += n; +} + +int +addmiss(Hunk *h, char *ln, int *nold, int *nnew) +{ + if(ln == nil) + return 1; + else if(ln[0] != '-' && ln[0] != '+') + return 0; + if(ln[0] == '-'){ + addold(h, ln); + *nold += 1; + }else{ + addnew(h, ln); + *nnew += 1; + } + return 1; +} + +void +addhunk(Patch *p, Hunk *h) +{ + p->hunk = erealloc(p->hunk, ++p->nhunk*sizeof(Hunk)); + p->hunk[p->nhunk-1] = *h; +} + +int +hunkcmp(void *a, void *b) +{ + int c; + + c = strcmp(((Hunk*)a)->oldpath, ((Hunk*)b)->oldpath); + if(c != 0) + return c; + return ((Hunk*)a)->oldln - ((Hunk*)b)->oldln; +} + +Patch* +parse(Biobuf *f, char *name) +{ + char *ln, *old, *new, **oldp, **newp; + int oldcnt, newcnt, lnum; + Patch *p; + Hunk h; + + ln = nil; + lnum = 0; + p = emalloc(sizeof(Patch)); + if(!reverse){ + oldp = &old; + newp = &new; + }else{ + oldp = &new; + newp = &old; + } +comment: + free(ln); + while((ln = readline(f, &lnum)) != nil){ + if(strncmp(ln, "--- ", 4) == 0) + goto patch; + free(ln); + } + if(p->nhunk == 0) + sysfatal("%s: could not find start of patch", name); + goto out; + +patch: + if(fileheader(ln, "--- ", oldp) == -1) + goto comment; + free(ln); + + if((ln = readline(f, &lnum)) == nil) + goto out; + if(fileheader(ln, "+++ ", newp) == -1) + goto comment; + free(ln); + + if((ln = readline(f, &lnum)) == nil) + goto out; +hunk: + oldcnt = 0; + newcnt = 0; + if(hunkheader(&h, ln, old, new, lnum) == -1) + goto comment; + free(ln); + + while(1){ + if((ln = readline(f, &lnum)) == nil){ + if(oldcnt != h.oldcnt || newcnt != h.newcnt) + sysfatal("%s:%d: malformed hunk", name, lnum); + addhunk(p, &h); + break; + } + switch(ln[0]){ + default: + sysfatal("%s:%d: malformed hunk2", name, lnum); + goto out; + case '-': + addold(&h, ln); + oldcnt++; + break; + case '+': + addnew(&h, ln); + newcnt++; + break; + case ' ': + addold(&h, ln); + addnew(&h, ln); + oldcnt++; + newcnt++; + break; + } + free(ln); + if(oldcnt > h.oldcnt || newcnt > h.newcnt) + sysfatal("%s:%d: malformed hunk", name, lnum); + if(oldcnt < h.oldcnt || newcnt < h.newcnt) + continue; + + addhunk(p, &h); + if((ln = readline(f, &lnum)) == nil) + goto out; + if(strncmp(ln, "--- ", 4) == 0) + goto patch; + if(strncmp(ln, "@@ ", 3) == 0) + goto hunk; + goto comment; + } + +out: + qsort(p->hunk, p->nhunk, sizeof(Hunk), hunkcmp); + free(old); + free(new); + free(ln); + return p; +} + +int +rename(int fd, char *name) +{ + Dir st; + char *p; + + nulldir(&st); + if((p = strrchr(name, '/')) == nil) + st.name = name; + else + st.name = p + 1; + return dirfwstat(fd, &st); +} + +int +mkpath(char *path) +{ + char *p, buf[ERRMAX]; + int f; + + if(*path == '\0') + return 0; + for(p = strchr(path+1, '/'); p != nil; p = strchr(p+1, '/')){ + *p = '\0'; + if(access(path, AEXIST) != 0){ + if((f = create(path, OREAD, DMDIR | 0777)) == -1){ + rerrstr(buf, sizeof(buf)); + if(strstr(buf, "exist") == nil) + return -1; + } + close(f); + } + *p = '/'; + } + return 0; +} + +void +blat(char *old, char *new, char *o, usize len) +{ + char *tmp; + int fd; + + if(strcmp(new, "/dev/null") == 0){ + if(len != 0) + sysfatal("diff modifies removed file"); + if(remove(old) == -1) + sysfatal("removeold %s: %r", old); + return; + } + if(mkpath(new) == -1) + sysfatal("mkpath %s: %r", new); + if((tmp = smprint("%s.tmp%d", new, getpid())) == nil) + sysfatal("smprint: %r"); + if((fd = create(tmp, OWRITE, 0666)) == -1) + sysfatal("open %s: %r", tmp); + if(write(fd, o, len) != len) + sysfatal("write %s: %r", tmp); + if(strcmp(old, new) == 0 && remove(old) == -1) + sysfatal("remove %s: %r", old); + if(rename(fd, new) == -1) + sysfatal("create %s: %r", new); + if(close(fd) == -1) + sysfatal("close %s: %r", tmp); + free(tmp); +} + +int +slurp(Fbuf *f, char *path) +{ + int n, i, fd, sz, len, nlines, linesz; + char *buf; + int *lines; + + if((fd = open(path, OREAD)) == -1) + sysfatal("open %s: %r", path); + sz = 8192; + len = 0; + buf = emalloc(sz); + while(1){ + if(len == sz){ + sz *= 2; + buf = erealloc(buf, sz); + } + n = read(fd, buf + len, sz - len); + if(n == 0) + break; + if(n == -1) + sysfatal("read %s: %r", path); + len += n; + } + + nlines = 0; + linesz = 32; + lines = emalloc(linesz*sizeof(int)); + lines[nlines++] = 0; + for(i = 0; i < len; i++){ + if(buf[i] != '\n') + continue; + if(nlines+1 == linesz){ + linesz *= 2; + lines = erealloc(lines, linesz*sizeof(int)); + } + lines[nlines++] = i+1; + } + f->len = len; + f->buf = buf; + f->lines = lines; + f->nlines = nlines; + f->lastln = -1; + return 0; +} + +char* +search(Fbuf *f, Hunk *h, char *fname) +{ + int ln, len, off, fuzz, nfuzz, scanning; + + scanning = 1; + len = h->oldlen; + nfuzz = (f->nlines < 250) ? f->nlines : 250; + for(fuzz = 0; scanning && fuzz <= nfuzz; fuzz++){ + scanning = 0; + ln = h->oldln - fuzz; + if(ln > f->lastln){ + off = f->lines[ln]; + if(off + len > f->len) + continue; + scanning = 1; + if(memcmp(f->buf + off, h->old, h->oldlen) == 0){ + f->lastln = ln; + return f->buf + off; + } + } + ln = h->oldln + fuzz - 1; + if(ln <= f->nlines){ + off = f->lines[ln]; + if(off + len >= f->len) + continue; + scanning = 1; + if(memcmp(f->buf + off, h->old, h->oldlen) == 0){ + f->lastln = ln; + return f->buf + off; + } + } + } + sysfatal("%s:%d: unable to find hunk offset in %s", fname, h->lnum, h->oldpath); + return nil; +} + +char* +append(char *o, int *sz, char *s, char *e) +{ + int n; + + n = (e - s); + o = erealloc(o, *sz + n); + memcpy(o + *sz, s, n); + *sz += n; + return o; +} + +int +apply(Patch *p, char *fname) +{ + char *o, *s, *e, *curfile; + int i, osz; + Hunk *h; + Fbuf f; + + e = nil; + o = nil; + osz = 0; + curfile = nil; + for(i = 0; i < p->nhunk; i++){ + h = &p->hunk[i]; + if(curfile == nil || strcmp(curfile, h->newpath) != 0){ + if(slurp(&f, h->oldpath) == -1) + sysfatal("slurp %s: %r", h->oldpath); + curfile = h->newpath; + e = f.buf; + } + s = e; + e = search(&f, h, fname); + o = append(o, &osz, s, e); + o = append(o, &osz, h->new, h->new + h->newlen); + e += h->oldlen; + if(i+1 == p->nhunk || strcmp(curfile, p->hunk[i+1].newpath) != 0){ + o = append(o, &osz, e, f.buf + f.len); + blat(h->oldpath, h->newpath, o, osz); + if(strcmp(h->newpath, "/dev/null") == 0) + print("%s\n", h->oldpath); + else + print("%s\n", h->newpath); + osz = 0; + } + } + free(o); + return 0; +} + +void +freepatch(Patch *p) +{ + Hunk *h; + int i; + + for(i = 0; i < p->nhunk; i++){ + h = &p->hunk[i]; + free(h->oldpath); + free(h->newpath); + free(h->old); + free(h->new); + } + free(p->hunk); + free(p->name); + free(p); +} + +void +usage(void) +{ + fprint(2, "usage: %s [-R] [-p nstrip] [patch...]\n", argv0); + exits("usage"); +} + +void +main(int argc, char **argv) +{ + Biobuf *f; + Patch *p; + int i; + + ARGBEGIN{ + case 'p': + strip = atoi(EARGF(usage())); + break; + case 'R': + reverse++; + break; + default: + usage(); + break; + }ARGEND; + + if(reverse){ + addnew = addoldfn; + addold = addnewfn; + }else{ + addnew = addnewfn; + addold = addoldfn; + } + if(argc == 0){ + if((f = Bfdopen(0, OREAD)) == nil) + sysfatal("open stdin: %r"); + if((p = parse(f, "stdin")) == nil) + sysfatal("parse patch: %r"); + if(apply(p, "stdin") == -1) + sysfatal("apply stdin: %r"); + freepatch(p); + Bterm(f); + }else{ + for(i = 0; i < argc; i++){ + if((f = Bopen(argv[i], OREAD)) == nil) + sysfatal("open %s: %r", argv[i]); + if((p = parse(f, argv[i])) == nil) + sysfatal("parse patch: %r"); + if(apply(p, argv[i]) == -1) + sysfatal("apply %s: %r", argv[i]); + freepatch(p); + Bterm(f); + } + } + exits(nil); +} diff --git a/sys/src/cmd/skelfs.c b/sys/src/cmd/skelfs.c new file mode 100644 index 000000000..137e19397 --- /dev/null +++ b/sys/src/cmd/skelfs.c @@ -0,0 +1,251 @@ +#include +#include +#include +#include +#include <9p.h> + +typedef struct Skel Skel; +struct Skel { + char name[64]; + char mode; +}; + +static uvlong sessions; +static char defmode; + +enum{ + Qroot, + Qdir, + Qskel, +}; + +#define qtype(x) (((ulong)x)&0x1f) +#define qsess(x) ((((ulong)x))>>5) +#define mkqid(i,t) ((((ulong)i)<<5)|(t)) + +static int +step(Fid *f, int way, Qid *res, Dir *dp) +{ + Skel *s; + int path; + char *name; + ulong perm; + + s = f->aux; + name = s->name; + perm = 0550|DMDIR; + path = qtype(f->qid.path) + way; + if(!name[0] && way > 0) + return -1; + + if(path < 0) + goto Root; + switch(path){ + Root: + case Qroot: + name = "/"; + /* fallthrough */ + case Qdir: + res->type = QTDIR; + break; + case Qskel: + switch(s->mode){ + case 'd': + res->type = QTDIR; + break; + case 'f': + default: + res->type = QTFILE; + perm = 0; + break; + } + break; + default: + return -1; + } + res->vers = qsess(f->qid.path); + res->path = mkqid(res->vers, path); + if(dp){ + dp->mode = perm; + dp->name = estrdup9p(name); + dp->uid = estrdup9p("sys"); + dp->gid = estrdup9p("sys"); + dp->qid = *res; + dp->length = 0; + } + return 1; +} + +static int +dirgen(int i, Dir *d, void *a) +{ + Fid *f; + Qid q; + + if(i > 0) + return -1; + f = a; + return step(f, 1, &q, d); +} + +static void +fidclunk(Fid *fid) +{ + free(fid->aux); +} + +static char* +fsclone(Fid *old, Fid *new, void*) +{ + Skel *s, *s2; + + s = old->aux; + s2 = emalloc9p(sizeof *s2); + if(s2 == nil) + return "out of memory"; + memset(s2, 0, sizeof *s2); + + s2->mode = s->mode; + utfecpy(s2->name, &s2->name[sizeof s2->name-1], s->name); + new->aux = s2; + return nil; +} + +static char* +fswalk1(Fid *old, char *name, void*) +{ + Skel *s; + + if(strcmp("..", name) == 0){ + step(old, -1, &old->qid, nil); + return nil; + } + + s = old->aux; + if(!s->name[0] && qtype(old->qid.path) == Qroot && s->mode != 'e'){ + utfecpy(s->name, &s->name[sizeof s->name-1], name); + old->qid.vers = sessions++; + old->qid.path = mkqid(old->qid.vers, qtype(old->qid.path)); + } else if(strcmp(name, s->name) != 0) + return "does not exist"; + + if(step(old, 1, &old->qid, nil) < 0) + return "does not exist"; + + return nil; +} + +static void +fswalk(Req *r) +{ + walkandclone(r, fswalk1, fsclone, nil); +} + +static void +fsattach(Req *r) +{ + Skel s; + Fid root; + char *spec; + Qid *q; + + spec = r->ifcall.aname; + if(spec && spec[0] != '\0') + s.mode = spec[0]; + else + s.mode = defmode; + + q = &r->fid->qid; + q->vers = sessions++; + q->path = mkqid(q->vers, Qroot); + q->type = QTDIR; + r->ofcall.qid = *q; + + s.name[0] = '\0'; + root.aux = &s; + respond(r, fsclone(&root, r->fid, nil)); +} + +static void +fsstat(Req *r) +{ + Qid q; + + if(step(r->fid, 0, &q, &r->d) < 0) + respond(r, "does not exist"); + respond(r, nil); +} + +static void +fsread(Req *r) +{ + dirread9p(r, dirgen, r->fid); + respond(r, nil); +} + +static void +fsopen(Req *r) +{ + r->ofcall.mode = r->ifcall.mode; + if(r->ifcall.mode != OREAD) + respond(r, "permission denied"); + else + respond(r, nil); +} + +Srv fs= +{ +.attach= fsattach, +.open= fsopen, +.read= fsread, +.stat= fsstat, +.walk= fswalk, +.destroyfid= fidclunk +}; + +void +usage(void) +{ + fprint(2, "usage: %s [ -Di ] [ -s service ] [ -t mode ] [ mntpt ]\n", argv0); + exits("usage"); +} + +void +main(int argc, char **argv) +{ + char *s, *mode; + int stdio; + + s = nil; + stdio = 0; + defmode = 'f'; + ARGBEGIN{ + case 'D': + chatty9p++; + break; + case 's': + s = EARGF(usage()); + break; + case 'i': + stdio = 1; + break; + case 't': + mode = EARGF(usage()); + defmode = mode[0]; + break; + default: + usage(); + }ARGEND + + if(argc > 1) + usage(); + + if(stdio == 0){ + postmountsrv(&fs, s, argc ? argv[0] : "/mnt/skel", MREPL); + exits(nil); + } + fs.infd = 0; + fs.outfd = 1; + srv(&fs); + exits(nil); +} diff --git a/sys/src/libc/port/runestrchr.c b/sys/src/libc/port/runestrchr.c index af7fc4e88..e4c757dff 100644 --- a/sys/src/libc/port/runestrchr.c +++ b/sys/src/libc/port/runestrchr.c @@ -4,17 +4,14 @@ Rune* runestrchr(Rune *s, Rune c) { - Rune c0 = c; - Rune c1; + Rune r; - if(c == 0) { + if(c == 0) while(*s++) ; - return s-1; - } - - while(c1 = *s++) - if(c1 == c0) - return s-1; - return 0; + else + while((r = *s++) != c) + if(r == 0) + return 0; + return s-1; } diff --git a/sys/src/libc/port/strchr.c b/sys/src/libc/port/strchr.c index 1e9aab597..72a8f1627 100644 --- a/sys/src/libc/port/strchr.c +++ b/sys/src/libc/port/strchr.c @@ -4,17 +4,14 @@ char* strchr(char *s, int c) { - char c0 = c; - char c1; + char r; - if(c == 0) { + if(c == 0) while(*s++) ; - return s-1; - } - - while(c1 = *s++) - if(c1 == c0) - return s-1; - return 0; + else + while((r = *s++) != c) + if(r == 0) + return 0; + return s-1; }