aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Shields <simon@lineageos.org>2018-05-02 01:29:30 +1000
committerDenis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org>2020-03-28 01:13:54 +0100
commitc5a09997b282ee928293543967db1746ef70eefe (patch)
treef08d132ef6b0ff586fa6d54843d5cec36c56e8dc
parent07e78e4cb879c0a933139d7280d83e8027ad10f5 (diff)
downloadu-boot-midas-c5a09997b282ee928293543967db1746ef70eefe.tar.gz
u-boot-midas-c5a09997b282ee928293543967db1746ef70eefe.tar.bz2
u-boot-midas-c5a09997b282ee928293543967db1746ef70eefe.zip
drivers: introduce the extcon subsystem
Loosely modelled on the Linux kernel's equivalent, the extcon subsystem provides a generic layer for detecting whether or not cables are plugged in, the type of said cables, and the ability of said cables to charge the board. The "extcon" subsystem loosely occupies the position of a "MUIC" in the PMIC dm hierarchy.
-rw-r--r--drivers/Kconfig2
-rw-r--r--drivers/Makefile1
-rw-r--r--drivers/extcon/Kconfig13
-rw-r--r--drivers/extcon/Makefile7
-rw-r--r--drivers/extcon/extcon-uclass.c217
-rw-r--r--include/dm/uclass-id.h1
-rw-r--r--include/extcon.h102
7 files changed, 343 insertions, 0 deletions
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 9e21b28750..c9f60faaab 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -28,6 +28,8 @@ source "drivers/dfu/Kconfig"
source "drivers/dma/Kconfig"
+source "drivers/extcon/Kconfig"
+
source "drivers/fastboot/Kconfig"
source "drivers/firmware/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index a213ea9671..abbcbe0dda 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -71,6 +71,7 @@ obj-y += block/
obj-$(CONFIG_BOOTCOUNT_LIMIT) += bootcount/
obj-$(CONFIG_CPU) += cpu/
obj-y += crypto/
+obj-$(CONFIG_DM_EXTCON) += extcon/
obj-$(CONFIG_FASTBOOT) += fastboot/
obj-y += firmware/
obj-$(CONFIG_FPGA) += fpga/
diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig
new file mode 100644
index 0000000000..eedd2376bd
--- /dev/null
+++ b/drivers/extcon/Kconfig
@@ -0,0 +1,13 @@
+menu "Extcon support"
+
+config DM_EXTCON
+ bool "Enable Driver Model for external connector drivers (UCLASS_EXTCON)"
+ depends on DM
+ ---help---
+ This config enables driver-model support for extcon devices, which provide
+ an interface to get information about currently plugged in cables.
+ For more information, see these files:
+ - 'include/extcon.h'
+ - 'drivers/extcon/extcon-uclass.c'
+
+endmenu
diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile
new file mode 100644
index 0000000000..d49dbc2489
--- /dev/null
+++ b/drivers/extcon/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright (C) 2018 Simon Shields <simon@lineageos.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-$(CONFIG_DM_EXTCON) += extcon-uclass.o
diff --git a/drivers/extcon/extcon-uclass.c b/drivers/extcon/extcon-uclass.c
new file mode 100644
index 0000000000..1ea480592b
--- /dev/null
+++ b/drivers/extcon/extcon-uclass.c
@@ -0,0 +1,217 @@
+#include <common.h>
+#include <dm.h>
+#include <dm/uclass-internal.h>
+#include <extcon.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static const struct __extcon_info {
+ unsigned int type;
+ unsigned int id;
+ const char *name;
+} extcon_info[] = {
+ [EXTCON_NONE] = {
+ .type = EXTCON_TYPE_MISC,
+ .id = EXTCON_NONE,
+ .name = "NONE",
+ },
+
+ /* USB external connector */
+ [EXTCON_USB] = {
+ .type = EXTCON_TYPE_USB,
+ .id = EXTCON_USB,
+ .name = "USB",
+ },
+ [EXTCON_USB_HOST] = {
+ .type = EXTCON_TYPE_USB,
+ .id = EXTCON_USB_HOST,
+ .name = "USB-HOST",
+ },
+
+ /* Charging external connector */
+ [EXTCON_CHG_USB_SDP] = {
+ .type = EXTCON_TYPE_CHG | EXTCON_TYPE_USB,
+ .id = EXTCON_CHG_USB_SDP,
+ .name = "SDP",
+ },
+ [EXTCON_CHG_USB_DCP] = {
+ .type = EXTCON_TYPE_CHG | EXTCON_TYPE_USB,
+ .id = EXTCON_CHG_USB_DCP,
+ .name = "DCP",
+ },
+ [EXTCON_CHG_USB_CDP] = {
+ .type = EXTCON_TYPE_CHG | EXTCON_TYPE_USB,
+ .id = EXTCON_CHG_USB_CDP,
+ .name = "CDP",
+ },
+ [EXTCON_CHG_USB_ACA] = {
+ .type = EXTCON_TYPE_CHG | EXTCON_TYPE_USB,
+ .id = EXTCON_CHG_USB_ACA,
+ .name = "ACA",
+ },
+ [EXTCON_CHG_USB_FAST] = {
+ .type = EXTCON_TYPE_CHG | EXTCON_TYPE_USB,
+ .id = EXTCON_CHG_USB_FAST,
+ .name = "FAST-CHARGER",
+ },
+ [EXTCON_CHG_USB_SLOW] = {
+ .type = EXTCON_TYPE_CHG | EXTCON_TYPE_USB,
+ .id = EXTCON_CHG_USB_SLOW,
+ .name = "SLOW-CHARGER",
+ },
+ [EXTCON_CHG_WPT] = {
+ .type = EXTCON_TYPE_CHG,
+ .id = EXTCON_CHG_WPT,
+ .name = "WPT",
+ },
+ [EXTCON_CHG_USB_PD] = {
+ .type = EXTCON_TYPE_CHG | EXTCON_TYPE_USB,
+ .id = EXTCON_CHG_USB_PD,
+ .name = "PD",
+ },
+
+ /* Jack external connector */
+ [EXTCON_JACK_MICROPHONE] = {
+ .type = EXTCON_TYPE_JACK,
+ .id = EXTCON_JACK_MICROPHONE,
+ .name = "MICROPHONE",
+ },
+ [EXTCON_JACK_HEADPHONE] = {
+ .type = EXTCON_TYPE_JACK,
+ .id = EXTCON_JACK_HEADPHONE,
+ .name = "HEADPHONE",
+ },
+ [EXTCON_JACK_LINE_IN] = {
+ .type = EXTCON_TYPE_JACK,
+ .id = EXTCON_JACK_LINE_IN,
+ .name = "LINE-IN",
+ },
+ [EXTCON_JACK_LINE_OUT] = {
+ .type = EXTCON_TYPE_JACK,
+ .id = EXTCON_JACK_LINE_OUT,
+ .name = "LINE-OUT",
+ },
+ [EXTCON_JACK_VIDEO_IN] = {
+ .type = EXTCON_TYPE_JACK,
+ .id = EXTCON_JACK_VIDEO_IN,
+ .name = "VIDEO-IN",
+ },
+ [EXTCON_JACK_VIDEO_OUT] = {
+ .type = EXTCON_TYPE_JACK,
+ .id = EXTCON_JACK_VIDEO_OUT,
+ .name = "VIDEO-OUT",
+ },
+ [EXTCON_JACK_SPDIF_IN] = {
+ .type = EXTCON_TYPE_JACK,
+ .id = EXTCON_JACK_SPDIF_IN,
+ .name = "SPDIF-IN",
+ },
+ [EXTCON_JACK_SPDIF_OUT] = {
+ .type = EXTCON_TYPE_JACK,
+ .id = EXTCON_JACK_SPDIF_OUT,
+ .name = "SPDIF-OUT",
+ },
+
+ /* Display external connector */
+ [EXTCON_DISP_HDMI] = {
+ .type = EXTCON_TYPE_DISP,
+ .id = EXTCON_DISP_HDMI,
+ .name = "HDMI",
+ },
+ [EXTCON_DISP_MHL] = {
+ .type = EXTCON_TYPE_DISP,
+ .id = EXTCON_DISP_MHL,
+ .name = "MHL",
+ },
+ [EXTCON_DISP_DVI] = {
+ .type = EXTCON_TYPE_DISP,
+ .id = EXTCON_DISP_DVI,
+ .name = "DVI",
+ },
+ [EXTCON_DISP_VGA] = {
+ .type = EXTCON_TYPE_DISP,
+ .id = EXTCON_DISP_VGA,
+ .name = "VGA",
+ },
+ [EXTCON_DISP_DP] = {
+ .type = EXTCON_TYPE_DISP | EXTCON_TYPE_USB,
+ .id = EXTCON_DISP_DP,
+ .name = "DP",
+ },
+ [EXTCON_DISP_HMD] = {
+ .type = EXTCON_TYPE_DISP | EXTCON_TYPE_USB,
+ .id = EXTCON_DISP_HMD,
+ .name = "HMD",
+ },
+
+ /* Miscellaneous external connector */
+ [EXTCON_DOCK] = {
+ .type = EXTCON_TYPE_MISC,
+ .id = EXTCON_DOCK,
+ .name = "DOCK",
+ },
+ [EXTCON_JIG] = {
+ .type = EXTCON_TYPE_MISC,
+ .id = EXTCON_JIG,
+ .name = "JIG",
+ },
+ [EXTCON_MECHANICAL] = {
+ .type = EXTCON_TYPE_MISC,
+ .id = EXTCON_MECHANICAL,
+ .name = "MECHANICAL",
+ },
+
+ { /* sentinel */ }
+};
+
+int extcon_get(const char *devname, struct udevice **devp)
+{
+ return uclass_get_device_by_name(UCLASS_EXTCON, devname, devp);
+}
+
+int extcon_get_cable_id(struct udevice *dev, int *type)
+{
+ const struct dm_extcon_ops *ops = dev_get_driver_ops(dev);
+ int id;
+
+ if (!ops || !ops->get_cable_id)
+ return -ENOSYS;
+
+ id = ops->get_cable_id(dev);
+ if (id < EXTCON_NONE || id >= EXTCON_NUM)
+ return id;
+
+ if (type)
+ *type = extcon_info[id].type;
+
+ return id;
+}
+
+int extcon_get_max_charge_current(struct udevice *dev)
+{
+ const struct dm_extcon_ops *ops = dev_get_driver_ops(dev);
+
+ if (!ops)
+ return -ENOSYS;
+
+ if (!ops->get_max_charge_current)
+ /* not an error to not implement this function */
+ return 0;
+
+ return ops->get_max_charge_current(dev);
+}
+
+const char *extcon_get_cable_name(int id) {
+ if (id < EXTCON_NONE || id >= EXTCON_NUM)
+ return "Unknown";
+
+ if (extcon_info[id].id != id)
+ return "Unknown";
+
+ return extcon_info[id].name;
+}
+
+UCLASS_DRIVER(extcon) = {
+ .id = UCLASS_EXTCON,
+ .name = "extcon",
+};
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index d7f9df3583..35990d0b03 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -36,6 +36,7 @@ enum uclass_id {
UCLASS_DMA, /* Direct Memory Access */
UCLASS_EFI, /* EFI managed devices */
UCLASS_ETH, /* Ethernet device */
+ UCLASS_EXTCON, /* External Connector (e.g. USB port, audio jack) */
UCLASS_GPIO, /* Bank of general-purpose I/O pins */
UCLASS_FIRMWARE, /* Firmware */
UCLASS_I2C, /* I2C bus */
diff --git a/include/extcon.h b/include/extcon.h
new file mode 100644
index 0000000000..2041e98821
--- /dev/null
+++ b/include/extcon.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2018 Simon Shields <simon@lineageos.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _INCLUDE_MUIC_H
+#define _INCLUDE_MUIC_H
+
+#include <linux/bitops.h>
+
+/* Following the Linux kernel */
+/*
+ * Define the type of supported external connectors
+ */
+#define EXTCON_TYPE_USB BIT(0) /* USB connector */
+#define EXTCON_TYPE_CHG BIT(1) /* Charger connector */
+#define EXTCON_TYPE_JACK BIT(2) /* Jack connector */
+#define EXTCON_TYPE_DISP BIT(3) /* Display connector */
+#define EXTCON_TYPE_MISC BIT(4) /* Miscellaneous connector */
+
+/*
+ * Define the unique id of supported external connectors
+ */
+#define EXTCON_NONE 0
+
+/* USB external connector */
+#define EXTCON_USB 1
+#define EXTCON_USB_HOST 2
+
+/*
+ * Charging external connector
+ *
+ * When one SDP charger connector was reported, we should also report
+ * the USB connector, which means EXTCON_CHG_USB_SDP should always
+ * appear together with EXTCON_USB. The same as ACA charger connector,
+ * EXTCON_CHG_USB_ACA would normally appear with EXTCON_USB_HOST.
+ *
+ * The EXTCON_CHG_USB_SLOW connector can provide at least 500mA of
+ * current at 5V. The EXTCON_CHG_USB_FAST connector can provide at
+ * least 1A of current at 5V.
+ */
+#define EXTCON_CHG_USB_SDP 5 /* Standard Downstream Port */
+#define EXTCON_CHG_USB_DCP 6 /* Dedicated Charging Port */
+#define EXTCON_CHG_USB_CDP 7 /* Charging Downstream Port */
+#define EXTCON_CHG_USB_ACA 8 /* Accessory Charger Adapter */
+#define EXTCON_CHG_USB_FAST 9
+#define EXTCON_CHG_USB_SLOW 10
+#define EXTCON_CHG_WPT 11 /* Wireless Power Transfer */
+#define EXTCON_CHG_USB_PD 12 /* USB Power Delivery */
+
+/* Jack external connector */
+#define EXTCON_JACK_MICROPHONE 20
+#define EXTCON_JACK_HEADPHONE 21
+#define EXTCON_JACK_LINE_IN 22
+#define EXTCON_JACK_LINE_OUT 23
+#define EXTCON_JACK_VIDEO_IN 24
+#define EXTCON_JACK_VIDEO_OUT 25
+#define EXTCON_JACK_SPDIF_IN 26 /* Sony Philips Digital InterFace */
+#define EXTCON_JACK_SPDIF_OUT 27
+
+/* Display external connector */
+#define EXTCON_DISP_HDMI 40 /* High-Definition Multimedia Interface */
+#define EXTCON_DISP_MHL 41 /* Mobile High-Definition Link */
+#define EXTCON_DISP_DVI 42 /* Digital Visual Interface */
+#define EXTCON_DISP_VGA 43 /* Video Graphics Array */
+#define EXTCON_DISP_DP 44 /* Display Port */
+#define EXTCON_DISP_HMD 45 /* Head-Mounted Display */
+
+/* Miscellaneous external connector */
+#define EXTCON_DOCK 60
+#define EXTCON_JIG 61
+#define EXTCON_MECHANICAL 62
+
+#define EXTCON_NUM 63
+
+/* MUIC device operations */
+struct dm_extcon_ops {
+ /**
+ * Get the current cable id.
+ * @dev - extcon device
+ * @return cable ID, EXTCON_NONE <= cable ID < EXTCON_NUM
+ */
+ int (*get_cable_id)(struct udevice *dev);
+ /**
+ * Get maximum charging current support by currently attached cable.
+ * This function may be NULL if that doesn't make sense for this connector.
+ * The value returned here may not necessarily correspond to the maximum
+ * input current the device itself is able to take - that may depend
+ * on other factors.
+ * @dev - extcon device
+ * @return - Maximum charging current supported by the currently attached cable in uA,
+ * or zero if the cable doesn't support charging.
+ */
+ int (*get_max_charge_current)(struct udevice *udev);
+};
+
+int extcon_get(const char *devname, struct udevice **devp);
+int extcon_get_cable_id(struct udevice *dev, int *type);
+int extcon_get_max_charge_current(struct udevice *udev);
+const char *extcon_get_cable_name(int id);
+#endif