#include <linux/regulator/consumer.h>
#include <linux/soc/samsung/exynos-regs-pmu.h>
#include <linux/usb/typec.h>
+#include <linux/usb/typec_mux.h>
/* Exynos USB PHY registers */
#define EXYNOS5_FSEL_9MHZ6 0x0
* @extrefclk: frequency select settings when using 'separate
* reference clocks' for SS and HS operations
* @regulators: regulators for phy
+ * @sw: TypeC orientation switch handle
* @orientation: TypeC connector orientation - normal or flipped
*/
struct exynos5_usbdrd_phy {
u32 extrefclk;
struct regulator_bulk_data *regulators;
+ struct typec_switch_dev *sw;
enum typec_orientation orientation;
};
return 0;
}
+static int exynos5_usbdrd_orien_sw_set(struct typec_switch_dev *sw,
+ enum typec_orientation orientation)
+{
+ struct exynos5_usbdrd_phy *phy_drd = typec_switch_get_drvdata(sw);
+
+ scoped_guard(mutex, &phy_drd->phy_mutex)
+ phy_drd->orientation = orientation;
+
+ return 0;
+}
+
+static void exynos5_usbdrd_orien_switch_unregister(void *data)
+{
+ struct exynos5_usbdrd_phy *phy_drd = data;
+
+ typec_switch_unregister(phy_drd->sw);
+}
+
+static int exynos5_usbdrd_setup_notifiers(struct exynos5_usbdrd_phy *phy_drd)
+{
+ int ret;
+
+ if (!IS_ENABLED(CONFIG_TYPEC))
+ return 0;
+
+ if (device_property_present(phy_drd->dev, "orientation-switch")) {
+ struct typec_switch_desc sw_desc = { };
+
+ sw_desc.drvdata = phy_drd;
+ sw_desc.fwnode = dev_fwnode(phy_drd->dev);
+ sw_desc.set = exynos5_usbdrd_orien_sw_set;
+
+ phy_drd->sw = typec_switch_register(phy_drd->dev, &sw_desc);
+ if (IS_ERR(phy_drd->sw))
+ return dev_err_probe(phy_drd->dev,
+ PTR_ERR(phy_drd->sw),
+ "Failed to register TypeC orientation switch\n");
+
+ ret = devm_add_action_or_reset(phy_drd->dev,
+ exynos5_usbdrd_orien_switch_unregister,
+ phy_drd);
+ if (ret)
+ return dev_err_probe(phy_drd->dev, ret,
+ "Failed to register TypeC orientation devm action\n");
+ }
+
+ return 0;
+}
+
static const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = {
{
.id = EXYNOS5_DRDPHY_UTMI,
if (ret)
return dev_err_probe(dev, ret, "failed to get regulators\n");
+ ret = exynos5_usbdrd_setup_notifiers(phy_drd);
+ if (ret)
+ return ret;
+
dev_vdbg(dev, "Creating usbdrd_phy phy\n");
for (i = 0; i < EXYNOS5_DRDPHYS_NUM; i++) {