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:
dian.shao
2024-08-29 17:27:09 +08:00
committed by gerrit autosubmit
parent 30ab20b79b
commit fcdaffa1b6
9 changed files with 275 additions and 93 deletions
+4
View File
@@ -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 {
+6 -1
View File
@@ -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
View File
@@ -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:
+118 -16
View File
@@ -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;
}
+11 -3
View File
@@ -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));
+30 -32
View File
@@ -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
View File
@@ -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
+4
View File
@@ -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);
+4
View File
@@ -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