1*2ee67178SXianjun Jiao /* 2*2ee67178SXianjun Jiao * axi lite register access driver 3*2ee67178SXianjun Jiao * Xianjun jiao. [email protected]; [email protected] 4*2ee67178SXianjun Jiao */ 5*2ee67178SXianjun Jiao 6*2ee67178SXianjun Jiao #include <linux/bitops.h> 7*2ee67178SXianjun Jiao #include <linux/dmapool.h> 8*2ee67178SXianjun Jiao #include <linux/dma/xilinx_dma.h> 9*2ee67178SXianjun Jiao #include <linux/init.h> 10*2ee67178SXianjun Jiao #include <linux/interrupt.h> 11*2ee67178SXianjun Jiao #include <linux/io.h> 12*2ee67178SXianjun Jiao #include <linux/iopoll.h> 13*2ee67178SXianjun Jiao #include <linux/module.h> 14*2ee67178SXianjun Jiao #include <linux/of_address.h> 15*2ee67178SXianjun Jiao #include <linux/of_dma.h> 16*2ee67178SXianjun Jiao #include <linux/of_platform.h> 17*2ee67178SXianjun Jiao #include <linux/of_irq.h> 18*2ee67178SXianjun Jiao #include <linux/slab.h> 19*2ee67178SXianjun Jiao #include <linux/clk.h> 20*2ee67178SXianjun Jiao #include <linux/io-64-nonatomic-lo-hi.h> 21*2ee67178SXianjun Jiao #include <linux/delay.h> 22*2ee67178SXianjun Jiao 23*2ee67178SXianjun Jiao #include "../hw_def.h" 24*2ee67178SXianjun Jiao 25*2ee67178SXianjun Jiao static void __iomem *base_addr; // to store driver specific base address needed for mmu to translate virtual address to physical address in our FPGA design 26*2ee67178SXianjun Jiao 27*2ee67178SXianjun Jiao /* IO accessors */ 28*2ee67178SXianjun Jiao static inline u32 reg_read(u32 reg) 29*2ee67178SXianjun Jiao { 30*2ee67178SXianjun Jiao return ioread32(base_addr + reg); 31*2ee67178SXianjun Jiao } 32*2ee67178SXianjun Jiao 33*2ee67178SXianjun Jiao static inline void reg_write(u32 reg, u32 value) 34*2ee67178SXianjun Jiao { 35*2ee67178SXianjun Jiao iowrite32(value, base_addr + reg); 36*2ee67178SXianjun Jiao } 37*2ee67178SXianjun Jiao 38*2ee67178SXianjun Jiao static inline void OPENOFDM_TX_REG_MULTI_RST_write(u32 Data) { 39*2ee67178SXianjun Jiao reg_write(OPENOFDM_TX_REG_MULTI_RST_ADDR, Data); 40*2ee67178SXianjun Jiao } 41*2ee67178SXianjun Jiao 42*2ee67178SXianjun Jiao static inline void OPENOFDM_TX_REG_INIT_PILOT_STATE_write(u32 Data) { 43*2ee67178SXianjun Jiao reg_write(OPENOFDM_TX_REG_INIT_PILOT_STATE_ADDR, Data); 44*2ee67178SXianjun Jiao } 45*2ee67178SXianjun Jiao 46*2ee67178SXianjun Jiao static inline void OPENOFDM_TX_REG_INIT_DATA_STATE_write(u32 Data) { 47*2ee67178SXianjun Jiao reg_write(OPENOFDM_TX_REG_INIT_DATA_STATE_ADDR, Data); 48*2ee67178SXianjun Jiao } 49*2ee67178SXianjun Jiao 50*2ee67178SXianjun Jiao static const struct of_device_id dev_of_ids[] = { 51*2ee67178SXianjun Jiao { .compatible = "sdr,openofdm_tx", }, 52*2ee67178SXianjun Jiao {} 53*2ee67178SXianjun Jiao }; 54*2ee67178SXianjun Jiao MODULE_DEVICE_TABLE(of, dev_of_ids); 55*2ee67178SXianjun Jiao 56*2ee67178SXianjun Jiao static struct openofdm_tx_driver_api openofdm_tx_driver_api_inst; 57*2ee67178SXianjun Jiao static struct openofdm_tx_driver_api *openofdm_tx_api = &openofdm_tx_driver_api_inst; 58*2ee67178SXianjun Jiao EXPORT_SYMBOL(openofdm_tx_api); 59*2ee67178SXianjun Jiao 60*2ee67178SXianjun Jiao static inline u32 hw_init(enum openofdm_tx_mode mode){ 61*2ee67178SXianjun Jiao int err=0; 62*2ee67178SXianjun Jiao 63*2ee67178SXianjun Jiao printk("%s hw_init mode %d\n", openofdm_tx_compatible_str, mode); 64*2ee67178SXianjun Jiao 65*2ee67178SXianjun Jiao switch(mode) 66*2ee67178SXianjun Jiao { 67*2ee67178SXianjun Jiao case OPENOFDM_TX_TEST: 68*2ee67178SXianjun Jiao printk("%s hw_init mode OPENOFDM_TX_TEST\n", openofdm_tx_compatible_str); 69*2ee67178SXianjun Jiao break; 70*2ee67178SXianjun Jiao 71*2ee67178SXianjun Jiao case OPENOFDM_TX_NORMAL: 72*2ee67178SXianjun Jiao printk("%s hw_init mode OPENOFDM_TX_NORMAL\n", openofdm_tx_compatible_str); 73*2ee67178SXianjun Jiao break; 74*2ee67178SXianjun Jiao 75*2ee67178SXianjun Jiao default: 76*2ee67178SXianjun Jiao printk("%s hw_init mode %d is wrong!\n", openofdm_tx_compatible_str, mode); 77*2ee67178SXianjun Jiao err=1; 78*2ee67178SXianjun Jiao } 79*2ee67178SXianjun Jiao 80*2ee67178SXianjun Jiao openofdm_tx_api->OPENOFDM_TX_REG_MULTI_RST_write(0xFFFFFFFF); 81*2ee67178SXianjun Jiao openofdm_tx_api->OPENOFDM_TX_REG_MULTI_RST_write(0xFFFFFFFF); 82*2ee67178SXianjun Jiao openofdm_tx_api->OPENOFDM_TX_REG_MULTI_RST_write(0xFFFFFFFF); 83*2ee67178SXianjun Jiao openofdm_tx_api->OPENOFDM_TX_REG_MULTI_RST_write(0xFFFFFFFF); 84*2ee67178SXianjun Jiao openofdm_tx_api->OPENOFDM_TX_REG_MULTI_RST_write(0xFFFFFFFF); 85*2ee67178SXianjun Jiao openofdm_tx_api->OPENOFDM_TX_REG_MULTI_RST_write(0xFFFFFFFF); 86*2ee67178SXianjun Jiao openofdm_tx_api->OPENOFDM_TX_REG_MULTI_RST_write(0); 87*2ee67178SXianjun Jiao 88*2ee67178SXianjun Jiao openofdm_tx_api->OPENOFDM_TX_REG_INIT_PILOT_STATE_write(0x7E); 89*2ee67178SXianjun Jiao openofdm_tx_api->OPENOFDM_TX_REG_INIT_DATA_STATE_write(0x7F); 90*2ee67178SXianjun Jiao 91*2ee67178SXianjun Jiao printk("%s hw_init err %d\n", openofdm_tx_compatible_str, err); 92*2ee67178SXianjun Jiao return(err); 93*2ee67178SXianjun Jiao } 94*2ee67178SXianjun Jiao 95*2ee67178SXianjun Jiao static int dev_probe(struct platform_device *pdev) 96*2ee67178SXianjun Jiao { 97*2ee67178SXianjun Jiao struct device_node *np = pdev->dev.of_node; 98*2ee67178SXianjun Jiao struct resource *io; 99*2ee67178SXianjun Jiao int err=1; 100*2ee67178SXianjun Jiao 101*2ee67178SXianjun Jiao printk("\n"); 102*2ee67178SXianjun Jiao 103*2ee67178SXianjun Jiao if (np) { 104*2ee67178SXianjun Jiao const struct of_device_id *match; 105*2ee67178SXianjun Jiao 106*2ee67178SXianjun Jiao match = of_match_node(dev_of_ids, np); 107*2ee67178SXianjun Jiao if (match) { 108*2ee67178SXianjun Jiao printk("%s dev_probe match!\n", openofdm_tx_compatible_str); 109*2ee67178SXianjun Jiao err = 0; 110*2ee67178SXianjun Jiao } 111*2ee67178SXianjun Jiao } 112*2ee67178SXianjun Jiao 113*2ee67178SXianjun Jiao if (err) 114*2ee67178SXianjun Jiao return err; 115*2ee67178SXianjun Jiao 116*2ee67178SXianjun Jiao openofdm_tx_api->hw_init=hw_init; 117*2ee67178SXianjun Jiao 118*2ee67178SXianjun Jiao openofdm_tx_api->reg_read=reg_read; 119*2ee67178SXianjun Jiao openofdm_tx_api->reg_write=reg_write; 120*2ee67178SXianjun Jiao 121*2ee67178SXianjun Jiao openofdm_tx_api->OPENOFDM_TX_REG_MULTI_RST_write=OPENOFDM_TX_REG_MULTI_RST_write; 122*2ee67178SXianjun Jiao openofdm_tx_api->OPENOFDM_TX_REG_INIT_PILOT_STATE_write=OPENOFDM_TX_REG_INIT_PILOT_STATE_write; 123*2ee67178SXianjun Jiao openofdm_tx_api->OPENOFDM_TX_REG_INIT_DATA_STATE_write=OPENOFDM_TX_REG_INIT_DATA_STATE_write; 124*2ee67178SXianjun Jiao 125*2ee67178SXianjun Jiao /* Request and map I/O memory */ 126*2ee67178SXianjun Jiao io = platform_get_resource(pdev, IORESOURCE_MEM, 0); 127*2ee67178SXianjun Jiao base_addr = devm_ioremap_resource(&pdev->dev, io); 128*2ee67178SXianjun Jiao if (IS_ERR(base_addr)) 129*2ee67178SXianjun Jiao return PTR_ERR(base_addr); 130*2ee67178SXianjun Jiao 131*2ee67178SXianjun Jiao printk("%s dev_probe io start 0x%08x end 0x%08x name %s flags 0x%08x desc 0x%08x\n", openofdm_tx_compatible_str,io->start,io->end,io->name,(u32)io->flags,(u32)io->desc); 132*2ee67178SXianjun Jiao printk("%s dev_probe base_addr 0x%08x\n", openofdm_tx_compatible_str,(u32)base_addr); 133*2ee67178SXianjun Jiao printk("%s dev_probe openofdm_tx_driver_api_inst 0x%08x\n", openofdm_tx_compatible_str, (u32)&openofdm_tx_driver_api_inst); 134*2ee67178SXianjun Jiao printk("%s dev_probe openofdm_tx_api 0x%08x\n", openofdm_tx_compatible_str, (u32)openofdm_tx_api); 135*2ee67178SXianjun Jiao 136*2ee67178SXianjun Jiao printk("%s dev_probe succeed!\n", openofdm_tx_compatible_str); 137*2ee67178SXianjun Jiao 138*2ee67178SXianjun Jiao err = hw_init(OPENOFDM_TX_NORMAL); 139*2ee67178SXianjun Jiao 140*2ee67178SXianjun Jiao return err; 141*2ee67178SXianjun Jiao } 142*2ee67178SXianjun Jiao 143*2ee67178SXianjun Jiao static int dev_remove(struct platform_device *pdev) 144*2ee67178SXianjun Jiao { 145*2ee67178SXianjun Jiao printk("\n"); 146*2ee67178SXianjun Jiao 147*2ee67178SXianjun Jiao printk("%s dev_remove base_addr 0x%08x\n", openofdm_tx_compatible_str,(u32)base_addr); 148*2ee67178SXianjun Jiao printk("%s dev_remove openofdm_tx_driver_api_inst 0x%08x\n", openofdm_tx_compatible_str, (u32)&openofdm_tx_driver_api_inst); 149*2ee67178SXianjun Jiao printk("%s dev_remove openofdm_tx_api 0x%08x\n", openofdm_tx_compatible_str, (u32)openofdm_tx_api); 150*2ee67178SXianjun Jiao 151*2ee67178SXianjun Jiao printk("%s dev_remove succeed!\n", openofdm_tx_compatible_str); 152*2ee67178SXianjun Jiao return 0; 153*2ee67178SXianjun Jiao } 154*2ee67178SXianjun Jiao 155*2ee67178SXianjun Jiao static struct platform_driver dev_driver = { 156*2ee67178SXianjun Jiao .driver = { 157*2ee67178SXianjun Jiao .name = "sdr,openofdm_tx", 158*2ee67178SXianjun Jiao .owner = THIS_MODULE, 159*2ee67178SXianjun Jiao .of_match_table = dev_of_ids, 160*2ee67178SXianjun Jiao }, 161*2ee67178SXianjun Jiao .probe = dev_probe, 162*2ee67178SXianjun Jiao .remove = dev_remove, 163*2ee67178SXianjun Jiao }; 164*2ee67178SXianjun Jiao 165*2ee67178SXianjun Jiao module_platform_driver(dev_driver); 166*2ee67178SXianjun Jiao 167*2ee67178SXianjun Jiao MODULE_AUTHOR("Xianjun Jiao"); 168*2ee67178SXianjun Jiao MODULE_DESCRIPTION("sdr,openofdm_tx"); 169*2ee67178SXianjun Jiao MODULE_LICENSE("GPL v2"); 170