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 u32 OPENOFDM_RX_REG_STATE_HISTORY_read(void){ 39*2ee67178SXianjun Jiao return reg_read(OPENOFDM_RX_REG_STATE_HISTORY_ADDR); 40*2ee67178SXianjun Jiao } 41*2ee67178SXianjun Jiao 42*2ee67178SXianjun Jiao static inline void OPENOFDM_RX_REG_MULTI_RST_write(u32 Data) { 43*2ee67178SXianjun Jiao reg_write(OPENOFDM_RX_REG_MULTI_RST_ADDR, Data); 44*2ee67178SXianjun Jiao } 45*2ee67178SXianjun Jiao static inline void OPENOFDM_RX_REG_ENABLE_write(u32 Data) { 46*2ee67178SXianjun Jiao reg_write(OPENOFDM_RX_REG_ENABLE_ADDR, Data); 47*2ee67178SXianjun Jiao } 48*2ee67178SXianjun Jiao static inline void OPENOFDM_RX_REG_POWER_THRES_write(u32 Data) { 49*2ee67178SXianjun Jiao reg_write(OPENOFDM_RX_REG_POWER_THRES_ADDR, Data); 50*2ee67178SXianjun Jiao } 51*2ee67178SXianjun Jiao static inline void OPENOFDM_RX_REG_MIN_PLATEAU_write(u32 Data) { 52*2ee67178SXianjun Jiao reg_write(OPENOFDM_RX_REG_MIN_PLATEAU_ADDR, Data); 53*2ee67178SXianjun Jiao } 54*2ee67178SXianjun Jiao 55*2ee67178SXianjun Jiao static const struct of_device_id dev_of_ids[] = { 56*2ee67178SXianjun Jiao { .compatible = "sdr,openofdm_rx", }, 57*2ee67178SXianjun Jiao {} 58*2ee67178SXianjun Jiao }; 59*2ee67178SXianjun Jiao MODULE_DEVICE_TABLE(of, dev_of_ids); 60*2ee67178SXianjun Jiao 61*2ee67178SXianjun Jiao static struct openofdm_rx_driver_api openofdm_rx_driver_api_inst; 62*2ee67178SXianjun Jiao static struct openofdm_rx_driver_api *openofdm_rx_api = &openofdm_rx_driver_api_inst; 63*2ee67178SXianjun Jiao EXPORT_SYMBOL(openofdm_rx_api); 64*2ee67178SXianjun Jiao 65*2ee67178SXianjun Jiao static inline u32 hw_init(enum openofdm_rx_mode mode){ 66*2ee67178SXianjun Jiao int err=0; 67*2ee67178SXianjun Jiao 68*2ee67178SXianjun Jiao printk("%s hw_init mode %d\n", openofdm_rx_compatible_str, mode); 69*2ee67178SXianjun Jiao 70*2ee67178SXianjun Jiao switch(mode) 71*2ee67178SXianjun Jiao { 72*2ee67178SXianjun Jiao case OPENOFDM_RX_TEST: 73*2ee67178SXianjun Jiao { 74*2ee67178SXianjun Jiao printk("%s hw_init mode OPENOFDM_RX_TEST\n", openofdm_rx_compatible_str); 75*2ee67178SXianjun Jiao break; 76*2ee67178SXianjun Jiao } 77*2ee67178SXianjun Jiao case OPENOFDM_RX_NORMAL: 78*2ee67178SXianjun Jiao { 79*2ee67178SXianjun Jiao printk("%s hw_init mode OPENOFDM_RX_NORMAL\n", openofdm_rx_compatible_str); 80*2ee67178SXianjun Jiao openofdm_rx_api->power_thres = 0; 81*2ee67178SXianjun Jiao openofdm_rx_api->min_plateau = 100; 82*2ee67178SXianjun Jiao break; 83*2ee67178SXianjun Jiao } 84*2ee67178SXianjun Jiao default: 85*2ee67178SXianjun Jiao { 86*2ee67178SXianjun Jiao printk("%s hw_init mode %d is wrong!\n", openofdm_rx_compatible_str, mode); 87*2ee67178SXianjun Jiao err=1; 88*2ee67178SXianjun Jiao } 89*2ee67178SXianjun Jiao } 90*2ee67178SXianjun Jiao printk("%s hw_init input:\npower_thres %d\nmin_plateau %d\n", 91*2ee67178SXianjun Jiao openofdm_rx_compatible_str, 92*2ee67178SXianjun Jiao openofdm_rx_api->power_thres, openofdm_rx_api->min_plateau); 93*2ee67178SXianjun Jiao 94*2ee67178SXianjun Jiao // 1) power threshold configuration and reset 95*2ee67178SXianjun Jiao openofdm_rx_api->OPENOFDM_RX_REG_POWER_THRES_write(0); 96*2ee67178SXianjun Jiao openofdm_rx_api->OPENOFDM_RX_REG_MIN_PLATEAU_write(100); 97*2ee67178SXianjun Jiao 98*2ee67178SXianjun Jiao openofdm_rx_api->OPENOFDM_RX_REG_MULTI_RST_write(0xFFFFFFFF); 99*2ee67178SXianjun Jiao openofdm_rx_api->OPENOFDM_RX_REG_MULTI_RST_write(0xFFFFFFFF); 100*2ee67178SXianjun Jiao openofdm_rx_api->OPENOFDM_RX_REG_MULTI_RST_write(0xFFFFFFFF); 101*2ee67178SXianjun Jiao openofdm_rx_api->OPENOFDM_RX_REG_MULTI_RST_write(0xFFFFFFFF); 102*2ee67178SXianjun Jiao openofdm_rx_api->OPENOFDM_RX_REG_MULTI_RST_write(0xFFFFFFFF); 103*2ee67178SXianjun Jiao openofdm_rx_api->OPENOFDM_RX_REG_MULTI_RST_write(0xFFFFFFFF); 104*2ee67178SXianjun Jiao openofdm_rx_api->OPENOFDM_RX_REG_MULTI_RST_write(0); 105*2ee67178SXianjun Jiao 106*2ee67178SXianjun Jiao printk("%s hw_init err %d\n", openofdm_rx_compatible_str, err); 107*2ee67178SXianjun Jiao 108*2ee67178SXianjun Jiao reg_write(4*4,1);//enable soft decoding 109*2ee67178SXianjun Jiao return(err); 110*2ee67178SXianjun Jiao } 111*2ee67178SXianjun Jiao 112*2ee67178SXianjun Jiao static int dev_probe(struct platform_device *pdev) 113*2ee67178SXianjun Jiao { 114*2ee67178SXianjun Jiao struct device_node *np = pdev->dev.of_node; 115*2ee67178SXianjun Jiao struct resource *io; 116*2ee67178SXianjun Jiao int err=1; 117*2ee67178SXianjun Jiao 118*2ee67178SXianjun Jiao printk("\n"); 119*2ee67178SXianjun Jiao 120*2ee67178SXianjun Jiao if (np) { 121*2ee67178SXianjun Jiao const struct of_device_id *match; 122*2ee67178SXianjun Jiao 123*2ee67178SXianjun Jiao match = of_match_node(dev_of_ids, np); 124*2ee67178SXianjun Jiao if (match) { 125*2ee67178SXianjun Jiao printk("%s dev_probe match!\n", openofdm_rx_compatible_str); 126*2ee67178SXianjun Jiao err = 0; 127*2ee67178SXianjun Jiao } 128*2ee67178SXianjun Jiao } 129*2ee67178SXianjun Jiao 130*2ee67178SXianjun Jiao if (err) 131*2ee67178SXianjun Jiao return err; 132*2ee67178SXianjun Jiao 133*2ee67178SXianjun Jiao openofdm_rx_api->hw_init=hw_init; 134*2ee67178SXianjun Jiao 135*2ee67178SXianjun Jiao openofdm_rx_api->reg_read=reg_read; 136*2ee67178SXianjun Jiao openofdm_rx_api->reg_write=reg_write; 137*2ee67178SXianjun Jiao 138*2ee67178SXianjun Jiao openofdm_rx_api->OPENOFDM_RX_REG_MULTI_RST_write=OPENOFDM_RX_REG_MULTI_RST_write; 139*2ee67178SXianjun Jiao openofdm_rx_api->OPENOFDM_RX_REG_ENABLE_write=OPENOFDM_RX_REG_ENABLE_write; 140*2ee67178SXianjun Jiao openofdm_rx_api->OPENOFDM_RX_REG_POWER_THRES_write=OPENOFDM_RX_REG_POWER_THRES_write; 141*2ee67178SXianjun Jiao openofdm_rx_api->OPENOFDM_RX_REG_MIN_PLATEAU_write=OPENOFDM_RX_REG_MIN_PLATEAU_write; 142*2ee67178SXianjun Jiao 143*2ee67178SXianjun Jiao /* Request and map I/O memory */ 144*2ee67178SXianjun Jiao io = platform_get_resource(pdev, IORESOURCE_MEM, 0); 145*2ee67178SXianjun Jiao base_addr = devm_ioremap_resource(&pdev->dev, io); 146*2ee67178SXianjun Jiao if (IS_ERR(base_addr)) 147*2ee67178SXianjun Jiao return PTR_ERR(base_addr); 148*2ee67178SXianjun Jiao 149*2ee67178SXianjun Jiao printk("%s dev_probe io start 0x%08x end 0x%08x name %s flags 0x%08x desc 0x%08x\n", openofdm_rx_compatible_str,io->start,io->end,io->name,(u32)io->flags,(u32)io->desc); 150*2ee67178SXianjun Jiao printk("%s dev_probe base_addr 0x%08x\n", openofdm_rx_compatible_str,(u32)base_addr); 151*2ee67178SXianjun Jiao printk("%s dev_probe openofdm_rx_driver_api_inst 0x%08x\n", openofdm_rx_compatible_str, (u32)&openofdm_rx_driver_api_inst); 152*2ee67178SXianjun Jiao printk("%s dev_probe openofdm_rx_api 0x%08x\n", openofdm_rx_compatible_str, (u32)openofdm_rx_api); 153*2ee67178SXianjun Jiao 154*2ee67178SXianjun Jiao printk("%s dev_probe succeed!\n", openofdm_rx_compatible_str); 155*2ee67178SXianjun Jiao 156*2ee67178SXianjun Jiao err = hw_init(OPENOFDM_RX_NORMAL); 157*2ee67178SXianjun Jiao 158*2ee67178SXianjun Jiao return err; 159*2ee67178SXianjun Jiao } 160*2ee67178SXianjun Jiao 161*2ee67178SXianjun Jiao static int dev_remove(struct platform_device *pdev) 162*2ee67178SXianjun Jiao { 163*2ee67178SXianjun Jiao printk("\n"); 164*2ee67178SXianjun Jiao 165*2ee67178SXianjun Jiao printk("%s dev_remove base_addr 0x%08x\n", openofdm_rx_compatible_str,(u32)base_addr); 166*2ee67178SXianjun Jiao printk("%s dev_remove openofdm_rx_driver_api_inst 0x%08x\n", openofdm_rx_compatible_str, (u32)&openofdm_rx_driver_api_inst); 167*2ee67178SXianjun Jiao printk("%s dev_remove openofdm_rx_api 0x%08x\n", openofdm_rx_compatible_str, (u32)openofdm_rx_api); 168*2ee67178SXianjun Jiao 169*2ee67178SXianjun Jiao printk("%s dev_remove succeed!\n", openofdm_rx_compatible_str); 170*2ee67178SXianjun Jiao return 0; 171*2ee67178SXianjun Jiao } 172*2ee67178SXianjun Jiao 173*2ee67178SXianjun Jiao static struct platform_driver dev_driver = { 174*2ee67178SXianjun Jiao .driver = { 175*2ee67178SXianjun Jiao .name = "sdr,openofdm_rx", 176*2ee67178SXianjun Jiao .owner = THIS_MODULE, 177*2ee67178SXianjun Jiao .of_match_table = dev_of_ids, 178*2ee67178SXianjun Jiao }, 179*2ee67178SXianjun Jiao .probe = dev_probe, 180*2ee67178SXianjun Jiao .remove = dev_remove, 181*2ee67178SXianjun Jiao }; 182*2ee67178SXianjun Jiao 183*2ee67178SXianjun Jiao module_platform_driver(dev_driver); 184*2ee67178SXianjun Jiao 185*2ee67178SXianjun Jiao MODULE_AUTHOR("Xianjun Jiao"); 186*2ee67178SXianjun Jiao MODULE_DESCRIPTION("sdr,openofdm_rx"); 187*2ee67178SXianjun Jiao MODULE_LICENSE("GPL v2"); 188