#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
+#include <linux/reset.h>
#include <linux/string.h>
#include <linux/usb/of.h>
#include <linux/workqueue.h>
/******* USB2.0 Host registers (original offset is +0x200) *******/
#define USB2_INT_ENABLE 0x000
+#define USB2_AHB_BUS_CTR 0x008
#define USB2_USBCTR 0x00c
#define USB2_SPD_RSM_TIMSET 0x10c
#define USB2_OC_TIMSET 0x110
#define USB2_INT_ENABLE_USBH_INTB_EN BIT(2) /* For EHCI */
#define USB2_INT_ENABLE_USBH_INTA_EN BIT(1) /* For OHCI */
+/* AHB_BUS_CTR */
+#define USB2_AHB_BUS_CTR_MBL_MASK GENMASK(1, 0)
+#define USB2_AHB_BUS_CTR_MBL_INCR4 2
+
/* USBCTR */
#define USB2_USBCTR_DIRPD BIT(2)
#define USB2_USBCTR_PLL_RST BIT(1)
struct extcon_dev *extcon;
struct rcar_gen3_phy rphys[NUM_OF_PHYS];
struct regulator *vbus;
+ struct reset_control *rstc;
struct work_struct work;
struct mutex lock; /* protects rphys[...].powered */
enum usb_dr_mode dr_mode;
struct rcar_gen3_phy_drv_data {
const struct phy_ops *phy_usb2_ops;
bool no_adp_ctrl;
+ bool init_bus;
};
/*
return candidate;
}
+static int rcar_gen3_phy_usb2_init_bus(struct rcar_gen3_chan *channel)
+{
+ struct device *dev = channel->dev;
+ int ret;
+ u32 val;
+
+ channel->rstc = devm_reset_control_array_get_shared(dev);
+ if (IS_ERR(channel->rstc))
+ return PTR_ERR(channel->rstc);
+
+ ret = pm_runtime_resume_and_get(dev);
+ if (ret)
+ return ret;
+
+ ret = reset_control_deassert(channel->rstc);
+ if (ret)
+ goto rpm_put;
+
+ val = readl(channel->base + USB2_AHB_BUS_CTR);
+ val &= ~USB2_AHB_BUS_CTR_MBL_MASK;
+ val |= USB2_AHB_BUS_CTR_MBL_INCR4;
+ writel(val, channel->base + USB2_AHB_BUS_CTR);
+
+rpm_put:
+ pm_runtime_put(dev);
+
+ return ret;
+}
+
static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
{
const struct rcar_gen3_phy_drv_data *phy_data;
goto error;
}
+ platform_set_drvdata(pdev, channel);
+ channel->dev = dev;
+
+ if (phy_data->init_bus) {
+ ret = rcar_gen3_phy_usb2_init_bus(channel);
+ if (ret)
+ goto error;
+ }
+
channel->soc_no_adp_ctrl = phy_data->no_adp_ctrl;
if (phy_data->no_adp_ctrl)
channel->obint_enable_bits = USB2_OBINT_IDCHG_EN;
channel->vbus = NULL;
}
- platform_set_drvdata(pdev, channel);
- channel->dev = dev;
-
provider = devm_of_phy_provider_register(dev, rcar_gen3_phy_usb2_xlate);
if (IS_ERR(provider)) {
dev_err(dev, "Failed to register PHY provider\n");
if (channel->is_otg_channel)
device_remove_file(&pdev->dev, &dev_attr_role);
+ reset_control_assert(channel->rstc);
pm_runtime_disable(&pdev->dev);
};