Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c2fda30f authored by Pavankumar Kondeti's avatar Pavankumar Kondeti
Browse files

USB: ice40-hcd: Add XO clock support



The bridge chip require a 19.2MHz clock for USB operations.
It is supplied by the PMIC on MSM8916. Add the XO clock.
The XO clock can operate either in pin-control or direct
mode. When it operates in pin-control mode, the clk-en gpio
also needs to be asserted to enable the clock.

Change-Id: Id181fd5edfe22c57f3c958e081454b4fe987a097
Signed-off-by: default avatarPavankumar Kondeti <pkondeti@codeaurora.org>
parent b5c75c4d
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -19,6 +19,9 @@ Required properties:

Optional properties:
- interrupts: IRQ lines used by this controller
- clocks: List of clock phandles.
- clock-names: List of clock names. Supported clock name string is
  "xo"
- clk-en-gpio: gpio used to enable the 19.2 MHZ clock to the bridge
  chip. If it is not present, assume that the clock is available on
  the bridge chip board.
@@ -41,5 +44,8 @@ Optional properties:
			lattice,slave-select-gpio = <&msmgpio 118 0>;
			lattice,config-done-gpio = <&msmgpio 115 0>;
			lattice,vcc-en-gpio = <&msmgpio 117 0>;

			clocks = <&clock_rpm clk_bb_clk2_pin>;
			clock-names = "xo";
		};
	};
+50 −2
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include <linux/uaccess.h>
#include <linux/debugfs.h>
#include <linux/pm_runtime.h>
#include <linux/clk.h>
#include <linux/regulator/consumer.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
@@ -151,6 +152,8 @@ struct ice40_hcd {
	struct workqueue_struct *wq;
	struct work_struct async_work;

	struct clk *xo_clk;

	int reset_gpio;
	int slave_select_gpio;
	int config_done_gpio;
@@ -1368,6 +1371,8 @@ static void ice40_spi_power_off(struct ice40_hcd *ihcd)
		regulator_disable(ihcd->gpio_vcc);
	if (ihcd->clk_en_gpio)
		gpio_direction_output(ihcd->clk_en_gpio, 0);
	if (ihcd->xo_clk)
		clk_disable_unprepare(ihcd->xo_clk);

	ihcd->powered = false;
}
@@ -1376,11 +1381,19 @@ static int ice40_spi_power_up(struct ice40_hcd *ihcd)
{
	int ret;

	if (ihcd->xo_clk) {
		ret = clk_prepare_enable(ihcd->xo_clk);
		if (ret < 0) {
			pr_err("fail to enable xo clk %d\n", ret);
			goto out;
		}
	}

	if (ihcd->clk_en_gpio) {
		ret = gpio_direction_output(ihcd->clk_en_gpio, 1);
		if (ret < 0) {
			pr_err("fail to enabel clk %d\n", ret);
			goto out;
			pr_err("fail to enable clk %d\n", ret);
			goto disable_xo;
		}
	}

@@ -1424,6 +1437,9 @@ disable_gpio_vcc:
disable_clk:
	if (ihcd->clk_en_gpio)
		gpio_direction_output(ihcd->clk_en_gpio, 0);
disable_xo:
	if (ihcd->xo_clk)
		clk_disable_unprepare(ihcd->xo_clk);
out:
	return ret;
}
@@ -1599,6 +1615,32 @@ out:
	return ret;
}

static int ice40_spi_init_clocks(struct ice40_hcd *ihcd)
{
	int ret = 0;

	/*
	 * XO clock is the only supported clock. So no need to parse
	 * the clock-names string. If there is no clock-names property,
	 * there will not be XO clock.
	 *
	 * This XO clock can be either direct clock or pin control clock.
	 * if it is pin control clock, clk_en gpio is used to control
	 * the clock.
	 */
	if (!of_get_property(ihcd->spi->dev.of_node, "clock-names", NULL))
		return 0;

	ihcd->xo_clk = devm_clk_get(&ihcd->spi->dev, "xo");
	if (IS_ERR(ihcd->xo_clk)) {
		ret = PTR_ERR(ihcd->xo_clk);
		if (ret != -EPROBE_DEFER)
			pr_err("fail to get xo clk %d\n", ret);
	}

	return ret;
}

static int ice40_spi_init_regulators(struct ice40_hcd *ihcd)
{
	int ret;
@@ -1952,6 +1994,12 @@ static int ice40_spi_probe(struct spi_device *spi)
		goto out;
	}

	ret = ice40_spi_init_clocks(ihcd);
	if (ret) {
		pr_err("fail to init clocks\n");
		goto out;
	}

	ret = ice40_spi_init_regulators(ihcd);
	if (ret) {
		pr_err("fail to init regulators\n");