summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/boot/dts/omap3-minnow.dtsi13
-rw-r--r--arch/arm/mach-omap2/board-minnow.c21
-rw-r--r--drivers/usb/phy/phy-tusb.c36
-rw-r--r--[-rwxr-xr-x]drivers/video/omap2/displays/panel-minnow.c50
4 files changed, 102 insertions, 18 deletions
diff --git a/arch/arm/boot/dts/omap3-minnow.dtsi b/arch/arm/boot/dts/omap3-minnow.dtsi
index 4c6fb7f4efd..22c272b84a0 100644
--- a/arch/arm/boot/dts/omap3-minnow.dtsi
+++ b/arch/arm/boot/dts/omap3-minnow.dtsi
@@ -42,6 +42,15 @@
};
+ /* external 26MHz clock which is controlled by gpio
+ * it's used for both Display Bridge and USB
+ */
+ periph_26mhz {
+ compatible = "gpio-clock";
+ #clock-cells = <0>;
+ enable-gpios = <&gpio6 17 0>; /* GPIO-177, OF_GPIO_ACTIVE_HIGH */
+ };
+
Display@0 {
compatible = "mot,minnow-panel-dsi-cm";
bridge-supply = <&ldo1_reg>;
@@ -53,7 +62,7 @@
id_panel = <2>;
gpio_panel_reset = <&gpio1 14 0>; /* RESET gpio-14 */
gpio_bridge_reset = <&gpio1 23 0>; /* RESET gpio-23 */
- gpio_clk_en = <&gpio6 17 0>; /* RESET gpio-177 */
+ clk_in = "periph_26mhz"; /* external 26MHz clock */
/* declare it if ext_te enable */
//gpio_te = <&gpio1 0 0>; /* EXT_TE gpio-0 */
//pins = <0 1 2 3>; /* DSI Pin config */
@@ -97,6 +106,7 @@
"tusb-resetn",
"tusb-cs",
"tusb-csn";
+ clk_in = "periph_26mhz"; /* external 26MHz clock */
reg = <0 0>;
};
@@ -494,6 +504,7 @@
0x19c 0x100 /* MCSPI1_SOMI, MODE0 | INPUT */
0x19e 0x000 /* MCSPI1_CS0, MODE0 | OUTPUT */
0x1a0 0x000 /* MCSPI1_CS1, MODE0 | OUTPUT */
+ 0x1a4 0x004 /* MCSPI1_CS3, MODE4 | OUTPUT */
0x1ae 0x004 /* MCSPI2_CS1, MODE4 | OUTPUT */
0x1b0 0x104 /* SYS_NIRQ, MODE4 | INPUT */
0x1b2 0x004 /* SYS_CLKOUT2, MODE4 | OUTPUT */
diff --git a/arch/arm/mach-omap2/board-minnow.c b/arch/arm/mach-omap2/board-minnow.c
index a41cec2a705..82748e2f6ce 100644
--- a/arch/arm/mach-omap2/board-minnow.c
+++ b/arch/arm/mach-omap2/board-minnow.c
@@ -18,6 +18,8 @@
#include <linux/usb/phy.h>
#include <linux/usb/nop-usb-xceiv.h>
#include <linux/ti_wilink_st.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
#include "mux.h"
#include "common.h"
#include "dss-common.h"
@@ -77,10 +79,27 @@ static inline void __init minnow_init_btwilink(void)
platform_device_register(&hci_tty_device);
}
+static void __init minnow_init_gpio_clock(void)
+{
+ struct of_phandle_args clkspec;
+ struct clk *clk;
+ struct clk_lookup *cl;
+ clkspec.np = of_find_compatible_node(NULL, NULL, "gpio-clock");
+ if (clkspec.np) {
+ of_gpio_clk_setup(clkspec.np);
+ clk = of_clk_get_from_provider(&clkspec);
+ if (!IS_ERR(clk)) {
+ cl = clkdev_alloc(clk, clkspec.np->name, NULL);
+ if (cl)
+ clkdev_add(cl);
+ }
+ }
+}
+
static void __init minnow_init(void)
{
of_platform_populate(NULL, omap_dt_match_table, NULL, NULL);
-
+ minnow_init_gpio_clock();
omap_sdrc_init(JEDEC_JESD209A_sdrc_params, JEDEC_JESD209A_sdrc_params);
omap3_enable_usim_buffer(); /* Needed for GPIOs in USIM block */
omap_minnow_display_init();
diff --git a/drivers/usb/phy/phy-tusb.c b/drivers/usb/phy/phy-tusb.c
index 997a92acadc..60ba8ec1f53 100644
--- a/drivers/usb/phy/phy-tusb.c
+++ b/drivers/usb/phy/phy-tusb.c
@@ -34,6 +34,7 @@
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/module.h>
+#include <linux/clk.h>
static bool factory_override;
@@ -46,6 +47,8 @@ struct tusb_usb {
int irq_gpio;
int num_gpios;
struct gpio *gpio_list;
+ struct clk *clk_in;
+ bool clk_in_en;
};
static int tusb_set_suspend(struct usb_phy *x, int suspend)
@@ -86,6 +89,20 @@ static int tusb_usb_start_srp(struct usb_otg *otg)
return 0;
}
+static int tusb_usb_enable_clkin(struct tusb_usb *tusb, bool enable)
+{
+ int r = 0;
+ if ((tusb->clk_in_en != enable) && (tusb->clk_in != NULL)) {
+ if (enable)
+ r = clk_prepare_enable(tusb->clk_in);
+ else
+ clk_disable_unprepare(tusb->clk_in);
+ if (!r)
+ tusb->clk_in_en = enable;
+ }
+ return r;
+}
+
static void tusb_usb_work_func(struct work_struct *work)
{
struct tusb_usb *tusb =
@@ -116,6 +133,9 @@ static void tusb_usb_work_func(struct work_struct *work)
dev_info(tusb->dev, "%s USB phy [%d/%d]\n",
(vbus_state | factory_override) ? "Enable" : "Disable",
vbus_state, factory_override);
+ /* enable external clock at first */
+ if (vbus_state | factory_override)
+ tusb_usb_enable_clkin(tusb, true);
for (i = 0; i < tusb->num_gpios; i++) {
if (!(tusb->gpio_list[i].flags & GPIOF_DIR_IN)) {
bool default_level =
@@ -124,6 +144,9 @@ static void tusb_usb_work_func(struct work_struct *work)
(vbus_state | factory_override) ^ default_level);
}
}
+ /* disable external clock at last */
+ if (!(vbus_state | factory_override))
+ tusb_usb_enable_clkin(tusb, false);
if (wake_lock_active(&tusb->wake_lock))
wake_unlock(&tusb->wake_lock);
@@ -145,6 +168,7 @@ static int tusb_parse_of(struct platform_device *pdev, struct tusb_usb *tusb)
int i;
struct device_node *np = pdev->dev.of_node;
enum of_gpio_flags flags;
+ char *clkin;
if (!tusb)
return -EINVAL;
@@ -182,6 +206,18 @@ static int tusb_parse_of(struct platform_device *pdev, struct tusb_usb *tusb)
tusb->gpio_list[i].flags);
}
+ clkin = (char *)of_get_property(np, "clk_in", NULL);
+ if (clkin) {
+ tusb->clk_in = clk_get(NULL, clkin);
+ if (IS_ERR(tusb->clk_in)) {
+ dev_err(&pdev->dev,
+ "Failed get external clock %s!\n", clkin);
+ i = PTR_ERR(tusb->clk_in);
+ tusb->clk_in = NULL;
+ return i;
+ }
+ }
+
return 0;
}
diff --git a/drivers/video/omap2/displays/panel-minnow.c b/drivers/video/omap2/displays/panel-minnow.c
index 97cbdd17db6..ed9b9c7eea8 100755..100644
--- a/drivers/video/omap2/displays/panel-minnow.c
+++ b/drivers/video/omap2/displays/panel-minnow.c
@@ -32,6 +32,7 @@
#include <linux/slab.h>
#include <linux/mutex.h>
#include <linux/regulator/consumer.h>
+#include <linux/clk.h>
#include <video/omapdss.h>
#include <video/omap-panel-data.h>
@@ -385,10 +386,11 @@ struct minnow_panel_data {
/* panel HW configuration from DT or platform data */
int reset_gpio[MINNOW_COMPONENT_MAX];
int ext_te_gpio;
- int clk_en_gpio;
int vio_en_gpio;
struct minnow_panel_hw_reset hw_reset[MINNOW_COMPONENT_MAX];
struct regulator *regulators[MINNOW_COMPONENT_MAX];
+ struct clk *clk_in;
+ bool clk_in_en;
bool use_dsi_backlight;
@@ -1529,6 +1531,21 @@ static void minnow_panel_enable_vio(struct minnow_panel_data *mpd, bool enable)
gpio_set_value(mpd->vio_en_gpio, enable ? 0 : 1);
}
+static int minnow_panel_enable_clkin(struct minnow_panel_data *mpd,
+ bool enable)
+{
+ int r = 0;
+ if ((mpd->clk_in_en != enable) && (mpd->clk_in != NULL)) {
+ if (enable)
+ r = clk_prepare_enable(mpd->clk_in);
+ else
+ clk_disable_unprepare(mpd->clk_in);
+ if (!r)
+ mpd->clk_in_en = enable;
+ }
+ return r;
+}
+
#define DEBUG_DT
#ifdef DEBUG_DT
#define DTINFO(fmt, ...) \
@@ -1561,6 +1578,7 @@ static int minnow_panel_dt_init(struct minnow_panel_data *mpd)
u32 range[2], value = 0;
struct minnow_panel_attr *panel_attr;
struct device_node *dt_node;
+ char *clkin;
dt_node = of_find_matching_node(NULL, minnow_panel_ids);
if (dt_node == NULL) {
@@ -1609,11 +1627,19 @@ static int minnow_panel_dt_init(struct minnow_panel_data *mpd)
mpd->reset_gpio[MINNOW_BRIDGE]);
mpd->ext_te_gpio = of_get_named_gpio(dt_node, "gpio_te", 0);
DTINFO("gpio_te = %d\n", mpd->ext_te_gpio);
- mpd->clk_en_gpio = of_get_named_gpio(dt_node, "gpio_clk_en", 0);
- DTINFO("gpio_clk_en = %d\n", mpd->clk_en_gpio);
mpd->vio_en_gpio = of_get_named_gpio(dt_node, "gpio_vio_en", 0);
DTINFO("gpio_vio_en = %d\n", mpd->vio_en_gpio);
-
+ clkin = (char *)of_get_property(dt_node, "clk_in", NULL);
+ if (clkin) {
+ mpd->clk_in = clk_get(NULL, clkin);
+ if (IS_ERR(mpd->clk_in)) {
+ int r = PTR_ERR(mpd->clk_in);
+ dev_err(&mpd->dssdev->dev,
+ "Failed get external clock %s!\n", clkin);
+ mpd->clk_in = NULL;
+ return r;
+ }
+ }
mpd->esd_interval = 0;
if (!of_property_read_u32(dt_node, "esd_interval", &value)) {
mpd->esd_interval = value;
@@ -1733,18 +1759,6 @@ static int minnow_panel_probe(struct omap_dss_device *dssdev)
dev_info(&dssdev->dev, "skip first time initialization is %s\n",
def_skip_first_init ? "enabled" : "disabled");
- if (gpio_is_valid(mpd->clk_en_gpio)) {
- r = devm_gpio_request_one(&dssdev->dev, mpd->clk_en_gpio,
- def_skip_first_init
- ? GPIOF_OUT_INIT_HIGH
- : GPIOF_OUT_INIT_LOW,
- "minnow-panel clk_en");
- if (r) {
- dev_err(&dssdev->dev,
- "failed to request panel clk_en gpio\n");
- return r;
- }
- }
if (gpio_is_valid(mpd->vio_en_gpio)) {
r = devm_gpio_request_one(&dssdev->dev, mpd->vio_en_gpio,
def_skip_first_init
@@ -2077,6 +2091,9 @@ static int minnow_panel_enable(struct omap_dss_device *dssdev)
goto err;
}
+ r = minnow_panel_enable_clkin(mpd, true);
+ if (r)
+ goto err;
r = minnow_panel_set_regulators(mpd, regulator_enable);
if (r)
goto err;
@@ -2142,6 +2159,7 @@ static void minnow_panel_disable(struct omap_dss_device *dssdev)
_minnow_panel_hw_active_reset(mpd);
minnow_panel_enable_vio(mpd, false);
minnow_panel_set_regulators(mpd, regulator_disable);
+ minnow_panel_enable_clkin(mpd, false);
mutex_unlock(&mpd->lock);
}