1*4882a593Smuzhiyun.. SPDX-License-Identifier: GPL-2.0 2*4882a593Smuzhiyun 3*4882a593Smuzhiyun======================== 4*4882a593SmuzhiyunSpear PCIe Gadget Driver 5*4882a593Smuzhiyun======================== 6*4882a593Smuzhiyun 7*4882a593SmuzhiyunAuthor 8*4882a593Smuzhiyun====== 9*4882a593SmuzhiyunPratyush Anand (pratyush.anand@gmail.com) 10*4882a593Smuzhiyun 11*4882a593SmuzhiyunLocation 12*4882a593Smuzhiyun======== 13*4882a593Smuzhiyundriver/misc/spear13xx_pcie_gadget.c 14*4882a593Smuzhiyun 15*4882a593SmuzhiyunSupported Chip: 16*4882a593Smuzhiyun=============== 17*4882a593SmuzhiyunSPEAr1300 18*4882a593SmuzhiyunSPEAr1310 19*4882a593Smuzhiyun 20*4882a593SmuzhiyunMenuconfig option: 21*4882a593Smuzhiyun================== 22*4882a593SmuzhiyunDevice Drivers 23*4882a593Smuzhiyun Misc devices 24*4882a593Smuzhiyun PCIe gadget support for SPEAr13XX platform 25*4882a593Smuzhiyun 26*4882a593Smuzhiyunpurpose 27*4882a593Smuzhiyun======= 28*4882a593SmuzhiyunThis driver has several nodes which can be read/written by configfs interface. 29*4882a593SmuzhiyunIts main purpose is to configure selected dual mode PCIe controller as device 30*4882a593Smuzhiyunand then program its various registers to configure it as a particular device 31*4882a593Smuzhiyuntype. This driver can be used to show spear's PCIe device capability. 32*4882a593Smuzhiyun 33*4882a593SmuzhiyunDescription of different nodes: 34*4882a593Smuzhiyun=============================== 35*4882a593Smuzhiyun 36*4882a593Smuzhiyunread behavior of nodes: 37*4882a593Smuzhiyun----------------------- 38*4882a593Smuzhiyun 39*4882a593Smuzhiyun=============== ============================================================== 40*4882a593Smuzhiyunlink gives ltssm status. 41*4882a593Smuzhiyunint_type type of supported interrupt 42*4882a593Smuzhiyunno_of_msi zero if MSI is not enabled by host. A positive value is the 43*4882a593Smuzhiyun number of MSI vector granted. 44*4882a593Smuzhiyunvendor_id returns programmed vendor id (hex) 45*4882a593Smuzhiyundevice_id returns programmed device id(hex) 46*4882a593Smuzhiyunbar0_size: returns size of bar0 in hex. 47*4882a593Smuzhiyunbar0_address returns address of bar0 mapped area in hex. 48*4882a593Smuzhiyunbar0_rw_offset returns offset of bar0 for which bar0_data will return value. 49*4882a593Smuzhiyunbar0_data returns data at bar0_rw_offset. 50*4882a593Smuzhiyun=============== ============================================================== 51*4882a593Smuzhiyun 52*4882a593Smuzhiyunwrite behavior of nodes: 53*4882a593Smuzhiyun------------------------ 54*4882a593Smuzhiyun 55*4882a593Smuzhiyun=============== ================================================================ 56*4882a593Smuzhiyunlink write UP to enable ltsmm DOWN to disable 57*4882a593Smuzhiyunint_type write interrupt type to be configured and (int_type could be 58*4882a593Smuzhiyun INTA, MSI or NO_INT). Select MSI only when you have programmed 59*4882a593Smuzhiyun no_of_msi node. 60*4882a593Smuzhiyunno_of_msi number of MSI vector needed. 61*4882a593Smuzhiyuninta write 1 to assert INTA and 0 to de-assert. 62*4882a593Smuzhiyunsend_msi write MSI vector to be sent. 63*4882a593Smuzhiyunvendor_id write vendor id(hex) to be programmed. 64*4882a593Smuzhiyundevice_id write device id(hex) to be programmed. 65*4882a593Smuzhiyunbar0_size write size of bar0 in hex. default bar0 size is 1000 (hex) 66*4882a593Smuzhiyun bytes. 67*4882a593Smuzhiyunbar0_address write address of bar0 mapped area in hex. (default mapping of 68*4882a593Smuzhiyun bar0 is SYSRAM1(E0800000). Always program bar size before bar 69*4882a593Smuzhiyun address. Kernel might modify bar size and address for alignment, 70*4882a593Smuzhiyun so read back bar size and address after writing to cross check. 71*4882a593Smuzhiyunbar0_rw_offset write offset of bar0 for which bar0_data will write value. 72*4882a593Smuzhiyunbar0_data write data to be written at bar0_rw_offset. 73*4882a593Smuzhiyun=============== ================================================================ 74*4882a593Smuzhiyun 75*4882a593SmuzhiyunNode programming example 76*4882a593Smuzhiyun======================== 77*4882a593Smuzhiyun 78*4882a593SmuzhiyunProgram all PCIe registers in such a way that when this device is connected 79*4882a593Smuzhiyunto the PCIe host, then host sees this device as 1MB RAM. 80*4882a593Smuzhiyun 81*4882a593Smuzhiyun:: 82*4882a593Smuzhiyun 83*4882a593Smuzhiyun #mount -t configfs none /Config 84*4882a593Smuzhiyun 85*4882a593SmuzhiyunFor nth PCIe Device Controller:: 86*4882a593Smuzhiyun 87*4882a593Smuzhiyun # cd /config/pcie_gadget.n/ 88*4882a593Smuzhiyun 89*4882a593SmuzhiyunNow you have all the nodes in this directory. 90*4882a593Smuzhiyunprogram vendor id as 0x104a:: 91*4882a593Smuzhiyun 92*4882a593Smuzhiyun # echo 104A >> vendor_id 93*4882a593Smuzhiyun 94*4882a593Smuzhiyunprogram device id as 0xCD80:: 95*4882a593Smuzhiyun 96*4882a593Smuzhiyun # echo CD80 >> device_id 97*4882a593Smuzhiyun 98*4882a593Smuzhiyunprogram BAR0 size as 1MB:: 99*4882a593Smuzhiyun 100*4882a593Smuzhiyun # echo 100000 >> bar0_size 101*4882a593Smuzhiyun 102*4882a593Smuzhiyuncheck for programmed bar0 size:: 103*4882a593Smuzhiyun 104*4882a593Smuzhiyun # cat bar0_size 105*4882a593Smuzhiyun 106*4882a593SmuzhiyunProgram BAR0 Address as DDR (0x2100000). This is the physical address of 107*4882a593Smuzhiyunmemory, which is to be made visible to PCIe host. Similarly any other peripheral 108*4882a593Smuzhiyuncan also be made visible to PCIe host. E.g., if you program base address of UART 109*4882a593Smuzhiyunas BAR0 address then when this device will be connected to a host, it will be 110*4882a593Smuzhiyunvisible as UART. 111*4882a593Smuzhiyun 112*4882a593Smuzhiyun:: 113*4882a593Smuzhiyun 114*4882a593Smuzhiyun # echo 2100000 >> bar0_address 115*4882a593Smuzhiyun 116*4882a593Smuzhiyunprogram interrupt type : INTA:: 117*4882a593Smuzhiyun 118*4882a593Smuzhiyun # echo INTA >> int_type 119*4882a593Smuzhiyun 120*4882a593Smuzhiyungo for link up now:: 121*4882a593Smuzhiyun 122*4882a593Smuzhiyun # echo UP >> link 123*4882a593Smuzhiyun 124*4882a593SmuzhiyunIt will have to be insured that, once link up is done on gadget, then only host 125*4882a593Smuzhiyunis initialized and start to search PCIe devices on its port. 126*4882a593Smuzhiyun 127*4882a593Smuzhiyun:: 128*4882a593Smuzhiyun 129*4882a593Smuzhiyun /*wait till link is up*/ 130*4882a593Smuzhiyun # cat link 131*4882a593Smuzhiyun 132*4882a593SmuzhiyunWait till it returns UP. 133*4882a593Smuzhiyun 134*4882a593SmuzhiyunTo assert INTA:: 135*4882a593Smuzhiyun 136*4882a593Smuzhiyun # echo 1 >> inta 137*4882a593Smuzhiyun 138*4882a593SmuzhiyunTo de-assert INTA:: 139*4882a593Smuzhiyun 140*4882a593Smuzhiyun # echo 0 >> inta 141*4882a593Smuzhiyun 142*4882a593Smuzhiyunif MSI is to be used as interrupt, program no of msi vector needed (say4):: 143*4882a593Smuzhiyun 144*4882a593Smuzhiyun # echo 4 >> no_of_msi 145*4882a593Smuzhiyun 146*4882a593Smuzhiyunselect MSI as interrupt type:: 147*4882a593Smuzhiyun 148*4882a593Smuzhiyun # echo MSI >> int_type 149*4882a593Smuzhiyun 150*4882a593Smuzhiyungo for link up now:: 151*4882a593Smuzhiyun 152*4882a593Smuzhiyun # echo UP >> link 153*4882a593Smuzhiyun 154*4882a593Smuzhiyunwait till link is up:: 155*4882a593Smuzhiyun 156*4882a593Smuzhiyun # cat link 157*4882a593Smuzhiyun 158*4882a593SmuzhiyunAn application can repetitively read this node till link is found UP. It can 159*4882a593Smuzhiyunsleep between two read. 160*4882a593Smuzhiyun 161*4882a593Smuzhiyunwait till msi is enabled:: 162*4882a593Smuzhiyun 163*4882a593Smuzhiyun # cat no_of_msi 164*4882a593Smuzhiyun 165*4882a593SmuzhiyunShould return 4 (number of requested MSI vector) 166*4882a593Smuzhiyun 167*4882a593Smuzhiyunto send msi vector 2:: 168*4882a593Smuzhiyun 169*4882a593Smuzhiyun # echo 2 >> send_msi 170*4882a593Smuzhiyun # cd - 171