mirror of
https://github.com/hardkernel/kernel_common_drivers.git
synced 2026-06-25 12:03:48 +09:00
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 <dian.shao@amlogic.com>
This commit is contained in:
committed by
gerrit autosubmit
parent
30ab20b79b
commit
fcdaffa1b6
@@ -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 {
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <linux/clk.h>
|
||||
#include <linux/phy/phy.h>
|
||||
#include <linux/amlogic/aml_gpio_consumer.h>
|
||||
#include <linux/amlogic/usb-v2.h>
|
||||
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/amlogic/cpu_version.h>
|
||||
@@ -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);
|
||||
|
||||
+84
-40
@@ -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:
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <linux/amlogic/gki_module.h>
|
||||
#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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
+14
-1
@@ -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
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
|
||||
#ifndef _USB_MAIN_H__
|
||||
#define _USB_MAIN_H__
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/usb.h>
|
||||
|
||||
extern struct dentry *amlogic_usb_debugfs_root;
|
||||
|
||||
#if IS_ENABLED(CONFIG_AMLOGIC_USBPHY)
|
||||
int __init amlogic_new_usb3_v2_driver_init(void);
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user