📄 usb-ohci-omap1510.c
字号:
/****************************************************************************** linux/drivers/usb/usb-ohci-omap1510.c USB OHCI Support for OMAP1510/1610 Author: MontaVista Software, Inc. <source@mvista.com> Copyright (c) 2003 MontaVista Software, Inc. The outline of this code was taken from Brad Parkers <brad@heeltoe.com> original OHCI driver modifications, and reworked into a cleaner form by Russell King <rmk@arm.linux.org.uk>. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*******************************************************************************/#include <linux/module.h>#include <linux/init.h>#include <linux/sched.h>#include <linux/ioport.h>#include <linux/interrupt.h>#include <linux/slab.h>#include <linux/pci.h> /* for pci_pool_* prototypes */#include <linux/usb.h>#include <asm/hardware.h>#include <asm/irq.h>#include <asm/io.h>#include "usb-ohci.h"#ifdef CONFIG_OMAP_H2#include <linux/i2c.h>#define ISP1301_I2C_ADDR 0x2D#define ISP1301_I2C_MODE_CONTROL_1 0x4#define ISP1301_I2C_MODE_CONTROL_2 0x12#define ISP1301_I2C_OTG_CONTROL_1 0x6#define ISP1301_I2C_OTG_CONTROL_2 0x10#define ISP1301_I2C_INTERRUPT_SOURCE 0x8#define ISP1301_I2C_INTERRUPT_LATCH 0xA#define ISP1301_I2C_INTERRUPT_FALLING 0xC#define ISP1301_I2C_INTERRUPT_RISING 0xE#define ISP1301_I2C_REG_CLEAR_ADDR 1#endif#define OMAP1510_LB_OFFSET (0x30000000UL)#ifdef CONFIG_ARCH_OMAP1610#define OMAP1610_SET_FUNC_MUX_CTRL(mode,reg,bit) outl((inl(reg)&~(0x7<<bit))|(mode<<bit),reg)#define OMAP1610_CONFIRM_MUX_SETUP() outl(0xeaef,COMP_MODE_CTRL_0)#define open_drain(bit,reg) outl(inl(reg)|(1<<bit),reg)#endifextern int __devinit hc_add_ohci(struct pci_dev *dev, int irq, void *membase, unsigned long flags, ohci_t ** ohci, const char *name, const char *slot_name);extern void hc_remove_ohci(ohci_t * ohci);static ohci_t *omap1510_ohci;/* bogus pci_dev structure */static struct pci_dev bogus_pcidev;static int __devinit omap1510_ohci_configure(void);static void omap1510_ohci_release(void);#ifdef CONFIG_OMAP_H2static struct file *i2c_file;static struct i2c_client *omap_i2c_client;static int initstate_i2c;static int initstate_region;static inti2c_configure(void){ char filename[20]; int tmp; if (initstate_i2c) return 0; /*find the I2C driver we need */ for (tmp = 0; tmp < I2C_ADAP_MAX; tmp++) {#ifdef CONFIG_DEVFS_FS sprintf(filename, "/dev/i2c/%d", tmp);#else sprintf(filename, "/dev/i2c-%d", tmp);#endif if (!IS_ERR(i2c_file = filp_open(filename, O_RDWR, 0))) { /*found some driver */ omap_i2c_client = (struct i2c_client *) i2c_file->private_data; if (strlen(omap_i2c_client->adapter->name) >= 12) { if (!memcmp (omap_i2c_client->adapter->name, "OMAP1610 I2C", 12)) break; /*we found our driver! */ } filp_close(i2c_file, NULL); } } if (tmp == I2C_ADAP_MAX) { /*no matching I2C driver found */ err("cannot find OMAP1610 I2C driver"); return -ENODEV; } initstate_i2c = 1; return 0;}static voidi2c_close(void){ if (initstate_i2c) filp_close(i2c_file, NULL); initstate_i2c = 0;}#if 0static inti2c_read(u8 subaddr){ u8 buf = 0; if (!i2c_configure()) { omap_i2c_client->addr = ISP1301_I2C_ADDR; i2c_master_send(omap_i2c_client, &subaddr, 1); i2c_master_recv(omap_i2c_client, &buf, 1); } return buf;}#endifstatic inti2c_write(u8 buf, u8 subaddr){ char tmpbuf[2]; if (!i2c_configure()) { omap_i2c_client->addr = ISP1301_I2C_ADDR; tmpbuf[0] = subaddr; /*register number */ tmpbuf[1] = buf; /*register data */ i2c_master_send(omap_i2c_client, &tmpbuf[0], 2); } return 0;}static voidisp1301_configure(void){ i2c_write(6, ISP1301_I2C_MODE_CONTROL_1); i2c_write(~6, ISP1301_I2C_MODE_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR); i2c_write(4, ISP1301_I2C_MODE_CONTROL_2); i2c_write(~4, ISP1301_I2C_MODE_CONTROL_2 | ISP1301_I2C_REG_CLEAR_ADDR); i2c_write(0xC, ISP1301_I2C_OTG_CONTROL_1); i2c_write(~0xC, ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR); i2c_write(0xFF, ISP1301_I2C_INTERRUPT_LATCH | ISP1301_I2C_REG_CLEAR_ADDR); i2c_write(0xFF, ISP1301_I2C_INTERRUPT_FALLING | ISP1301_I2C_REG_CLEAR_ADDR); i2c_write(0xFF, ISP1301_I2C_INTERRUPT_RISING | ISP1301_I2C_REG_CLEAR_ADDR);}#endif#if defined(CONFIG_OMAP_INNOVATOR) /* MVL-CEE */#include <linux/device.h>static int omap1510_ohci_suspend(struct device *dev, u32 state, u32 level);static int omap1510_ohci_resume(struct device *dev, u32 level);static int omap1510_ohci_scale(struct bus_op_point *op, u32 level);static int omap1510_ohci_pid;static DECLARE_COMPLETION(kusbdpmd);static int omap1510_usbpmd_req;static wait_queue_head_t kusbdpmd_wait;static struct device_driver omap1510_ohci_driver_ldm = { .name = "omap1510/1610-ohci", .devclass = NULL, .probe = NULL, .suspend = omap1510_ohci_suspend, .resume = omap1510_ohci_resume, .scale = omap1510_ohci_scale, .remove = NULL, .constraints = NULL,};static struct device omap1510_ohci_device_ldm = { .name = "OMAP1510/1610 OHCI", .bus_id = "OHCI", .driver = NULL, .power_state = DPM_POWER_ON,};static intomap1510_ohci_thread(void){ int ret; struct task_struct *tsk = current; /* * We don't want /any/ signals, not even SIGKILL */ sigfillset(&tsk->blocked); sigemptyset(&tsk->pending.signal); recalc_sigpending(tsk); daemonize(); reparent_to_init(); strcpy(tsk->comm, "kusbdpmd"); tsk->tty = NULL; while (1) { int req; do { req = xchg(&omap1510_usbpmd_req, 0); if (req == 0) { sigemptyset(&tsk->pending.signal); interruptible_sleep_on(&kusbdpmd_wait); } } while (req == 0); if (req == SIGTERM) { break; } else if (req == SIGHUP) { ret = omap1510_ohci_configure(); complete(&kusbdpmd); } else { printk(KERN_DEBUG "%s: Unknown Request: %d\n", __FUNCTION__, req); } } complete_and_exit(&kusbdpmd, 0);}static voidomap1510_ohci_ldm_driver_register(void){ extern void mpu_public_driver_register(struct device_driver *driver); mpu_public_driver_register(&omap1510_ohci_driver_ldm);}static voidomap1510_ohci_ldm_device_register(void){ extern void mpu_public_device_register(struct device *device); mpu_public_device_register(&omap1510_ohci_device_ldm);}static voidomap1510_ohci_ldm_driver_unregister(void){ extern void mpu_public_driver_unregister(struct device_driver *driver); mpu_public_driver_unregister(&omap1510_ohci_driver_ldm);}static voidomap1510_ohci_ldm_device_unregister(void){ extern void mpu_public_device_unregister(struct device *device); mpu_public_device_unregister(&omap1510_ohci_device_ldm);}static intomap1510_ohci_scale(struct bus_op_point *op, u32 level){ /* REVISIT */ return 0;}static intomap1510_ohci_suspend(struct device *dev, u32 state, u32 level){ switch (level) { case SUSPEND_POWER_DOWN: omap1510_ohci_release(); break; } return 0;}static intomap1510_ohci_resume(struct device *dev, u32 level){ int ret = 0; switch (level) { case RESUME_POWER_ON: /* Wake up thread for reinit. */ init_completion(&kusbdpmd); omap1510_usbpmd_req = SIGHUP; wake_up(&kusbdpmd_wait); break; } return ret;}#endif /* MVL-CEE */static int __devinitomap1510_ohci_configure(void){#ifndef CONFIG_ARCH_OMAP1610 /* TO DO: make a proper header file for all of these registers. */#ifdef CONFIG_OMAP_INNOVATOR volatile unsigned char *fpga_usb_host_ctrl = (unsigned char *) 0xe800020c;#endif volatile unsigned short *apll_ctrl_reg = (unsigned short *) 0xfffe084c; volatile unsigned short *dpll_ctrl_reg = (unsigned short *) 0xfffe083c; volatile unsigned short *soft_req_reg = (unsigned short *) 0xfffe0834; volatile unsigned short *clock_ctrl_reg = (unsigned short *) 0xfffe0830; volatile unsigned long *mod_conf_ctrl_0 = (unsigned long *) 0xfffe1080; volatile unsigned long *lb_clock_div = (unsigned long *) 0xfffec10c; volatile unsigned short *lb_mmu_cntl_reg = (unsigned short *) 0xfffec208; volatile unsigned short *lb_mmu_lock_reg = (unsigned short *) 0xfffec224; volatile unsigned short *lb_mmu_ld_tlb_reg = (unsigned short *) 0xfffec228; volatile unsigned short *lb_mmu_cam_h_reg = (unsigned short *) 0xfffec22c; volatile unsigned short *lb_mmu_cam_l_reg = (unsigned short *) 0xfffec230; volatile unsigned short *lb_mmu_ram_h_reg = (unsigned short *) 0xfffec234; volatile unsigned short *lb_mmu_ram_l_reg =
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -