From fcdaffa1b6f46ee1cbf678a47876f5eb03b88515 Mon Sep 17 00:00:00 2001 From: "dian.shao" Date: Thu, 29 Aug 2024 17:27:09 +0800 Subject: [PATCH] usb: str power optimise [1/1] PD#SWPL-183487 Problem: AVDD18_AUDIO high. Solution: Power off controller when str. Verify: br301 Change-Id: I7fa56ca3449df6196cd0e6e7d0ee9ba108712928 Signed-off-by: dian.shao --- arch/arm/boot/dts/amlogic/mesont6d.dtsi | 4 + drivers/usb/crg/crg_drd.c | 7 +- drivers/usb/crg/crg_udc.c | 124 +++++++++++------ drivers/usb/crgdrdphy/phy-aml-crg-drd-otg.c | 134 ++++++++++++++++--- drivers/usb/crgdrdphy/phy-aml-crg-drd-usb.c | 14 +- drivers/usb/crgdrdphy/phy-aml-crg-drd-usb2.c | 62 +++++---- drivers/usb/usb_main.c | 15 ++- drivers/usb/usb_main.h | 4 + include/linux/amlogic/usb-v2.h | 4 + 9 files changed, 275 insertions(+), 93 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesont6d.dtsi b/arch/arm/boot/dts/amlogic/mesont6d.dtsi index 37d3fe64a..60f337361 100644 --- a/arch/arm/boot/dts/amlogic/mesont6d.dtsi +++ b/arch/arm/boot/dts/amlogic/mesont6d.dtsi @@ -1563,6 +1563,7 @@ // <&clkc CLKID_USB2_48M_CLK_TMP>; phy-id = <0>; usb-phy-trim-reg = <0xfe010330>; + pm-controller; }; usb_phy30: usbphy30@fe488100 { @@ -1598,6 +1599,7 @@ phy-id = <2>; usb-phy-trim-reg = <0xfe010330>; status = "disable"; + pm-controller; }; usb_phy32: usbphy32@fe4a8000 { @@ -1621,6 +1623,7 @@ clock-names = "crg_general"; phy-id = <1>; usb-phy-trim-reg = <0xfe010330>; + pm-controller; }; usb_phy31: usbphy31@fe498100 { @@ -1665,6 +1668,7 @@ clock-names = "usb_general"; phy-id = <0>; version = <1>; /* forbid vbus detect */ + suspend-scheme = <0x1>; }; crg22_host: crg22@fe4a0000 { diff --git a/drivers/usb/crg/crg_drd.c b/drivers/usb/crg/crg_drd.c index 06979e7c0..52938de0e 100644 --- a/drivers/usb/crg/crg_drd.c +++ b/drivers/usb/crg/crg_drd.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -87,11 +88,15 @@ static int crg_core_soft_reset(struct crg_drd *crg) if (crg->usb3_phy) usb_phy_init(crg->usb3_phy); + amlogic_crg_host_power(crg->usb2_phy, false, true); + return 0; } static void crg_core_exit(struct crg_drd *crg) { + amlogic_crg_host_power(crg->usb2_phy, false, false); + if (crg->usb2_phy) usb_phy_shutdown(crg->usb2_phy); if (crg->usb3_phy) @@ -510,7 +515,6 @@ static void crg_shutdown(struct platform_device *pdev) pm_runtime_get_sync(&pdev->dev); crg_host_exit(crg); - /* wait for unregister. */ crg_core_exit(crg); pm_runtime_put_sync(&pdev->dev); @@ -527,6 +531,7 @@ static int crg_remove(struct platform_device *pdev) pm_runtime_get_sync(&pdev->dev); crg_host_exit(crg); + crg_core_exit(crg); pm_runtime_put_sync(&pdev->dev); pm_runtime_allow(&pdev->dev); diff --git a/drivers/usb/crg/crg_udc.c b/drivers/usb/crg/crg_udc.c index 7c14051c6..d6eab078c 100644 --- a/drivers/usb/crg/crg_udc.c +++ b/drivers/usb/crg/crg_udc.c @@ -368,6 +368,9 @@ struct crg_gadget_dev { int connected; bool async_cb_flag; + int suspend_scheme; +#define SUSPEND_SCHEME_POWER_OFF_ONLY 0 +#define SUSPEND_SCHEME_REINIT 1 unsigned u2_RWE:1; unsigned feature_u1_enable:1; @@ -379,6 +382,11 @@ struct crg_gadget_dev { u32 phy_id; }; +static inline bool crg_udc_suspend_reinit(struct crg_gadget_dev *crg_udc) +{ + return crg_udc->suspend_scheme == SUSPEND_SCHEME_REINIT ? true : false; +} + struct gadget_info { struct config_group group; struct config_group functions_group; @@ -426,51 +434,45 @@ static int crg_udc_probe_state; /* Serialize init/exit&pm_cb. */ DEFINE_MUTEX(crg_udc_driver_lock); -static bool xfer_debug; -module_param(xfer_debug, bool, 0644); -MODULE_PARM_DESC(xfer_debug, "0 or 1"); +static bool crg_udc_xfer_debug; +module_param(crg_udc_xfer_debug, bool, 0644); +MODULE_PARM_DESC(crg_udc_xfer_debug, "0 or 1"); -static bool crg_debug = 1; -module_param(crg_debug, bool, 0644); -MODULE_PARM_DESC(crg_debug, "0 or 1"); +static bool crg_udc_debug; +module_param(crg_udc_debug, bool, 0644); +MODULE_PARM_DESC(crg_udc_debug, "0 or 1"); -static bool portsc_debug = 1; -module_param(portsc_debug, bool, 0644); -MODULE_PARM_DESC(portsc_debug, "0 or 1"); +static bool crg_udc_portsc_debug; +module_param(crg_udc_portsc_debug, bool, 0644); +MODULE_PARM_DESC(crg_udc_portsc_debug, "0 or 1"); #ifdef CRG_DUAL_ROLE -static bool dr_udc_debug; -module_param(dr_udc_debug, bool, 0644); -MODULE_PARM_DESC(dr_udc_debug, "0 or 1"); +static bool crg_udc_dr_udc_debug; +module_param(crg_udc_dr_udc_debug, bool, 0644); +MODULE_PARM_DESC(crg_udc_dr_udc_debug, "0 or 1"); #endif static bool eltest_flag; module_param(eltest_flag, bool, 0644); MODULE_PARM_DESC(eltest_flag, "0 or 1"); -#ifdef CRG_UDC_DEBUG #define xdebug(fmt...) \ do { \ - if (xfer_debug) \ + if (crg_udc_xfer_debug) \ pr_err(fmt); \ } while (0) #define CRG_DEBUG(fmt...) \ do { \ - if (crg_debug) \ + if (crg_udc_debug) \ pr_err(fmt); \ } while (0) #define pdebug(fmt...) \ do { \ - if (portsc_debug) \ + if (crg_udc_portsc_debug) \ pr_err(fmt); \ } while (0) -#else -#define xdebug(fmt...) -#define CRG_DEBUG(fmt...) -#define pdebug(fmt...) -#endif #define CRG_ERROR(fmt...) pr_err(fmt) @@ -484,7 +486,10 @@ static struct usb_endpoint_descriptor crg_udc_ep0_desc = { void crg_gadget_hold(struct crg_udc_lock *lock) { - if (!lock->held) { + struct crg_gadget_dev *crg_udc = + container_of(lock, struct crg_gadget_dev, crg_gadget_lock); + + if (!crg_udc_suspend_reinit(crg_udc) && !lock->held) { __pm_stay_awake(lock->wakesrc); lock->held = true; } @@ -492,7 +497,10 @@ void crg_gadget_hold(struct crg_udc_lock *lock) void crg_gadget_drop(struct crg_udc_lock *lock) { - if (lock->held) { + struct crg_gadget_dev *crg_udc = + container_of(lock, struct crg_gadget_dev, crg_gadget_lock); + + if (!crg_udc_suspend_reinit(crg_udc) && lock->held) { __pm_relax(lock->wakesrc); lock->held = false; } @@ -741,7 +749,7 @@ static void crg_udc_epcx_setup(struct crg_udc_ep *udc_ep) u32 dw; CRG_DEBUG("crgudc->p_epcx %p, epcx %p\n", crg_udc->p_epcx, epcx); - CRG_DEBUG("DCI %d, sizeof ep_cx %ld\n", DCI, sizeof(struct ep_cx_s)); + CRG_DEBUG("DCI %d, sizeof ep_cx %llu\n", DCI, (u64)sizeof(struct ep_cx_s)); CRG_DEBUG("desc epaddr = 0x%x\n", desc->bEndpointAddress); /*corigine gadget dir should be opposite to host dir*/ @@ -894,8 +902,8 @@ void setup_datastage_trb(struct crg_gadget_dev *crg_udc, { u32 tmp; - CRG_DEBUG("dma = 0x%x, ", usb_req->dma); - CRG_DEBUG("buf = 0x%x, ", usb_req->buf); + CRG_DEBUG("dma = 0x%llx, ", (u64)usb_req->dma); + CRG_DEBUG("buf = 0x%px, ", usb_req->buf); p_trb->dw0 = lower_32_bits(usb_req->dma); p_trb->dw1 = upper_32_bits(usb_req->dma); @@ -1765,7 +1773,7 @@ static int ep_halt(struct crg_udc_ep *udc_ep_ptr, udc_ep_ptr->deq_pt = udc_ep_ptr->enq_pt; udc_ep_ptr->tran_ring_full = false; - CRG_DEBUG("update deq_pt tp enq_pt 0x%x\n", udc_ep_ptr->deq_pt); + CRG_DEBUG("update deq_pt tp enq_pt %px\n", udc_ep_ptr->deq_pt); } /* clean up the request queue */ //nuke(udc_ep_ptr, -ECONNRESET); maybe we no need clean up the request queue @@ -2791,7 +2799,7 @@ static int init_ep0(struct crg_gadget_dev *crg_udc) CRG_CMD0_0_DCS(udc_ep_ptr->pcs); cmd_param1 = upper_32_bits(udc_ep_ptr->tran_ring_info.dma); - CRG_DEBUG("ep0 ring dma addr = 0x%llx\n", udc_ep_ptr->tran_ring_info.dma); + CRG_DEBUG("ep0 ring dma addr = 0x%llx\n", (u64)udc_ep_ptr->tran_ring_info.dma); CRG_DEBUG("ep0 ring vaddr = 0x%p\n", udc_ep_ptr->tran_ring_info.vaddr); @@ -3279,7 +3287,7 @@ get_status_error: CRG_DEBUG("udc_req_ptr->usb_req.buf = 0x%p, value = 0x%x\n", udc_req_ptr->usb_req.buf, *(u16 *)(udc_req_ptr->usb_req.buf)); CRG_DEBUG("udc_req_ptr->usb_req.dma = 0x%llx\n", - udc_req_ptr->usb_req.dma); + (u64)udc_req_ptr->usb_req.dma); udc_ep_ptr = &crg_udc->udc_ep[0]; @@ -4466,13 +4474,13 @@ static ssize_t udc_debug_store(struct device *_dev, struct device_attribute *att if (ret) { CRG_ERROR("is not in hex or decimal form.\n"); } else if (val == CRG_DEBUG_OFF) { - crg_debug = 0; - xfer_debug = 0; - portsc_debug = 0; + crg_udc_debug = 0; + crg_udc_xfer_debug = 0; + crg_udc_portsc_debug = 0; } else if (val == CRG_DEBUG_ON) { - crg_debug = 1; - xfer_debug = 1; - portsc_debug = 1; + crg_udc_debug = 1; + crg_udc_xfer_debug = 1; + crg_udc_portsc_debug = 1; } else { CRG_ERROR("error\n"); } @@ -4620,6 +4628,11 @@ static int crg_udc_probe(struct platform_device *pdev) goto err0; } + retval = of_property_read_s32(of_node, "suspend-scheme", + &crg_udc->suspend_scheme); + if (retval < 0) + crg_udc->suspend_scheme = SUSPEND_SCHEME_POWER_OFF_ONLY; + phy_reg_addr = devm_ioremap (&pdev->dev, (resource_size_t)p_phy_reg_addr, (unsigned long)phy_reg_addr_size); @@ -4678,6 +4691,8 @@ static int crg_udc_probe(struct platform_device *pdev) else amlogic_crg_m31_phy_init(crg_udc); + amlogic_crg_device_power(phy_id, false, true); + crg_udc->mmio_phys_base = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!crg_udc->mmio_phys_base) { dev_err(&pdev->dev, "missing memory resource\n"); @@ -4699,7 +4714,7 @@ static int crg_udc_probe(struct platform_device *pdev) (reg_read(crg_udc->mmio_virt_base + 0x20FC) | 0x1)); if (version == 1) { - dev_err(&pdev->dev, "disable vbus detect.\n"); + CRG_DEBUG("disable vbus detect.\n"); reg_write(crg_udc->mmio_virt_base + 0x2110, (reg_read(crg_udc->mmio_virt_base + 0x2110) & (~0x1f))); } @@ -4708,7 +4723,7 @@ static int crg_udc_probe(struct platform_device *pdev) crg_udc->uicr[i] = crg_udc->mmio_virt_base + CRG_UICR_OFFSET + i * CRG_UICR_STRIDE; - CRG_DEBUG("crg_udc->uicr[%d] = %x\n", i, crg_udc->uicr[i]); + CRG_DEBUG("crg_udc->uicr[%d] = %px\n", i, crg_udc->uicr[i]); } crg_udc->uccr = crg_udc->mmio_virt_base + CRG_UCCR_OFFSET; @@ -4738,7 +4753,7 @@ static int crg_udc_probe(struct platform_device *pdev) } /* It is unable to set controller_cfg reg of the U2PHY - * that has reg val reset feature before controller role switch. + * that has reg val reset feature before controller role switch. */ if (controller_type != USB_M31) amlogic_crg_device_usb2_init(phy_id); @@ -4749,7 +4764,7 @@ static int crg_udc_probe(struct platform_device *pdev) goto errfile; } - if (!crg_udc->crg_gadget_lock.wakesrc) { + if (!crg_udc->crg_gadget_lock.wakesrc && !crg_udc_suspend_reinit(crg_udc)) { crg_udc->crg_gadget_lock.wakesrc = wakeup_source_register(NULL, "crg-gadget-connect"); if (!crg_udc->crg_gadget_lock.wakesrc) @@ -4810,6 +4825,8 @@ static int crg_udc_remove(struct platform_device *pdev) if (crg_udc->irq) free_irq(crg_udc->irq, crg_udc); + amlogic_crg_device_power(crg_udc->phy_id, false, false); + if (crg_udc->controller_type != USB_M31) amlogic_crg_device_usb2_shutdown(g_device_phy_id); @@ -4843,6 +4860,8 @@ static void crg_udc_shutdown(struct platform_device *pdev) if (crg_udc->irq) free_irq(crg_udc->irq, crg_udc); + amlogic_crg_device_power(crg_udc->phy_id, false, false); + if (crg_udc->controller_type != USB_M31) amlogic_crg_device_usb2_shutdown(g_device_phy_id); @@ -4996,10 +5015,14 @@ static int crg_udc_suspend(struct device *dev) crg_udc = &crg_udc_dev; + if (crg_udc_suspend_reinit(crg_udc)) + amlogic_crg_device_power(crg_udc->phy_id, crg_udc_suspend_reinit(crg_udc), false); + if (crg_udc->controller_type != USB_M31) amlogic_crg_device_usb2_shutdown(crg_udc->phy_id); crg_clk_disable_usb(pdev, (unsigned long)crg_udc->phy_reg_addr); + return 0; } @@ -5009,6 +5032,7 @@ static int crg_udc_resume(struct device *dev) struct crg_gadget_dev *crg_udc; crg_udc = &crg_udc_dev; + crg_clk_enable_usb(pdev, (unsigned long)crg_udc->phy_reg_addr, crg_udc->controller_type); @@ -5016,10 +5040,20 @@ static int crg_udc_resume(struct device *dev) if (crg_udc->controller_type != USB_M31) amlogic_crg_device_usb2_init(crg_udc->phy_id); + if (crg_udc_suspend_reinit(crg_udc)) + amlogic_crg_device_power(crg_udc->phy_id, crg_udc_suspend_reinit(crg_udc), true); + #if IS_ENABLED(CONFIG_AMLOGIC_COMMON_USB) + /* Actually the crg_rewrite_otg_write_UDC() is used to restart the controller + * to workaround quirks emerge in suspend-resume stress test. + * It is safe to skip it if the driver chooses to use resume-reinit scheme. + */ + if (crg_udc_suspend_reinit(crg_udc)) + goto done; + crg_rewrite_otg_write_UDC(); #endif - +done: return 0; } @@ -5072,7 +5106,17 @@ static int crg_udc_pm_cb(struct notifier_block *notifier, crg_udc_probe(pdev); break; case PM_SUSPEND_PREPARE: + /* Removing gadget dev causes ep_poll_callback()->__pm_stay_awake(). + * Don't do it or the pm_wakeup_pending() will just fail. + * Now we delay the de-init codes until the system is resumed. + */ + break; case PM_POST_SUSPEND: + if (crg_udc_suspend_reinit(crg_udc)) { + crg_udc_remove(pdev); + crg_udc_probe(pdev); + } + break; case PM_RESTORE_PREPARE: case PM_POST_RESTORE: default: diff --git a/drivers/usb/crgdrdphy/phy-aml-crg-drd-otg.c b/drivers/usb/crgdrdphy/phy-aml-crg-drd-otg.c index 936362462..da35ef90e 100644 --- a/drivers/usb/crgdrdphy/phy-aml-crg-drd-otg.c +++ b/drivers/usb/crgdrdphy/phy-aml-crg-drd-otg.c @@ -27,6 +27,7 @@ #include #define HOST_MODE 0 #define DEVICE_MODE 1 +#define OTG_MODE 2 static int UDC_exist_flag = -1; static char crg_UDC_name[128]; @@ -58,11 +59,13 @@ struct amlogic_crg_otg { union u2p_r1_v2 usb_r1; } pm_buf; struct notifier_block pm_notifier; + u32 mode; +#define HOST_MODE_MASK BIT(HOST_MODE) +#define DEVICE_MODE_MASK BIT(DEVICE_MODE) +#define OTG_MODE_MASK BIT(OTG_MODE) + struct dentry *debugfs_root; }; -static void set_mode - (unsigned long reg_addr, int mode, unsigned long phy3_addr); - static int amlogic_crg_otg_pm_cb(struct notifier_block *notifier, unsigned long pm_event, void *unused); @@ -107,12 +110,12 @@ static int amlogic_crg_otg_init(struct amlogic_crg_otg *phy) return 0; } -static void set_mode(unsigned long reg_addr, int mode, unsigned long phy3_addr) +static void set_mode(struct amlogic_crg_otg *phy, u8 mode) { struct u2p_aml_regs_v2 u2p_aml_regs; union u2p_r0_v2 reg0; - u2p_aml_regs.u2p_r_v2[0] = (void __iomem *)((unsigned long)reg_addr); + u2p_aml_regs.u2p_r_v2[0] = (void __iomem *)((unsigned long)phy->usb2_phy_cfg); reg0.d32 = readl(u2p_aml_regs.u2p_r_v2[0]); if (mode == DEVICE_MODE) { @@ -123,17 +126,116 @@ static void set_mode(unsigned long reg_addr, int mode, unsigned long phy3_addr) reg0.b.POR = 0; } writel(reg0.d32, u2p_aml_regs.u2p_r_v2[0]); - usleep_range(500, 600); + + phy->mode &= ~(HOST_MODE_MASK | DEVICE_MODE_MASK); + phy->mode |= BIT(mode); } +static int mode_show(struct seq_file *s, void *unused) +{ + struct amlogic_crg_otg *phy = s->private; + int cnt; + char tmp[8] = {'\0'}; + char buf[16]; + + if (phy->mode & HOST_MODE_MASK) + cnt = sprintf(tmp, "%s", "host"); + if (phy->mode & DEVICE_MODE_MASK) + cnt = sprintf(tmp, "%s", "device"); + if (phy->mode & OTG_MODE_MASK) + cnt = sprintf(buf, "%s-%s\n", "otg", tmp); + else + cnt = sprintf(buf, "%s-%s\n", "notg", tmp); + + seq_printf(s, "%s", buf); + + return 0; +} + +static int mode_open(struct inode *inode, struct file *file) +{ + return single_open(file, mode_show, inode->i_private); +} + +static ssize_t mode_write(struct file *file, const char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct seq_file *s = file->private_data; + struct amlogic_crg_otg *phy = s->private; + u8 i_mode = (u8)-1; + int ret = -EINVAL; + char buf[32]; + + if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) + return ret; + + buf[count - 1] = '\0'; + + if (phy->mode & OTG_MODE_MASK) + return ret; + + au2p_dbg(phy->dev, "%s %lu", buf, (unsigned long)count); + + if (!strncmp("host", buf, count)) + i_mode = HOST_MODE; + + if (!strncmp("device", buf, count)) + i_mode = DEVICE_MODE; + + if (i_mode == (u8)-1 || phy->mode & BIT(i_mode)) + return ret; + + if (i_mode == HOST_MODE) { + crg_gadget_exit(); + amlogic_m31_set_vbus_power(phy, 1); + set_mode(phy, HOST_MODE); + crg_init(); + ret = count; + } else if (i_mode == DEVICE_MODE) { + crg_exit(); + set_mode(phy, DEVICE_MODE); + amlogic_m31_set_vbus_power(phy, 0); + crg_gadget_init(); + if (UDC_exist_flag != 1) { + ret = crg_otg_write_UDC(crg_UDC_name); + if (ret == 0 || ret == -EBUSY) + UDC_exist_flag = 1; + } + ret = count; + } + + return ret; +} + +static const struct file_operations mode_fops = { + .open = mode_open, + .write = mode_write, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +void amlogic_crg_otg_debugfs_init(struct amlogic_crg_otg *phy) +{ + phy->debugfs_root = + debugfs_create_dir("crg-drd-otg", amlogic_usb_debugfs_root); + + debugfs_create_file("mode", 0644, phy->debugfs_root, phy, &mode_fops); +} + +//void amlogic_crg_otg_debugfs_exit(struct amlogic_crg_otg *phy) +//{ +// debugfs_remove_recursive(phy->debugfs_root); +// phy->debugfs_root = NULL; +//} + static void amlogic_crg_otg_work(struct work_struct *work) { struct amlogic_crg_otg *phy = container_of(work, struct amlogic_crg_otg, work.work); union u2p_r2_v2 reg2; unsigned long reg_addr = ((unsigned long)phy->usb2_phy_cfg); - unsigned long phy3_addr = ((unsigned long)phy->phy3_cfg); int ret; bool curr; @@ -147,11 +249,11 @@ static void amlogic_crg_otg_work(struct work_struct *work) if (reg2.b.iddig_curr == 0) { crg_gadget_exit(); amlogic_m31_set_vbus_power(phy, 1); - set_mode(reg_addr, HOST_MODE, phy3_addr); + set_mode(phy, HOST_MODE); crg_init(); } else { crg_exit(); - set_mode(reg_addr, DEVICE_MODE, phy3_addr); + set_mode(phy, DEVICE_MODE); amlogic_m31_set_vbus_power(phy, 0); crg_gadget_init(); if (UDC_exist_flag != 1) { @@ -184,17 +286,16 @@ static void amlogic_crg_otg_set_m_work(struct work_struct *work) container_of(work, struct amlogic_crg_otg, set_mode_work.work); union u2p_r2_v2 reg2; unsigned long reg_addr = ((unsigned long)phy->usb2_phy_cfg); - unsigned long phy3_addr = ((unsigned long)phy->phy3_cfg); mutex_lock(phy->otg_mutex); phy->mode_work_flag = 0; reg2.d32 = readl((void __iomem *)(reg_addr + 8)); if (reg2.b.iddig_curr == 0) { amlogic_m31_set_vbus_power(phy, 1); - set_mode(reg_addr, HOST_MODE, phy3_addr); + set_mode(phy, HOST_MODE); crg_init(); } else { - set_mode(reg_addr, DEVICE_MODE, phy3_addr); + set_mode(phy, DEVICE_MODE); amlogic_m31_set_vbus_power(phy, 0); crg_gadget_init(); } @@ -375,13 +476,11 @@ NO_M31: if (otg == 0) { if (get_otg_mode() || controller_type == USB_DEVICE_ONLY) { - set_mode((unsigned long)phy->usb2_phy_cfg, - DEVICE_MODE, (unsigned long)phy->phy3_cfg); + set_mode(phy, DEVICE_MODE); amlogic_m31_set_vbus_power(phy, 0); crg_gadget_init(); } else if (controller_type == USB_HOST_ONLY) { - set_mode((unsigned long)phy->usb2_phy_cfg, - HOST_MODE, (unsigned long)phy->phy3_cfg); + set_mode(phy, HOST_MODE); amlogic_m31_set_vbus_power(phy, 1); crg_init(); } @@ -391,10 +490,13 @@ NO_M31: * excess host mode init. */ phy->mode_work_flag = 1; + phy->mode |= OTG_MODE_MASK; INIT_DELAYED_WORK(&phy->set_mode_work, amlogic_crg_otg_set_m_work); schedule_delayed_work(&phy->set_mode_work, msecs_to_jiffies(500)); } + amlogic_crg_otg_debugfs_init(phy); + return 0; } diff --git a/drivers/usb/crgdrdphy/phy-aml-crg-drd-usb.c b/drivers/usb/crgdrdphy/phy-aml-crg-drd-usb.c index b71f00279..7f7edf3ca 100644 --- a/drivers/usb/crgdrdphy/phy-aml-crg-drd-usb.c +++ b/drivers/usb/crgdrdphy/phy-aml-crg-drd-usb.c @@ -41,21 +41,29 @@ int amlogic_crg_drd_usbphy_usb_hold_reset(struct amlogic_usb_v2 *phy, bool on) { u32 val = 0; size_t mask = 0; + u32 tmp = 0; au2p_dbg(phy->dev, "%s initial: 0x%x.\n", __func__, readl(phy->reset_regs + phy->reset_level)); + mask = (size_t)phy->reset_regs & 0xf; - val = readl((void __iomem *) + if (phy->usb_reset_bit != -1U) + tmp |= BIT(phy->usb_reset_bit); + if (phy->usb_comb_reset_bit != -1U) + tmp |= BIT(phy->usb_comb_reset_bit); + + val = readl((void __iomem *) ((unsigned long)phy->reset_regs + (phy->reset_level - mask))); if (on) { - writel(val | (0x1 << phy->usb_reset_bit), (void __iomem *) + writel(val | tmp, (void __iomem *) ((unsigned long)phy->reset_regs + (phy->reset_level - mask))); } else { - writel(val & ~(0x1 << phy->usb_reset_bit), (void __iomem *) + writel(val & ~tmp, (void __iomem *) ((unsigned long)phy->reset_regs + (phy->reset_level - mask))); } + au2p_dbg(phy->dev, "%s after: 0x%x.\n", __func__, readl(phy->reset_regs + phy->reset_level)); diff --git a/drivers/usb/crgdrdphy/phy-aml-crg-drd-usb2.c b/drivers/usb/crgdrdphy/phy-aml-crg-drd-usb2.c index 227f6f5dd..020783228 100644 --- a/drivers/usb/crgdrdphy/phy-aml-crg-drd-usb2.c +++ b/drivers/usb/crgdrdphy/phy-aml-crg-drd-usb2.c @@ -370,37 +370,12 @@ static void amlogic_crg_drd_usb2_set_vbus_power } static void amlogic_crg_drd_usb2_set_controller_power - (struct amlogic_usb_v2 *phy, bool on) + (struct amlogic_usb_v2 *phy, bool force, bool on) { - u32 val; - u32 temp = 0; - size_t mask = 0; - - if (!phy->pm_controller) + if (!phy->pm_controller && !force) return; - mask = (size_t)phy->reset_regs & 0xf; - - val = readl((void __iomem *) - ((unsigned long)phy->reset_regs + (phy->reset_level - mask))); - - if (phy->usb_reset_bit != -1U) - temp |= BIT(phy->usb_reset_bit); - if (phy->usb_comb_reset_bit != -1U) - temp |= BIT(phy->usb_comb_reset_bit); - - if (on) - val |= temp; - else - val &= ~temp; - - writel(val, (void __iomem *) - ((unsigned long)phy->reset_regs + (phy->reset_level - mask))); - - val = readl((void __iomem *) - ((unsigned long)phy->reset_regs + (phy->reset_level - mask))); - - temp = 0; + amlogic_crg_drd_usbphy_usb_hold_reset(phy, on); } static int amlogic_crg_drd_usb2_init_v0(struct usb_phy *x) @@ -431,7 +406,7 @@ static int amlogic_crg_drd_usb2_init_v0(struct usb_phy *x) } } - amlogic_crg_drd_usb2_set_controller_power(phy, true); + amlogic_crg_drd_usb2_set_controller_power(phy, false, true); for (i = 0; i < portnum; i++) temp = temp | (1 << phy->phy_reset_level_bit[i]); @@ -912,8 +887,13 @@ static int amlogic_crg_drd_usb2_init(struct usb_phy *x) static void amlogic_crg_drd_usb2phy_shutdown(struct usb_phy *x) { struct amlogic_usb_v2 *phy = phy_to_amlusb(x); + int ret; - amlogic_crg_drd_usbphy_hold_reset(phy, false); + if (local_pdata(phy)->ver == AML_CRG_DRD_USB2_PHY_V0) + amlogic_crg_drd_usb2_set_controller_power(phy, false, false); + + ret = amlogic_crg_drd_usbphy_hold_reset(phy, false); + ret = amlogic_crg_drd_usbphy_reg_hold_reset(phy, false); if (phy->suspend_flag == 0) if (phy->phy.flags == AML_USB2_PHY_ENABLE) @@ -1006,10 +986,12 @@ EXPORT_SYMBOL(amlogic_crg_device_usb2_init); int amlogic_crg_device_usb2_shutdown(u32 phy_id) { struct amlogic_usb_v2 *phy; + int ret = 0; phy = g_crg_drd_phy2[phy_id]; - amlogic_crg_drd_usbphy_hold_reset(phy, false); + ret = amlogic_crg_drd_usbphy_hold_reset(phy, false); + ret = amlogic_crg_drd_usbphy_reg_hold_reset(phy, false); if (phy->suspend_flag == 0) if (phy->phy.flags == AML_USB2_PHY_ENABLE) @@ -1017,10 +999,26 @@ int amlogic_crg_device_usb2_shutdown(u32 phy_id) phy->suspend_flag = 1; - return 0; + return ret; } EXPORT_SYMBOL(amlogic_crg_device_usb2_shutdown); +int amlogic_crg_host_power(struct usb_phy *p, bool force, bool on) +{ + struct amlogic_usb_v2 *phy = phy_to_amlusb(p); + + amlogic_crg_drd_usb2_set_controller_power(phy, force, on); + return 0; +} + +int amlogic_crg_device_power(u32 phy_id, bool force, bool on) +{ + struct amlogic_usb_v2 *phy = g_crg_drd_phy2[phy_id]; + + amlogic_crg_drd_usb2_set_controller_power(phy, force, on); + return 0; +} + static int amlogic_crg_drd_usb2_probe(struct platform_device *pdev) { struct amlogic_usb_v2 *phy; diff --git a/drivers/usb/usb_main.c b/drivers/usb/usb_main.c index 0c281687b..f08f9f15c 100644 --- a/drivers/usb/usb_main.c +++ b/drivers/usb/usb_main.c @@ -20,8 +20,9 @@ bool force_device_mode; module_param_named(otg_device, force_device_mode, bool, 0644); - static char otg_mode_string[2] = "0"; +struct dentry *amlogic_usb_debugfs_root; + static int force_otg_mode(char *s) { if (s) @@ -40,9 +41,21 @@ int get_otg_mode(void) } EXPORT_SYMBOL(get_otg_mode); +static inline void __init amlogic_usb_debugfs_create_root(void) +{ + amlogic_usb_debugfs_root = debugfs_create_dir("amlogic", usb_debug_root); +} + +//void __exit amlogic_usb_debugfs_remove_root(void) +//{ +// debugfs_remove_recursive(amlogic_usb_debugfs_root); +// amlogic_usb_debugfs_root = NULL; +//} + static int __init usb_main_init(void) { pr_debug("### %s() start\n", __func__); + amlogic_usb_debugfs_create_root(); call_sub_init(amlogic_new_c2_usb2_v2_driver_init);//usbc2phy call_sub_init(amlogic_new_c2_usb3_v2_driver_init);//usbc2phy call_sub_init(amlogic_new_usb3_v3_driver_init); //usb3v3phy diff --git a/drivers/usb/usb_main.h b/drivers/usb/usb_main.h index 5c3d85dc1..9b52526de 100644 --- a/drivers/usb/usb_main.h +++ b/drivers/usb/usb_main.h @@ -5,6 +5,10 @@ #ifndef _USB_MAIN_H__ #define _USB_MAIN_H__ +#include +#include + +extern struct dentry *amlogic_usb_debugfs_root; #if IS_ENABLED(CONFIG_AMLOGIC_USBPHY) int __init amlogic_new_usb3_v2_driver_init(void); diff --git a/include/linux/amlogic/usb-v2.h b/include/linux/amlogic/usb-v2.h index 9ba9a7649..83e39616d 100644 --- a/include/linux/amlogic/usb-v2.h +++ b/include/linux/amlogic/usb-v2.h @@ -533,8 +533,12 @@ void cr_bus_write(unsigned int addr, unsigned int data); int aml_new_otg_get_mode(void); int aml_new_usb_get_mode(void); + +int amlogic_crg_host_power(struct usb_phy *p, bool force, bool on); int amlogic_crg_device_usb2_init(u32 phy_id); int amlogic_crg_device_usb2_shutdown(u32 phy_id); +int amlogic_crg_device_power(u32 phy_id, bool force, bool on); + #ifdef CONFIG_AMLOGIC_USB3PHY void aml_new_otg_init(void); #endif