Changeset View
Changeset View
Standalone View
Standalone View
sys/arm/ti/clk/ti_clk_clkctrl.c
Show All 27 Lines | |||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <sys/bus.h> | #include <sys/bus.h> | ||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
#include <dev/clk/clk.h> | #include <dev/clk/clk.h> | ||||
#include <arm/ti/clk/ti_clk_clkctrl.h> | #include <arm/ti/clk/ti_clk_clkctrl.h> | ||||
#include <arm/ti/clk/ti_clock_common.h> | |||||
#include "clkdev_if.h" | #include "clkdev_if.h" | ||||
#if 0 | #if 0 | ||||
#define DPRINTF(dev, msg...) device_printf(dev, msg) | #define DPRINTF(dev, msg...) device_printf(dev, msg) | ||||
#else | #else | ||||
#define DPRINTF(dev, msg...) | #define DPRINTF(dev, msg...) | ||||
#endif | #endif | ||||
/* | /* | ||||
* clknode for clkctrl, implements gate and mux (for gpioc) | * clknode for clkctrl, implements gate and mux (for gpioc) | ||||
*/ | */ | ||||
#define GPIO_X_GDBCLK_MASK 0x00040000 | |||||
#define IDLEST_MASK 0x00030000 | #define IDLEST_MASK 0x00030000 | ||||
#define MODULEMODE_MASK 0x00000003 | #define MODULEMODE_MASK 0x00000003 | ||||
#define GPIOX_GDBCLK_ENABLE 0x00040000 | |||||
#define GPIOX_GDBCLK_DISABLE 0x00000000 | |||||
#define IDLEST_FUNC 0x00000000 | #define IDLEST_FUNC 0x00000000 | ||||
#define IDLEST_TRANS 0x00010000 | #define IDLEST_TRANS 0x00010000 | ||||
#define IDLEST_IDLE 0x00020000 | #define IDLEST_IDLE 0x00020000 | ||||
#define IDLEST_DISABLE 0x00030000 | #define IDLEST_DISABLE 0x00030000 | ||||
#define MODULEMODE_DISABLE 0x0 | #define MODULEMODE_DISABLE 0x0 | ||||
#define MODULEMODE_ENABLE 0x2 | #define MODULEMODE_ENABLE_HW 0x1 | ||||
#define MODULEMODE_ENABLE_SW 0x2 | |||||
struct ti_clkctrl_clknode_sc { | struct ti_clkctrl_clknode_sc { | ||||
device_t dev; | device_t dev; | ||||
bool gdbclk; | |||||
/* omap4-cm range.host + ti,clkctrl reg[0] */ | /* omap4-cm range.host + ti,clkctrl reg[0] */ | ||||
uint32_t register_offset; | uint32_t register_offset; | ||||
uint8_t flags; | |||||
}; | }; | ||||
#define WRITE4(_clk, off, val) \ | #define WRITE4(_clk, off, val) \ | ||||
CLKDEV_WRITE_4(clknode_get_device(_clk), off, val) | CLKDEV_WRITE_4(clknode_get_device(_clk), off, val) | ||||
#define READ4(_clk, off, val) \ | #define READ4(_clk, off, val) \ | ||||
CLKDEV_READ_4(clknode_get_device(_clk), off, val) | CLKDEV_READ_4(clknode_get_device(_clk), off, val) | ||||
#define DEVICE_LOCK(_clk) \ | #define DEVICE_LOCK(_clk) \ | ||||
CLKDEV_DEVICE_LOCK(clknode_get_device(_clk)) | CLKDEV_DEVICE_LOCK(clknode_get_device(_clk)) | ||||
#define DEVICE_UNLOCK(_clk) \ | #define DEVICE_UNLOCK(_clk) \ | ||||
CLKDEV_DEVICE_UNLOCK(clknode_get_device(_clk)) | CLKDEV_DEVICE_UNLOCK(clknode_get_device(_clk)) | ||||
static int | static int | ||||
ti_clkctrl_init(struct clknode *clk, device_t dev) | ti_clkctrl_init(struct clknode *clk, device_t dev) | ||||
{ | { | ||||
struct ti_clkctrl_clknode_sc *sc; | struct ti_clkctrl_clknode_sc *sc; | ||||
sc = clknode_get_softc(clk); | sc = clknode_get_softc(clk); | ||||
sc->dev = dev; | sc->dev = dev; | ||||
clknode_init_parent_idx(clk, 0); | clknode_init_parent_idx(clk, 0); | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
ti_clkctrl_set_gdbclk_gate(struct clknode *clk, bool enable) | ti_clkctrl_set_gate(struct clknode *clk, bool enable) | ||||
{ | { | ||||
struct ti_clkctrl_clknode_sc *sc; | struct ti_clkctrl_clknode_sc *sc; | ||||
uint32_t val, gpio_x_gdbclk; | uint32_t val, idlest, modulemode_reg, modulemode_val=0; | ||||
uint32_t timeout = 100; | uint32_t timeout=100; | ||||
sc = clknode_get_softc(clk); | sc = clknode_get_softc(clk); | ||||
DEVICE_LOCK(clk); | |||||
READ4(clk, sc->register_offset, &val); | READ4(clk, sc->register_offset, &val); | ||||
DPRINTF(sc->dev, "val(%x) & (%x | %x = %x)\n", | |||||
val, GPIO_X_GDBCLK_MASK, MODULEMODE_MASK, | |||||
GPIO_X_GDBCLK_MASK | MODULEMODE_MASK); | |||||
if (enable) { | if (enable == false) | ||||
val = val & MODULEMODE_MASK; | WRITE4(clk, sc->register_offset, MODULEMODE_DISABLE); | ||||
val |= GPIOX_GDBCLK_ENABLE; | /* enable == true for following two */ | ||||
else if ((sc->flags & TI_CLKCTRL_FLAGS_MM_HW) == TI_CLKCTRL_FLAGS_MM_HW) { | |||||
modulemode_val = MODULEMODE_ENABLE_HW; | |||||
WRITE4(clk, sc->register_offset, MODULEMODE_ENABLE_HW); | |||||
} else { | } else { | ||||
val = val & MODULEMODE_MASK; | modulemode_val = MODULEMODE_ENABLE_SW; | ||||
val |= GPIOX_GDBCLK_DISABLE; | WRITE4(clk, sc->register_offset, MODULEMODE_ENABLE_SW); | ||||
} | } | ||||
DPRINTF(sc->dev, "val %x\n", val); | |||||
WRITE4(clk, sc->register_offset, val); | |||||
/* Wait */ | |||||
while (timeout) { | while (timeout) { | ||||
READ4(clk, sc->register_offset, &val); | READ4(clk, sc->register_offset, &val); | ||||
gpio_x_gdbclk = val & GPIO_X_GDBCLK_MASK; | |||||
if (enable && (gpio_x_gdbclk == GPIOX_GDBCLK_ENABLE)) | |||||
break; | |||||
else if (!enable && (gpio_x_gdbclk == GPIOX_GDBCLK_DISABLE)) | |||||
break; | |||||
DELAY(10); | |||||
timeout--; | |||||
} | |||||
if (timeout == 0) { | |||||
device_printf(sc->dev, "ti_clkctrl_set_gdbclk_gate: Timeout\n"); | |||||
return (1); | |||||
} | |||||
return (0); | |||||
} | |||||
static int | |||||
ti_clkctrl_set_gate(struct clknode *clk, bool enable) | |||||
{ | |||||
struct ti_clkctrl_clknode_sc *sc; | |||||
uint32_t val, idlest, module; | |||||
uint32_t timeout=100; | |||||
int err; | |||||
sc = clknode_get_softc(clk); | |||||
if (sc->gdbclk) { | |||||
err = ti_clkctrl_set_gdbclk_gate(clk, enable); | |||||
return (err); | |||||
} | |||||
READ4(clk, sc->register_offset, &val); | |||||
if (enable) | |||||
WRITE4(clk, sc->register_offset, MODULEMODE_ENABLE); | |||||
else | |||||
WRITE4(clk, sc->register_offset, MODULEMODE_DISABLE); | |||||
while (timeout) { | |||||
READ4(clk, sc->register_offset, &val); | |||||
idlest = val & IDLEST_MASK; | idlest = val & IDLEST_MASK; | ||||
module = val & MODULEMODE_MASK; | modulemode_reg = val & MODULEMODE_MASK; | ||||
if (enable && | if (enable == true && | ||||
(idlest == IDLEST_FUNC || idlest == IDLEST_TRANS) && | (idlest == IDLEST_FUNC || idlest == IDLEST_IDLE) && | ||||
module == MODULEMODE_ENABLE) | modulemode_reg == modulemode_val) | ||||
break; | break; | ||||
else if (!enable && | else if (enable == false && | ||||
idlest == IDLEST_DISABLE && | idlest == IDLEST_DISABLE && | ||||
module == MODULEMODE_DISABLE) | modulemode_reg == MODULEMODE_DISABLE) | ||||
break; | break; | ||||
DELAY(10); | DELAY(10); | ||||
timeout--; | timeout--; | ||||
} | } | ||||
DEVICE_UNLOCK(clk); | |||||
if (timeout == 0) { | if (timeout == 0) { | ||||
device_printf(sc->dev, "ti_clkctrl_set_gate: Timeout\n"); | DPRINTF(sc->dev, "ti_clkctrl_set_gate: Timeout\n"); | ||||
return (1); | return (1); | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
static clknode_method_t ti_clkctrl_clknode_methods[] = { | static clknode_method_t ti_clkctrl_clknode_methods[] = { | ||||
/* Device interface */ | /* Device interface */ | ||||
Show All 12 Lines | |||||
{ | { | ||||
struct clknode *clk; | struct clknode *clk; | ||||
struct ti_clkctrl_clknode_sc *sc; | struct ti_clkctrl_clknode_sc *sc; | ||||
clk = clknode_create(clkdom, &ti_clkctrl_clknode_class, | clk = clknode_create(clkdom, &ti_clkctrl_clknode_class, | ||||
&clkdef->clkdef); | &clkdef->clkdef); | ||||
if (clk == NULL) { | if (clk == NULL) { | ||||
DPRINTF(sc->dev, "clknode_create failed.\n"); | |||||
return (1); | return (1); | ||||
} | } | ||||
sc = clknode_get_softc(clk); | sc = clknode_get_softc(clk); | ||||
sc->register_offset = clkdef->register_offset; | sc->register_offset = clkdef->register_offset; | ||||
sc->gdbclk = clkdef->gdbclk; | sc->flags = clkdef->flags; | ||||
if (clknode_register(clkdom, clk) == NULL) { | if (clknode_register(clkdom, clk) == NULL) { | ||||
DPRINTF(sc->dev, "clknode_register failed.\n"); | |||||
return (2); | return (2); | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } |