📄 cy7c67200_300_pcd.c
字号:
lcd_read_reg(OTG_CTL_REG, ®_val, cy_priv); reg_val |= DPLUS_PULLUP_EN; lcd_write_reg(OTG_CTL_REG, reg_val, cy_priv); mdelay(8); lcd_read_reg(OTG_CTL_REG, ®_val, cy_priv); reg_val &= ~DPLUS_PULLUP_EN; lcd_write_reg(OTG_CTL_REG, reg_val, cy_priv); //pcd_dbg("END D+ PULLUP"); lcd_read_reg(OTG_CTL_REG, ®_val, cy_priv); if( reg_val & VBUS_VALID_FLG ) { pcd_dbg("VBUS high 3"); /* A-Device has raised VBUS */ return SUCCESS; } /* Pulse VBUS */ //pcd_dbg("START VBUS PULLUP"); lcd_read_reg(OTG_CTL_REG, ®_val, cy_priv); lcd_write_reg(OTG_CTL_REG, reg_val | VBUS_PULLUP_EN, cy_priv); mdelay(vbus_pulse_time); lcd_read_reg(OTG_CTL_REG, ®_val, cy_priv); lcd_write_reg(OTG_CTL_REG, reg_val & ~VBUS_PULLUP_EN, cy_priv); //pcd_dbg("END VBUS PULLUP"); /* Discharge VBUS again to prevent false transitions to b_peripheral */ lcd_read_reg(OTG_CTL_REG, ®_val, cy_priv); lcd_write_reg(OTG_CTL_REG, reg_val | VBUS_DISCH_EN, cy_priv); mdelay(30); lcd_read_reg(OTG_CTL_REG, ®_val, cy_priv); lcd_write_reg(OTG_CTL_REG, reg_val & ~VBUS_DISCH_EN, cy_priv); } return SUCCESS;}/***************************************************************** * * Function Name: load_configuration_data * * DESCRIPTION: This function will obtain descriptors from the function * drivers attached above it, and will then load them to the EZ-HOST * memory. * * A device will contain a single device descriptor. Device, configuration, * interface, and endpoint descriptors are written to EZ-HOST RAM during * initialization. The BIOS then will handle any standard requests made * by a host to the control endpoint. * *****************************************************************/int load_configuration_data(cy_priv_t * cy_priv){ int port = 0; int bNumConfigurations; int bNumInterfaces; int bLength = 0; unsigned short wTotalLength = 0; unsigned short length_remaining = 0; char * descriptor_buffer; char * buffer_position; size_t index = 0; struct usb_string_descriptor *string; unsigned short string_loc; struct usb_device_instance * dev; int class; int bNumEndpoint; struct usb_device_descriptor * device_descriptor; struct usb_configuration_descriptor * configuration_descriptor; struct usb_interface_descriptor * interface_descriptor; struct usb_alternate_instance * alternate_instance; struct usb_otg_descriptor * otg_descriptor; pcd_dbg("load_configuration_data enter"); dev = sie->bus->device; /* load the descriptors to the ASIC to handle enumeration. load the device descriptor */ if(!(device_descriptor = usbd_device_device_descriptor(dev, port))) { cy_err("usbd_device_device_descriptor() failed, dev:%p, port:%d", dev, port); return(ERROR); } if(lcd_write_memory(sie->sie_dev_desc_location, sizeof(*device_descriptor), (char *)device_descriptor, cy_priv) == ERROR) { cy_err("lcd_write_memory() failed"); return(ERROR); } /* write the vector address to the software interrupt. */ if(lcd_write_reg(sie->susb_dev_desc_vec, sie->sie_dev_desc_location, cy_priv) == ERROR) { cy_err("lcd_write_reg() failed"); return(ERROR); } /* create a buffer and write all descriptor information to the buffer. */ descriptor_buffer = (char *)kmalloc(DESCRIPTOR_BUFFER_SIZE, GFP_ATOMIC); /* determine the number of configurations. */ for(bNumConfigurations = 0; bNumConfigurations < device_descriptor->bNumConfigurations; bNumConfigurations++) { configuration_descriptor = usbd_device_configuration_descriptor( dev, port, bNumConfigurations); /* get config descriptor length */ bLength = configuration_descriptor->bLength; /* get the total length of all descriptors for this configuration */ wTotalLength = configuration_descriptor->wTotalLength; length_remaining = wTotalLength - bLength; memcpy(descriptor_buffer, configuration_descriptor, bLength); buffer_position = descriptor_buffer + bLength; /* iterate across interfaces for specified configuration */ for(bNumInterfaces = 0; bNumInterfaces < configuration_descriptor->bNumInterfaces ; bNumInterfaces++) { int bAlternateSetting; struct usb_interface_instance * interface_instance; if(!(interface_instance = usbd_device_interface_instance(dev, port, 0, bNumInterfaces))) { cy_err("usbd_device_interface_instance() failed"); return(ERROR); } /* iterate across interface alternates */ for(bAlternateSetting = 0; bAlternateSetting < interface_instance->alternates; bAlternateSetting++) { if (!(alternate_instance = usbd_device_alternate_instance( dev, port, 0, bNumInterfaces, bAlternateSetting))) { cy_err("usbd_device_alternate_instance() failed"); return(ERROR); } length_remaining = length_remaining - alternate_instance->interface_descriptor->bLength; /* copy interface descriptor to buffer */ memcpy(buffer_position, alternate_instance->interface_descriptor, alternate_instance->interface_descriptor->bLength); buffer_position = buffer_position + alternate_instance-> interface_descriptor-> bLength; /* iterate across classes for this alternate interface */ for (class = 0; class < alternate_instance->classes ; class++) { struct usb_class_descriptor * class_descriptor; if (!(class_descriptor = usbd_device_class_descriptor_index(dev, port, 0, bNumInterfaces, bAlternateSetting, class))) { cy_err("usbd_device_class_descriptor_index() failed"); return(ERROR); } length_remaining = length_remaining - class_descriptor->descriptor.generic.bFunctionLength; /* copy descriptor for this class */ memcpy(buffer_position, class_descriptor, class_descriptor->descriptor.generic.bFunctionLength); buffer_position = buffer_position + class_descriptor->descriptor.generic.bFunctionLength; } /* iterate across endpoints for this alternate interface */ interface_descriptor = alternate_instance->interface_descriptor; for (bNumEndpoint = 0; bNumEndpoint < alternate_instance->endpoints; bNumEndpoint++) { struct usb_endpoint_descriptor * endpoint_descriptor; if (!(endpoint_descriptor = usbd_device_endpoint_descriptor_index(dev, port, 0, bNumInterfaces, bAlternateSetting, bNumEndpoint))) { cy_err("usbd_device_endpoint_descriptor_index()" " failed"); return(ERROR); } length_remaining = length_remaining - endpoint_descriptor->bLength; /* copy descriptor for this endpoint */ memcpy(buffer_position, endpoint_descriptor, endpoint_descriptor->bLength); buffer_position = buffer_position + endpoint_descriptor->bLength; } /* get the otg descriptor if it is available, the * length_remaining if the otg_descriptor is present should * be three, otherwise the otg_descriptor will not be present * for this function */ if(alternate_instance->otg_descriptor != NULL) { otg_descriptor = usbd_device_otg_descriptor(dev, port, bNumConfigurations, bNumInterfaces, bAlternateSetting); memcpy(buffer_position, otg_descriptor, otg_descriptor->bLength); buffer_position = buffer_position + otg_descriptor->bLength; } } } } /* write the config descriptor to EZ-HOST */ if (lcd_write_memory(sie->sie_config_desc_location, wTotalLength, descriptor_buffer, cy_priv) == ERROR) { kfree(descriptor_buffer); cy_err("lcd_write_memory() failed for config descriptors"); return(ERROR); } /* write the config descriptor address to the software interrupt. */ if (lcd_write_reg(sie->susb_config_desc_vec, sie->sie_config_desc_location, cy_priv) == ERROR) { kfree(descriptor_buffer); cy_err("lcd_write_reg() failed"); return(ERROR); } /* Enable HNP in BIOS */ if (lcd_write_reg(0xb0, 3, cy_priv) == ERROR) { kfree(descriptor_buffer); cy_err("lcd_write_reg() failed"); return(ERROR); } /* write string descriptors to EZ-HOST */ string_loc = sie->sie_string_desc_location; while( (string = usbd_get_string(index++)) != NULL ) { if (lcd_write_memory(string_loc, string->bLength, (char*)string, cy_priv) == ERROR) { kfree(descriptor_buffer); cy_err("lcd_write_memory() failed for string descriptors"); return(ERROR); } string_loc += string->bLength; } pcd_dbg("Device descriptor address: 0x%04x", sie->sie_dev_desc_location); pcd_dbg("Config descriptor address: 0x%04x", sie->sie_config_desc_location); pcd_dbg("String descriptor address: 0x%04x", sie->sie_string_desc_location); /* write the string descriptor address to the software interrupt. */ if (lcd_write_reg(sie->susb_string_desc_vec, sie->sie_string_desc_location, cy_priv) == ERROR) { kfree(descriptor_buffer); cy_err("lcd_write_reg() failed for string descriptors"); return(ERROR); } kfree(descriptor_buffer); return(SUCCESS);}/***************************************************************** * * Function Name: Various * * This is a collection of handlers called at interrupt context * from the main interrupt handler defined in lcd. * * Input: cy_priv - Private data structure maintaining certain * state for hcd, pcd, lcd, otg. * * Return: none * *****************************************************************/void pcd_irq_sofeop1(cy_priv_t *cy_priv){ // not used}/*****************************************************************/void pcd_irq_sofeop2(cy_priv_t *cy_priv){ // not used}/*****************************************************************/void pcd_irq_rst1(cy_priv_t *cy_priv){ sie_info *sie_var = (sie_info *)cy_priv->pcdi; pcd_dbg("pcd_irq_rst1 enter"); // not initialized yet, ignore interrupt if(sie_var == NULL) { return; } if( sie_var->sie_number == SIE1 ) { sie_var->usb_address = 0; usbd_device_event(sie_var->bus->device, DEVICE_RESET, 0); } /* clear the associated interrupt */ lcd_write_reg(HOST1_STAT_REG, RST_IRQ_FLG, cy_priv);}/*****************************************************************/void pcd_irq_rst2(cy_priv_t *cy_priv){ sie_info *sie_var = (sie_info *)cy_priv->pcdi; pcd_dbg("pcd_irq_rst2 enter"); // not initialized yet, ignore interrupt if(sie_var == NULL) { return; } if( sie_var->sie_number == SIE2 ) { sie_var->usb_address = 0; usbd_device_event(sie_var->bus->device, DEVICE_RESET, 0); } /* clear the associated interrupt */ lcd_write_reg(HOST2_STAT_REG, RST_IRQ_FLG, cy_priv);}/*****************************************************************//* OTG 4.4V Peripheral Mode only */void vbus_timeout(unsigned long data){ cy_priv_t *cy_priv = (cy_priv_t*)data; unsigned short value; otg_t *otg = cy_priv->otg; boolean prev_a_vbus_vld; boolean prev_a_sess_vld; lcd_read_reg(OTG_CTL_REG, &value, cy_priv); prev_a_vbus_vld = otg->a_vbus_vld; prev_a_sess_vld = otg->a_sess_vld; if (value & VBUS_VALID_FLG) { pcd_dbg("pcd_irq_vbus enter, VBUS_VLD, otg_reg:0x%04x", value); otg->a_vbus_vld = TRUE; // HPI can not distinguish between the two thresholds. otg->a_sess_vld = otg->b_sess_vld = TRUE; otg->b_sess_end = FALSE; } else { pcd_dbg("pcd_irq_vbus enter, !vbus_vld, otg_reg:0x%04x", value); otg->a_vbus_vld = FALSE; // HPI can not distinguish between the two thresholds. otg->a_sess_vld = otg->b_sess_vld = (value & OTG_DATA_STAT) ? TRUE : FALSE; otg->b_sess_end = (value & OTG_DATA_STAT) ? FALSE : TRUE; } if( prev_a_vbus_vld != otg->a_vbus_vld || prev_a_sess_vld != otg->a_sess_vld ) { update_otg_state(otg); } lcd_read_reg (HOST1_IRQ_EN_REG, &value, cy_priv); value |= VBUS_IRQ_EN; lcd_write_reg(HOST1_IRQ_EN_REG, value, cy_priv);}void pcd_irq_vbus(cy_priv_t *cy_priv){ unsigned short intStat;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -