Module Name: src
Committed By: jmcneill
Date: Thu Oct 26 23:28:15 UTC 2017
Modified Files:
src/sys/arch/arm/ti: files.ti ti_com.c
src/sys/arch/evbarm/conf: TI
Added Files:
src/sys/arch/arm/ti: am3_prcm.c ti_prcm.c ti_prcm.h
Log Message:
Add support for enabling modules specified in ti,hwmods property. Very
primitive am3xxx prcm driver added to validate it, needs work.
To generate a diff of this commit:
cvs rdiff -u -r0 -r1.1 src/sys/arch/arm/ti/am3_prcm.c \
src/sys/arch/arm/ti/ti_prcm.c src/sys/arch/arm/ti/ti_prcm.h
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/arm/ti/files.ti
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/arm/ti/ti_com.c
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/evbarm/conf/TI
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/arch/arm/ti/files.ti
diff -u src/sys/arch/arm/ti/files.ti:1.1 src/sys/arch/arm/ti/files.ti:1.2
--- src/sys/arch/arm/ti/files.ti:1.1 Thu Oct 26 01:16:32 2017
+++ src/sys/arch/arm/ti/files.ti Thu Oct 26 23:28:15 2017
@@ -1,4 +1,4 @@
-# $NetBSD: files.ti,v 1.1 2017/10/26 01:16:32 jakllsch Exp $
+# $NetBSD: files.ti,v 1.2 2017/10/26 23:28:15 jmcneill Exp $
#
include arch/arm/pic/files.pic
@@ -15,11 +15,20 @@ file arch/arm/arm/bus_space_a4x.S
file arch/arm/ti/ti_platform.c
-# interrupt controller
+# Interrupt controller
device omapintc: pic, pic_splfuncs
attach omapintc at fdt
file arch/arm/ti/ti_omapintc.c omapintc
+# PRCM
+define ti_prcm
+file arch/arm/ti/ti_prcm.c ti_prcm
+
+# PRCM (AM3xxx)
+device am3prcm: ti_prcm
+attach am3prcm at fdt with am3_prcm
+file arch/arm/ti/am3_prcm.c am3_prcm
+
# UART
attach com at fdt with ti_com
file arch/arm/ti/ti_com.c ti_com needs-flag
@@ -29,6 +38,7 @@ device omaptimer
attach omaptimer at fdt
file arch/arm/ti/ti_omaptimer.c omaptimer
+# Ethernet
device cpsw: ether, ifnet, arp, mii, mii_phy
attach cpsw at fdt
file arch/arm/ti/if_cpsw.c cpsw
Index: src/sys/arch/arm/ti/ti_com.c
diff -u src/sys/arch/arm/ti/ti_com.c:1.2 src/sys/arch/arm/ti/ti_com.c:1.3
--- src/sys/arch/arm/ti/ti_com.c:1.2 Thu Oct 26 10:56:57 2017
+++ src/sys/arch/arm/ti/ti_com.c Thu Oct 26 23:28:15 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: ti_com.c,v 1.2 2017/10/26 10:56:57 jmcneill Exp $ */
+/* $NetBSD: ti_com.c,v 1.3 2017/10/26 23:28:15 jmcneill Exp $ */
/*-
* Copyright (c) 2017 Jared McNeill <[email protected]>
@@ -28,7 +28,7 @@
#include <sys/cdefs.h>
-__KERNEL_RCSID(1, "$NetBSD: ti_com.c,v 1.2 2017/10/26 10:56:57 jmcneill Exp $");
+__KERNEL_RCSID(1, "$NetBSD: ti_com.c,v 1.3 2017/10/26 23:28:15 jmcneill Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@@ -42,6 +42,8 @@ __KERNEL_RCSID(1, "$NetBSD: ti_com.c,v 1
#include <dev/fdt/fdtvar.h>
+#include <arch/arm/ti/ti_prcm.h>
+
static int ti_com_match(device_t, cfdata_t, void *);
static void ti_com_attach(device_t, device_t, void *);
@@ -77,6 +79,7 @@ ti_com_attach(device_t parent, device_t
bus_space_handle_t bsh;
bus_space_tag_t bst;
char intrstr[128];
+ struct clk *hwmod;
bus_addr_t addr;
bus_size_t size;
int error;
@@ -103,6 +106,13 @@ ti_com_attach(device_t parent, device_t
return;
}
+ hwmod = ti_prcm_get_hwmod(phandle, 0);
+ KASSERT(hwmod != NULL);
+ if (clk_enable(hwmod) != 0) {
+ aprint_error(": couldn't enable module\n");
+ return;
+ }
+
COM_INIT_REGS(sc->sc_regs, bst, bsh, addr);
com_attach_subr(sc);
Index: src/sys/arch/evbarm/conf/TI
diff -u src/sys/arch/evbarm/conf/TI:1.1 src/sys/arch/evbarm/conf/TI:1.2
--- src/sys/arch/evbarm/conf/TI:1.1 Thu Oct 26 01:16:32 2017
+++ src/sys/arch/evbarm/conf/TI Thu Oct 26 23:28:14 2017
@@ -1,4 +1,4 @@
-# $NetBSD: TI,v 1.1 2017/10/26 01:16:32 jakllsch Exp $
+# $NetBSD: TI,v 1.2 2017/10/26 23:28:14 jmcneill Exp $
#
include "arch/evbarm/conf/std.ti"
@@ -34,9 +34,11 @@ fdt* at fdtbus?
cpus* at fdt? pass 0
cpu* at cpus?
+am3prcm* at fdt? pass 1
+
com* at fdt?
-omapintc* at fdt? pass 1
+omapintc* at fdt? pass 2
omaptimer* at fdt?
fregulator* at fdt?
Added files:
Index: src/sys/arch/arm/ti/am3_prcm.c
diff -u /dev/null src/sys/arch/arm/ti/am3_prcm.c:1.1
--- /dev/null Thu Oct 26 23:28:15 2017
+++ src/sys/arch/arm/ti/am3_prcm.c Thu Oct 26 23:28:15 2017
@@ -0,0 +1,139 @@
+/* $NetBSD: am3_prcm.c,v 1.1 2017/10/26 23:28:15 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2017 Jared McNeill <[email protected]>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+__KERNEL_RCSID(1, "$NetBSD: am3_prcm.c,v 1.1 2017/10/26 23:28:15 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/device.h>
+#include <sys/systm.h>
+
+#include <dev/fdt/fdtvar.h>
+
+#define TI_PRCM_PRIVATE
+#include <arm/ti/ti_prcm.h>
+
+#define AM3_PRCM_CM_PER 0x0000
+#define AM3_PRCM_CM_WKUP 0x0400
+#define AM3_PRCM_CM_DPLL 0x0500
+#define AM3_PRCM_CM_MPU 0x0600
+#define AM3_PRCM_CM_DEVICE 0x0700
+#define AM3_PRCM_CM_RTC 0x0800
+#define AM3_PRCM_CM_GFX 0x0900
+#define AM3_PRCM_CM_CEFUSE 0x0a00
+
+#define AM3_PRCM_CLKCTRL_MODULEMODE __BITS(1,0)
+#define AM3_PRCM_CLKCTRL_MODULEMODE_ENABLE 0x2
+
+static int am3_prcm_match(device_t, cfdata_t, void *);
+static void am3_prcm_attach(device_t, device_t, void *);
+
+static int
+am3_prcm_hwmod_enable(struct ti_prcm_softc *sc, struct ti_prcm_clk *tc, int enable)
+{
+ uint32_t val;
+
+ val = PRCM_READ(sc, tc->u.hwmod.reg);
+ val &= ~AM3_PRCM_CLKCTRL_MODULEMODE;
+ if (enable)
+ val |= __SHIFTIN(AM3_PRCM_CLKCTRL_MODULEMODE_ENABLE,
+ AM3_PRCM_CLKCTRL_MODULEMODE);
+ PRCM_WRITE(sc, tc->u.hwmod.reg, val);
+
+ return 0;
+}
+
+#define AM3_PRCM_HWMOD_PER(_name, _reg, _parent) \
+ TI_PRCM_HWMOD((_name), AM3_PRCM_CM_PER + (_reg), (_parent), am3_prcm_hwmod_enable)
+#define AM3_PRCM_HWMOD_WKUP(_name, _reg, _parent) \
+ TI_PRCM_HWMOD((_name), AM3_PRCM_CM_WKUP + (_reg), (_parent), am3_prcm_hwmod_enable)
+
+static const char * const compatible[] = {
+ "ti,am3-prcm",
+ NULL
+};
+
+CFATTACH_DECL_NEW(am3_prcm, sizeof(struct ti_prcm_softc),
+ am3_prcm_match, am3_prcm_attach, NULL, NULL);
+
+static struct ti_prcm_clk am3_prcm_clks[] = {
+ /* XXX until we get a proper clock tree */
+ TI_PRCM_FIXED("FIXED_32K", 32768),
+ TI_PRCM_FIXED("FIXED_48MHZ", 48000000),
+ TI_PRCM_FIXED("FIXED_96MHZ", 96000000),
+ TI_PRCM_FIXED_FACTOR("PERIPH_CLK", 1, 1, "FIXED_48MHZ"),
+ TI_PRCM_FIXED_FACTOR("MMC_CLK", 1, 1, "FIXED_96MHZ"),
+
+ AM3_PRCM_HWMOD_PER("uart1", 0x6c, "PERIPH_CLK"),
+ AM3_PRCM_HWMOD_PER("uart2", 0x70, "PERIPH_CLK"),
+ AM3_PRCM_HWMOD_PER("uart3", 0x74, "PERIPH_CLK"),
+ AM3_PRCM_HWMOD_PER("uart4", 0x78, "PERIPH_CLK"),
+ AM3_PRCM_HWMOD_PER("uart5", 0x38, "PERIPH_CLK"),
+
+ AM3_PRCM_HWMOD_WKUP("timer0", 0x10, "FIXED_32K"),
+ AM3_PRCM_HWMOD_PER("timer2", 0x80, "PERIPH_CLK"),
+ AM3_PRCM_HWMOD_PER("timer3", 0x84, "PERIPH_CLK"),
+ AM3_PRCM_HWMOD_PER("timer4", 0x88, "PERIPH_CLK"),
+ AM3_PRCM_HWMOD_PER("timer5", 0xec, "PERIPH_CLK"),
+ AM3_PRCM_HWMOD_PER("timer6", 0xf0, "PERIPH_CLK"),
+ AM3_PRCM_HWMOD_PER("timer7", 0x7c, "PERIPH_CLK"),
+
+ AM3_PRCM_HWMOD_PER("mmc0", 0x3c, "MMC_CLK"),
+ AM3_PRCM_HWMOD_PER("mmc1", 0xf4, "MMC_CLK"),
+ AM3_PRCM_HWMOD_PER("mmc2", 0xf8, "MMC_CLK"),
+};
+
+static int
+am3_prcm_match(device_t parent, cfdata_t cf, void *aux)
+{
+ struct fdt_attach_args * const faa = aux;
+
+ return of_match_compatible(faa->faa_phandle, compatible);
+}
+
+static void
+am3_prcm_attach(device_t parent, device_t self, void *aux)
+{
+ struct ti_prcm_softc * const sc = device_private(self);
+ struct fdt_attach_args * const faa = aux;
+
+ sc->sc_dev = self;
+ sc->sc_phandle = faa->faa_phandle;
+ sc->sc_bst = faa->faa_bst;
+
+ sc->sc_clks = am3_prcm_clks;
+ sc->sc_nclks = __arraycount(am3_prcm_clks);
+
+ if (ti_prcm_attach(sc) != 0)
+ return;
+
+ aprint_naive("\n");
+ aprint_normal(": AM3xxx PRCM\n");
+}
Index: src/sys/arch/arm/ti/ti_prcm.c
diff -u /dev/null src/sys/arch/arm/ti/ti_prcm.c:1.1
--- /dev/null Thu Oct 26 23:28:15 2017
+++ src/sys/arch/arm/ti/ti_prcm.c Thu Oct 26 23:28:15 2017
@@ -0,0 +1,257 @@
+/* $NetBSD: ti_prcm.c,v 1.1 2017/10/26 23:28:15 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2017 Jared McNeill <[email protected]>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: ti_prcm.c,v 1.1 2017/10/26 23:28:15 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/cpu.h>
+#include <sys/device.h>
+
+#include <dev/fdt/fdtvar.h>
+
+#include <dev/clk/clk_backend.h>
+
+#define TI_PRCM_PRIVATE
+#include <arm/ti/ti_prcm.h>
+
+static struct ti_prcm_softc *prcm_softc = NULL;
+
+static struct clk *
+ti_prcm_clock_get(void *priv, const char *name)
+{
+ struct ti_prcm_softc * const sc = priv;
+ struct ti_prcm_clk *clk;
+
+ clk = ti_prcm_clock_find(sc, name);
+ if (clk == NULL)
+ return NULL;
+
+ return &clk->base;
+}
+
+static void
+ti_prcm_clock_put(void *priv, struct clk *clk)
+{
+}
+
+static u_int
+ti_prcm_clock_get_rate(void *priv, struct clk *clkp)
+{
+ struct ti_prcm_softc * const sc = priv;
+ struct ti_prcm_clk *clk = (struct ti_prcm_clk *)clkp;
+ struct clk *clkp_parent;
+
+ if (clk->get_rate)
+ return clk->get_rate(sc, clk);
+
+ clkp_parent = clk_get_parent(clkp);
+ if (clkp_parent == NULL) {
+ aprint_error("%s: no parent for %s\n", __func__, clk->base.name);
+ return 0;
+ }
+
+ return clk_get_rate(clkp_parent);
+}
+
+static int
+ti_prcm_clock_set_rate(void *priv, struct clk *clkp, u_int rate)
+{
+ struct ti_prcm_softc * const sc = priv;
+ struct ti_prcm_clk *clk = (struct ti_prcm_clk *)clkp;
+ struct clk *clkp_parent;
+
+ if (clkp->flags & CLK_SET_RATE_PARENT) {
+ clkp_parent = clk_get_parent(clkp);
+ if (clkp_parent == NULL) {
+ aprint_error("%s: no parent for %s\n", __func__, clk->base.name);
+ return ENXIO;
+ }
+ return clk_set_rate(clkp_parent, rate);
+ }
+
+ if (clk->set_rate)
+ return clk->set_rate(sc, clk, rate);
+
+ return ENXIO;
+}
+
+static int
+ti_prcm_clock_enable(void *priv, struct clk *clkp)
+{
+ struct ti_prcm_softc * const sc = priv;
+ struct ti_prcm_clk *clk = (struct ti_prcm_clk *)clkp;
+ struct clk *clkp_parent;
+ int error = 0;
+
+ clkp_parent = clk_get_parent(clkp);
+ if (clkp_parent != NULL) {
+ error = clk_enable(clkp_parent);
+ if (error != 0)
+ return error;
+ }
+
+ if (clk->enable)
+ error = clk->enable(sc, clk, 1);
+
+ return error;
+}
+
+static int
+ti_prcm_clock_disable(void *priv, struct clk *clkp)
+{
+ struct ti_prcm_softc * const sc = priv;
+ struct ti_prcm_clk *clk = (struct ti_prcm_clk *)clkp;
+ int error = EINVAL;
+
+ if (clk->enable)
+ error = clk->enable(sc, clk, 0);
+
+ return error;
+}
+
+static int
+ti_prcm_clock_set_parent(void *priv, struct clk *clkp,
+ struct clk *clkp_parent)
+{
+ struct ti_prcm_softc * const sc = priv;
+ struct ti_prcm_clk *clk = (struct ti_prcm_clk *)clkp;
+
+ if (clk->set_parent == NULL)
+ return EINVAL;
+
+ return clk->set_parent(sc, clk, clkp_parent->name);
+}
+
+static struct clk *
+ti_prcm_clock_get_parent(void *priv, struct clk *clkp)
+{
+ struct ti_prcm_softc * const sc = priv;
+ struct ti_prcm_clk *clk = (struct ti_prcm_clk *)clkp;
+ struct ti_prcm_clk *clk_parent;
+ const char *parent;
+
+ if (clk->get_parent == NULL)
+ return NULL;
+
+ parent = clk->get_parent(sc, clk);
+ if (parent == NULL)
+ return NULL;
+
+ clk_parent = ti_prcm_clock_find(sc, parent);
+ if (clk_parent != NULL)
+ return &clk_parent->base;
+
+ /* No parent in this domain, try FDT */
+ return fdtbus_clock_get(sc->sc_phandle, parent);
+}
+
+static const struct clk_funcs ti_prcm_clock_funcs = {
+ .get = ti_prcm_clock_get,
+ .put = ti_prcm_clock_put,
+ .get_rate = ti_prcm_clock_get_rate,
+ .set_rate = ti_prcm_clock_set_rate,
+ .enable = ti_prcm_clock_enable,
+ .disable = ti_prcm_clock_disable,
+ .set_parent = ti_prcm_clock_set_parent,
+ .get_parent = ti_prcm_clock_get_parent,
+};
+
+struct ti_prcm_clk *
+ti_prcm_clock_find(struct ti_prcm_softc *sc, const char *name)
+{
+ for (int i = 0; i < sc->sc_nclks; i++) {
+ if (sc->sc_clks[i].base.name == NULL)
+ continue;
+ if (strcmp(sc->sc_clks[i].base.name, name) == 0)
+ return &sc->sc_clks[i];
+ }
+
+ return NULL;
+}
+
+int
+ti_prcm_attach(struct ti_prcm_softc *sc)
+{
+ bus_addr_t addr;
+ bus_size_t size;
+ int i;
+
+ if (fdtbus_get_reg(sc->sc_phandle, 0, &addr, &size) != 0) {
+ aprint_error(": couldn't get registers\n");
+ return ENXIO;
+ }
+ if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
+ aprint_error(": couldn't map registers\n");
+ return ENXIO;
+ }
+
+ sc->sc_clkdom.funcs = &ti_prcm_clock_funcs;
+ sc->sc_clkdom.priv = sc;
+ for (i = 0; i < sc->sc_nclks; i++)
+ sc->sc_clks[i].base.domain = &sc->sc_clkdom;
+
+ KASSERT(prcm_softc == NULL);
+ prcm_softc = sc;
+
+ return 0;
+}
+
+struct clk *
+ti_prcm_get_hwmod(const int phandle, u_int index)
+{
+ struct ti_prcm_clk *tc;
+ const char *hwmods, *p;
+ int len, resid;
+ u_int n;
+
+ KASSERTMSG(prcm_softc != NULL, "prcm driver not attached");
+
+ hwmods = fdtbus_get_prop(phandle, "ti,hwmods", &len);
+ if (len <= 0)
+ return NULL;
+
+ p = hwmods;
+ for (n = 0, resid = len; resid > 0; n++) {
+ if (n == index) {
+ tc = ti_prcm_clock_find(prcm_softc, p);
+ if (tc == NULL) {
+ aprint_error_dev(prcm_softc->sc_dev,
+ "no hwmod with name '%s'\n", p);
+ return NULL;
+ }
+ KASSERT(tc->type == TI_PRCM_HWMOD);
+ return &tc->base;
+ }
+ resid -= strlen(p);
+ p += strlen(p) + 1;
+ }
+
+ return NULL;
+}
Index: src/sys/arch/arm/ti/ti_prcm.h
diff -u /dev/null src/sys/arch/arm/ti/ti_prcm.h:1.1
--- /dev/null Thu Oct 26 23:28:15 2017
+++ src/sys/arch/arm/ti/ti_prcm.h Thu Oct 26 23:28:15 2017
@@ -0,0 +1,169 @@
+/* $NetBSD: ti_prcm.h,v 1.1 2017/10/26 23:28:15 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2017 Jared McNeill <[email protected]>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _ARM_TI_PRCM_H
+#define _ARM_TI_PRCM_H
+
+#ifdef TI_PRCM_PRIVATE
+
+#include <dev/clk/clk_backend.h>
+
+struct ti_prcm_clk;
+struct ti_prcm_softc;
+
+enum ti_prcm_clktype {
+ TI_PRCM_UNKNOWN,
+ TI_PRCM_FIXED,
+ TI_PRCM_FIXED_FACTOR,
+ TI_PRCM_HWMOD,
+};
+
+struct ti_prcm_fixed {
+ u_int rate;
+};
+
+struct ti_prcm_fixed_factor {
+ u_int mult;
+ u_int div;
+ const char *parent;
+};
+
+struct ti_prcm_hwmod {
+ bus_size_t reg;
+ const char *parent;
+};
+
+struct ti_prcm_clk {
+ struct clk base;
+ enum ti_prcm_clktype type;
+ union {
+ struct ti_prcm_fixed fixed;
+ struct ti_prcm_fixed_factor fixed_factor;
+ struct ti_prcm_hwmod hwmod;
+ } u;
+
+ int (*enable)(struct ti_prcm_softc *,
+ struct ti_prcm_clk *, int);
+ u_int (*get_rate)(struct ti_prcm_softc *,
+ struct ti_prcm_clk *);
+ int (*set_rate)(struct ti_prcm_softc *,
+ struct ti_prcm_clk *, u_int);
+ const char * (*get_parent)(struct ti_prcm_softc *,
+ struct ti_prcm_clk *);
+ int (*set_parent)(struct ti_prcm_softc *,
+ struct ti_prcm_clk *,
+ const char *);
+};
+
+int ti_prcm_attach(struct ti_prcm_softc *);
+struct ti_prcm_clk *ti_prcm_clock_find(struct ti_prcm_softc *, const char *);
+
+static inline u_int
+ti_prcm_fixed_get_rate(struct ti_prcm_softc *sc, struct ti_prcm_clk *tc)
+{
+ KASSERT(tc->type == TI_PRCM_FIXED);
+ return tc->u.fixed.rate;
+}
+
+#define TI_PRCM_FIXED(_name, _rate) \
+ { \
+ .type = TI_PRCM_FIXED, .base.name = (_name), \
+ .u.fixed.rate = (_rate), \
+ .get_rate = ti_prcm_fixed_get_rate, \
+ }
+
+static inline u_int
+ti_prcm_fixed_factor_get_rate(struct ti_prcm_softc *sc, struct ti_prcm_clk *tc)
+{
+ KASSERT(tc->type == TI_PRCM_FIXED_FACTOR);
+ struct ti_prcm_clk *tc_parent;
+
+ tc_parent = ti_prcm_clock_find(sc, tc->u.fixed_factor.parent);
+ KASSERT(tc_parent != NULL);
+
+ const u_int mult = tc->u.fixed_factor.mult;
+ const u_int div = tc->u.fixed_factor.div;
+
+ return (clk_get_rate(&tc_parent->base) * mult) / div;
+}
+
+static inline const char *
+ti_prcm_fixed_factor_get_parent(struct ti_prcm_softc *sc, struct ti_prcm_clk *tc)
+{
+ KASSERT(tc->type == TI_PRCM_FIXED_FACTOR);
+ return tc->u.fixed_factor.parent;
+}
+
+#define TI_PRCM_FIXED_FACTOR(_name, _mult, _div, _parent) \
+ { \
+ .type = TI_PRCM_FIXED_FACTOR, .base.name = (_name), \
+ .u.fixed_factor.mult = (_mult), \
+ .u.fixed_factor.div = (_div), \
+ .u.fixed_factor.parent = (_parent), \
+ .get_rate = ti_prcm_fixed_factor_get_rate, \
+ .get_parent = ti_prcm_fixed_factor_get_parent, \
+ }
+
+static inline const char *
+ti_prcm_hwmod_get_parent(struct ti_prcm_softc *sc, struct ti_prcm_clk *tc)
+{
+ KASSERT(tc->type == TI_PRCM_HWMOD);
+ return tc->u.hwmod.parent;
+}
+
+#define TI_PRCM_HWMOD(_name, _reg, _parent, _enable) \
+ { \
+ .type = TI_PRCM_HWMOD, .base.name = (_name), \
+ .u.hwmod.reg = (_reg), \
+ .u.hwmod.parent = (_parent), \
+ .enable = (_enable), \
+ .get_parent = ti_prcm_hwmod_get_parent, \
+ }
+
+struct ti_prcm_softc {
+ device_t sc_dev;
+ int sc_phandle;
+ bus_space_tag_t sc_bst;
+ bus_space_handle_t sc_bsh;
+
+ struct clk_domain sc_clkdom;
+
+ struct ti_prcm_clk *sc_clks;
+ u_int sc_nclks;
+};
+
+#define PRCM_READ(sc, reg) \
+ bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
+#define PRCM_WRITE(sc, reg, val) \
+ bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
+
+#endif /* !TI_PRCM_PRIVATE */
+
+struct clk * ti_prcm_get_hwmod(const int, u_int);
+
+#endif /* !_ARM_TI_PRCM_H */