I've some trouble on dsplink, so I want to write a driver by myself.
I think dsp is considered as a char device in linux,
So I read sprugm7d.pdf 13.2 "DSP Wake up" and write a driver , would you pls tell me what should I do next?
///////////////////////////////// DRV.c ////////////////////////
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");
#include <linux/mm.h>
#include <asm/io.h> //ioremap
#include <linux/fcntl.h> //struct file
#include <linux/fs.h> //regiser_chrdev
static unsigned int major =0;
static char device_name[]="start_dsp";
//System Config Mod0 Registers:
static unsigned int SYSCFG0 = 0x01c14000; // Base Addr
static int SYSCFG0_SIZE = 0x48; //I only use 0x48 bytes
static unsigned int KICK0R = 0x38; //OFFSET
static unsigned int KICK1R = 0x3c;
static unsigned int HOST1CFG = 0x44;
volatile unsigned int* remapped_syscfg0;
//Power and Sleep Controller 0 (PSC0)
static unsigned int PSC0 = 0x01C10000; // Base Addr
static unsigned int PTCMD = 0x120;
static unsigned int PTSTAT = 0x128;
static unsigned int MDSTAT15 = 0x83c;
static unsigned int MDCTL15 = 0xa3c;
static int PSC0_SIZE = 0xa40 ; //
volatile unsigned int* remapped_psc0;
static struct file_operations dsp_fops=
{
};
static int hello_init(void)
{
int retv;
unsigned int temp;
//IO remap
request_mem_region(SYSCFG0,SYSCFG0_SIZE,device_name );
remapped_syscfg0 = (volatile unsigned int*) ioremap (SYSCFG0,SYSCFG0_SIZE);
request_mem_region(PSC0,PSC0_SIZE,device_name );
remapped_psc0 = (volatile unsigned int*) ioremap (PSC0,PSC0_SIZE);
//Register dev
register_chrdev(major,device_name,&dsp_fops);
//1. Write a 83E7 0B13h to the KICK0R register in the SYSCFG module.
writel ( 0x83e70b13, remapped_syscfg0 + KICK0R );
//2. Write a 95A4 F1E0h to the KICK1R register in the SYSCFG module.
writel ( 0x95a4f1e0, remapped_syscfg0 + KICK1R );
//3. Write the truncated DSP boot address vector to the DSP_ISTP_RST_VAL field in the host 1
//configuration register (HOST1CFG) of the SYSCFG module. The least-significant bits of the boot
//address are fixed at 0.
writel ( 0x00700000, remapped_syscfg0 + HOST1CFG );
//4. Write a 3h to the NEXT bit in the DSP local power sleep controller (LPSC) module control register
//(PSC0.MDCTL15) to prepare the DSP module for an enable transition (to enable the clocks and all
//transitioning from the SwRstDisable state to Enable state).
temp = readl ( remapped_psc0 + MDCTL15 );
writel ( temp | 0x3, remapped_psc0 + MDCTL15 );
//5. Write a 1 to the GO[1] bit (DSP subsystem is part of the PD_DSP domain) in the power domain
//transition command register (PSC0.PTCMD) to start the state transition sequence for the DSP module.
temp = readl ( remapped_psc0 + PTCMD );
writel ( temp | 0x2, remapped_psc0 + PTCMD );
//6. Check (poll for 0) the GOSTAT[1] bit in the power domain transition status register (PSC0.PTSTAT) for
//power transition sequence completion. The domain is only safely in the new state after the GOSTAT[1]
//bit is cleared to 0.
while ( 1 )
{
temp = readl ( remapped_psc0 + PTSTAT );
if ( temp & 0x2 == 0 )
break;
}
//7. Wait for the STATE bit field in the DSP LPSC module status register (PSC0.MDSTAT15) to change to
//3h. The module is only safely in the new state after the STATE bit field changes to reflect the new state.
while ( 1 )
{
temp = readl ( remapped_psc0 + MDSTAT15 );
if ( temp & 0x0x1f == 3 )
break;
}
//8. Write a 1 to the LRST bit in PSC0.MDCTL15 to release the DSP local reset controlled by the PSC module.
temp = readl ( remapped_psc0 + MDCTL15 );
writel ( temp | 0x100, remapped_psc0 + MDCTL15 );
printk("<1>Load AD driver success major = %d\n", major );
return 0;
}
static void hello_exit(void)
{
printk(KERN_ALERT "Goodbye, cruel world\n");
}
module_init(hello_init);
module_exit(hello_exit);