diff options
| -rw-r--r-- | arch/arm/boot/dts/omap3-minnow.dtsi | 13 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/board-minnow.c | 21 | ||||
| -rw-r--r-- | drivers/usb/phy/phy-tusb.c | 36 | ||||
| -rw-r--r--[-rwxr-xr-x] | drivers/video/omap2/displays/panel-minnow.c | 50 |
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); } |