Commit 0f8913ed authored by David Brownell's avatar David Brownell Committed by Kevin Hilman

clock updates: support logical clock names

Update the DaVinci clock framework to handle clk_get(dev, name)
better, adding davinci_clk_associate() method letting logical
names be associated with devices.  This lets drivers move away
from using "physical" clock names, which are changed in new chip
versions and by adding more controller instances.

Plus a few unrelated fixes to the DM355 clock tree:  it doesn't
have IDE or EMAC, or their clocks, so don't list them.  But it
does have two more SPI controllers ... list them instead.
Signed-off-by: default avatarDavid Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: default avatarKevin Hilman <khilman@deeprootsystems.com>
parent 9a5668e7
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/clk.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
...@@ -42,6 +43,63 @@ static unsigned int fixedrate = 27000000; /* 27 MHZ */ ...@@ -42,6 +43,63 @@ static unsigned int fixedrate = 27000000; /* 27 MHZ */
extern void davinci_psc_config(unsigned int domain, unsigned int id, char enable); extern void davinci_psc_config(unsigned int domain, unsigned int id, char enable);
/*
* Register a mapping { dev, logical_clockname } --> clock
*
* Device drivers should always use logical clocknames, so they
* don't need to change the physical name when new silicon grows
* another instance of that module or changes the clock tree.
*/
struct clk_mapping {
struct device *dev;
const char *name;
struct clk *clock;
struct clk_mapping *next;
};
static struct clk_mapping *maplist;
int __init davinci_clk_associate(struct device *dev,
const char *logical_clockname,
const char *physical_clockname)
{
int status = -EINVAL;
struct clk *clock;
struct clk_mapping *mapping;
if (!dev)
goto done;
clock = clk_get(dev, physical_clockname);
if (IS_ERR(clock) || !try_module_get(clock->owner))
goto done;
mutex_lock(&clocks_mutex);
for (mapping = maplist; mapping; mapping = mapping->next) {
if (dev != mapping->dev)
continue;
if (strcmp(logical_clockname, mapping->name) != 0)
continue;
goto fail;
}
mapping = kzalloc(sizeof *mapping, GFP_KERNEL);
mapping->dev = dev;
mapping->name = logical_clockname;
mapping->clock = clock;
mapping->next = maplist;
maplist = mapping;
status = 0;
fail:
mutex_unlock(&clocks_mutex);
done:
WARN_ON(status < 0);
return status;
}
/* /*
* Returns a clock. Note that we first try to use device id on the bus * Returns a clock. Note that we first try to use device id on the bus
* and clock name. If this fails, we try to use clock name only. * and clock name. If this fails, we try to use clock name only.
...@@ -50,6 +108,7 @@ struct clk *clk_get(struct device *dev, const char *id) ...@@ -50,6 +108,7 @@ struct clk *clk_get(struct device *dev, const char *id)
{ {
struct clk *p, *clk = ERR_PTR(-ENOENT); struct clk *p, *clk = ERR_PTR(-ENOENT);
int idno; int idno;
struct clk_mapping *mapping;
if (dev == NULL || dev->bus != &platform_bus_type) if (dev == NULL || dev->bus != &platform_bus_type)
idno = -1; idno = -1;
...@@ -58,6 +117,18 @@ struct clk *clk_get(struct device *dev, const char *id) ...@@ -58,6 +117,18 @@ struct clk *clk_get(struct device *dev, const char *id)
mutex_lock(&clocks_mutex); mutex_lock(&clocks_mutex);
/* always prefer logical clock names */
if (dev) {
for (mapping = maplist; mapping; mapping = mapping->next) {
if (dev != mapping->dev)
continue;
if (strcmp(id, mapping->name) != 0)
continue;
clk = mapping->clock;
goto found;
}
}
list_for_each_entry(p, &clocks, node) { list_for_each_entry(p, &clocks, node) {
if (p->id == idno && if (p->id == idno &&
strcmp(id, p->name) == 0 && try_module_get(p->owner)) { strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
...@@ -65,7 +136,7 @@ struct clk *clk_get(struct device *dev, const char *id) ...@@ -65,7 +136,7 @@ struct clk *clk_get(struct device *dev, const char *id)
goto found; goto found;
} }
} }
list_for_each_entry(p, &clocks, node) { list_for_each_entry(p, &clocks, node) {
if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) { if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
clk = p; clk = p;
...@@ -322,21 +393,11 @@ static struct clk davinci_dm355_clks[] = { ...@@ -322,21 +393,11 @@ static struct clk davinci_dm355_clks[] = {
.lpsc = DAVINCI_LPSC_UART2, .lpsc = DAVINCI_LPSC_UART2,
.usecount = 1, .usecount = 1,
}, },
{
.name = "EMACCLK",
.rate = &commonrate,
.lpsc = DAVINCI_LPSC_EMAC_WRAPPER,
},
{ {
.name = "I2CCLK", .name = "I2CCLK",
.rate = &fixedrate, .rate = &fixedrate,
.lpsc = DAVINCI_LPSC_I2C, .lpsc = DAVINCI_LPSC_I2C,
}, },
{
.name = "IDECLK",
.rate = &commonrate,
.lpsc = DAVINCI_LPSC_ATA,
},
{ {
.name = "McBSPCLK0", .name = "McBSPCLK0",
.rate = &commonrate, .rate = &commonrate,
...@@ -362,6 +423,16 @@ static struct clk davinci_dm355_clks[] = { ...@@ -362,6 +423,16 @@ static struct clk davinci_dm355_clks[] = {
.rate = &commonrate, .rate = &commonrate,
.lpsc = DAVINCI_LPSC_SPI, .lpsc = DAVINCI_LPSC_SPI,
}, },
{
.name = "SPICLK1",
.rate = &commonrate,
.lpsc = DM355_LPSC_SPI1,
},
{
.name = "SPICLK2",
.rate = &commonrate,
.lpsc = DM355_LPSC_SPI2,
},
{ {
.name = "gpio", .name = "gpio",
.rate = &commonrate, .rate = &commonrate,
......
...@@ -36,4 +36,7 @@ struct clk { ...@@ -36,4 +36,7 @@ struct clk {
#define DM646X_CLOCK_TICK_RATE 148500000 #define DM646X_CLOCK_TICK_RATE 148500000
#define DM355_CLOCK_TICK_RATE 24000000 #define DM355_CLOCK_TICK_RATE 24000000
int davinci_clk_associate(struct device *dev, const char *logical_clockname,
const char *physical_clockname);
#endif #endif
...@@ -73,9 +73,13 @@ ...@@ -73,9 +73,13 @@
#define DAVINCI_LPSC_GEM 39 #define DAVINCI_LPSC_GEM 39
#define DAVINCI_LPSC_IMCOP 40 #define DAVINCI_LPSC_IMCOP 40
#define DM355_LPSC_TIMER3 5
#define DM355_LPSC_SPI1 6
#define DM355_LPSC_MMC_SD1 7 #define DM355_LPSC_MMC_SD1 7
#define DM355_LPSC_McBSP1 8 #define DM355_LPSC_McBSP1 8
#define DM355_LPSC_PWM3 10 #define DM355_LPSC_PWM3 10
#define DM355_LPSC_SPI2 11
#define DM355_LPSC_RTO 12
/* /*
* LPSC Assignments * LPSC Assignments
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment