📄 init.c
字号:
#include "usblink.h"
/*
* Version Information
*/
#define DRIVER_VERSION "v5.3"
#define DRIVER_AUTHOR "Roman Weissgaerber <weissg@vienna.at>, David Brownell"
#define DRIVER_DESC "USB OHCI Host Controller Driver"
typedef struct _UsblinkOtg
{
U32 driverObject;
U32 ohciIntr;
SctBool ohciDriverInitialized;
SctBool ohciInterruptPending;
void *ohci;
struct pci_dev *pci;
U32 intr;
char *name;
U32 start;
U32 size;
} UsblinkOtg;
static UsblinkOtg otg = {0, 0, SCC_FALSE, SCC_FALSE, 0};
/*
extern int __devinit hc_found_ohci(struct pci_dev *dev, int irq,
void *mem_base, const struct pci_device_id *id);
extern void __devexit ohci_pci_remove(struct pci_dev *dev);
*/
extern int __devinit hc_add_ohci (struct pci_dev *dev, int irq,
void *mem_base, unsigned long flags, const char* name);
struct ohci;
extern void __devexit hc_remove_ohci (struct ohci*);
extern void hc_interrupt (int irq, void * __ohci, struct pt_regs * r);
extern int ohci_pci_suspend (struct pci_dev *dev, u32 state);
extern int ohci_pci_resume (struct pci_dev *dev);
#ifdef OTG_16_BIT_DATA_BUS
//some tricks here, addr + offset is working because addr
//is declared as U8, sigh...
U32 HW_ReadOtg242Register(volatile U8* addr, U32 offset)
{
volatile U16 *Address;
U32 value;
Address = (U16 *)(addr + offset);
value = (U32)(*Address++) & 0xFFFF;
value |= (*Address & 0xFFFF) << 16;
/*
info("read [0x%03x]=0x%08x", offset, value);
*/
return value;
}
void HW_WriteOtg242Register(volatile U8* addr, U32 offset, U32 val)
{
volatile U16 *Address;
//write the lower 16bits of val
Address = (U16 *)(addr + offset);
*Address = val &0xFFFF;
//write the higher 16bits of val
Address++;
*Address = (val>>16) & 0xFFFF;
/*
info("write [0x%03x]=0x%08x", offset, val);
*/
}
U16 HW_ReadOtg242Register16(volatile U8* addr, U32 offset)
{
volatile U16 *Address;
U16 value;
Address = (U16 *)((U32)addr + offset);
value = (U16)((*Address) & 0xFFFF);
return value;
}
void HW_WriteOtg242Register16(volatile U8* addr, U32 offset, U16 val)
{
volatile U16 *Address;
Address = (U16 *)((U32)addr + offset);
*Address = val;
}
#endif
static int __devinit
otg242_probe(U32 addr, U32 intr_no)
{
unsigned long mem_addr, mem_len;
void *mem_base;
int status;
SctBool rc;
struct pci_device_id id;
info("probe: addr=0x%x intr=0x%x", addr, intr_no);
if (otg.driverObject != 0)
{
dbg ("controller already in use");
return -EBUSY;
}
mem_addr = addr;
mem_len = 0x20000;
otg.start = mem_addr;
otg.size = mem_len;
if (!request_mem_region (mem_addr, mem_len, "TD242")) {
dbg ("controller already in use");
return -EBUSY;
}
mem_base = ioremap_nocache (mem_addr, mem_len);
if (!mem_base) {
err("Error mapping OHCI memory");
release_mem_region (mem_addr, mem_len);
return -EFAULT;
}
otg.driverObject = OTG242_Create(mem_base, intr_no, (U32)(&otg));
if (otg.driverObject == 0)
{
err("Failed to create otg242");
release_mem_region (mem_addr, mem_len);
return -EFAULT;
}
rc = OTG242_Initialize(otg.driverObject);
if (rc != SCS_SUCCESS)
{
err("Failed to initialize otg242");
OTG242_Delete(otg.driverObject);
otg.driverObject = 0;
release_mem_region (mem_addr, mem_len);
return -EFAULT;
}
rc = OTG242_Start(otg.driverObject);
if (rc != SCS_SUCCESS)
{
err("Failed to start otg242");
OTG242_Delete(otg.driverObject);
otg.driverObject = 0;
release_mem_region (mem_addr, mem_len);
return -EFAULT;
}
otg.ohciIntr = 0xff;
memset(&id, 0, sizeof(id));
/*
status = hc_found_ohci (otg.pci, otg.ohciIntr,
OTG242_GetOHCIRegisterBase(otg.driverObject), &id);
*/
status = hc_add_ohci (otg.pci, otg.ohciIntr,
OTG242_GetOHCIRegisterBase(otg.driverObject), 0, "otg242");
if (status < 0)
{
err("Failed to start ohci driver");
OTG242_Delete(otg.driverObject);
otg.driverObject = 0;
iounmap (mem_base);
release_mem_region (mem_addr, mem_len);
return -EFAULT;
}
otg.ohci = pci_get_drvdata(otg.pci);
otg.ohciDriverInitialized = SCC_TRUE;
info(" **OTG242** Start successful, baseAddress %p ohci=%p!", mem_base, otg.ohci);
if (otg.ohciInterruptPending == SCC_TRUE)
{
otg.ohciInterruptPending = SCC_FALSE;
TriggerOhciInterrupt((U32)(&otg));
}
return status;
}
/*-------------------------------------------------------------------------*/
/* may be called from interrupt context [interface spec] */
/* may be called without controller present */
/* may be called with controller, bus, and devices active */
static void __devexit
otg242_remove (void)
{
hc_remove_ohci(otg.ohci);
OTG242_Delete(otg.driverObject);
otg.driverObject = 0;
release_mem_region (otg.start, otg.size);
}
void TriggerOhciInterrupt(U32 context)
{
if (otg.ohciDriverInitialized == SCC_FALSE)
{
otg.ohciInterruptPending = SCC_TRUE;
return;
}
hc_interrupt(otg.ohciIntr, otg.ohci, NULL);
}
/*-------------------------------------------------------------------------*/
static int __init otg242_hcd_init (void)
{
int rc;
/*
U32 msc2;
msc2 = MSC2 & 0x0000FFFF;
MSC2 = msc2 | 0x4C690000;
*/
otg.driverObject = 0;
otg.ohciIntr = 0;
otg.ohciDriverInitialized = SCC_FALSE;
otg.ohciInterruptPending = SCC_FALSE;
otg.pci = 0;
GPDR &= ~(GPIO_GPIO(14));
set_GPIO_IRQ_edge(GPIO_GPIO(14), GPIO_RISING_EDGE);
otg.pci = kmalloc(sizeof(struct pci_dev), GFP_KERNEL);
if (0 == otg.pci)
{
dbg("Failed to allocate memory for ochi device");
return -EFAULT;
}
memcpy(otg.pci->slot_name, "NonePCI", 8);
memcpy(otg.pci->name, "otg242", 7);
otg.pci->dma_mask = -1;
rc = otg242_probe(OTG243_MEM_START, OTG243_INT_LVL);
return rc;
}
/*-------------------------------------------------------------------------*/
static void __exit otg242_hcd_cleanup (void)
{
otg242_remove();
kfree(otg.pci);
}
module_init (otg242_hcd_init);
module_exit (otg242_hcd_cleanup);
MODULE_AUTHOR( DRIVER_AUTHOR );
MODULE_DESCRIPTION( DRIVER_DESC );
MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -