Skip to content

Commit

Permalink
Merge tag 'davinci-fixes-for-v4.10' of git://git.kernel.org/pub/scm/l…
Browse files Browse the repository at this point in the history
…inux/kernel/git/nsekhar/linux-davinci into fixes

Pull "DaVinci fixes for v4.10" from Sekhar Nori:

This pull request contains fixes for the following issues

1) Fix two instances of infinite loop occurring in
   clock list for DA850. This fixes kernel hangs in some
   instances and so have been marked for stable kernel.

2) Fix for sleeping function called from atomic context
   with USB 2.0 clock management code introduced in v4.10
   merge window.

* tag 'davinci-fixes-for-v4.10' of git://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci:
  ARM: davinci: da8xx: Fix sleeping function called from invalid context
  ARM: davinci: Make __clk_{enable,disable} functions public
  ARM: davinci: da850: don't add emac clock to lookup table twice
  ARM: davinci: da850: fix infinite loop in clk_set_rate()
  • Loading branch information
arndb committed Jan 4, 2017
2 parents e9b2aef + d1df1e0 commit 1b9ec81
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 27 deletions.
12 changes: 6 additions & 6 deletions arch/arm/mach-davinci/clock.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ static LIST_HEAD(clocks);
static DEFINE_MUTEX(clocks_mutex);
static DEFINE_SPINLOCK(clockfw_lock);

static void __clk_enable(struct clk *clk)
void davinci_clk_enable(struct clk *clk)
{
if (clk->parent)
__clk_enable(clk->parent);
davinci_clk_enable(clk->parent);
if (clk->usecount++ == 0) {
if (clk->flags & CLK_PSC)
davinci_psc_config(clk->domain, clk->gpsc, clk->lpsc,
Expand All @@ -44,7 +44,7 @@ static void __clk_enable(struct clk *clk)
}
}

static void __clk_disable(struct clk *clk)
void davinci_clk_disable(struct clk *clk)
{
if (WARN_ON(clk->usecount == 0))
return;
Expand All @@ -56,7 +56,7 @@ static void __clk_disable(struct clk *clk)
clk->clk_disable(clk);
}
if (clk->parent)
__clk_disable(clk->parent);
davinci_clk_disable(clk->parent);
}

int davinci_clk_reset(struct clk *clk, bool reset)
Expand Down Expand Up @@ -103,7 +103,7 @@ int clk_enable(struct clk *clk)
return -EINVAL;

spin_lock_irqsave(&clockfw_lock, flags);
__clk_enable(clk);
davinci_clk_enable(clk);
spin_unlock_irqrestore(&clockfw_lock, flags);

return 0;
Expand All @@ -118,7 +118,7 @@ void clk_disable(struct clk *clk)
return;

spin_lock_irqsave(&clockfw_lock, flags);
__clk_disable(clk);
davinci_clk_disable(clk);
spin_unlock_irqrestore(&clockfw_lock, flags);
}
EXPORT_SYMBOL(clk_disable);
Expand Down
2 changes: 2 additions & 0 deletions arch/arm/mach-davinci/clock.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ int davinci_set_sysclk_rate(struct clk *clk, unsigned long rate);
int davinci_set_refclk_rate(unsigned long rate);
int davinci_simple_set_rate(struct clk *clk, unsigned long rate);
int davinci_clk_reset(struct clk *clk, bool reset);
void davinci_clk_enable(struct clk *clk);
void davinci_clk_disable(struct clk *clk);

extern struct platform_device davinci_wdt_device;
extern void davinci_watchdog_reset(struct platform_device *);
Expand Down
32 changes: 30 additions & 2 deletions arch/arm/mach-davinci/da850.c
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,16 @@ static struct clk emac_clk = {
.gpsc = 1,
};

/*
* In order to avoid adding the emac_clk to the clock lookup table twice (and
* screwing up the linked list in the process) create a separate clock for
* mdio inheriting the rate from emac_clk.
*/
static struct clk mdio_clk = {
.name = "mdio",
.parent = &emac_clk,
};

