Loading Documentation/devicetree/bindings/soc/qcom/qcom,msm-eud.txt +6 −0 Original line number Diff line number Diff line Loading @@ -10,6 +10,10 @@ Required properties: - interrupts: Interrupt number - reg: Should be address and size of EUD register space - reg-names: Should be "eud_base" - clocks: a list of phandles to the PHY clocks. Use as per Documentation/devicetree/bindings/clock/clock-bindings.txt - clock-names: Names of the clocks in 1-1 correspondence with the "clocks" property. Driver notifies clients via extcon for VBUS spoof attach/detach and charger enable/disable events. Clients registered for these Loading @@ -23,6 +27,8 @@ An example for EUD device node: interrupts = <GIC_SPI 492 IRQ_TYPE_LEVEL_HIGH>; reg = <0x88e0000 0x4000>; reg-names = "eud_base"; clocks = <&clock_gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>; clock-names = "cfg_ahb_clk"; }; An example for EUD extcon client: Loading arch/arm64/boot/dts/qcom/sdm845.dtsi +2 −0 Original line number Diff line number Diff line Loading @@ -1881,6 +1881,8 @@ interrupts = <GIC_SPI 492 IRQ_TYPE_LEVEL_HIGH>; reg = <0x88e0000 0x2000>; reg-names = "eud_base"; clocks = <&clock_gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>; clock-names = "cfg_ahb_clk"; status = "ok"; }; Loading drivers/soc/qcom/eud.c +29 −4 Original line number Diff line number Diff line Loading @@ -27,6 +27,8 @@ #include <linux/serial.h> #include <linux/workqueue.h> #include <linux/power_supply.h> #include <linux/clk.h> #include <linux/of.h> #define EUD_ENABLE_CMD 1 #define EUD_DISABLE_CMD 0 Loading Loading @@ -71,6 +73,7 @@ struct eud_chip { struct uart_port port; struct work_struct eud_work; struct power_supply *batt_psy; struct clk *cfg_ahb_clk; }; static const unsigned int eud_extcon_cable[] = { Loading Loading @@ -119,7 +122,7 @@ static void enable_eud(struct platform_device *pdev) /* write into CSR to enable EUD */ writel_relaxed(BIT(0), priv->eud_reg_base + EUD_REG_CSR_EUD_EN); /* Enable vbus, chgr & safe mode warning interrupts */ writel_relaxed(EUD_INT_VBUS | EUD_INT_CHGR | EUD_INT_SAFE_MODE, writel_relaxed(EUD_INT_VBUS | EUD_INT_CHGR, priv->eud_reg_base + EUD_REG_INT1_EN_MASK); /* Ensure Register Writes Complete */ Loading Loading @@ -448,7 +451,11 @@ static irqreturn_t handle_eud_irq(int irq, void *data) { struct eud_chip *chip = data; u32 reg; u32 int_mask_en1 = readl_relaxed(chip->eud_reg_base + u32 int_mask_en1; clk_prepare_enable(chip->cfg_ahb_clk); int_mask_en1 = readl_relaxed(chip->eud_reg_base + EUD_REG_INT1_EN_MASK); /* read status register and find out which interrupt triggered */ Loading @@ -472,9 +479,11 @@ static irqreturn_t handle_eud_irq(int irq, void *data) pet_eud(chip); } else { dev_dbg(chip->dev, "Unknown/spurious EUD Interrupt!\n"); clk_disable_unprepare(chip->cfg_ahb_clk); return IRQ_NONE; } clk_disable_unprepare(chip->cfg_ahb_clk); return IRQ_HANDLED; } Loading @@ -492,6 +501,7 @@ static int msm_eud_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, chip); chip->dev = &pdev->dev; chip->extcon = devm_extcon_dev_allocate(&pdev->dev, eud_extcon_cable); if (IS_ERR(chip->extcon)) { Loading @@ -517,10 +527,25 @@ static int msm_eud_probe(struct platform_device *pdev) if (IS_ERR(chip->eud_reg_base)) return PTR_ERR(chip->eud_reg_base); if (of_property_match_string(pdev->dev.of_node, "clock-names", "cfg_ahb_clk") >= 0) { chip->cfg_ahb_clk = devm_clk_get(&pdev->dev, "cfg_ahb_clk"); if (IS_ERR(chip->cfg_ahb_clk)) { ret = PTR_ERR(chip->cfg_ahb_clk); if (ret != -EPROBE_DEFER) dev_err(chip->dev, "clk get failed for cfg_ahb_clk ret %d\n", ret); return ret; } } chip->eud_irq = platform_get_irq_byname(pdev, "eud_irq"); ret = devm_request_irq(&pdev->dev, chip->eud_irq, handle_eud_irq, IRQF_TRIGGER_HIGH, "eud_irq", chip); ret = devm_request_threaded_irq(&pdev->dev, chip->eud_irq, NULL, handle_eud_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "eud_irq", chip); if (ret) { dev_err(chip->dev, "request failed for eud irq\n"); return ret; Loading Loading
Documentation/devicetree/bindings/soc/qcom/qcom,msm-eud.txt +6 −0 Original line number Diff line number Diff line Loading @@ -10,6 +10,10 @@ Required properties: - interrupts: Interrupt number - reg: Should be address and size of EUD register space - reg-names: Should be "eud_base" - clocks: a list of phandles to the PHY clocks. Use as per Documentation/devicetree/bindings/clock/clock-bindings.txt - clock-names: Names of the clocks in 1-1 correspondence with the "clocks" property. Driver notifies clients via extcon for VBUS spoof attach/detach and charger enable/disable events. Clients registered for these Loading @@ -23,6 +27,8 @@ An example for EUD device node: interrupts = <GIC_SPI 492 IRQ_TYPE_LEVEL_HIGH>; reg = <0x88e0000 0x4000>; reg-names = "eud_base"; clocks = <&clock_gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>; clock-names = "cfg_ahb_clk"; }; An example for EUD extcon client: Loading
arch/arm64/boot/dts/qcom/sdm845.dtsi +2 −0 Original line number Diff line number Diff line Loading @@ -1881,6 +1881,8 @@ interrupts = <GIC_SPI 492 IRQ_TYPE_LEVEL_HIGH>; reg = <0x88e0000 0x2000>; reg-names = "eud_base"; clocks = <&clock_gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>; clock-names = "cfg_ahb_clk"; status = "ok"; }; Loading
drivers/soc/qcom/eud.c +29 −4 Original line number Diff line number Diff line Loading @@ -27,6 +27,8 @@ #include <linux/serial.h> #include <linux/workqueue.h> #include <linux/power_supply.h> #include <linux/clk.h> #include <linux/of.h> #define EUD_ENABLE_CMD 1 #define EUD_DISABLE_CMD 0 Loading Loading @@ -71,6 +73,7 @@ struct eud_chip { struct uart_port port; struct work_struct eud_work; struct power_supply *batt_psy; struct clk *cfg_ahb_clk; }; static const unsigned int eud_extcon_cable[] = { Loading Loading @@ -119,7 +122,7 @@ static void enable_eud(struct platform_device *pdev) /* write into CSR to enable EUD */ writel_relaxed(BIT(0), priv->eud_reg_base + EUD_REG_CSR_EUD_EN); /* Enable vbus, chgr & safe mode warning interrupts */ writel_relaxed(EUD_INT_VBUS | EUD_INT_CHGR | EUD_INT_SAFE_MODE, writel_relaxed(EUD_INT_VBUS | EUD_INT_CHGR, priv->eud_reg_base + EUD_REG_INT1_EN_MASK); /* Ensure Register Writes Complete */ Loading Loading @@ -448,7 +451,11 @@ static irqreturn_t handle_eud_irq(int irq, void *data) { struct eud_chip *chip = data; u32 reg; u32 int_mask_en1 = readl_relaxed(chip->eud_reg_base + u32 int_mask_en1; clk_prepare_enable(chip->cfg_ahb_clk); int_mask_en1 = readl_relaxed(chip->eud_reg_base + EUD_REG_INT1_EN_MASK); /* read status register and find out which interrupt triggered */ Loading @@ -472,9 +479,11 @@ static irqreturn_t handle_eud_irq(int irq, void *data) pet_eud(chip); } else { dev_dbg(chip->dev, "Unknown/spurious EUD Interrupt!\n"); clk_disable_unprepare(chip->cfg_ahb_clk); return IRQ_NONE; } clk_disable_unprepare(chip->cfg_ahb_clk); return IRQ_HANDLED; } Loading @@ -492,6 +501,7 @@ static int msm_eud_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, chip); chip->dev = &pdev->dev; chip->extcon = devm_extcon_dev_allocate(&pdev->dev, eud_extcon_cable); if (IS_ERR(chip->extcon)) { Loading @@ -517,10 +527,25 @@ static int msm_eud_probe(struct platform_device *pdev) if (IS_ERR(chip->eud_reg_base)) return PTR_ERR(chip->eud_reg_base); if (of_property_match_string(pdev->dev.of_node, "clock-names", "cfg_ahb_clk") >= 0) { chip->cfg_ahb_clk = devm_clk_get(&pdev->dev, "cfg_ahb_clk"); if (IS_ERR(chip->cfg_ahb_clk)) { ret = PTR_ERR(chip->cfg_ahb_clk); if (ret != -EPROBE_DEFER) dev_err(chip->dev, "clk get failed for cfg_ahb_clk ret %d\n", ret); return ret; } } chip->eud_irq = platform_get_irq_byname(pdev, "eud_irq"); ret = devm_request_irq(&pdev->dev, chip->eud_irq, handle_eud_irq, IRQF_TRIGGER_HIGH, "eud_irq", chip); ret = devm_request_threaded_irq(&pdev->dev, chip->eud_irq, NULL, handle_eud_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "eud_irq", chip); if (ret) { dev_err(chip->dev, "request failed for eud irq\n"); return ret; Loading