static struct clk mcasp_clk = {
.name = "mcasp",
.parent = &async3_clk,
Expand Down Expand Up @@ -367,6 +377,16 @@ static struct clk aemif_clk = {
.flags = ALWAYS_ENABLED,
};

/*
* In order to avoid adding the aemif_clk to the clock lookup table twice (and
* screwing up the linked list in the process) create a separate clock for
* nand inheriting the rate from aemif_clk.
*/
static struct clk aemif_nand_clk = {
.name = "nand",
.parent = &aemif_clk,
};

static struct clk usb11_clk = {
.name = "usb11",
.parent = &pll0_sysclk4,
Expand Down Expand Up @@ -529,15 +549,23 @@ static struct clk_lookup da850_clks[] = {
CLK(NULL, "arm", &arm_clk),
CLK(NULL, "rmii", &rmii_clk),
CLK("davinci_emac.1", NULL, &emac_clk),
CLK("davinci_mdio.0", "fck", &emac_clk),
CLK("davinci_mdio.0", "fck", &mdio_clk),
CLK("davinci-mcasp.0", NULL, &mcasp_clk),
CLK("davinci-mcbsp.0", NULL, &mcbsp0_clk),
CLK("davinci-mcbsp.1", NULL, &mcbsp1_clk),
CLK("da8xx_lcdc.0", "fck", &lcdc_clk),
CLK("da830-mmc.0", NULL, &mmcsd0_clk),
CLK("da830-mmc.1", NULL, &mmcsd1_clk),
CLK("ti-aemif", NULL, &aemif_clk),
CLK(NULL, "aemif", &aemif_clk),
/*
* The only user of this clock is davinci_nand and it get's it through
* con_id. The nand node itself is created from within the aemif
* driver to guarantee that it's probed after the aemif timing
* parameters are configured. of_dev_auxdata is not accessible from
* the aemif driver and can't be passed to of_platform_populate(). For
* that reason we're leaving the dev_id here as NULL.
*/
CLK(NULL, "aemif", &aemif_nand_clk),
CLK("ohci-da8xx", "usb11", &usb11_clk),
CLK("musb-da8xx", "usb20", &usb20_clk),
CLK("spi_davinci.0", NULL, &spi0_clk),
Expand Down
34 changes: 15 additions & 19 deletions arch/arm/mach-davinci/usb-da8xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
#define DA8XX_USB0_BASE 0x01e00000
#define DA8XX_USB1_BASE 0x01e25000

static struct clk *usb20_clk;

static struct platform_device da8xx_usb_phy = {
.name = "da8xx-usb-phy",
.id = -1,
Expand Down Expand Up @@ -158,26 +160,13 @@ int __init da8xx_register_usb_refclkin(int rate)

static void usb20_phy_clk_enable(struct clk *clk)
{
struct clk *usb20_clk;
int err;
u32 val;
u32 timeout = 500000; /* 500 msec */

val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));

usb20_clk = clk_get(&da8xx_usb20_dev.dev, "usb20");
if (IS_ERR(usb20_clk)) {
pr_err("could not get usb20 clk: %ld\n", PTR_ERR(usb20_clk));
return;
}

/* The USB 2.O PLL requires that the USB 2.O PSC is enabled as well. */
err = clk_prepare_enable(usb20_clk);
if (err) {
pr_err("failed to enable usb20 clk: %d\n", err);
clk_put(usb20_clk);
return;
}
davinci_clk_enable(usb20_clk);

/*
* Turn on the USB 2.0 PHY, but just the PLL, and not OTG. The USB 1.1
Expand All @@ -197,8 +186,7 @@ static void usb20_phy_clk_enable(struct clk *clk)

pr_err("Timeout waiting for USB 2.0 PHY clock good\n");
done:
clk_disable_unprepare(usb20_clk);
clk_put(usb20_clk);
davinci_clk_disable(usb20_clk);
}

static void usb20_phy_clk_disable(struct clk *clk)
Expand Down Expand Up @@ -285,11 +273,19 @@ static struct clk_lookup usb20_phy_clk_lookup =
int __init da8xx_register_usb20_phy_clk(bool use_usb_refclkin)
{
struct clk *parent;
int ret = 0;
int ret;

usb20_clk = clk_get(&da8xx_usb20_dev.dev, "usb20");
ret = PTR_ERR_OR_ZERO(usb20_clk);
if (ret)
return ret;

parent = clk_get(NULL, use_usb_refclkin ? "usb_refclkin" : "pll0_aux");
if (IS_ERR(parent))
return PTR_ERR(parent);
ret = PTR_ERR_OR_ZERO(parent);
if (ret) {
clk_put(usb20_clk);
return ret;
}

usb20_phy_clk.parent = parent;
ret = clk_register(&usb20_phy_clk);
Expand Down

0 comments on commit 1b9ec81

Please sign in to comment.