Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F137938097
D25118.id72803.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
224 KB
Referenced Files
None
Subscribers
None
D25118.id72803.diff
View Options
Index: sys/arm/ti/am335x/am3359_cppi41.c
===================================================================
--- sys/arm/ti/am335x/am3359_cppi41.c
+++ sys/arm/ti/am335x/am3359_cppi41.c
@@ -0,0 +1,192 @@
+/*-
+ * Copyright (c) 2019 Emmanuel Vadot <manu@FreeBSD.org>
+ *
+ * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se>
+ *
+ * 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.
+ *
+ * $FreeBSD$
+ */
+/* Based on sys/arm/ti/ti_sysc.c */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <dev/fdt/simplebus.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <arm/ti/ti_sysc.h>
+
+#if 0
+#define DPRINTF(dev, msg...) device_printf(dev, msg)
+#else
+#define DPRINTF(dev, msg...)
+#endif
+
+struct ti_am3359_cppi41_softc {
+ device_t dev;
+ struct syscon * syscon;
+ struct resource * res[4];
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+ struct mtx mtx;
+};
+
+static struct resource_spec ti_am3359_cppi41_res_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE | RF_SHAREABLE },
+ { SYS_RES_MEMORY, 1, RF_ACTIVE | RF_SHAREABLE },
+ { SYS_RES_MEMORY, 2, RF_ACTIVE | RF_SHAREABLE },
+ { SYS_RES_MEMORY, 3, RF_ACTIVE | RF_SHAREABLE },
+ { -1, 0 }
+};
+
+/* Device */
+static struct ofw_compat_data compat_data[] = {
+ { "ti,am3359-cppi41", 1 },
+ { NULL, 0 }
+};
+
+static int
+ti_am3359_cppi41_write_4(device_t dev, bus_addr_t addr, uint32_t val)
+{
+ struct ti_am3359_cppi41_softc *sc;
+
+ sc = device_get_softc(dev);
+ DPRINTF(sc->dev, "offset=%lx write %x\n", addr, val);
+ mtx_lock(&sc->mtx);
+ bus_space_write_4(sc->bst, sc->bsh, addr, val);
+ mtx_unlock(&sc->mtx);
+ return (0);
+}
+
+static uint32_t
+ti_am3359_cppi41_read_4(device_t dev, bus_addr_t addr)
+{
+ struct ti_am3359_cppi41_softc *sc;
+ uint32_t val;
+
+ sc = device_get_softc(dev);
+
+ mtx_lock(&sc->mtx);
+ val = bus_space_read_4(sc->bst, sc->bsh, addr);
+ mtx_unlock(&sc->mtx);
+ DPRINTF(sc->dev, "offset=%lx Read %x\n", addr, val);
+ return (val);
+}
+
+/* device interface */
+static int
+ti_am3359_cppi41_probe(device_t dev)
+{
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "TI AM3359 CPPI 41");
+ return(BUS_PROBE_DEFAULT);
+}
+
+static int
+ti_am3359_cppi41_attach(device_t dev)
+{
+ struct ti_am3359_cppi41_softc *sc;
+ phandle_t node;
+ uint32_t reg, reset_bit, timeout=10;
+ uint64_t sysc_address;
+ device_t parent;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ if (bus_alloc_resources(dev, ti_am3359_cppi41_res_spec, sc->res)) {
+ device_printf(sc->dev, "Cant allocate resources\n");
+ return (ENXIO);
+ }
+
+ sc->dev = dev;
+ sc->bst = rman_get_bustag(sc->res[0]);
+ sc->bsh = rman_get_bushandle(sc->res[0]);
+
+ mtx_init(&sc->mtx, device_get_nameunit(sc->dev), NULL, MTX_DEF);
+ node = ofw_bus_get_node(sc->dev);
+
+ /* variant of am335x_usbss.c */
+ DPRINTF(dev, "-- RESET USB --\n");
+ parent = device_get_parent(dev);
+ reset_bit = ti_sysc_get_soft_reset_bit(parent);
+ if (reset_bit == 0) {
+ DPRINTF(dev, "Dont have reset bit\n");
+ return (0);
+ }
+ sysc_address = ti_sysc_get_sysc_address_offset_host(parent);
+ DPRINTF(dev, "sysc_address %x\n", sysc_address);
+ ti_am3359_cppi41_write_4(dev, sysc_address, reset_bit);
+ DELAY(100);
+ reg = ti_am3359_cppi41_read_4(dev, sysc_address);
+ if ((reg & reset_bit) && timeout--) {
+ DPRINTF(dev, "Reset still ongoing - wait a little bit longer\n");
+ DELAY(100);
+ reg = ti_am3359_cppi41_read_4(dev, sysc_address);
+ }
+ if (timeout == 0)
+ device_printf(dev, "USB Reset timeout\n");
+
+ return (0);
+}
+
+
+static device_method_t ti_am3359_cppi41_methods[] = {
+ DEVMETHOD(device_probe, ti_am3359_cppi41_probe),
+ DEVMETHOD(device_attach, ti_am3359_cppi41_attach),
+
+ DEVMETHOD_END
+};
+
+
+DEFINE_CLASS_1(ti_am3359_cppi41, ti_am3359_cppi41_driver,
+ ti_am3359_cppi41_methods,sizeof(struct ti_am3359_cppi41_softc),
+ simplebus_driver);
+
+static devclass_t ti_am3359_cppi41_devclass;
+
+EARLY_DRIVER_MODULE(ti_am3359_cppi41, simplebus, ti_am3359_cppi41_driver,
+ ti_am3359_cppi41_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
+MODULE_VERSION(ti_am3359_cppi41, 1);
+MODULE_DEPEND(ti_am3359_cppi41, ti_sysc, 1, 1, 1);
Index: sys/arm/ti/am335x/am335x_dmtimer.c
===================================================================
--- sys/arm/ti/am335x/am335x_dmtimer.c
+++ sys/arm/ti/am335x/am335x_dmtimer.c
@@ -42,12 +42,13 @@
#include <machine/machdep.h> /* For arm_set_delay */
+#include <dev/extres/clk/clk.h>
+
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
-#include <arm/ti/ti_prcm.h>
-#include <arm/ti/ti_hwmods.h>
+#include <arm/ti/ti_sysc.h>
#include "am335x_dmtreg.h"
@@ -58,7 +59,8 @@
int tmr_irq_rid;
struct resource * tmr_irq_res;
void *tmr_irq_handler;
- uint32_t sysclk_freq;
+ clk_t clk_fck;
+ uint64_t sysclk_freq;
uint32_t tclr; /* Cached TCLR register. */
union {
struct timecounter tc;
@@ -251,6 +253,7 @@
{
char strbuf[32];
int tmr_num;
+ uint64_t rev_address;
if (!ofw_bus_status_okay(dev))
return (ENXIO);
@@ -259,13 +262,22 @@
return (ENXIO);
/*
- * Get the hardware unit number (the N from ti,hwmods="timerN").
+ * Get the hardware unit number from address of rev register.
* If this isn't the hardware unit we're going to use for either the
* eventtimer or the timecounter, no point in instantiating the device.
*/
- tmr_num = ti_hwmods_get_unit(dev, "timer");
- if (tmr_num != ET_TMR_NUM && tmr_num != TC_TMR_NUM)
- return (ENXIO);
+ rev_address = ti_sysc_get_rev_address(device_get_parent(dev));
+ switch (rev_address) {
+ case DMTIMER2_REV:
+ tmr_num = 2;
+ break;
+ case DMTIMER3_REV:
+ tmr_num = 3;
+ break;
+ default:
+ /* Not DMTIMER2 or DMTIMER3 */
+ return (ENXIO);
+ }
snprintf(strbuf, sizeof(strbuf), "AM335x DMTimer%d", tmr_num);
device_set_desc_copy(dev, strbuf);
@@ -277,24 +289,47 @@
am335x_dmtimer_attach(device_t dev)
{
struct am335x_dmtimer_softc *sc;
- clk_ident_t timer_id;
int err;
+ uint64_t rev_address;
+ clk_t sys_clkin;
sc = device_get_softc(dev);
sc->dev = dev;
- /* Get the base clock frequency. */
- if ((err = ti_prcm_clk_get_source_freq(SYS_CLK, &sc->sysclk_freq)) != 0)
- return (err);
+ /* expect one clock */
+ err = clk_get_by_ofw_index(dev, 0, 0, &sc->clk_fck);
+ if (err != 0) {
+ device_printf(dev, "Cant find clock index 0. err: %d\n", err);
+ return (ENXIO);
+ }
+ err = clk_get_by_name(dev, "sys_clkin_ck@40", &sys_clkin);
+ if (err != 0) {
+ device_printf(dev, "Cant find sys_clkin_ck@40 err: %d\n", err);
+ return (ENXIO);
+ }
+
+ /* Select M_OSC as DPLL parent */
+ err = clk_set_parent_by_clk(sc->clk_fck, sys_clkin);
+ if (err != 0) {
+ device_printf(dev, "Cant set mux to CLK_M_OSC\n");
+ return (ENXIO);
+ }
+
/* Enable clocks and power on the device. */
- if ((timer_id = ti_hwmods_get_clock(dev)) == INVALID_CLK_IDENT)
+ err = ti_sysc_clock_enable(device_get_parent(dev));
+ if (err != 0) {
+ device_printf(dev, "Cant enable sysc clkctrl, err %d\n", err);
return (ENXIO);
- if ((err = ti_prcm_clk_set_source(timer_id, SYSCLK_CLK)) != 0)
- return (err);
- if ((err = ti_prcm_clk_enable(timer_id)) != 0)
- return (err);
+ }
+ /* Get the base clock frequency. */
+ err = clk_get_freq(sc->clk_fck, &sc->sysclk_freq);
+ if (err != 0) {
+ device_printf(dev, "Cant get sysclk frequency, err %d\n", err);
+ return (ENXIO);
+ }
+
/* Request the memory resources. */
sc->tmr_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
&sc->tmr_mem_rid, RF_ACTIVE);
@@ -302,7 +337,20 @@
return (ENXIO);
}
- sc->tmr_num = ti_hwmods_get_unit(dev, "timer");
+ rev_address = ti_sysc_get_rev_address(device_get_parent(dev));
+ switch (rev_address) {
+ case DMTIMER2_REV:
+ sc->tmr_num = 2;
+ break;
+ case DMTIMER3_REV:
+ sc->tmr_num = 3;
+ break;
+ default:
+ device_printf(dev, "Not timer 2 or 3! %#jx\n",
+ rev_address);
+ return (ENXIO);
+ }
+
snprintf(sc->tmr_name, sizeof(sc->tmr_name), "DMTimer%d", sc->tmr_num);
/*
@@ -334,7 +382,7 @@
static devclass_t am335x_dmtimer_devclass;
DRIVER_MODULE(am335x_dmtimer, simplebus, am335x_dmtimer_driver, am335x_dmtimer_devclass, 0, 0);
-MODULE_DEPEND(am335x_dmtimer, am335x_prcm, 1, 1, 1);
+MODULE_DEPEND(am335x_dmtimer, ti_sysc, 1, 1, 1);
static void
am335x_dmtimer_delay(int usec, void *arg)
Index: sys/arm/ti/am335x/am335x_dmtpps.c
===================================================================
--- sys/arm/ti/am335x/am335x_dmtpps.c
+++ sys/arm/ti/am335x/am335x_dmtpps.c
@@ -61,8 +61,7 @@
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
-#include <arm/ti/ti_prcm.h>
-#include <arm/ti/ti_hwmods.h>
+#include <arm/ti/ti_sysc.h>
#include <arm/ti/ti_pinmux.h>
#include <arm/ti/am335x/am335x_scm_padconf.h>
@@ -383,6 +382,7 @@
{
char strbuf[64];
int tmr_num;
+ uint64_t rev_address;
if (!ofw_bus_status_okay(dev))
return (ENXIO);
@@ -402,7 +402,33 @@
* Figure out which hardware timer is being probed and see if it matches
* the configured timer number determined earlier.
*/
- tmr_num = ti_hwmods_get_unit(dev, "timer");
+ rev_address = ti_sysc_get_rev_address(device_get_parent(dev));
+ switch (rev_address) {
+ case DMTIMER1_1MS_REV:
+ tmr_num = 1;
+ break;
+ case DMTIMER2_REV:
+ tmr_num = 2;
+ break;
+ case DMTIMER3_REV:
+ tmr_num = 3;
+ break;
+ case DMTIMER4_REV:
+ tmr_num = 4;
+ break;
+ case DMTIMER5_REV:
+ tmr_num = 5;
+ break;
+ case DMTIMER6_REV:
+ tmr_num = 6;
+ break;
+ case DMTIMER7_REV:
+ tmr_num = 7;
+ break;
+ default:
+ return (ENXIO);
+ }
+
if (dmtpps_tmr_num != tmr_num)
return (ENXIO);
@@ -418,23 +444,72 @@
{
struct dmtpps_softc *sc;
struct make_dev_args mda;
- clk_ident_t timer_id;
int err, sysclk_freq;
+ clk_t sys_clkin;
sc = device_get_softc(dev);
sc->dev = dev;
- /* Get the base clock frequency. */
- err = ti_prcm_clk_get_source_freq(SYS_CLK, &sysclk_freq);
+ /* Figure out which hardware timer this is and set the name string. */
+ rev_address = ti_sysc_get_rev_address(device_get_parent(dev));
+ switch (rev_address) {
+ case DMTIMER1_1MS_REV:
+ sc->tmr_num = 1;
+ break;
+ case DMTIMER2_REV:
+ sc->tmr_num = 2;
+ break;
+ case DMTIMER3_REV:
+ sc->tmr_num = 3;
+ break;
+ case DMTIMER4_REV:
+ sc->tmr_num = 4;
+ break;
+ case DMTIMER5_REV:
+ sc->tmr_num = 5;
+ break;
+ case DMTIMER6_REV:
+ sc->tmr_num = 6;
+ break;
+ case DMTIMER7_REV:
+ sc->tmr_num = 7;
+ break;
+ }
+ snprintf(sc->tmr_name, sizeof(sc->tmr_name), "DMTimer%d", sc->tmr_num);
+ /* expect one clock */
+ err = clk_get_by_ofw_index(dev, 0, 0, &sc->clk_fck);
+ if (err != 0) {
+ device_printf(dev, "Cant find clock index 0. err: %d\n", err);
+ return (ENXIO);
+ }
+
+ err = clk_get_by_name(dev, "sys_clkin_ck@40", &sys_clkin);
+ if (err != 0) {
+ device_printf(dev, "Cant find sys_clkin_ck@40 err: %d\n", err);
+ return (ENXIO);
+ }
+
+ /* Select M_OSC as DPLL parent */
+ err = clk_set_parent_by_clk(sc->clk_fck, sys_clkin);
+ if (err != 0) {
+ device_printf(dev, "Cant set mux to CLK_M_OSC\n");
+ return (ENXIO);
+ }
+
/* Enable clocks and power on the device. */
- if ((timer_id = ti_hwmods_get_clock(dev)) == INVALID_CLK_IDENT)
+ err = ti_sysc_clock_enable(device_get_parent(dev));
+ if (err != 0) {
+ device_printf(dev, "Cant enable sysc clkctrl, err %d\n", err);
return (ENXIO);
- if ((err = ti_prcm_clk_set_source(timer_id, SYSCLK_CLK)) != 0)
- return (err);
- if ((err = ti_prcm_clk_enable(timer_id)) != 0)
- return (err);
+ }
+ /* Get the base clock frequency. */
+ err = clk_get_freq(sc->clk_fck, &sc->sysclk_freq);
+ if (err != 0) {
+ device_printf(dev, "Cant get sysclk frequency, err %d\n", err);
+ return (ENXIO);
+ }
/* Request the memory resources. */
sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
&sc->mem_rid, RF_ACTIVE);
@@ -442,10 +517,6 @@
return (ENXIO);
}
- /* Figure out which hardware timer this is and set the name string. */
- sc->tmr_num = ti_hwmods_get_unit(dev, "timer");
- snprintf(sc->tmr_name, sizeof(sc->tmr_name), "DMTimer%d", sc->tmr_num);
-
/*
* Configure the timer pulse/capture pin to input/capture mode. This is
* required in addition to configuring the pin as input with the pinmux
@@ -541,5 +612,4 @@
static devclass_t dmtpps_devclass;
DRIVER_MODULE(am335x_dmtpps, simplebus, dmtpps_driver, dmtpps_devclass, 0, 0);
-MODULE_DEPEND(am335x_dmtpps, am335x_prcm, 1, 1, 1);
-
+MODULE_DEPEND(am335x_dmtpps, ti_sysc, 1, 1, 1);
Index: sys/arm/ti/am335x/am335x_dmtreg.h
===================================================================
--- sys/arm/ti/am335x/am335x_dmtreg.h
+++ sys/arm/ti/am335x/am335x_dmtreg.h
@@ -73,4 +73,16 @@
#define DMT_TSICR_RESET (1 << 1) /* TSICR perform soft reset */
#define DMT_TCAR2 0x48 /* Capture Reg */
+/* Location of revision register from TRM Memory map chapter 2 */
+/* L4_WKUP */
+#define DMTIMER0_REV 0x05000
+#define DMTIMER1_1MS_REV 0x31000
+/* L4_PER */
+#define DMTIMER2_REV 0x40000
+#define DMTIMER3_REV 0x42000
+#define DMTIMER4_REV 0x44000
+#define DMTIMER5_REV 0x46000
+#define DMTIMER6_REV 0x48000
+#define DMTIMER7_REV 0x4A000
+
#endif /* AM335X_DMTREG_H */
Index: sys/arm/ti/am335x/am335x_gpio.c
===================================================================
--- sys/arm/ti/am335x/am335x_gpio.c
+++ sys/arm/ti/am335x/am335x_gpio.c
@@ -155,3 +155,4 @@
sizeof(struct ti_gpio_softc), ti_gpio_driver);
DRIVER_MODULE(am335x_gpio, simplebus, am335x_gpio_driver, am335x_gpio_devclass,
0, 0);
+MODULE_DEPEND(am335x_gpio, ti_sysc, 1, 1, 1);
Index: sys/arm/ti/am335x/am335x_lcd.c
===================================================================
--- sys/arm/ti/am335x/am335x_lcd.c
+++ sys/arm/ti/am335x/am335x_lcd.c
@@ -50,6 +50,8 @@
#include <machine/bus.h>
+#include <dev/extres/clk/clk.h>
+
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
@@ -65,7 +67,7 @@
#include <dev/vt/vt.h>
#endif
-#include <arm/ti/ti_prcm.h>
+#include <arm/ti/ti_sysc.h>
#include <arm/ti/ti_scm.h>
#include "am335x_lcd.h"
@@ -219,6 +221,9 @@
/* HDMI framer */
phandle_t sc_hdmi_framer;
eventhandler_tag sc_hdmi_evh;
+
+ /* Clock */
+ clk_t sc_clk_dpll_disp_ck;
};
static void
@@ -615,24 +620,28 @@
uint32_t hbp, hfp, hsw;
uint32_t vbp, vfp, vsw;
uint32_t width, height;
- unsigned int ref_freq;
+ uint64_t ref_freq;
int err;
/*
* try to adjust clock to get double of requested frequency
* HDMI/DVI displays are very sensitive to error in frequncy value
*/
- if (ti_prcm_clk_set_source_freq(LCDC_CLK, sc->sc_panel.panel_pxl_clk*2)) {
+
+ err = clk_set_freq(sc->sc_clk_dpll_disp_ck, sc->sc_panel.panel_pxl_clk*2,
+ CLK_SET_ROUND_ANY);
+ if (err != 0) {
device_printf(sc->sc_dev, "can't set source frequency\n");
return (ENXIO);
}
- if (ti_prcm_clk_get_source_freq(LCDC_CLK, &ref_freq)) {
+ err = clk_get_freq(sc->sc_clk_dpll_disp_ck, &ref_freq);
+ if (err != 0) {
device_printf(sc->sc_dev, "can't get reference frequency\n");
return (ENXIO);
}
- /* Panle initialization */
+ /* Panel initialization */
dma_size = round_page(sc->sc_panel.panel_width*sc->sc_panel.panel_height*sc->sc_panel.bpp/8);
/*
@@ -967,6 +976,13 @@
return (ENXIO);
}
+ /* Fixme: Cant find any reference in DTS for dpll_disp_ck@498 for now. */
+ err = clk_get_by_name(dev, "dpll_disp_ck@498", &sc->sc_clk_dpll_disp_ck);
+ if (err != 0) {
+ device_printf(dev, "Cant get dpll_disp_ck@49\n");
+ return (ENXIO);
+ }
+
sc->sc_panel.ac_bias = 255;
sc->sc_panel.ac_bias_intrpt = 0;
sc->sc_panel.dma_burst_sz = 16;
@@ -989,7 +1005,11 @@
}
}
- ti_prcm_clk_enable(LCDC_CLK);
+ err = ti_sysc_clock_enable(device_get_parent(dev));
+ if (err != 0) {
+ device_printf(dev, "Failed to enable sysc clkctrl, err %d\n", err);
+ return (ENXIO);
+ }
rid = 0;
sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
@@ -1081,3 +1101,4 @@
DRIVER_MODULE(am335x_lcd, simplebus, am335x_lcd_driver, am335x_lcd_devclass, 0, 0);
MODULE_VERSION(am335x_lcd, 1);
MODULE_DEPEND(am335x_lcd, simplebus, 1, 1, 1);
+MODULE_DEPEND(am335x_lcd, ti_sysc, 1, 1, 1);
Index: sys/arm/ti/am335x/am335x_musb.c
===================================================================
--- sys/arm/ti/am335x/am335x_musb.c
+++ sys/arm/ti/am335x/am335x_musb.c
@@ -66,9 +66,11 @@
#include <sys/rman.h>
-#include <arm/ti/ti_prcm.h>
-#include <arm/ti/ti_scm.h>
#include <arm/ti/am335x/am335x_scm.h>
+#include <arm/ti/ti_sysc.h>
+#include <dev/extres/clk/clk.h>
+#include <dev/extres/syscon/syscon.h>
+#include "syscon_if.h"
#define USBCTRL_REV 0x00
#define USBCTRL_CTRL 0x14
@@ -130,6 +132,7 @@
struct musbotg_softc sc_otg;
struct resource *sc_mem_res[2];
int sc_irq_rid;
+ struct syscon *syscon;
};
static void
@@ -155,30 +158,33 @@
musbotg_clocks_on(void *arg)
{
struct musbotg_softc *sc;
- uint32_t c, reg;
+ struct musbotg_super_softc *ssc;
+ uint32_t reg;
sc = arg;
- reg = USB_CTRL[sc->sc_id];
+ ssc = sc->sc_platform_data;
- ti_scm_reg_read_4(reg, &c);
- c &= ~3; /* Enable power */
- c |= 1 << 19; /* VBUS detect enable */
- c |= 1 << 20; /* Session end enable */
- ti_scm_reg_write_4(reg, c);
+ reg = SYSCON_READ_4(ssc->syscon, USB_CTRL[sc->sc_id]);
+ reg &= ~3; /* Enable power */
+ reg |= 1 << 19; /* VBUS detect enable */
+ reg |= 1 << 20; /* Session end enable */
+
+ SYSCON_WRITE_4(ssc->syscon, USB_CTRL[sc->sc_id], reg);
}
static void
musbotg_clocks_off(void *arg)
{
struct musbotg_softc *sc;
- uint32_t c, reg;
+ struct musbotg_super_softc *ssc;
+ uint32_t reg;
sc = arg;
- reg = USB_CTRL[sc->sc_id];
+ ssc = sc->sc_platform_data;
/* Disable power to PHY */
- ti_scm_reg_read_4(reg, &c);
- ti_scm_reg_write_4(reg, c | 3);
+ reg = SYSCON_READ_4(ssc->syscon, USB_CTRL[sc->sc_id]);
+ SYSCON_WRITE_4(ssc->syscon, USB_CTRL[sc->sc_id], reg | 3);
}
static void
@@ -241,9 +247,42 @@
char mode[16];
int err;
uint32_t reg;
+ phandle_t opp_table;
+ clk_t clk_usbotg_fck;
sc->sc_otg.sc_id = device_get_unit(dev);
+ /* FIXME: The devicetree needs to be updated to get a handle to the gate
+ * usbotg_fck@47c. see TRM 8.1.12.2 CM_WKUP CM_CLKDCOLDO_DPLL_PER.
+ */
+ err = clk_get_by_name(dev, "usbotg_fck@47c", &clk_usbotg_fck);
+ if (err) {
+ device_printf(dev, "Can not find usbotg_fck@47c\n");
+ return (ENXIO);
+ }
+
+ err = clk_enable(clk_usbotg_fck);
+ if (err) {
+ device_printf(dev, "Can not enable usbotg_fck@47c\n");
+ return (ENXIO);
+ }
+
+ /* FIXME: For now; Go and kidnap syscon from opp-table */
+ opp_table = OF_finddevice("/opp-table");
+ if (opp_table == -1) {
+ device_printf(dev, "Cant find /opp-table\n");
+ return (ENXIO);
+ }
+ if (!OF_hasprop(opp_table, "syscon")) {
+ device_printf(dev, "/opp-table missing syscon property\n");
+ return (ENXIO);
+ }
+ err = syscon_get_by_ofw_property(dev, opp_table, "syscon", &sc->syscon);
+ if (err) {
+ device_printf(dev, "Failed to get syscon\n");
+ return (ENXIO);
+ }
+
/* Request the memory resources */
err = bus_alloc_resources(dev, am335x_musbotg_mem_spec,
sc->sc_mem_res);
@@ -417,5 +456,7 @@
static devclass_t musbotg_devclass;
-DRIVER_MODULE(musbotg, usbss, musbotg_driver, musbotg_devclass, 0, 0);
-MODULE_DEPEND(musbotg, usbss, 1, 1, 1);
+DRIVER_MODULE(musbotg, ti_sysc, musbotg_driver, musbotg_devclass, 0, 0);
+MODULE_DEPEND(musbotg, ti_sysc, 1, 1, 1);
+MODULE_DEPEND(musbotg, ti_am3359_cppi41, 1, 1, 1);
+MODULE_DEPEND(usbss, usb, 1, 1, 1);
Index: sys/arm/ti/am335x/am335x_prcm.c
===================================================================
--- sys/arm/ti/am335x/am335x_prcm.c
+++ sys/arm/ti/am335x/am335x_prcm.c
@@ -1,884 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2012 Damjan Marion <dmarion@Freebsd.org>
- * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/bus.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/malloc.h>
-#include <sys/rman.h>
-#include <sys/timeet.h>
-#include <sys/timetc.h>
-#include <sys/watchdog.h>
-#include <machine/bus.h>
-#include <machine/cpu.h>
-#include <machine/intr.h>
-
-#include <arm/ti/tivar.h>
-#include <arm/ti/ti_scm.h>
-#include <arm/ti/ti_prcm.h>
-
-#include <dev/ofw/openfirm.h>
-#include <dev/ofw/ofw_bus.h>
-#include <dev/ofw/ofw_bus_subr.h>
-
-#include <machine/bus.h>
-
-#include "am335x_scm.h"
-
-#define CM_PER 0
-#define CM_PER_L4LS_CLKSTCTRL (CM_PER + 0x000)
-#define CM_PER_L3S_CLKSTCTRL (CM_PER + 0x004)
-#define CM_PER_L3_CLKSTCTRL (CM_PER + 0x00C)
-#define CM_PER_CPGMAC0_CLKCTRL (CM_PER + 0x014)
-#define CM_PER_LCDC_CLKCTRL (CM_PER + 0x018)
-#define CM_PER_USB0_CLKCTRL (CM_PER + 0x01C)
-#define CM_PER_TPTC0_CLKCTRL (CM_PER + 0x024)
-#define CM_PER_UART5_CLKCTRL (CM_PER + 0x038)
-#define CM_PER_MMC0_CLKCTRL (CM_PER + 0x03C)
-#define CM_PER_I2C2_CLKCTRL (CM_PER + 0x044)
-#define CM_PER_I2C1_CLKCTRL (CM_PER + 0x048)
-#define CM_PER_SPI0_CLKCTRL (CM_PER + 0x04C)
-#define CM_PER_SPI1_CLKCTRL (CM_PER + 0x050)
-#define CM_PER_UART1_CLKCTRL (CM_PER + 0x06C)
-#define CM_PER_UART2_CLKCTRL (CM_PER + 0x070)
-#define CM_PER_UART3_CLKCTRL (CM_PER + 0x074)
-#define CM_PER_UART4_CLKCTRL (CM_PER + 0x078)
-#define CM_PER_TIMER7_CLKCTRL (CM_PER + 0x07C)
-#define CM_PER_TIMER2_CLKCTRL (CM_PER + 0x080)
-#define CM_PER_TIMER3_CLKCTRL (CM_PER + 0x084)
-#define CM_PER_TIMER4_CLKCTRL (CM_PER + 0x088)
-#define CM_PER_GPIO1_CLKCTRL (CM_PER + 0x0AC)
-#define CM_PER_GPIO2_CLKCTRL (CM_PER + 0x0B0)
-#define CM_PER_GPIO3_CLKCTRL (CM_PER + 0x0B4)
-#define CM_PER_TPCC_CLKCTRL (CM_PER + 0x0BC)
-#define CM_PER_EPWMSS1_CLKCTRL (CM_PER + 0x0CC)
-#define CM_PER_EPWMSS0_CLKCTRL (CM_PER + 0x0D4)
-#define CM_PER_EPWMSS2_CLKCTRL (CM_PER + 0x0D8)
-#define CM_PER_L3_INSTR_CLKCTRL (CM_PER + 0x0DC)
-#define CM_PER_L3_CLKCTRL (CM_PER + 0x0E0)
-#define CM_PER_PRUSS_CLKCTRL (CM_PER + 0x0E8)
-#define CM_PER_TIMER5_CLKCTRL (CM_PER + 0x0EC)
-#define CM_PER_TIMER6_CLKCTRL (CM_PER + 0x0F0)
-#define CM_PER_MMC1_CLKCTRL (CM_PER + 0x0F4)
-#define CM_PER_MMC2_CLKCTRL (CM_PER + 0x0F8)
-#define CM_PER_TPTC1_CLKCTRL (CM_PER + 0x0FC)
-#define CM_PER_TPTC2_CLKCTRL (CM_PER + 0x100)
-#define CM_PER_SPINLOCK0_CLKCTRL (CM_PER + 0x10C)
-#define CM_PER_MAILBOX0_CLKCTRL (CM_PER + 0x110)
-#define CM_PER_OCPWP_L3_CLKSTCTRL (CM_PER + 0x12C)
-#define CM_PER_OCPWP_CLKCTRL (CM_PER + 0x130)
-#define CM_PER_CPSW_CLKSTCTRL (CM_PER + 0x144)
-#define CM_PER_PRUSS_CLKSTCTRL (CM_PER + 0x140)
-
-#define CM_WKUP 0x400
-#define CM_WKUP_CLKSTCTRL (CM_WKUP + 0x000)
-#define CM_WKUP_CONTROL_CLKCTRL (CM_WKUP + 0x004)
-#define CM_WKUP_GPIO0_CLKCTRL (CM_WKUP + 0x008)
-#define CM_WKUP_CM_L3_AON_CLKSTCTRL (CM_WKUP + 0x01C)
-#define CM_WKUP_CM_CLKSEL_DPLL_MPU (CM_WKUP + 0x02C)
-#define CM_WKUP_CM_IDLEST_DPLL_DISP (CM_WKUP + 0x048)
-#define CM_WKUP_CM_CLKSEL_DPLL_DISP (CM_WKUP + 0x054)
-#define CM_WKUP_CM_CLKDCOLDO_DPLL_PER (CM_WKUP + 0x07C)
-#define CM_WKUP_CM_CLKMODE_DPLL_DISP (CM_WKUP + 0x098)
-#define CM_WKUP_I2C0_CLKCTRL (CM_WKUP + 0x0B8)
-#define CM_WKUP_ADC_TSC_CLKCTRL (CM_WKUP + 0x0BC)
-
-#define CM_DPLL 0x500
-#define CLKSEL_TIMER7_CLK (CM_DPLL + 0x004)
-#define CLKSEL_TIMER2_CLK (CM_DPLL + 0x008)
-#define CLKSEL_TIMER3_CLK (CM_DPLL + 0x00C)
-#define CLKSEL_TIMER4_CLK (CM_DPLL + 0x010)
-#define CLKSEL_TIMER5_CLK (CM_DPLL + 0x018)
-#define CLKSEL_TIMER6_CLK (CM_DPLL + 0x01C)
-#define CLKSEL_PRUSS_OCP_CLK (CM_DPLL + 0x030)
-
-#define CM_RTC 0x800
-#define CM_RTC_RTC_CLKCTRL (CM_RTC + 0x000)
-#define CM_RTC_CLKSTCTRL (CM_RTC + 0x004)
-
-#define PRM_PER 0xC00
-#define PRM_PER_RSTCTRL (PRM_PER + 0x00)
-
-#define PRM_DEVICE_OFFSET 0xF00
-#define PRM_RSTCTRL (PRM_DEVICE_OFFSET + 0x00)
-
-struct am335x_prcm_softc {
- struct resource * res[2];
- bus_space_tag_t bst;
- bus_space_handle_t bsh;
- int attach_done;
-};
-
-static struct resource_spec am335x_prcm_spec[] = {
- { SYS_RES_MEMORY, 0, RF_ACTIVE },
- { -1, 0 }
-};
-
-static struct am335x_prcm_softc *am335x_prcm_sc = NULL;
-
-static int am335x_clk_noop_activate(struct ti_clock_dev *clkdev);
-static int am335x_clk_generic_activate(struct ti_clock_dev *clkdev);
-static int am335x_clk_gpio_activate(struct ti_clock_dev *clkdev);
-static int am335x_clk_noop_deactivate(struct ti_clock_dev *clkdev);
-static int am335x_clk_generic_deactivate(struct ti_clock_dev *clkdev);
-static int am335x_clk_noop_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc);
-static int am335x_clk_generic_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc);
-static int am335x_clk_hsmmc_get_source_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
-static int am335x_clk_get_sysclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
-static int am335x_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
-static int am335x_clk_get_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
-static int am335x_clk_set_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int freq);
-static void am335x_prcm_reset(void);
-static int am335x_clk_cpsw_activate(struct ti_clock_dev *clkdev);
-static int am335x_clk_musb0_activate(struct ti_clock_dev *clkdev);
-static int am335x_clk_lcdc_activate(struct ti_clock_dev *clkdev);
-static int am335x_clk_pruss_activate(struct ti_clock_dev *clkdev);
-
-#define AM335X_NOOP_CLOCK_DEV(i) \
- { .id = (i), \
- .clk_activate = am335x_clk_noop_activate, \
- .clk_deactivate = am335x_clk_noop_deactivate, \
- .clk_set_source = am335x_clk_noop_set_source, \
- .clk_accessible = NULL, \
- .clk_get_source_freq = NULL, \
- .clk_set_source_freq = NULL \
- }
-
-#define AM335X_GENERIC_CLOCK_DEV(i) \
- { .id = (i), \
- .clk_activate = am335x_clk_generic_activate, \
- .clk_deactivate = am335x_clk_generic_deactivate, \
- .clk_set_source = am335x_clk_generic_set_source, \
- .clk_accessible = NULL, \
- .clk_get_source_freq = NULL, \
- .clk_set_source_freq = NULL \
- }
-
-#define AM335X_GPIO_CLOCK_DEV(i) \
- { .id = (i), \
- .clk_activate = am335x_clk_gpio_activate, \
- .clk_deactivate = am335x_clk_generic_deactivate, \
- .clk_set_source = am335x_clk_generic_set_source, \
- .clk_accessible = NULL, \
- .clk_get_source_freq = NULL, \
- .clk_set_source_freq = NULL \
- }
-
-#define AM335X_MMCHS_CLOCK_DEV(i) \
- { .id = (i), \
- .clk_activate = am335x_clk_generic_activate, \
- .clk_deactivate = am335x_clk_generic_deactivate, \
- .clk_set_source = am335x_clk_generic_set_source, \
- .clk_accessible = NULL, \
- .clk_get_source_freq = am335x_clk_hsmmc_get_source_freq, \
- .clk_set_source_freq = NULL \
- }
-
-struct ti_clock_dev ti_am335x_clk_devmap[] = {
- /* System clocks */
- { .id = SYS_CLK,
- .clk_activate = NULL,
- .clk_deactivate = NULL,
- .clk_set_source = NULL,
- .clk_accessible = NULL,
- .clk_get_source_freq = am335x_clk_get_sysclk_freq,
- .clk_set_source_freq = NULL,
- },
- /* MPU (ARM) core clocks */
- { .id = MPU_CLK,
- .clk_activate = NULL,
- .clk_deactivate = NULL,
- .clk_set_source = NULL,
- .clk_accessible = NULL,
- .clk_get_source_freq = am335x_clk_get_arm_fclk_freq,
- .clk_set_source_freq = NULL,
- },
- /* CPSW Ethernet Switch core clocks */
- { .id = CPSW_CLK,
- .clk_activate = am335x_clk_cpsw_activate,
- .clk_deactivate = NULL,
- .clk_set_source = NULL,
- .clk_accessible = NULL,
- .clk_get_source_freq = NULL,
- .clk_set_source_freq = NULL,
- },
-
- /* Mentor USB HS controller core clocks */
- { .id = MUSB0_CLK,
- .clk_activate = am335x_clk_musb0_activate,
- .clk_deactivate = NULL,
- .clk_set_source = NULL,
- .clk_accessible = NULL,
- .clk_get_source_freq = NULL,
- .clk_set_source_freq = NULL,
- },
-
- /* LCD controller clocks */
- { .id = LCDC_CLK,
- .clk_activate = am335x_clk_lcdc_activate,
- .clk_deactivate = NULL,
- .clk_set_source = NULL,
- .clk_accessible = NULL,
- .clk_get_source_freq = am335x_clk_get_arm_disp_freq,
- .clk_set_source_freq = am335x_clk_set_arm_disp_freq,
- },
-
- /* UART */
- AM335X_NOOP_CLOCK_DEV(UART1_CLK),
- AM335X_GENERIC_CLOCK_DEV(UART2_CLK),
- AM335X_GENERIC_CLOCK_DEV(UART3_CLK),
- AM335X_GENERIC_CLOCK_DEV(UART4_CLK),
- AM335X_GENERIC_CLOCK_DEV(UART5_CLK),
- AM335X_GENERIC_CLOCK_DEV(UART6_CLK),
-
- /* DMTimer */
- AM335X_GENERIC_CLOCK_DEV(TIMER2_CLK),
- AM335X_GENERIC_CLOCK_DEV(TIMER3_CLK),
- AM335X_GENERIC_CLOCK_DEV(TIMER4_CLK),
- AM335X_GENERIC_CLOCK_DEV(TIMER5_CLK),
- AM335X_GENERIC_CLOCK_DEV(TIMER6_CLK),
- AM335X_GENERIC_CLOCK_DEV(TIMER7_CLK),
-
- /* GPIO, we use hwmods as reference, not units in spec */
- AM335X_GPIO_CLOCK_DEV(GPIO1_CLK),
- AM335X_GPIO_CLOCK_DEV(GPIO2_CLK),
- AM335X_GPIO_CLOCK_DEV(GPIO3_CLK),
- AM335X_GPIO_CLOCK_DEV(GPIO4_CLK),
-
- /* I2C we use hwmods as reference, not units in spec */
- AM335X_GENERIC_CLOCK_DEV(I2C1_CLK),
- AM335X_GENERIC_CLOCK_DEV(I2C2_CLK),
- AM335X_GENERIC_CLOCK_DEV(I2C3_CLK),
-
- /* McSPI we use hwmods as reference, not units in spec */
- AM335X_GENERIC_CLOCK_DEV(SPI0_CLK),
- AM335X_GENERIC_CLOCK_DEV(SPI1_CLK),
-
- /* TSC_ADC */
- AM335X_GENERIC_CLOCK_DEV(TSC_ADC_CLK),
-
- /* EDMA */
- AM335X_GENERIC_CLOCK_DEV(EDMA_TPCC_CLK),
- AM335X_GENERIC_CLOCK_DEV(EDMA_TPTC0_CLK),
- AM335X_GENERIC_CLOCK_DEV(EDMA_TPTC1_CLK),
- AM335X_GENERIC_CLOCK_DEV(EDMA_TPTC2_CLK),
-
- /* MMCHS */
- AM335X_MMCHS_CLOCK_DEV(MMC1_CLK),
- AM335X_MMCHS_CLOCK_DEV(MMC2_CLK),
- AM335X_MMCHS_CLOCK_DEV(MMC3_CLK),
-
- /* PWMSS */
- AM335X_GENERIC_CLOCK_DEV(PWMSS0_CLK),
- AM335X_GENERIC_CLOCK_DEV(PWMSS1_CLK),
- AM335X_GENERIC_CLOCK_DEV(PWMSS2_CLK),
-
- /* System Mailbox clock */
- AM335X_GENERIC_CLOCK_DEV(MAILBOX0_CLK),
-
- /* SPINLOCK */
- AM335X_GENERIC_CLOCK_DEV(SPINLOCK0_CLK),
-
- /* PRU-ICSS */
- { .id = PRUSS_CLK,
- .clk_activate = am335x_clk_pruss_activate,
- .clk_deactivate = NULL,
- .clk_set_source = NULL,
- .clk_accessible = NULL,
- .clk_get_source_freq = NULL,
- .clk_set_source_freq = NULL,
- },
-
- /* RTC */
- AM335X_GENERIC_CLOCK_DEV(RTC_CLK),
-
- { INVALID_CLK_IDENT, NULL, NULL, NULL, NULL }
-};
-
-struct am335x_clk_details {
- clk_ident_t id;
- uint32_t clkctrl_reg;
- uint32_t clksel_reg;
-};
-
-#define _CLK_DETAIL(i, c, s) \
- { .id = (i), \
- .clkctrl_reg = (c), \
- .clksel_reg = (s), \
- }
-
-static struct am335x_clk_details g_am335x_clk_details[] = {
-
- /* UART. UART0 clock not controllable. */
- _CLK_DETAIL(UART1_CLK, 0, 0),
- _CLK_DETAIL(UART2_CLK, CM_PER_UART1_CLKCTRL, 0),
- _CLK_DETAIL(UART3_CLK, CM_PER_UART2_CLKCTRL, 0),
- _CLK_DETAIL(UART4_CLK, CM_PER_UART3_CLKCTRL, 0),
- _CLK_DETAIL(UART5_CLK, CM_PER_UART4_CLKCTRL, 0),
- _CLK_DETAIL(UART6_CLK, CM_PER_UART5_CLKCTRL, 0),
-
- /* DMTimer modules */
- _CLK_DETAIL(TIMER2_CLK, CM_PER_TIMER2_CLKCTRL, CLKSEL_TIMER2_CLK),
- _CLK_DETAIL(TIMER3_CLK, CM_PER_TIMER3_CLKCTRL, CLKSEL_TIMER3_CLK),
- _CLK_DETAIL(TIMER4_CLK, CM_PER_TIMER4_CLKCTRL, CLKSEL_TIMER4_CLK),
- _CLK_DETAIL(TIMER5_CLK, CM_PER_TIMER5_CLKCTRL, CLKSEL_TIMER5_CLK),
- _CLK_DETAIL(TIMER6_CLK, CM_PER_TIMER6_CLKCTRL, CLKSEL_TIMER6_CLK),
- _CLK_DETAIL(TIMER7_CLK, CM_PER_TIMER7_CLKCTRL, CLKSEL_TIMER7_CLK),
-
- /* GPIO modules, hwmods start with gpio1 */
- _CLK_DETAIL(GPIO1_CLK, CM_WKUP_GPIO0_CLKCTRL, 0),
- _CLK_DETAIL(GPIO2_CLK, CM_PER_GPIO1_CLKCTRL, 0),
- _CLK_DETAIL(GPIO3_CLK, CM_PER_GPIO2_CLKCTRL, 0),
- _CLK_DETAIL(GPIO4_CLK, CM_PER_GPIO3_CLKCTRL, 0),
-
- /* I2C modules, hwmods start with i2c1 */
- _CLK_DETAIL(I2C1_CLK, CM_WKUP_I2C0_CLKCTRL, 0),
- _CLK_DETAIL(I2C2_CLK, CM_PER_I2C1_CLKCTRL, 0),
- _CLK_DETAIL(I2C3_CLK, CM_PER_I2C2_CLKCTRL, 0),
-
- /* McSPI modules, hwmods start with spi0 */
- _CLK_DETAIL(SPI0_CLK, CM_PER_SPI0_CLKCTRL, 0),
- _CLK_DETAIL(SPI1_CLK, CM_PER_SPI1_CLKCTRL, 0),
-
- /* TSC_ADC module */
- _CLK_DETAIL(TSC_ADC_CLK, CM_WKUP_ADC_TSC_CLKCTRL, 0),
-
- /* EDMA modules */
- _CLK_DETAIL(EDMA_TPCC_CLK, CM_PER_TPCC_CLKCTRL, 0),
- _CLK_DETAIL(EDMA_TPTC0_CLK, CM_PER_TPTC0_CLKCTRL, 0),
- _CLK_DETAIL(EDMA_TPTC1_CLK, CM_PER_TPTC1_CLKCTRL, 0),
- _CLK_DETAIL(EDMA_TPTC2_CLK, CM_PER_TPTC2_CLKCTRL, 0),
-
- /* MMCHS modules, hwmods start with mmc1*/
- _CLK_DETAIL(MMC1_CLK, CM_PER_MMC0_CLKCTRL, 0),
- _CLK_DETAIL(MMC2_CLK, CM_PER_MMC1_CLKCTRL, 0),
- _CLK_DETAIL(MMC3_CLK, CM_PER_MMC1_CLKCTRL, 0),
-
- /* PWMSS modules */
- _CLK_DETAIL(PWMSS0_CLK, CM_PER_EPWMSS0_CLKCTRL, 0),
- _CLK_DETAIL(PWMSS1_CLK, CM_PER_EPWMSS1_CLKCTRL, 0),
- _CLK_DETAIL(PWMSS2_CLK, CM_PER_EPWMSS2_CLKCTRL, 0),
-
- _CLK_DETAIL(MAILBOX0_CLK, CM_PER_MAILBOX0_CLKCTRL, 0),
- _CLK_DETAIL(SPINLOCK0_CLK, CM_PER_SPINLOCK0_CLKCTRL, 0),
-
- /* RTC module */
- _CLK_DETAIL(RTC_CLK, CM_RTC_RTC_CLKCTRL, 0),
-
- { INVALID_CLK_IDENT, 0},
-};
-
-/* Read/Write macros */
-#define prcm_read_4(reg) \
- bus_space_read_4(am335x_prcm_sc->bst, am335x_prcm_sc->bsh, reg)
-#define prcm_write_4(reg, val) \
- bus_space_write_4(am335x_prcm_sc->bst, am335x_prcm_sc->bsh, reg, val)
-
-void am335x_prcm_setup_dmtimer(int);
-
-static int
-am335x_prcm_probe(device_t dev)
-{
-
- if (!ofw_bus_status_okay(dev))
- return (ENXIO);
-
- if (ofw_bus_is_compatible(dev, "ti,am3-prcm")) {
- device_set_desc(dev, "AM335x Power and Clock Management");
- return(BUS_PROBE_DEFAULT);
- }
-
- return (ENXIO);
-}
-
-static int
-am335x_prcm_attach(device_t dev)
-{
- struct am335x_prcm_softc *sc = device_get_softc(dev);
-
- if (am335x_prcm_sc)
- return (ENXIO);
-
- if (bus_alloc_resources(dev, am335x_prcm_spec, sc->res)) {
- device_printf(dev, "could not allocate resources\n");
- return (ENXIO);
- }
-
- sc->bst = rman_get_bustag(sc->res[0]);
- sc->bsh = rman_get_bushandle(sc->res[0]);
-
- am335x_prcm_sc = sc;
- ti_cpu_reset = am335x_prcm_reset;
-
- return (0);
-}
-
-static void
-am335x_prcm_new_pass(device_t dev)
-{
- struct am335x_prcm_softc *sc = device_get_softc(dev);
- unsigned int sysclk, fclk;
-
- sc = device_get_softc(dev);
- if (sc->attach_done ||
- bus_current_pass < (BUS_PASS_TIMER + BUS_PASS_ORDER_EARLY)) {
- bus_generic_new_pass(dev);
- return;
- }
-
- sc->attach_done = 1;
-
- if (am335x_clk_get_sysclk_freq(NULL, &sysclk) != 0)
- sysclk = 0;
- if (am335x_clk_get_arm_fclk_freq(NULL, &fclk) != 0)
- fclk = 0;
- if (sysclk && fclk)
- device_printf(dev, "Clocks: System %u.%01u MHz, CPU %u MHz\n",
- sysclk/1000000, (sysclk % 1000000)/100000, fclk/1000000);
- else {
- device_printf(dev, "can't read frequencies yet (SCM device not ready?)\n");
- goto fail;
- }
-
- return;
-
-fail:
- device_detach(dev);
- return;
-}
-
-static device_method_t am335x_prcm_methods[] = {
- DEVMETHOD(device_probe, am335x_prcm_probe),
- DEVMETHOD(device_attach, am335x_prcm_attach),
-
- /* Bus interface */
- DEVMETHOD(bus_new_pass, am335x_prcm_new_pass),
- { 0, 0 }
-};
-
-static driver_t am335x_prcm_driver = {
- "am335x_prcm",
- am335x_prcm_methods,
- sizeof(struct am335x_prcm_softc),
-};
-
-static devclass_t am335x_prcm_devclass;
-
-EARLY_DRIVER_MODULE(am335x_prcm, simplebus, am335x_prcm_driver,
- am335x_prcm_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
-MODULE_VERSION(am335x_prcm, 1);
-MODULE_DEPEND(am335x_prcm, ti_scm, 1, 1, 1);
-
-static struct am335x_clk_details*
-am335x_clk_details(clk_ident_t id)
-{
- struct am335x_clk_details *walker;
-
- for (walker = g_am335x_clk_details; walker->id != INVALID_CLK_IDENT; walker++) {
- if (id == walker->id)
- return (walker);
- }
-
- return NULL;
-}
-
-static int
-am335x_clk_noop_activate(struct ti_clock_dev *clkdev)
-{
-
- return (0);
-}
-
-static int
-am335x_clk_generic_activate(struct ti_clock_dev *clkdev)
-{
- struct am335x_prcm_softc *sc = am335x_prcm_sc;
- struct am335x_clk_details* clk_details;
-
- if (sc == NULL)
- return ENXIO;
-
- clk_details = am335x_clk_details(clkdev->id);
-
- if (clk_details == NULL)
- return (ENXIO);
-
- /* set *_CLKCTRL register MODULEMODE[1:0] to enable(2) */
- prcm_write_4(clk_details->clkctrl_reg, 2);
- while ((prcm_read_4(clk_details->clkctrl_reg) & 0x3) != 2)
- DELAY(10);
-
- return (0);
-}
-
-static int
-am335x_clk_gpio_activate(struct ti_clock_dev *clkdev)
-{
- struct am335x_prcm_softc *sc = am335x_prcm_sc;
- struct am335x_clk_details* clk_details;
-
- if (sc == NULL)
- return ENXIO;
-
- clk_details = am335x_clk_details(clkdev->id);
-
- if (clk_details == NULL)
- return (ENXIO);
-
- /* set *_CLKCTRL register MODULEMODE[1:0] to enable(2) */
- /* set *_CLKCTRL register OPTFCLKEN_GPIO_1_G DBCLK[18] to FCLK_EN(1) */
- prcm_write_4(clk_details->clkctrl_reg, 2 | (1 << 18));
- while ((prcm_read_4(clk_details->clkctrl_reg) &
- (3 | (1 << 18) )) != (2 | (1 << 18)))
- DELAY(10);
-
- return (0);
-}
-
-static int
-am335x_clk_noop_deactivate(struct ti_clock_dev *clkdev)
-{
-
- return(0);
-}
-
-static int
-am335x_clk_generic_deactivate(struct ti_clock_dev *clkdev)
-{
- struct am335x_prcm_softc *sc = am335x_prcm_sc;
- struct am335x_clk_details* clk_details;
-
- if (sc == NULL)
- return ENXIO;
-
- clk_details = am335x_clk_details(clkdev->id);
-
- if (clk_details == NULL)
- return (ENXIO);
-
- /* set *_CLKCTRL register MODULEMODE[1:0] to disable(0) */
- prcm_write_4(clk_details->clkctrl_reg, 0);
- while ((prcm_read_4(clk_details->clkctrl_reg) & 0x3) != 0)
- DELAY(10);
-
- return (0);
-}
-
-static int
-am335x_clk_noop_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc)
-{
-
- return (0);
-}
-
-static int
-am335x_clk_generic_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc)
-{
- struct am335x_prcm_softc *sc = am335x_prcm_sc;
- struct am335x_clk_details* clk_details;
- uint32_t reg;
-
- if (sc == NULL)
- return ENXIO;
-
- clk_details = am335x_clk_details(clkdev->id);
-
- if (clk_details == NULL)
- return (ENXIO);
-
- switch (clksrc) {
- case EXT_CLK:
- reg = 0; /* SEL2: TCLKIN clock */
- break;
- case SYSCLK_CLK:
- reg = 1; /* SEL1: CLK_M_OSC clock */
- break;
- case F32KHZ_CLK:
- reg = 2; /* SEL3: CLK_32KHZ clock */
- break;
- default:
- return (ENXIO);
- }
-
- prcm_write_4(clk_details->clksel_reg, reg);
- while ((prcm_read_4(clk_details->clksel_reg) & 0x3) != reg)
- DELAY(10);
-
- return (0);
-}
-
-static int
-am335x_clk_hsmmc_get_source_freq(struct ti_clock_dev *clkdev, unsigned int *freq)
-{
- *freq = 96000000;
- return (0);
-}
-
-static int
-am335x_clk_get_sysclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq)
-{
- uint32_t ctrl_status;
-
- /* Read the input clock freq from the control module. */
- if (ti_scm_reg_read_4(SCM_CTRL_STATUS, &ctrl_status))
- return (ENXIO);
-
- switch ((ctrl_status>>22) & 0x3) {
- case 0x0:
- /* 19.2Mhz */
- *freq = 19200000;
- break;
- case 0x1:
- /* 24Mhz */
- *freq = 24000000;
- break;
- case 0x2:
- /* 25Mhz */
- *freq = 25000000;
- break;
- case 0x3:
- /* 26Mhz */
- *freq = 26000000;
- break;
- }
-
- return (0);
-}
-
-#define DPLL_BYP_CLKSEL(reg) ((reg>>23) & 1)
-#define DPLL_DIV(reg) ((reg & 0x7f)+1)
-#define DPLL_MULT(reg) ((reg>>8) & 0x7FF)
-#define DPLL_MAX_MUL 0x800
-#define DPLL_MAX_DIV 0x80
-
-static int
-am335x_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq)
-{
- uint32_t reg;
- uint32_t sysclk;
-
- reg = prcm_read_4(CM_WKUP_CM_CLKSEL_DPLL_MPU);
-
- /*Check if we are running in bypass */
- if (DPLL_BYP_CLKSEL(reg))
- return ENXIO;
-
- am335x_clk_get_sysclk_freq(NULL, &sysclk);
- *freq = DPLL_MULT(reg) * (sysclk / DPLL_DIV(reg));
- return(0);
-}
-
-static int
-am335x_clk_get_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int *freq)
-{
- uint32_t reg;
- uint32_t sysclk;
-
- reg = prcm_read_4(CM_WKUP_CM_CLKSEL_DPLL_DISP);
-
- /*Check if we are running in bypass */
- if (DPLL_BYP_CLKSEL(reg))
- return ENXIO;
-
- am335x_clk_get_sysclk_freq(NULL, &sysclk);
- *freq = DPLL_MULT(reg) * (sysclk / DPLL_DIV(reg));
- return(0);
-}
-
-static int
-am335x_clk_set_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int freq)
-{
- uint32_t sysclk;
- uint32_t mul, div;
- uint32_t i, j;
- unsigned int delta, min_delta;
-
- am335x_clk_get_sysclk_freq(NULL, &sysclk);
-
- /* Bypass mode */
- prcm_write_4(CM_WKUP_CM_CLKMODE_DPLL_DISP, 0x4);
-
- /* Make sure it's in bypass mode */
- while (!(prcm_read_4(CM_WKUP_CM_IDLEST_DPLL_DISP)
- & (1 << 8)))
- DELAY(10);
-
- /* Dumb and non-optimal implementation */
- min_delta = freq;
- for (i = 1; i < DPLL_MAX_MUL; i++) {
- for (j = 1; j < DPLL_MAX_DIV; j++) {
- delta = abs(freq - i*(sysclk/j));
- if (delta < min_delta) {
- mul = i;
- div = j;
- min_delta = delta;
- }
- if (min_delta == 0)
- break;
- }
- }
-
- prcm_write_4(CM_WKUP_CM_CLKSEL_DPLL_DISP, (mul << 8) | (div - 1));
-
- /* Locked mode */
- prcm_write_4(CM_WKUP_CM_CLKMODE_DPLL_DISP, 0x7);
-
- int timeout = 10000;
- while ((!(prcm_read_4(CM_WKUP_CM_IDLEST_DPLL_DISP)
- & (1 << 0))) && timeout--)
- DELAY(10);
-
- return(0);
-}
-
-static void
-am335x_prcm_reset(void)
-{
- prcm_write_4(PRM_RSTCTRL, (1<<1));
-}
-
-static int
-am335x_clk_cpsw_activate(struct ti_clock_dev *clkdev)
-{
- struct am335x_prcm_softc *sc = am335x_prcm_sc;
-
- if (sc == NULL)
- return ENXIO;
-
- /* set MODULENAME to ENABLE */
- prcm_write_4(CM_PER_CPGMAC0_CLKCTRL, 2);
-
- /* wait for IDLEST to become Func(0) */
- while(prcm_read_4(CM_PER_CPGMAC0_CLKCTRL) & (3<<16));
-
- /*set CLKTRCTRL to SW_WKUP(2) */
- prcm_write_4(CM_PER_CPSW_CLKSTCTRL, 2);
-
- /* wait for 125 MHz OCP clock to become active */
- while((prcm_read_4(CM_PER_CPSW_CLKSTCTRL) & (1<<4)) == 0);
- return(0);
-}
-
-static int
-am335x_clk_musb0_activate(struct ti_clock_dev *clkdev)
-{
- struct am335x_prcm_softc *sc = am335x_prcm_sc;
-
- if (sc == NULL)
- return ENXIO;
-
- /* set ST_DPLL_CLKDCOLDO(9) to CLK_GATED(1) */
- /* set DPLL_CLKDCOLDO_GATE_CTRL(8) to CLK_ENABLE(1)*/
- prcm_write_4(CM_WKUP_CM_CLKDCOLDO_DPLL_PER, 0x300);
-
- /*set MODULEMODE to ENABLE(2) */
- prcm_write_4(CM_PER_USB0_CLKCTRL, 2);
-
- /* wait for MODULEMODE to become ENABLE(2) */
- while ((prcm_read_4(CM_PER_USB0_CLKCTRL) & 0x3) != 2)
- DELAY(10);
-
- /* wait for IDLEST to become Func(0) */
- while(prcm_read_4(CM_PER_USB0_CLKCTRL) & (3<<16))
- DELAY(10);
-
- return(0);
-}
-
-static int
-am335x_clk_lcdc_activate(struct ti_clock_dev *clkdev)
-{
- struct am335x_prcm_softc *sc = am335x_prcm_sc;
-
- if (sc == NULL)
- return (ENXIO);
-
- /*
- * For now set frequency to 2*VGA_PIXEL_CLOCK
- */
- am335x_clk_set_arm_disp_freq(clkdev, 25175000*2);
-
- /*set MODULEMODE to ENABLE(2) */
- prcm_write_4(CM_PER_LCDC_CLKCTRL, 2);
-
- /* wait for MODULEMODE to become ENABLE(2) */
- while ((prcm_read_4(CM_PER_LCDC_CLKCTRL) & 0x3) != 2)
- DELAY(10);
-
- /* wait for IDLEST to become Func(0) */
- while(prcm_read_4(CM_PER_LCDC_CLKCTRL) & (3<<16))
- DELAY(10);
-
- return (0);
-}
-
-static int
-am335x_clk_pruss_activate(struct ti_clock_dev *clkdev)
-{
- struct am335x_prcm_softc *sc = am335x_prcm_sc;
-
- if (sc == NULL)
- return (ENXIO);
-
- /* Set MODULEMODE to ENABLE(2) */
- prcm_write_4(CM_PER_PRUSS_CLKCTRL, 2);
-
- /* Wait for MODULEMODE to become ENABLE(2) */
- while ((prcm_read_4(CM_PER_PRUSS_CLKCTRL) & 0x3) != 2)
- DELAY(10);
-
- /* Set CLKTRCTRL to SW_WKUP(2) */
- prcm_write_4(CM_PER_PRUSS_CLKSTCTRL, 2);
-
- /* Wait for the 200 MHz OCP clock to become active */
- while ((prcm_read_4(CM_PER_PRUSS_CLKSTCTRL) & (1<<4)) == 0)
- DELAY(10);
-
- /* Wait for the 200 MHz IEP clock to become active */
- while ((prcm_read_4(CM_PER_PRUSS_CLKSTCTRL) & (1<<5)) == 0)
- DELAY(10);
-
- /* Wait for the 192 MHz UART clock to become active */
- while ((prcm_read_4(CM_PER_PRUSS_CLKSTCTRL) & (1<<6)) == 0)
- DELAY(10);
-
- /* Select L3F as OCP clock */
- prcm_write_4(CLKSEL_PRUSS_OCP_CLK, 0);
- while ((prcm_read_4(CLKSEL_PRUSS_OCP_CLK) & 0x3) != 0)
- DELAY(10);
-
- /* Clear the RESET bit */
- prcm_write_4(PRM_PER_RSTCTRL, prcm_read_4(PRM_PER_RSTCTRL) & ~2);
-
- return (0);
-}
Index: sys/arm/ti/am335x/am335x_pwmss.c
===================================================================
--- sys/arm/ti/am335x/am335x_pwmss.c
+++ sys/arm/ti/am335x/am335x_pwmss.c
@@ -46,10 +46,11 @@
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
-#include <arm/ti/ti_prcm.h>
-#include <arm/ti/ti_hwmods.h>
-#include <arm/ti/ti_scm.h>
+#include <arm/ti/ti_sysc.h>
+#include <dev/extres/syscon/syscon.h>
+#include "syscon_if.h"
+
#include "am335x_pwm.h"
#include "am335x_scm.h"
@@ -59,6 +60,11 @@
#define CLKCONFIG_EPWMCLK_EN (1 << 8)
#define PWMSS_CLKSTATUS 0x0C
+/* TRM chapter 2 memory map table 2-3 + VER register location */
+#define PWMSS_REV_0 0x0000
+#define PWMSS_REV_1 0x2000
+#define PWMSS_REV_2 0x4000
+
static device_probe_t am335x_pwmss_probe;
static device_attach_t am335x_pwmss_attach;
static device_detach_t am335x_pwmss_detach;
@@ -66,7 +72,7 @@
struct am335x_pwmss_softc {
struct simplebus_softc sc_simplebus;
device_t sc_dev;
- clk_ident_t sc_clk;
+ struct syscon *syscon;
};
static device_method_t am335x_pwmss_methods[] = {
@@ -97,36 +103,45 @@
{
struct am335x_pwmss_softc *sc;
uint32_t reg, id;
- phandle_t node;
+ uint64_t rev_address;
+ phandle_t node, opp_table;
sc = device_get_softc(dev);
sc->sc_dev = dev;
- sc->sc_clk = ti_hwmods_get_clock(dev);
- if (sc->sc_clk == INVALID_CLK_IDENT) {
- device_printf(dev, "failed to get device id based on ti,hwmods\n");
- return (EINVAL);
+ /* FIXME: For now; Go and kidnap syscon from opp-table */
+ opp_table = OF_finddevice("/opp-table");
+ if (opp_table == -1) {
+ device_printf(dev, "Cant find /opp-table\n");
+ return (ENXIO);
}
+ if (!OF_hasprop(opp_table, "syscon")) {
+ device_printf(dev, "/opp-table doesnt have required syscon property\n");
+ return (ENXIO);
+ }
+ if (syscon_get_by_ofw_property(dev, opp_table, "syscon", &sc->syscon) != 0) {
+ device_printf(dev, "Failed to get syscon\n");
+ return (ENXIO);
+ }
- ti_prcm_clk_enable(sc->sc_clk);
- ti_scm_reg_read_4(SCM_PWMSS_CTRL, ®);
- switch (sc->sc_clk) {
- case PWMSS0_CLK:
- id = 0;
- break;
- case PWMSS1_CLK:
- id = 1;
- break;
+ ti_sysc_clock_enable(device_get_parent(dev));
- case PWMSS2_CLK:
- id = 2;
- break;
- default:
- device_printf(dev, "unknown pwmss clock id: %d\n", sc->sc_clk);
- return (EINVAL);
+ rev_address = ti_sysc_get_rev_address(device_get_parent(dev));
+ switch (rev_address) {
+ case PWMSS_REV_0:
+ id = 0;
+ break;
+ case PWMSS_REV_1:
+ id = 1;
+ break;
+ case PWMSS_REV_2:
+ id = 2;
+ break;
}
+
+ reg = SYSCON_READ_4(sc->syscon, SCM_PWMSS_CTRL);
reg |= (1 << id);
- ti_scm_reg_write_4(SCM_PWMSS_CTRL, reg);
+ SYSCON_WRITE_4(sc->syscon, SCM_PWMSS_CTRL, reg);
node = ofw_bus_get_node(dev);
@@ -161,3 +176,4 @@
static devclass_t am335x_pwmss_devclass;
DRIVER_MODULE(am335x_pwmss, simplebus, am335x_pwmss_driver, am335x_pwmss_devclass, 0, 0);
MODULE_VERSION(am335x_pwmss, 1);
+MODULE_DEPEND(am335x_pwmss, ti_sysc, 1, 1, 1);
Index: sys/arm/ti/am335x/am335x_rtc.c
===================================================================
--- sys/arm/ti/am335x/am335x_rtc.c
+++ sys/arm/ti/am335x/am335x_rtc.c
@@ -39,8 +39,9 @@
#include <machine/bus.h>
+#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
-#include <arm/ti/ti_prcm.h>
+#include <arm/ti/ti_sysc.h>
#include <arm/ti/am335x/am335x_rtcvar.h>
#include <arm/ti/am335x/am335x_rtcreg.h>
@@ -110,7 +111,7 @@
RTC_LOCK_INIT(sc);
/* Enable the RTC module. */
- ti_prcm_clk_enable(RTC_CLK);
+ ti_sysc_clock_enable(device_get_parent(dev));
rev = RTC_READ4(sc, RTC_REVISION);
device_printf(dev, "AM335X RTC v%d.%d.%d\n",
(rev >> 8) & 0x7, (rev >> 6) & 0x3, rev & 0x3f);
@@ -209,3 +210,4 @@
DRIVER_MODULE(am335x_rtc, simplebus, am335x_rtc_driver, am335x_rtc_devclass, 0, 0);
MODULE_VERSION(am335x_rtc, 1);
MODULE_DEPEND(am335x_rtc, simplebus, 1, 1, 1);
+MODULE_DEPEND(am335x_rtc, ti_sysc, 1, 1, 1);
Index: sys/arm/ti/am335x/am335x_scm.c
===================================================================
--- sys/arm/ti/am335x/am335x_scm.c
+++ sys/arm/ti/am335x/am335x_scm.c
@@ -40,11 +40,15 @@
#include <arm/ti/ti_cpuid.h>
#include <arm/ti/ti_scm.h>
+#include <dev/extres/syscon/syscon.h>
+#include "syscon_if.h"
+
#define TZ_ZEROC 2731
struct am335x_scm_softc {
int sc_last_temp;
struct sysctl_oid *sc_temp_oid;
+ struct syscon *syscon;
};
static int
@@ -60,7 +64,7 @@
/* Read the temperature and convert to Kelvin. */
for(i = 50; i > 0; i--) {
- ti_scm_reg_read_4(SCM_BGAP_CTRL, ®);
+ reg = SYSCON_READ_4(sc->syscon, SCM_BGAP_CTRL);
if ((reg & SCM_BGAP_EOCZ) == 0)
break;
DELAY(50);
@@ -96,6 +100,9 @@
static int
am335x_scm_probe(device_t dev)
{
+ /* Just allow the first one */
+ if (strcmp(device_get_nameunit(dev), "am335x_scm0") != 0)
+ return (ENXIO);
device_set_desc(dev, "AM335x Control Module Extension");
@@ -109,21 +116,40 @@
struct sysctl_ctx_list *ctx;
struct sysctl_oid_list *tree;
uint32_t reg;
+ phandle_t opp_table;
+ int err;
+ sc = device_get_softc(dev);
+
+ /* FIXME: For now; Go and kidnap syscon from opp-table */
+ opp_table = OF_finddevice("/opp-table");
+ if (opp_table == -1) {
+ device_printf(dev, "Cant find /opp-table\n");
+ return (ENXIO);
+ }
+ if (!OF_hasprop(opp_table, "syscon")) {
+ device_printf(dev, "/opp-table missing syscon property\n");
+ return (ENXIO);
+ }
+ err = syscon_get_by_ofw_property(dev, opp_table, "syscon", &sc->syscon);
+ if (err) {
+ device_printf(dev, "Failed to get syscon\n");
+ return (ENXIO);
+ }
+
/* Reset the digital outputs. */
- ti_scm_reg_write_4(SCM_BGAP_CTRL, 0);
- ti_scm_reg_read_4(SCM_BGAP_CTRL, ®);
+ SYSCON_WRITE_4(sc->syscon, SCM_BGAP_CTRL, 0);
+ reg = SYSCON_READ_4(sc->syscon, SCM_BGAP_CTRL);
DELAY(500);
/* Set continous mode. */
- ti_scm_reg_write_4(SCM_BGAP_CTRL, SCM_BGAP_CONTCONV);
- ti_scm_reg_read_4(SCM_BGAP_CTRL, ®);
+ SYSCON_WRITE_4(sc->syscon, SCM_BGAP_CTRL, SCM_BGAP_CONTCONV);
+ reg = SYSCON_READ_4(sc->syscon, SCM_BGAP_CTRL);
DELAY(500);
/* Start the ADC conversion. */
reg = SCM_BGAP_CLRZ | SCM_BGAP_CONTCONV | SCM_BGAP_SOC;
- ti_scm_reg_write_4(SCM_BGAP_CTRL, reg);
+ SYSCON_WRITE_4(sc->syscon, SCM_BGAP_CTRL, reg);
/* Temperature sysctl. */
- sc = device_get_softc(dev);
ctx = device_get_sysctl_ctx(dev);
tree = SYSCTL_CHILDREN(device_get_sysctl_tree(dev));
sc->sc_temp_oid = SYSCTL_ADD_PROC(ctx, tree, OID_AUTO,
@@ -145,7 +171,7 @@
sysctl_remove_oid(sc->sc_temp_oid, 1, 0);
/* Stop the bandgap ADC. */
- ti_scm_reg_write_4(SCM_BGAP_CTRL, SCM_BGAP_BGOFF);
+ SYSCON_WRITE_4(sc->syscon, SCM_BGAP_CTRL, SCM_BGAP_BGOFF);
return (0);
}
@@ -169,4 +195,4 @@
DRIVER_MODULE(am335x_scm, ti_scm, am335x_scm_driver, am335x_scm_devclass, 0, 0);
MODULE_VERSION(am335x_scm, 1);
-MODULE_DEPEND(am335x_scm, ti_scm, 1, 1, 1);
+MODULE_DEPEND(am335x_scm, ti_scm_syscon, 1, 1, 1);
Index: sys/arm/ti/am335x/am335x_usb_phy.c
===================================================================
--- sys/arm/ti/am335x/am335x_usb_phy.c
+++ sys/arm/ti/am335x/am335x_usb_phy.c
@@ -0,0 +1,122 @@
+/*-
+ *
+ * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se>
+ *
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/fbio.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/resource.h>
+#include <machine/bus.h>
+#include <vm/vm.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_kern.h>
+#include <vm/pmap.h>
+
+#include <dev/fdt/simplebus.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#define TI_AM335X_USB_PHY 1
+#define TI_AM335X_USB_PHY_END 0
+
+static struct ofw_compat_data compat_data[] = {
+ { "ti,am335x-usb-phy", TI_AM335X_USB_PHY },
+ { NULL, TI_AM335X_USB_PHY_END }
+};
+
+struct ti_usb_phy_softc {
+ device_t dev;
+};
+
+static int ti_usb_phy_probe(device_t dev);
+static int ti_usb_phy_attach(device_t dev);
+static int ti_usb_phy_detach(device_t dev);
+
+static int
+ti_usb_phy_probe(device_t dev)
+{
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "TI AM335x USB PHY");
+ if (!bootverbose)
+ device_quiet(dev);
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+ti_usb_phy_attach(device_t dev)
+{
+ struct ti_usb_phy_softc *sc;
+ phandle_t node;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+ node = ofw_bus_get_node(dev);
+
+ /* FIXME: Add dev/extres/phy/ interface */
+
+ return (bus_generic_attach(dev));
+}
+
+static int
+ti_usb_phy_detach(device_t dev)
+{
+ return (EBUSY);
+}
+
+static device_method_t ti_usb_phy_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, ti_usb_phy_probe),
+ DEVMETHOD(device_attach, ti_usb_phy_attach),
+ DEVMETHOD(device_detach, ti_usb_phy_detach),
+
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_1(ti_usb_phy, ti_usb_phy_driver, ti_usb_phy_methods,
+ sizeof(struct ti_usb_phy_softc), simplebus_driver);
+
+static devclass_t ti_usb_phy_devclass;
+
+EARLY_DRIVER_MODULE(ti_usb_phy, simplebus, ti_usb_phy_driver,
+ ti_usb_phy_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_FIRST);
+MODULE_VERSION(ti_usb_phy, 1);
+MODULE_DEPEND(ti_usb_phy, ti_sysc, 1, 1, 1);
+
Index: sys/arm/ti/am335x/am335x_usbss.c
===================================================================
--- sys/arm/ti/am335x/am335x_usbss.c
+++ sys/arm/ti/am335x/am335x_usbss.c
@@ -1,226 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2013 Oleksandr Tymoshenko <gonzo@freebsd.org>
- *
- * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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>
-__FBSDID("$FreeBSD$");
-
-#include <sys/stdint.h>
-#include <sys/stddef.h>
-#include <sys/param.h>
-#include <sys/queue.h>
-#include <sys/types.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/bus.h>
-#include <sys/module.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
-#include <sys/condvar.h>
-#include <sys/sysctl.h>
-#include <sys/sx.h>
-#include <sys/unistd.h>
-#include <sys/callout.h>
-#include <sys/malloc.h>
-#include <sys/priv.h>
-
-#include <dev/fdt/simplebus.h>
-#include <dev/ofw/openfirm.h>
-#include <dev/ofw/ofw_bus.h>
-#include <dev/ofw/ofw_bus_subr.h>
-
-#include <dev/usb/usb.h>
-#include <dev/usb/usbdi.h>
-
-#include <dev/usb/usb_core.h>
-#include <dev/usb/usb_busdma.h>
-#include <dev/usb/usb_process.h>
-#include <dev/usb/usb_util.h>
-
-#include <dev/usb/usb_controller.h>
-#include <dev/usb/usb_bus.h>
-#include <dev/usb/controller/musb_otg.h>
-#include <dev/usb/usb_debug.h>
-
-#include <sys/rman.h>
-
-#include <arm/ti/ti_prcm.h>
-#include <arm/ti/ti_scm.h>
-#include <arm/ti/am335x/am335x_scm.h>
-
-#define AM335X_USB_PORTS 2
-
-#define USBSS_REVREG 0x00
-#define USBSS_SYSCONFIG 0x10
-#define USBSS_SYSCONFIG_SRESET 1
-
-#define USBCTRL_REV 0x00
-#define USBCTRL_CTRL 0x14
-#define USBCTRL_STAT 0x18
-#define USBCTRL_IRQ_STAT0 0x30
-#define IRQ_STAT0_RXSHIFT 16
-#define IRQ_STAT0_TXSHIFT 0
-#define USBCTRL_IRQ_STAT1 0x34
-#define IRQ_STAT1_DRVVBUS (1 << 8)
-#define USBCTRL_INTEN_SET0 0x38
-#define USBCTRL_INTEN_SET1 0x3C
-#define USBCTRL_INTEN_USB_ALL 0x1ff
-#define USBCTRL_INTEN_USB_SOF (1 << 3)
-#define USBCTRL_INTEN_CLR0 0x40
-#define USBCTRL_INTEN_CLR1 0x44
-#define USBCTRL_UTMI 0xE0
-#define USBCTRL_UTMI_FSDATAEXT (1 << 1)
-#define USBCTRL_MODE 0xE8
-#define USBCTRL_MODE_IDDIG (1 << 8)
-#define USBCTRL_MODE_IDDIGMUX (1 << 7)
-
-#define USBSS_WRITE4(sc, reg, val) \
- bus_write_4((sc)->sc_mem_res, (reg), (val))
-#define USBSS_READ4(sc, reg) \
- bus_read_4((sc)->sc_mem_res, (reg))
-
-static device_probe_t usbss_probe;
-static device_attach_t usbss_attach;
-static device_detach_t usbss_detach;
-
-struct usbss_softc {
- struct simplebus_softc simplebus_sc;
- struct resource *sc_mem_res;
- int sc_mem_rid;
-};
-
-static int
-usbss_probe(device_t dev)
-{
-
- if (!ofw_bus_status_okay(dev))
- return (ENXIO);
-
- if (!ofw_bus_is_compatible(dev, "ti,am33xx-usb"))
- return (ENXIO);
-
- device_set_desc(dev, "TI AM33xx integrated USB OTG controller");
-
- return (BUS_PROBE_DEFAULT);
-}
-
-static int
-usbss_attach(device_t dev)
-{
- struct usbss_softc *sc = device_get_softc(dev);
- int i;
- uint32_t rev;
- phandle_t node;
-
- /* Request the memory resources */
- sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
- &sc->sc_mem_rid, RF_ACTIVE);
- if (sc->sc_mem_res == NULL) {
- device_printf(dev,
- "Error: could not allocate mem resources\n");
- return (ENXIO);
- }
-
- /* Enable device clocks. */
- ti_prcm_clk_enable(MUSB0_CLK);
-
- /*
- * Reset USBSS, USB0 and USB1.
- * The registers of USB subsystem must not be accessed while the
- * reset pulse is active (200ns).
- */
- USBSS_WRITE4(sc, USBSS_SYSCONFIG, USBSS_SYSCONFIG_SRESET);
- DELAY(100);
- i = 10;
- while (USBSS_READ4(sc, USBSS_SYSCONFIG) & USBSS_SYSCONFIG_SRESET) {
- DELAY(100);
- if (i-- == 0) {
- device_printf(dev, "reset timeout.\n");
- return (ENXIO);
- }
- }
-
- /* Read the module revision. */
- rev = USBSS_READ4(sc, USBSS_REVREG);
- device_printf(dev, "TI AM335X USBSS v%d.%d.%d\n",
- (rev >> 8) & 7, (rev >> 6) & 3, rev & 63);
-
- node = ofw_bus_get_node(dev);
-
- if (node == -1) {
- usbss_detach(dev);
- return (ENXIO);
- }
-
- simplebus_init(dev, node);
-
- /*
- * Allow devices to identify.
- */
- bus_generic_probe(dev);
-
- /*
- * Now walk the OFW tree and attach top-level devices.
- */
- for (node = OF_child(node); node > 0; node = OF_peer(node))
- simplebus_add_device(dev, node, 0, NULL, -1, NULL);
-
- return (bus_generic_attach(dev));
-}
-
-static int
-usbss_detach(device_t dev)
-{
- struct usbss_softc *sc = device_get_softc(dev);
-
- /* Free resources if any */
- if (sc->sc_mem_res)
- bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_mem_rid,
- sc->sc_mem_res);
-
- /* during module unload there are lots of children leftover */
- device_delete_children(dev);
-
- return (0);
-}
-
-static device_method_t usbss_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, usbss_probe),
- DEVMETHOD(device_attach, usbss_attach),
- DEVMETHOD(device_detach, usbss_detach),
- DEVMETHOD(device_suspend, bus_generic_suspend),
- DEVMETHOD(device_resume, bus_generic_resume),
- DEVMETHOD(device_shutdown, bus_generic_shutdown),
-
- DEVMETHOD_END
-};
-
-DEFINE_CLASS_1(usbss, usbss_driver, usbss_methods,
- sizeof(struct usbss_softc), simplebus_driver);
-static devclass_t usbss_devclass;
-DRIVER_MODULE(usbss, simplebus, usbss_driver, usbss_devclass, 0, 0);
-MODULE_DEPEND(usbss, usb, 1, 1, 1);
Index: sys/arm/ti/am335x/files.am335x
===================================================================
--- sys/arm/ti/am335x/files.am335x
+++ sys/arm/ti/am335x/files.am335x
@@ -8,7 +8,6 @@
arm/ti/am335x/am335x_lcd.c optional sc | vt
arm/ti/am335x/am335x_lcd_syscons.c optional sc
arm/ti/am335x/am335x_pmic.c optional am335x_pmic
-arm/ti/am335x/am335x_prcm.c standard
arm/ti/am335x/am335x_pwmss.c standard
dev/pwm/pwmbus_if.m standard
arm/ti/am335x/am335x_ehrpwm.c standard
@@ -16,8 +15,9 @@
arm/ti/am335x/am335x_rtc.c optional am335x_rtc
arm/ti/am335x/am335x_scm.c standard
arm/ti/am335x/am335x_scm_padconf.c standard
-arm/ti/am335x/am335x_usbss.c optional musb fdt
arm/ti/am335x/am335x_musb.c optional musb fdt
+arm/ti/am335x/am335x_usb_phy.c optional musb fdt
+arm/ti/am335x/am3359_cppi41.c optional musb fdt
arm/ti/am335x/tda19988.c optional hdmi
Index: sys/arm/ti/clk/clock_common.h
===================================================================
--- sys/arm/ti/clk/clock_common.h
+++ sys/arm/ti/clk/clock_common.h
@@ -0,0 +1,43 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se>
+ *
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+struct clock_cell_info {
+ cell_t *clock_cells;
+ uint8_t *clock_cells_ncells;
+ uint32_t num_clock_cells;
+ uint8_t num_real_clocks;
+};
+
+void read_clock_cells(device_t dev, struct clock_cell_info *clk);
+int find_parent_clock_names(device_t dev, struct clock_cell_info *clk, struct clknode_init_def *def);
+void create_clkdef(device_t dev, struct clock_cell_info *clk, struct clknode_init_def *def);
+void free_clkdef(struct clknode_init_def *def);
Index: sys/arm/ti/clk/clock_common.c
===================================================================
--- sys/arm/ti/clk/clock_common.c
+++ sys/arm/ti/clk/clock_common.c
@@ -0,0 +1,149 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se>
+ *
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/systm.h>
+#include <sys/libkern.h>
+#include <sys/types.h>
+#include <sys/malloc.h>
+
+#include <machine/bus.h>
+#include <dev/fdt/simplebus.h>
+
+#include <dev/extres/clk/clk_mux.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include "clock_common.h"
+
+#if 0
+#define DPRINTF(dev, msg...) device_printf(dev, msg)
+#else
+#define DPRINTF(dev, msg...)
+#endif
+
+void
+read_clock_cells(device_t dev, struct clock_cell_info *clk) {
+ ssize_t numbytes_clocks;
+ phandle_t node, parent, *cells;
+ int index, ncells, rv;
+
+ node = ofw_bus_get_node(dev);
+
+ /* Get names of parent clocks */
+ numbytes_clocks = OF_getproplen(node, "clocks");
+ clk->num_clock_cells = numbytes_clocks / sizeof(cell_t);
+
+ /* Allocate space and get clock cells content */
+ clk->clock_cells = malloc(numbytes_clocks, M_DEVBUF, M_WAITOK|M_ZERO);
+ clk->clock_cells_ncells = malloc(clk->num_clock_cells*sizeof(uint8_t),
+ M_DEVBUF, M_WAITOK|M_ZERO);
+ OF_getencprop(node, "clocks", clk->clock_cells, numbytes_clocks);
+
+ /* Count number of clocks */
+ clk->num_real_clocks = 0;
+ for (index = 0; index < clk->num_clock_cells; index++) {
+ rv = ofw_bus_parse_xref_list_alloc(node, "clocks", "#clock-cells",
+ clk->num_real_clocks, &parent, &ncells, &cells);
+ if (rv != 0)
+ continue;
+
+ if (cells != NULL)
+ OF_prop_free(cells);
+
+ clk->clock_cells_ncells[index] = ncells;
+ index += ncells;
+ clk->num_real_clocks++;
+ }
+}
+
+int
+find_parent_clock_names(device_t dev, struct clock_cell_info *clk, struct clknode_init_def *def) {
+ int index, clock_index, err;
+ bool found_all = true;
+ clk_t parent;
+
+ /* Figure out names */
+ for (index = 0, clock_index = 0; index < clk->num_clock_cells; index++) {
+ /* Get name of parent clock */
+ err = clk_get_by_ofw_index(dev, 0, clock_index, &parent);
+ if (err != 0) {
+ clock_index++;
+ found_all = false;
+ DPRINTF(dev, "Failed to find clock_cells[%d]=0x%x\n",
+ index, clk->clock_cells[index]);
+
+ index += clk->clock_cells_ncells[index];
+ continue;
+ }
+
+ def->parent_names[clock_index] = clk_get_name(parent);
+ clk_release(parent);
+
+ DPRINTF(dev, "Found parent clock[%d/%d]: %s\n",
+ clock_index, clk->num_real_clocks,
+ def->parent_names[clock_index]);
+
+ clock_index++;
+ index += clk->clock_cells_ncells[index];
+ }
+
+ if (!found_all) {
+ return 1;
+ }
+
+ free(clk->clock_cells, M_DEVBUF);
+ free(clk->clock_cells_ncells, M_DEVBUF);
+ return 0;
+}
+
+void
+create_clkdef(device_t dev, struct clock_cell_info *clk, struct clknode_init_def *def) {
+ def->id = 1;
+
+ clk_parse_ofw_clk_name(dev, ofw_bus_get_node(dev), &def->name);
+
+ DPRINTF(dev, "node name: %s\n", def->name);
+
+ def->parent_cnt = clk->num_real_clocks;
+ def->parent_names = malloc(clk->num_real_clocks*sizeof(char *),
+ M_OFWPROP, M_WAITOK);
+}
+void
+free_clkdef(struct clknode_init_def *def) {
+ OF_prop_free(__DECONST(char *, def->name));
+ OF_prop_free(def->parent_names);
+}
Index: sys/arm/ti/clk/ti_clk_clkctrl.h
===================================================================
--- sys/arm/ti/clk/ti_clk_clkctrl.h
+++ sys/arm/ti/clk/ti_clk_clkctrl.h
@@ -0,0 +1,42 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se>
+ *
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _TI_CLK_CLKCTRL_H_
+#define _TI_CLK_CLKCTRL_H_
+
+#include <dev/extres/clk/clk.h>
+
+struct ti_clk_clkctrl_def {
+ struct clknode_init_def clkdef;
+ uint32_t register_offset;
+};
+
+int ti_clknode_clkctrl_register(struct clkdom *clkdom, struct ti_clk_clkctrl_def *clkdef);
+
+#endif /* _TI_CLK_CLKCTRL_H_ */
Index: sys/arm/ti/clk/ti_clk_clkctrl.c
===================================================================
--- sys/arm/ti/clk/ti_clk_clkctrl.c
+++ sys/arm/ti/clk/ti_clk_clkctrl.c
@@ -0,0 +1,192 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se>
+ *
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/malloc.h>
+
+#include <dev/extres/clk/clk.h>
+
+#include <arm/ti/clk/ti_clk_clkctrl.h>
+
+#include "clkdev_if.h"
+
+#if 0
+#define DPRINTF(dev, msg...) device_printf(dev, msg)
+#else
+#define DPRINTF(dev, msg...)
+#endif
+
+/*
+ * clknode for clkctrl, implements gate and mux (for gpioc)
+ */
+
+#define GPIO_X_GDBCLK_MASK 0x00040000
+#define IDLEST_MASK 0x00030000
+#define MODULEMODE_MASK 0x00000003
+
+#define GPIOX_GDBCLK_ENABLE 0x00040000
+#define GPIOX_GDBCLK_DISABLE 0x00000000
+
+#define MODULEMODE_DISABLE 0x0
+#define MODULEMODE_ENABLE 0x2
+
+struct ti_clkctrl_clknode_sc {
+ device_t dev;
+ uint32_t register_offset; /* omap4-cm range.host + ti,clkctrl reg[0] */
+};
+
+#define WRITE4(_clk, off, val) \
+ CLKDEV_WRITE_4(clknode_get_device(_clk), off, val)
+#define READ4(_clk, off, val) \
+ CLKDEV_READ_4(clknode_get_device(_clk), off, val)
+#define DEVICE_LOCK(_clk) \
+ CLKDEV_DEVICE_LOCK(clknode_get_device(_clk))
+#define DEVICE_UNLOCK(_clk) \
+ CLKDEV_DEVICE_UNLOCK(clknode_get_device(_clk))
+
+static int
+ti_clkctrl_init(struct clknode *clk, device_t dev)
+{
+ struct ti_clkctrl_clknode_sc *sc;
+
+ sc = clknode_get_softc(clk);
+ sc->dev = dev;
+
+ clknode_init_parent_idx(clk, 0);
+ return (0);
+}
+
+static int
+ti_clkctrl_set_mux(struct clknode *clk, int idx)
+{
+ struct ti_clkctrl_clknode_sc *sc;
+ uint32_t val;
+ uint32_t timeout = 100;
+
+ sc = clknode_get_softc(clk);
+
+ 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);
+
+ val = val & (GPIO_X_GDBCLK_MASK | MODULEMODE_MASK);
+ val |= GPIOX_GDBCLK_ENABLE;
+
+ DPRINTF(sc->dev, "val %x\n", val);
+ WRITE4(clk, sc->register_offset, val);
+
+ /* Wait */
+ READ4(clk, sc->register_offset, &val);
+ while (((val & GPIO_X_GDBCLK_MASK) != GPIOX_GDBCLK_ENABLE) &&
+ timeout--) {
+ DELAY(10);
+ READ4(clk, sc->register_offset, &val);
+ }
+ if (timeout == 0) {
+ device_printf(sc->dev, "ti_clkctrl_set_mux: 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;
+ uint32_t timeout=100;
+
+ sc = clknode_get_softc(clk);
+
+ 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);
+ if (enable &&
+ (val & IDLEST_MASK) == 0x0 &&
+ (val & MODULEMODE_MASK) == MODULEMODE_ENABLE)
+ break;
+ else if (!enable &&
+ (val & IDLEST_MASK) == 0x3 &&
+ (val & MODULEMODE_MASK) == MODULEMODE_DISABLE)
+ break;
+ DELAY(10);
+ timeout--;
+ }
+ if (timeout == 0) {
+ device_printf(sc->dev, "ti_clkctrl_set_gate: Timeout\n");
+ return (1);
+ }
+
+ return (0);
+}
+
+static clknode_method_t ti_clkctrl_clknode_methods[] = {
+ /* Device interface */
+ CLKNODEMETHOD(clknode_init, ti_clkctrl_init),
+ CLKNODEMETHOD(clknode_set_mux, ti_clkctrl_set_mux),
+ CLKNODEMETHOD(clknode_set_gate, ti_clkctrl_set_gate),
+ CLKNODEMETHOD_END
+};
+
+DEFINE_CLASS_1(ti_clkctrl_clknode, ti_clkctrl_clknode_class, ti_clkctrl_clknode_methods,
+ sizeof(struct ti_clkctrl_clknode_sc), clknode_class);
+
+int
+ti_clknode_clkctrl_register(struct clkdom *clkdom, struct ti_clk_clkctrl_def *clkdef)
+{
+ struct clknode *clk;
+ struct ti_clkctrl_clknode_sc *sc;
+
+ clk = clknode_create(clkdom, &ti_clkctrl_clknode_class, &clkdef->clkdef);
+
+ if (clk == NULL) {
+ return (1);
+ }
+
+ sc = clknode_get_softc(clk);
+ sc->register_offset = clkdef->register_offset;
+
+ if (clknode_register(clkdom, clk) == NULL) {
+ return (2);
+ }
+ return (0);
+}
Index: sys/arm/ti/clk/ti_clk_dpll.h
===================================================================
--- sys/arm/ti/clk/ti_clk_dpll.h
+++ sys/arm/ti/clk/ti_clk_dpll.h
@@ -0,0 +1,97 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2017 Emmanuel Vadot <manu@freebsd.org>
+ *
+ * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se>
+ *
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _TI_DPLL_CLOCK_H_
+#define _TI_DPLL_CLOCK_H_
+
+#include <dev/extres/clk/clk.h>
+
+/* Registers are described in AM335x TRM chapter 8.1.12.2.* */
+
+/* Register offsets */
+#define CM_CLKSEL_DPLL_PERIPH 0x49C
+
+/* CM_IDLEST_DPLL_xxx */
+#define ST_MN_BYPASS_MASK 0x0100
+#define ST_MN_BYPASS_SHIFT 8
+#define ST_DPLL_CLK_MASK 0x0001
+
+/* CM_CLKMODE_DPLL_DPLL_EN feature flag */
+#define LOW_POWER_STOP_MODE_FLAG 0x01
+#define MN_BYPASS_MODE_FLAG 0x02
+#define IDLE_BYPASS_LOW_POWER_MODE_FLAG 0x04
+#define IDLE_BYPASS_FAST_RELOCK_MODE_FLAG 0x08
+#define LOCK_MODE_FLAG 0x10
+
+/* CM_CLKMODE_DPLL_xxx */
+#define DPLL_EN_LOW_POWER_STOP_MODE 0x01
+#define DPLL_EN_MN_BYPASS_MODE 0x04
+#define DPLL_EN_IDLE_BYPASS_LOW_POWER_MODE 0x05
+#define DPLL_EN_IDLE_BYPASS_FAST_RELOCK_MODE 0x06
+#define DPLL_EN_LOCK_MODE 0x07
+
+
+#define TI_CLK_FACTOR_ZERO_BASED 0x0002
+#define TI_CLK_FACTOR_FIXED 0x0008
+#define TI_CLK_FACTOR_MIN_VALUE 0x0020
+#define TI_CLK_FACTOR_MAX_VALUE 0x0040
+
+/* Based on aw_clk_factor sys/arm/allwinner/clkng/aw_clk.h */
+struct ti_clk_factor {
+ uint32_t shift; /* Shift bits for the factor */
+ uint32_t mask; /* Mask to get the factor */
+ uint32_t width; /* Number of bits for the factor */
+ uint32_t value; /* Fixed value */
+
+ uint32_t min_value;
+ uint32_t max_value;
+
+ uint32_t flags; /* Flags */
+};
+
+struct ti_clk_dpll_def {
+ struct clknode_init_def clkdef;
+
+ uint32_t ti_clkmode_offset; /* control */
+ uint8_t ti_clkmode_flags;
+
+ uint32_t ti_idlest_offset;
+
+ uint32_t ti_clksel_offset; /* mult-div1 */
+ struct ti_clk_factor ti_clksel_mult;
+ struct ti_clk_factor ti_clksel_div;
+
+ uint32_t ti_autoidle_offset;
+};
+
+int ti_clknode_dpll_register(struct clkdom *clkdom, struct ti_clk_dpll_def *clkdef);
+
+#endif /* _TI_DPLL_CLOCK_H_ */
Index: sys/arm/ti/clk/ti_clk_dpll.c
===================================================================
--- sys/arm/ti/clk/ti_clk_dpll.c
+++ sys/arm/ti/clk/ti_clk_dpll.c
@@ -0,0 +1,341 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2019 Emmanuel Vadot <manu@freebsd.org>
+ *
+ * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se>
+ *
+ * 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.
+ *
+ * based on sys/arm/allwinner/clkng/aw_clk_np.c
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+
+#include <dev/extres/clk/clk.h>
+
+#include <arm/ti/clk/ti_clk_dpll.h>
+
+#include "clkdev_if.h"
+
+/*
+ * clknode for clocks matching the formula :
+ *
+ * clk = clkin * n / p
+ *
+ */
+
+struct ti_dpll_clknode_sc {
+ uint32_t ti_clkmode_offset; /* control */
+ uint8_t ti_clkmode_flags;
+
+ uint32_t ti_idlest_offset;
+
+ uint32_t ti_clksel_offset; /* mult-div1 */
+ struct ti_clk_factor n; /* ti_clksel_mult */
+ struct ti_clk_factor p; /* ti_clksel_div */
+
+ uint32_t ti_autoidle_offset;
+};
+
+#define WRITE4(_clk, off, val) \
+ CLKDEV_WRITE_4(clknode_get_device(_clk), off, val)
+#define READ4(_clk, off, val) \
+ CLKDEV_READ_4(clknode_get_device(_clk), off, val)
+#define DEVICE_LOCK(_clk) \
+ CLKDEV_DEVICE_LOCK(clknode_get_device(_clk))
+#define DEVICE_UNLOCK(_clk) \
+ CLKDEV_DEVICE_UNLOCK(clknode_get_device(_clk))
+
+static int
+ti_dpll_clk_init(struct clknode *clk, device_t dev)
+{
+ struct ti_dpll_clknode_sc *sc;
+
+ sc = clknode_get_softc(clk);
+
+ clknode_init_parent_idx(clk, 0);
+ return (0);
+}
+
+/* helper to keep aw_clk_np_find_best "intact" */
+static inline uint32_t
+ti_clk_factor_get_max(struct ti_clk_factor *factor)
+{
+ uint32_t max;
+
+ if (factor->flags & TI_CLK_FACTOR_FIXED)
+ max = factor->value;
+ else {
+ max = (1 << factor->width);
+ }
+
+ return (max);
+}
+
+static inline uint32_t
+ti_clk_factor_get_min(struct ti_clk_factor *factor)
+{
+ uint32_t min;
+
+ if (factor->flags & TI_CLK_FACTOR_FIXED)
+ min = factor->value;
+ else if (factor->flags & TI_CLK_FACTOR_ZERO_BASED)
+ min = 0;
+ else if (factor->flags & TI_CLK_FACTOR_MIN_VALUE)
+ min = factor->min_value;
+ else
+ min = 1;
+
+ return (min);
+}
+
+static uint64_t
+ti_dpll_clk_find_best(struct ti_dpll_clknode_sc *sc, uint64_t fparent,
+ uint64_t *fout, uint32_t *factor_n, uint32_t *factor_p)
+{
+ uint64_t cur, best;
+ uint32_t n, p, max_n, max_p, min_n, min_p;
+
+ *factor_n = *factor_p = 0;
+
+ max_n = ti_clk_factor_get_max(&sc->n);
+ max_p = ti_clk_factor_get_max(&sc->p);
+ min_n = ti_clk_factor_get_min(&sc->n);
+ min_p = ti_clk_factor_get_min(&sc->p);
+
+ for (p = min_p; p <= max_p; ) {
+ for (n = min_n; n <= max_n; ) {
+ cur = fparent * n / p;
+ if (abs(*fout - cur) < abs(*fout - best)) {
+ best = cur;
+ *factor_n = n;
+ *factor_p = p;
+ }
+
+ n++;
+ }
+ p++;
+ }
+
+ return (best);
+}
+
+static inline uint32_t
+ti_clk_get_factor(uint32_t val, struct ti_clk_factor *factor)
+{
+ uint32_t factor_val;
+
+ if (factor->flags & TI_CLK_FACTOR_FIXED)
+ return (factor->value);
+
+ factor_val = (val & factor->mask) >> factor->shift;
+ if (!(factor->flags & TI_CLK_FACTOR_ZERO_BASED))
+ factor_val += 1;
+
+ return (factor_val);
+}
+
+static inline uint32_t
+ti_clk_factor_get_value(struct ti_clk_factor *factor, uint32_t raw)
+{
+ uint32_t val;
+
+ if (factor->flags & TI_CLK_FACTOR_FIXED)
+ return (factor->value);
+
+ if (factor->flags & TI_CLK_FACTOR_ZERO_BASED)
+ val = raw;
+ else if (factor->flags & TI_CLK_FACTOR_MAX_VALUE &&
+ raw > factor->max_value)
+ val = factor->max_value;
+ else
+ val = raw - 1;
+
+ return (val);
+}
+
+
+static int
+ti_dpll_clk_set_freq(struct clknode *clk, uint64_t fparent, uint64_t *fout,
+ int flags, int *stop)
+{
+ struct ti_dpll_clknode_sc *sc;
+ uint64_t cur, best;
+ uint32_t val, n, p, best_n, best_p, timeout;
+
+ sc = clknode_get_softc(clk);
+
+ best = cur = 0;
+
+ best = ti_dpll_clk_find_best(sc, fparent, fout,
+ &best_n, &best_p);
+
+ if ((flags & CLK_SET_DRYRUN) != 0) {
+ *fout = best;
+ *stop = 1;
+ return (0);
+ }
+
+ if ((best < *fout) &&
+ (flags == CLK_SET_ROUND_DOWN)) {
+ *stop = 1;
+ return (ERANGE);
+ }
+ if ((best > *fout) &&
+ (flags == CLK_SET_ROUND_UP)) {
+ *stop = 1;
+ return (ERANGE);
+ }
+
+ DEVICE_LOCK(clk);
+ /* 1 switch PLL to bypass mode */
+ WRITE4(clk, sc->ti_clkmode_offset, DPLL_EN_MN_BYPASS_MODE);
+
+ /* 2 Ensure PLL is in bypass */
+ timeout = 10000;
+ do {
+ DELAY(10);
+ READ4(clk, sc->ti_idlest_offset, &val);
+ } while (!(val & ST_MN_BYPASS_MASK) && timeout--);
+
+ if (timeout == 0) {
+ DEVICE_UNLOCK(clk);
+ return (ERANGE); // FIXME: Better return value?
+ }
+
+ /* 3 Set DPLL_MULT & DPLL_DIV bits */
+ READ4(clk, sc->ti_clksel_offset, &val);
+
+ n = ti_clk_factor_get_value(&sc->n, best_n);
+ p = ti_clk_factor_get_value(&sc->p, best_p);
+ val &= ~sc->n.mask;
+ val &= ~sc->p.mask;
+ val |= n << sc->n.shift;
+ val |= p << sc->p.shift;
+
+ WRITE4(clk, sc->ti_clksel_offset, val);
+
+ /* 4. configure M2, M4, M5 and M6 */
+ /*
+ * FIXME: According to documentation M2/M4/M5/M6 can be set "later"
+ * See note in TRM 8.1.6.7.1
+ */
+
+ /* 5 Switch over to lock mode */
+ WRITE4(clk, sc->ti_clkmode_offset, DPLL_EN_LOCK_MODE);
+
+ /* 6 Ensure PLL is locked */
+ timeout = 10000;
+ do {
+ DELAY(10);
+ READ4(clk, sc->ti_idlest_offset, &val);
+ } while (!(val & ST_DPLL_CLK_MASK) && timeout--);
+
+ DEVICE_UNLOCK(clk);
+ if (timeout == 0) {
+ return (ERANGE); // FIXME: Better return value?
+ }
+
+ *fout = best;
+ *stop = 1;
+
+ return (0);
+}
+
+static int
+ti_dpll_clk_recalc(struct clknode *clk, uint64_t *freq)
+{
+ struct ti_dpll_clknode_sc *sc;
+ uint32_t val, n, p;
+
+ sc = clknode_get_softc(clk);
+
+ DEVICE_LOCK(clk);
+ READ4(clk, sc->ti_clksel_offset, &val);
+ DEVICE_UNLOCK(clk);
+
+ n = ti_clk_get_factor(val, &sc->n);
+ p = ti_clk_get_factor(val, &sc->p);
+
+ *freq = *freq * n / p;
+
+ return (0);
+}
+
+static clknode_method_t ti_dpll_clknode_methods[] = {
+ /* Device interface */
+ CLKNODEMETHOD(clknode_init, ti_dpll_clk_init),
+ CLKNODEMETHOD(clknode_recalc_freq, ti_dpll_clk_recalc),
+ CLKNODEMETHOD(clknode_set_freq, ti_dpll_clk_set_freq),
+ CLKNODEMETHOD_END
+};
+
+DEFINE_CLASS_1(ti_dpll_clknode, ti_dpll_clknode_class, ti_dpll_clknode_methods,
+ sizeof(struct ti_dpll_clknode_sc), clknode_class);
+
+int
+ti_clknode_dpll_register(struct clkdom *clkdom, struct ti_clk_dpll_def *clkdef)
+{
+ struct clknode *clk;
+ struct ti_dpll_clknode_sc *sc;
+
+ clk = clknode_create(clkdom, &ti_dpll_clknode_class, &clkdef->clkdef);
+ if (clk == NULL)
+ return (1);
+
+ sc = clknode_get_softc(clk);
+
+ sc->ti_clkmode_offset = clkdef->ti_clkmode_offset;
+ sc->ti_clkmode_flags = clkdef->ti_clkmode_flags;
+ sc->ti_idlest_offset = clkdef->ti_idlest_offset;
+ sc->ti_clksel_offset = clkdef->ti_clksel_offset;
+
+ sc->n.shift = clkdef->ti_clksel_mult.shift;
+ sc->n.mask = clkdef->ti_clksel_mult.mask;
+ sc->n.width = clkdef->ti_clksel_mult.width;
+ sc->n.value = clkdef->ti_clksel_mult.value;
+ sc->n.min_value = clkdef->ti_clksel_mult.min_value;
+ sc->n.max_value = clkdef->ti_clksel_mult.max_value;
+ sc->n.flags = clkdef->ti_clksel_mult.flags;
+
+ sc->p.shift = clkdef->ti_clksel_div.shift;
+ sc->p.mask = clkdef->ti_clksel_div.mask;
+ sc->p.width = clkdef->ti_clksel_div.width;
+ sc->p.value = clkdef->ti_clksel_div.value;
+ sc->p.min_value = clkdef->ti_clksel_div.min_value;
+ sc->p.max_value = clkdef->ti_clksel_div.max_value;
+ sc->p.flags = clkdef->ti_clksel_div.flags;
+
+ sc->ti_autoidle_offset = clkdef->ti_autoidle_offset;
+
+ clknode_register(clkdom, clk);
+
+ return (0);
+}
Index: sys/arm/ti/clk/ti_clkctrl.c
===================================================================
--- sys/arm/ti/clk/ti_clkctrl.c
+++ sys/arm/ti/clk/ti_clkctrl.c
@@ -0,0 +1,238 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se>
+ *
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/fbio.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/resource.h>
+#include <machine/bus.h>
+#include <vm/vm.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_kern.h>
+#include <vm/pmap.h>
+
+#include <dev/fdt/simplebus.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <arm/ti/clk/ti_clk_clkctrl.h>
+#include <arm/ti/ti_omap4_cm.h>
+
+#if 0
+#define DPRINTF(dev, msg...) device_printf(dev, msg)
+#else
+#define DPRINTF(dev, msg...)
+#endif
+
+/* Documentation/devicetree/bindings/clock/ti-clkctrl.txt */
+
+#define TI_CLKCTRL_L4_WKUP 5
+#define TI_CLKCTRL_L4_SECURE 4
+#define TI_CLKCTRL_L4_PER 3
+#define TI_CLKCTRL_L4_CFG 2
+#define TI_CLKCTRL 1
+#define TI_CLKCTRL_END 0
+
+static struct ofw_compat_data compat_data[] = {
+ { "ti,clkctrl-l4-wkup", TI_CLKCTRL_L4_WKUP },
+ { "ti,clkctrl-l4-secure", TI_CLKCTRL_L4_SECURE },
+ { "ti,clkctrl-l4-per", TI_CLKCTRL_L4_PER },
+ { "ti,clkctrl-l4-cfg", TI_CLKCTRL_L4_CFG },
+ { "ti,clkctrl", TI_CLKCTRL },
+ { NULL, TI_CLKCTRL_END }
+};
+
+struct ti_clkctrl_softc {
+ device_t dev;
+
+ struct clkdom *clkdom;
+};
+
+static int ti_clkctrl_probe(device_t dev);
+static int ti_clkctrl_attach(device_t dev);
+static int ti_clkctrl_detach(device_t dev);
+
+static int
+ti_clkctrl_probe(device_t dev)
+{
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "TI clkctrl");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+ti_clkctrl_attach(device_t dev)
+{
+ struct ti_clkctrl_softc *sc;
+ phandle_t node;
+ cell_t *reg;
+ ssize_t numbytes_reg;
+ int num_reg, err, ti_clock_cells, index, reg_offset;
+ struct ti_clk_clkctrl_def def;
+ const char *org_name;
+ char *name;
+ size_t name_len;
+ uint64_t parent_offset;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+ node = ofw_bus_get_node(dev);
+
+ /* Sanity check */
+ err = OF_searchencprop(node, "#clock-cells",
+ &ti_clock_cells, sizeof(ti_clock_cells));
+ if (err == -1) {
+ device_printf(sc->dev, "Failed to get #clock-cells\n");
+ return (ENXIO);
+ }
+
+ if (ti_clock_cells != 2) {
+ device_printf(sc->dev, "clock cells(%d) != 2\n",
+ ti_clock_cells);
+ return (ENXIO);
+ }
+
+ /* Grab the content of reg properties */
+ numbytes_reg = OF_getproplen(node, "reg");
+ if (numbytes_reg == 0) {
+ device_printf(sc->dev, "reg property empty - check your devicetree\n");
+ return (ENXIO);
+ }
+ num_reg = numbytes_reg / sizeof(cell_t);
+
+ reg = malloc(numbytes_reg, M_DEVBUF, M_WAITOK);
+ OF_getencprop(node, "reg", reg, numbytes_reg);
+
+ /* Create clock domain */
+ sc->clkdom = clkdom_create(sc->dev);
+ if (sc->clkdom == NULL) {
+ free(reg, M_DEVBUF);
+ DPRINTF(sc->dev, "Failed to create clkdom\n");
+ return (ENXIO);
+ }
+
+ /* Create clock nodes */
+ /* name */
+ clk_parse_ofw_clk_name(sc->dev, node, &org_name);
+ name_len = strlen(org_name) + 1 + 5; /* 5 = _xxxx */
+ name = malloc(name_len, M_OFWPROP, M_WAITOK);
+
+ /* No parent name */
+ def.clkdef.parent_cnt = 0;
+
+ /* set flags */
+ def.clkdef.flags = 0x0;
+
+ /* Get parent range */
+ parent_offset = ti_omap4_cm_get_simplebus_base_host(device_get_parent(dev));
+
+ /* reg property has a pair of (base address, length) */
+ for (index = 0; index < num_reg; index += 2) {
+ for (reg_offset = 0; reg_offset < reg[index+1]; reg_offset += sizeof(cell_t)) {
+ /*
+ * Check out XX_CLKCTRL-INDEX(offset)-macro dance in the
+ * sys/gnu/dts/dts/include/dt-bindings/clock/am3.h
+ * sys/gnu/dts/dts/include/dt-bindings/clock/am4.h
+ * sys/gnu/dts/dts/include/dt-bindings/clock/dra7.h
+ * reg[0] are in practice the same as the offset described in the dts.
+ */
+ def.clkdef.id = reg[index] + reg_offset - reg[0];
+ def.register_offset = parent_offset + reg[index] + reg_offset;
+
+ /* Make up an uniq name in the namespace for each clkctrl */
+ snprintf(name, name_len, "%s_%x\0",
+ org_name, def.clkdef.id);
+ def.clkdef.name = (const char *) name;
+
+ DPRINTF(sc->dev, "ti_clkctrl_attach: reg[%d]: %s %x\n",
+ index, def.clkdef.name, def.clkdef.id);
+
+ /* Register the clkctrl */
+ err = ti_clknode_clkctrl_register(sc->clkdom, &def);
+ if (err) {
+ DPRINTF(sc->dev,
+ "ti_clknode_clkctrl_register[%d:%d] failed %x\n",
+ index, reg_offset, err);
+ return (ENXIO);
+ }
+ }
+ }
+
+ err = clkdom_finit(sc->clkdom);
+ if (err) {
+ DPRINTF(sc->dev, "Clk domain finit fails %x.\n", err);
+ return (ENXIO);
+ }
+
+ OF_prop_free(name);
+ OF_prop_free(__DECONST(char *, org_name));
+
+ free(reg, M_DEVBUF);
+
+ return (bus_generic_attach(dev));
+}
+
+static int
+ti_clkctrl_detach(device_t dev)
+{
+ return (EBUSY);
+}
+
+static device_method_t ti_clkctrl_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, ti_clkctrl_probe),
+ DEVMETHOD(device_attach, ti_clkctrl_attach),
+ DEVMETHOD(device_detach, ti_clkctrl_detach),
+
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_0(ti_clkctrl, ti_clkctrl_driver, ti_clkctrl_methods,
+ sizeof(struct ti_clkctrl_softc));
+
+static devclass_t ti_clkctrl_devclass;
+
+EARLY_DRIVER_MODULE(ti_clkctrl, simplebus, ti_clkctrl_driver,
+ti_clkctrl_devclass, 0, 0, BUS_PASS_BUS+BUS_PASS_ORDER_MIDDLE);
+
+MODULE_VERSION(ti_clkctrl, 1);
Index: sys/arm/ti/clk/ti_divider_clock.c
===================================================================
--- sys/arm/ti/clk/ti_divider_clock.c
+++ sys/arm/ti/clk/ti_divider_clock.c
@@ -0,0 +1,260 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se>
+ *
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/systm.h>
+#include <sys/libkern.h>
+
+#include <machine/bus.h>
+#include <dev/fdt/simplebus.h>
+
+#include <dev/extres/clk/clk_div.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include "clock_common.h"
+
+#if 0
+#define DPRINTF(dev, msg...) device_printf(dev, msg)
+#else
+#define DPRINTF(dev, msg...)
+#endif
+
+/*
+ * Devicetree description
+ * Documentation/devicetree/bindings/clock/ti/divider.txt
+ */
+
+struct ti_divider_softc {
+ device_t sc_dev;
+ bool attach_done;
+ struct clk_div_def div_def;
+
+ struct clock_cell_info clock_cell;
+ struct clkdom *clkdom;
+};
+
+static int ti_divider_probe(device_t dev);
+static int ti_divider_attach(device_t dev);
+static int ti_divider_detach(device_t dev);
+
+#define TI_DIVIDER_CLOCK 2
+#define TI_COMPOSITE_DIVIDER_CLOCK 1
+#define TI_DIVIDER_END 0
+
+static struct ofw_compat_data compat_data[] = {
+ { "ti,divider-clock", TI_DIVIDER_CLOCK },
+ { "ti,composite-divider-clock", TI_COMPOSITE_DIVIDER_CLOCK },
+ { NULL, TI_DIVIDER_END }
+};
+
+static int
+register_clk(struct ti_divider_softc *sc) {
+ int err;
+
+ sc->clkdom = clkdom_create(sc->sc_dev);
+ if (sc->clkdom == NULL) {
+ DPRINTF(sc->sc_dev, "Failed to create clkdom\n");
+ return (ENXIO);
+ }
+
+ err = clknode_div_register(sc->clkdom, &sc->div_def);
+ if (err) {
+ DPRINTF(sc->sc_dev, "clknode_div_register failed %x\n", err);
+ return (ENXIO);
+ }
+
+ err = clkdom_finit(sc->clkdom);
+ if (err) {
+ DPRINTF(sc->sc_dev, "Clk domain finit fails %x.\n", err);
+ return (ENXIO);
+ }
+
+ return (0);
+}
+
+static int
+ti_divider_probe(device_t dev)
+{
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "TI Divider Clock");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+ti_divider_attach(device_t dev)
+{
+ struct ti_divider_softc *sc;
+ phandle_t node;
+ int err;
+ cell_t value;
+ uint32_t ti_max_div;
+
+ sc = device_get_softc(dev);
+ sc->sc_dev = dev;
+ node = ofw_bus_get_node(dev);
+
+ /* Grab the content of reg properties */
+ OF_getencprop(node, "reg", &value, sizeof(value));
+ sc->div_def.offset = value;
+
+ if (OF_hasprop(node, "ti,bit-shift")) {
+ OF_getencprop(node, "ti,bit-shift", &value, sizeof(value));
+ sc->div_def.i_shift = value;
+ }
+
+ if (OF_hasprop(node, "ti,index-starts-at-one")) {
+ sc->div_def.div_flags = CLK_DIV_ZERO_BASED;
+ }
+
+ if (OF_hasprop(node, "ti,index-power-of-two")) {
+ /* FIXME: later */
+ device_printf(sc->sc_dev, "ti,index-power-of-two - Not implemented\n");
+ /* remember to update i_width a few lines below */
+ }
+ if (OF_hasprop(node, "ti,max-div")) {
+ OF_getencprop(node, "ti,max-div", &value, sizeof(value));
+ ti_max_div = value;
+ }
+
+ if (OF_hasprop(node, "clock-output-names"))
+ device_printf(sc->sc_dev, "clock-output-names\n");
+ if (OF_hasprop(node, "ti,dividers"))
+ device_printf(sc->sc_dev, "ti,dividers\n");
+ if (OF_hasprop(node, "ti,min-div"))
+ device_printf(sc->sc_dev, "ti,min-div - Not implemented\n");
+
+ if (OF_hasprop(node, "ti,autoidle-shift"))
+ device_printf(sc->sc_dev, "ti,autoidle-shift - Not implemented\n");
+ if (OF_hasprop(node, "ti,set-rate-parent"))
+ device_printf(sc->sc_dev, "ti,set-rate-parent - Not implemented\n");
+ if (OF_hasprop(node, "ti,latch-bit"))
+ device_printf(sc->sc_dev, "ti,latch-bit - Not implemented\n");
+
+ /* Figure out the width from ti_max_div */
+ if (sc->div_def.div_flags)
+ sc->div_def.i_width = fls(ti_max_div-1);
+ else
+ sc->div_def.i_width = fls(ti_max_div);
+
+ DPRINTF(sc->sc_dev, "div_def.i_width %x\n", sc->div_def.i_width);
+
+ read_clock_cells(sc->sc_dev, &sc->clock_cell);
+
+ create_clkdef(sc->sc_dev, &sc->clock_cell, &sc->div_def.clkdef);
+
+ err = find_parent_clock_names(sc->sc_dev, &sc->clock_cell, &sc->div_def.clkdef);
+
+ if (err) {
+ DPRINTF(sc->sc_dev, "find_parent_clock_names failed\n");
+ return (bus_generic_attach(sc->sc_dev));
+ }
+
+ err = register_clk(sc);
+
+ if (err) {
+ DPRINTF(sc->sc_dev, "register_clk failed\n");
+ return (bus_generic_attach(sc->sc_dev));
+ }
+
+ sc->attach_done = true;
+
+ free_clkdef(&sc->div_def.clkdef);
+
+ return (bus_generic_attach(sc->sc_dev));
+}
+
+static int
+ti_divider_detach(device_t dev)
+{
+ return (EBUSY);
+}
+
+static void
+ti_divider_new_pass(device_t dev)
+{
+ struct ti_divider_softc *sc;
+ int err;
+
+ sc = device_get_softc(dev);
+
+ if (sc->attach_done) {
+ return;
+ }
+
+ err = find_parent_clock_names(sc->sc_dev, &sc->clock_cell, &sc->div_def.clkdef);
+ if (err) {
+ DPRINTF(sc->sc_dev, "new_pass find_parent_clock_names failed\n");
+ return;
+ }
+
+ err = register_clk(sc);
+ if (err) {
+ DPRINTF(sc->sc_dev, "new_pass register_clk failed\n");
+ return;
+ }
+
+ sc->attach_done = true;
+
+ free_clkdef(&sc->div_def.clkdef);
+}
+
+static device_method_t ti_divider_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, ti_divider_probe),
+ DEVMETHOD(device_attach, ti_divider_attach),
+ DEVMETHOD(device_detach, ti_divider_detach),
+
+ /* Bus interface */
+ DEVMETHOD(bus_new_pass, ti_divider_new_pass),
+
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_0(ti_divider, ti_divider_driver, ti_divider_methods,
+ sizeof(struct ti_divider_softc));
+
+static devclass_t ti_divider_devclass;
+
+EARLY_DRIVER_MODULE(ti_divider, simplebus, ti_divider_driver,
+ ti_divider_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
+MODULE_VERSION(ti_divider, 1);
Index: sys/arm/ti/clk/ti_dpll_clock.c
===================================================================
--- sys/arm/ti/clk/ti_dpll_clock.c
+++ sys/arm/ti/clk/ti_dpll_clock.c
@@ -0,0 +1,371 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se>
+ *
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/systm.h>
+#include <sys/libkern.h>
+
+#include <machine/bus.h>
+#include <dev/fdt/simplebus.h>
+
+#include <dev/extres/clk/clk_div.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <arm/ti/clk/ti_clk_dpll.h>
+#include "clock_common.h"
+
+#if 0
+#define DPRINTF(dev, msg...) device_printf(dev, msg)
+#else
+#define DPRINTF(dev, msg...)
+#endif
+
+/*
+ * Devicetree description
+ * Documentation/devicetree/bindings/clock/ti/dpll.txt
+ */
+
+struct ti_dpll_softc {
+ device_t dev;
+ uint8_t dpll_type;
+
+ bool attach_done;
+ struct ti_clk_dpll_def dpll_def;
+
+ struct clock_cell_info clock_cell;
+ struct clkdom *clkdom;
+};
+
+static int ti_dpll_probe(device_t dev);
+static int ti_dpll_attach(device_t dev);
+static int ti_dpll_detach(device_t dev);
+
+#define TI_OMAP3_DPLL_CLOCK 17
+#define TI_OMAP3_DPLL_CORE_CLOCK 16
+#define TI_OMAP3_DPLL_PER_CLOCK 15
+#define TI_OMAP3_DPLL_PER_J_TYPE_CLOCK 14
+#define TI_OMAP4_DPLL_CLOCK 13
+#define TI_OMAP4_DPLL_X2_CLOCK 12
+#define TI_OMAP4_DPLL_CORE_CLOCK 11
+#define TI_OMAP4_DPLL_M4XEN_CLOCK 10
+#define TI_OMAP4_DPLL_J_TYPE_CLOCK 9
+#define TI_OMAP5_MPU_DPLL_CLOCK 8
+#define TI_AM3_DPLL_NO_GATE_CLOCK 7
+#define TI_AM3_DPLL_J_TYPE_CLOCK 6
+#define TI_AM3_DPLL_NO_GATE_J_TYPE_CLOCK 5
+#define TI_AM3_DPLL_CLOCK 4
+#define TI_AM3_DPLL_CORE_CLOCK 3
+#define TI_AM3_DPLL_X2_CLOCK 2
+#define TI_OMAP2_DPLL_CORE_CLOCK 1
+#define TI_DPLL_END 0
+
+static struct ofw_compat_data compat_data[] = {
+ { "ti,omap3-dpll-clock", TI_OMAP3_DPLL_CLOCK },
+ { "ti,omap3-dpll-core-clock", TI_OMAP3_DPLL_CORE_CLOCK },
+ { "ti,omap3-dpll-per-clock", TI_OMAP3_DPLL_PER_CLOCK },
+ { "ti,omap3-dpll-per-j-type-clock",TI_OMAP3_DPLL_PER_J_TYPE_CLOCK },
+ { "ti,omap4-dpll-clock", TI_OMAP4_DPLL_CLOCK },
+ { "ti,omap4-dpll-x2-clock", TI_OMAP4_DPLL_X2_CLOCK },
+ { "ti,omap4-dpll-core-clock", TI_OMAP4_DPLL_CORE_CLOCK },
+ { "ti,omap4-dpll-m4xen-clock", TI_OMAP4_DPLL_M4XEN_CLOCK },
+ { "ti,omap4-dpll-j-type-clock", TI_OMAP4_DPLL_J_TYPE_CLOCK },
+ { "ti,omap5-mpu-dpll-clock", TI_OMAP5_MPU_DPLL_CLOCK },
+ { "ti,am3-dpll-no-gate-clock", TI_AM3_DPLL_NO_GATE_CLOCK },
+ { "ti,am3-dpll-j-type-clock", TI_AM3_DPLL_J_TYPE_CLOCK },
+ { "ti,am3-dpll-no-gate-j-type-clock",TI_AM3_DPLL_NO_GATE_J_TYPE_CLOCK },
+ { "ti,am3-dpll-clock", TI_AM3_DPLL_CLOCK },
+ { "ti,am3-dpll-core-clock", TI_AM3_DPLL_CORE_CLOCK },
+ { "ti,am3-dpll-x2-clock", TI_AM3_DPLL_X2_CLOCK },
+ { "ti,omap2-dpll-core-clock", TI_OMAP2_DPLL_CORE_CLOCK },
+ { NULL, TI_DPLL_END }
+};
+
+static int
+register_clk(struct ti_dpll_softc *sc) {
+ int err;
+
+ sc->clkdom = clkdom_create(sc->dev);
+ if (sc->clkdom == NULL) {
+ DPRINTF(sc->dev, "Failed to create clkdom\n");
+ return (ENXIO);
+ }
+
+ err = ti_clknode_dpll_register(sc->clkdom, &sc->dpll_def);
+ if (err) {
+ DPRINTF(sc->dev,
+ "ti_clknode_dpll_register failed %x\n", err);
+ return (ENXIO);
+ }
+
+ err = clkdom_finit(sc->clkdom);
+ if (err) {
+ DPRINTF(sc->dev, "Clk domain finit fails %x.\n", err);
+ return (ENXIO);
+ }
+
+ return (0);
+}
+
+static int
+ti_dpll_probe(device_t dev)
+{
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "TI DPLL Clock");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+parse_dpll_reg(struct ti_dpll_softc *sc) {
+ ssize_t numbytes_regs;
+ uint32_t num_regs;
+ phandle_t node;
+ cell_t reg_cells[4];
+
+ if (sc->dpll_type == TI_AM3_DPLL_X2_CLOCK ||
+ sc->dpll_type == TI_OMAP4_DPLL_X2_CLOCK) {
+ sc->dpll_def.ti_clksel_mult.value = 2;
+ sc->dpll_def.ti_clksel_mult.flags = TI_CLK_FACTOR_FIXED;
+
+ sc->dpll_def.ti_clksel_div.value = 1;
+ sc->dpll_def.ti_clksel_div.flags = TI_CLK_FACTOR_FIXED;
+ return (0);
+ }
+
+ node = ofw_bus_get_node(sc->dev);
+
+ numbytes_regs = OF_getproplen(node, "reg");
+ num_regs = numbytes_regs / sizeof(cell_t);
+
+ /* Sanity check */
+ if (num_regs > 4)
+ return (ENXIO);
+
+ OF_getencprop(node, "reg", reg_cells, numbytes_regs);
+
+ switch (sc->dpll_type) {
+ case TI_AM3_DPLL_NO_GATE_CLOCK:
+ case TI_AM3_DPLL_J_TYPE_CLOCK:
+ case TI_AM3_DPLL_NO_GATE_J_TYPE_CLOCK:
+ case TI_AM3_DPLL_CLOCK:
+ case TI_AM3_DPLL_CORE_CLOCK:
+ case TI_AM3_DPLL_X2_CLOCK:
+ if (num_regs != 3)
+ return (ENXIO);
+ sc->dpll_def.ti_clkmode_offset = reg_cells[0];
+ sc->dpll_def.ti_idlest_offset = reg_cells[1];
+ sc->dpll_def.ti_clksel_offset = reg_cells[2];
+ break;
+
+ case TI_OMAP2_DPLL_CORE_CLOCK:
+ if (num_regs != 2)
+ return (ENXIO);
+ sc->dpll_def.ti_clkmode_offset = reg_cells[0];
+ sc->dpll_def.ti_clksel_offset = reg_cells[1];
+ break;
+
+ default:
+ sc->dpll_def.ti_clkmode_offset = reg_cells[0];
+ sc->dpll_def.ti_idlest_offset = reg_cells[1];
+ sc->dpll_def.ti_clksel_offset = reg_cells[2];
+ sc->dpll_def.ti_autoidle_offset = reg_cells[3];
+ break;
+ }
+
+ /* AM335x */
+ if (sc->dpll_def.ti_clksel_offset == CM_CLKSEL_DPLL_PERIPH) {
+ sc->dpll_def.ti_clksel_mult.shift = 8;
+ sc->dpll_def.ti_clksel_mult.mask = 0x000FFF00;
+ sc->dpll_def.ti_clksel_mult.width = 12;
+ sc->dpll_def.ti_clksel_mult.value = 0;
+ sc->dpll_def.ti_clksel_mult.min_value = 2;
+ sc->dpll_def.ti_clksel_mult.max_value = 4095;
+ sc->dpll_def.ti_clksel_mult.flags = TI_CLK_FACTOR_ZERO_BASED |
+ TI_CLK_FACTOR_MIN_VALUE |
+ TI_CLK_FACTOR_MAX_VALUE;
+
+ sc->dpll_def.ti_clksel_div.shift = 0;
+ sc->dpll_def.ti_clksel_div.mask = 0x000000FF;
+ sc->dpll_def.ti_clksel_div.width = 8;
+ sc->dpll_def.ti_clksel_div.value = 0;
+ sc->dpll_def.ti_clksel_div.min_value = 0;
+ sc->dpll_def.ti_clksel_div.max_value = 255;
+ sc->dpll_def.ti_clksel_div.flags = TI_CLK_FACTOR_MIN_VALUE |
+ TI_CLK_FACTOR_MAX_VALUE;
+ } else {
+ sc->dpll_def.ti_clksel_mult.shift = 8;
+ sc->dpll_def.ti_clksel_mult.mask = 0x0007FF00;
+ sc->dpll_def.ti_clksel_mult.width = 11;
+ sc->dpll_def.ti_clksel_mult.value = 0;
+ sc->dpll_def.ti_clksel_mult.min_value = 2;
+ sc->dpll_def.ti_clksel_mult.max_value = 2047;
+ sc->dpll_def.ti_clksel_mult.flags = TI_CLK_FACTOR_ZERO_BASED |
+ TI_CLK_FACTOR_MIN_VALUE |
+ TI_CLK_FACTOR_MAX_VALUE;
+
+ sc->dpll_def.ti_clksel_div.shift = 0;
+ sc->dpll_def.ti_clksel_div.mask = 0x0000007F;
+ sc->dpll_def.ti_clksel_div.width = 7;
+ sc->dpll_def.ti_clksel_div.value = 0;
+ sc->dpll_def.ti_clksel_div.min_value = 0;
+ sc->dpll_def.ti_clksel_div.max_value = 127;
+ sc->dpll_def.ti_clksel_div.flags = TI_CLK_FACTOR_MIN_VALUE |
+ TI_CLK_FACTOR_MAX_VALUE;
+ }
+ DPRINTF(sc->dev, "clkmode %x idlest %x clksel %x autoidle %x\n",
+ sc->dpll_def.ti_clkmode_offset, sc->dpll_def.ti_idlest_offset,
+ sc->dpll_def.ti_clksel_offset,
+ sc->dpll_def.ti_autoidle_offset);
+
+ return (0);
+}
+static int
+ti_dpll_attach(device_t dev)
+{
+ struct ti_dpll_softc *sc;
+ phandle_t node;
+ int err;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ sc->dpll_type = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
+ node = ofw_bus_get_node(dev);
+
+ /* Grab the content of reg properties */
+ parse_dpll_reg(sc);
+
+ /* default flags (OMAP4&AM335x) not present in the dts at moment */
+ sc->dpll_def.ti_clkmode_flags = MN_BYPASS_MODE_FLAG | LOCK_MODE_FLAG;
+
+ if (OF_hasprop(node, "ti,low-power-stop")) {
+ sc->dpll_def.ti_clkmode_flags |= LOW_POWER_STOP_MODE_FLAG;
+ }
+ if (OF_hasprop(node, "ti,low-power-bypass")) {
+ sc->dpll_def.ti_clkmode_flags |= IDLE_BYPASS_LOW_POWER_MODE_FLAG;
+ }
+ if (OF_hasprop(node, "ti,lock")) {
+ sc->dpll_def.ti_clkmode_flags |= LOCK_MODE_FLAG;
+ }
+
+ read_clock_cells(sc->dev, &sc->clock_cell);
+
+ create_clkdef(sc->dev, &sc->clock_cell, &sc->dpll_def.clkdef);
+
+ err = find_parent_clock_names(sc->dev, &sc->clock_cell,
+ &sc->dpll_def.clkdef);
+
+ if (err) {
+ DPRINTF(sc->dev, "find_parent_clock_names failed\n");
+ return (bus_generic_attach(sc->dev));
+ }
+
+ err = register_clk(sc);
+
+ if (err) {
+ DPRINTF(sc->dev, "register_clk failed\n");
+ return (bus_generic_attach(sc->dev));
+ }
+
+ sc->attach_done = true;
+
+ free_clkdef(&sc->dpll_def.clkdef);
+
+ return (bus_generic_attach(sc->dev));
+}
+
+static int
+ti_dpll_detach(device_t dev)
+{
+ return (EBUSY);
+}
+
+static void
+ti_dpll_new_pass(device_t dev)
+{
+ struct ti_dpll_softc *sc;
+ int err;
+
+ sc = device_get_softc(dev);
+
+ if (sc->attach_done) {
+ return;
+ }
+
+ err = find_parent_clock_names(sc->dev, &sc->clock_cell,
+ &sc->dpll_def.clkdef);
+ if (err) {
+ DPRINTF(sc->dev,
+ "new_pass find_parent_clock_names failed\n");
+ return;
+ }
+
+ err = register_clk(sc);
+ if (err) {
+ DPRINTF(sc->dev, "new_pass register_clk failed\n");
+ return;
+ }
+
+ sc->attach_done = true;
+ free_clkdef(&sc->dpll_def.clkdef);
+}
+
+static device_method_t ti_dpll_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, ti_dpll_probe),
+ DEVMETHOD(device_attach, ti_dpll_attach),
+ DEVMETHOD(device_detach, ti_dpll_detach),
+
+ /* Bus interface */
+ DEVMETHOD(bus_new_pass, ti_dpll_new_pass),
+
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_0(ti_dpll, ti_dpll_driver, ti_dpll_methods,
+ sizeof(struct ti_dpll_softc));
+
+static devclass_t ti_dpll_devclass;
+
+EARLY_DRIVER_MODULE(ti_dpll, simplebus, ti_dpll_driver,
+ ti_dpll_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
+MODULE_VERSION(ti_dpll, 1);
Index: sys/arm/ti/clk/ti_gate_clock.c
===================================================================
--- sys/arm/ti/clk/ti_gate_clock.c
+++ sys/arm/ti/clk/ti_gate_clock.c
@@ -0,0 +1,262 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se>
+ *
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/systm.h>
+#include <sys/libkern.h>
+
+#include <machine/bus.h>
+#include <dev/fdt/simplebus.h>
+
+#include <dev/extres/clk/clk_gate.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include "clock_common.h"
+
+#define DEBUG_GATE 0
+
+#if DEBUG_GATE
+#define DPRINTF(dev, msg...) device_printf(dev, msg)
+#else
+#define DPRINTF(dev, msg...)
+#endif
+
+/*
+ * Devicetree description
+ * Documentation/devicetree/bindings/clock/ti/gate.txt
+ */
+
+struct ti_gate_softc {
+ device_t sc_dev;
+ bool attach_done;
+ uint8_t sc_type;
+
+ struct clk_gate_def gate_def;
+ struct clock_cell_info clock_cell;
+ struct clkdom *clkdom;
+};
+
+static int ti_gate_probe(device_t dev);
+static int ti_gate_attach(device_t dev);
+static int ti_gate_detach(device_t dev);
+
+#define TI_GATE_CLOCK 7
+#define TI_WAIT_GATE_CLOCK 6
+#define TI_DSS_GATE_CLOCK 5
+#define TI_AM35XX_GATE_CLOCK 4
+#define TI_CLKDM_GATE_CLOCK 3
+#define TI_HSDIV_GATE_CLOCK 2
+#define TI_COMPOSITE_NO_WAIT_GATE_CLOCK 1
+#define TI_GATE_END 0
+
+static struct ofw_compat_data compat_data[] = {
+ { "ti,gate-clock", TI_GATE_CLOCK },
+ { "ti,wait-gate-clock", TI_WAIT_GATE_CLOCK },
+ { "ti,dss-gate-clock", TI_DSS_GATE_CLOCK },
+ { "ti,am35xx-gate-clock", TI_AM35XX_GATE_CLOCK },
+ { "ti,clkdm-gate-clock", TI_CLKDM_GATE_CLOCK },
+ { "ti,hsdiv-gate-cloc", TI_HSDIV_GATE_CLOCK },
+ { "ti,composite-no-wait-gate-clock", TI_COMPOSITE_NO_WAIT_GATE_CLOCK },
+ { NULL, TI_GATE_END }
+};
+
+static int
+ti_gate_probe(device_t dev)
+{
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "TI Gate Clock");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+register_clk(struct ti_gate_softc *sc) {
+ int err;
+ sc->clkdom = clkdom_create(sc->sc_dev);
+ if (sc->clkdom == NULL) {
+ DPRINTF(sc->sc_dev, "Failed to create clkdom\n");
+ return ENXIO;
+ }
+
+ err = clknode_gate_register(sc->clkdom, &sc->gate_def);
+ if (err) {
+ DPRINTF(sc->sc_dev, "clknode_gate_register failed %x\n", err);
+ return ENXIO;
+ }
+
+ err = clkdom_finit(sc->clkdom);
+ if (err) {
+ DPRINTF(sc->sc_dev, "Clk domain finit fails %x.\n", err);
+ return ENXIO;
+ }
+
+ return (0);
+}
+
+static int
+ti_gate_attach(device_t dev)
+{
+ struct ti_gate_softc *sc;
+ phandle_t node;
+ int err;
+ cell_t value;
+
+ sc = device_get_softc(dev);
+ sc->sc_dev = dev;
+ node = ofw_bus_get_node(dev);
+
+ /* Get the compatible type */
+ sc->sc_type = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
+
+ /* Get the content of reg properties */
+ if (sc->sc_type != TI_CLKDM_GATE_CLOCK) {
+ OF_getencprop(node, "reg", &value, sizeof(value));
+ sc->gate_def.offset = value;
+ }
+#if DEBUG_GATE
+ else {
+ DPRINTF(sc->sc_dev, "no reg (TI_CLKDM_GATE_CLOCK)\n");
+ }
+#endif
+
+ if (OF_hasprop(node, "ti,bit-shift")) {
+ OF_getencprop(node, "ti,bit-shift", &value, sizeof(value));
+ sc->gate_def.shift = value;
+ DPRINTF(sc->sc_dev, "ti,bit-shift => shift %x\n", sc->gate_def.shift);
+ }
+ if (OF_hasprop(node, "ti,set-bit-to-disable")) {
+ sc->gate_def.on_value = 0;
+ sc->gate_def.off_value = 1;
+ DPRINTF(sc->sc_dev,
+ "on_value = 0, off_value = 1 (ti,set-bit-to-disable)\n");
+ } else {
+ sc->gate_def.on_value = 1;
+ sc->gate_def.off_value = 0;
+ DPRINTF(sc->sc_dev, "on_value = 1, off_value = 0\n");
+ }
+
+ sc->gate_def.gate_flags = 0x0;
+
+ read_clock_cells(sc->sc_dev, &sc->clock_cell);
+
+ create_clkdef(sc->sc_dev, &sc->clock_cell, &sc->gate_def.clkdef);
+
+ /* Calculate mask */
+ sc->gate_def.mask = (1 << fls(sc->clock_cell.num_real_clocks)) - 1;
+ DPRINTF(sc->sc_dev, "num_real_clocks %x gate_def.mask %x\n",
+ sc->clock_cell.num_real_clocks, sc->gate_def.mask);
+
+ err = find_parent_clock_names(sc->sc_dev, &sc->clock_cell, &sc->gate_def.clkdef);
+
+ if (err) {
+ DPRINTF(sc->sc_dev, "find_parent_clock_names failed\n");
+ return (bus_generic_attach(sc->sc_dev));
+ }
+
+ err = register_clk(sc);
+
+ if (err) {
+ DPRINTF(sc->sc_dev, "register_clk failed\n");
+ return (bus_generic_attach(sc->sc_dev));
+ }
+
+ sc->attach_done = true;
+
+ free_clkdef(&sc->gate_def.clkdef);
+
+ return (bus_generic_attach(sc->sc_dev));
+}
+
+static int
+ti_gate_detach(device_t dev)
+{
+ return (EBUSY);
+}
+
+static void
+ti_gate_new_pass(device_t dev) {
+ struct ti_gate_softc *sc;
+ int err;
+
+ sc = device_get_softc(dev);
+
+ if (sc->attach_done) {
+ return;
+ }
+
+ err = find_parent_clock_names(sc->sc_dev, &sc->clock_cell, &sc->gate_def.clkdef);
+ if (err) {
+ DPRINTF(sc->sc_dev, "new_pass find_parent_clock_names failed\n");
+ return;
+ }
+
+ err = register_clk(sc);
+ if (err) {
+ DPRINTF(sc->sc_dev, "new_pass register_clk failed\n");
+ return;
+ }
+
+ sc->attach_done = true;
+
+ free_clkdef(&sc->gate_def.clkdef);
+}
+
+static device_method_t ti_gate_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, ti_gate_probe),
+ DEVMETHOD(device_attach, ti_gate_attach),
+ DEVMETHOD(device_detach, ti_gate_detach),
+
+ /* Bus interface */
+ DEVMETHOD(bus_new_pass, ti_gate_new_pass),
+
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_0(ti_gate, ti_gate_driver, ti_gate_methods,
+ sizeof(struct ti_gate_softc));
+
+static devclass_t ti_gate_devclass;
+
+EARLY_DRIVER_MODULE(ti_gate, simplebus, ti_gate_driver,
+ ti_gate_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
+MODULE_VERSION(ti_gate, 1);
Index: sys/arm/ti/clk/ti_mux_clock.c
===================================================================
--- sys/arm/ti/clk/ti_mux_clock.c
+++ sys/arm/ti/clk/ti_mux_clock.c
@@ -0,0 +1,245 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se>
+ *
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/systm.h>
+#include <sys/libkern.h>
+#include <sys/types.h>
+#include <sys/malloc.h>
+
+#include <machine/bus.h>
+#include <dev/fdt/simplebus.h>
+
+#include <dev/extres/clk/clk_mux.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include "clock_common.h"
+
+#if 0
+#define DPRINTF(dev, msg...) device_printf(dev, msg)
+#else
+#define DPRINTF(dev, msg...)
+#endif
+
+/*
+ * Devicetree description
+ * Documentation/devicetree/bindings/clock/ti/mux.txt
+ */
+
+struct ti_mux_softc {
+ device_t sc_dev;
+ bool attach_done;
+
+ struct clk_mux_def mux_def;
+ struct clock_cell_info clock_cell;
+ struct clkdom *clkdom;
+};
+
+static int ti_mux_probe(device_t dev);
+static int ti_mux_attach(device_t dev);
+static int ti_mux_detach(device_t dev);
+
+#define TI_MUX_CLOCK 2
+#define TI_COMPOSITE_MUX_CLOCK 1
+#define TI_MUX_END 0
+
+static struct ofw_compat_data compat_data[] = {
+ { "ti,mux-clock", TI_MUX_CLOCK },
+ { "ti,composite-mux-clock", TI_COMPOSITE_MUX_CLOCK },
+ { NULL, TI_MUX_END }
+};
+
+static int
+ti_mux_probe(device_t dev)
+{
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "TI Mux Clock");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+register_clk(struct ti_mux_softc *sc) {
+ int err;
+
+ sc->clkdom = clkdom_create(sc->sc_dev);
+ if (sc->clkdom == NULL) {
+ DPRINTF(sc->sc_dev, "Failed to create clkdom\n");
+ return ENXIO;
+ }
+
+ err = clknode_mux_register(sc->clkdom, &sc->mux_def);
+ if (err) {
+ DPRINTF(sc->sc_dev, "clknode_mux_register failed %x\n", err);
+ return ENXIO;
+ }
+
+ err = clkdom_finit(sc->clkdom);
+ if (err) {
+ DPRINTF(sc->sc_dev, "Clk domain finit fails %x.\n", err);
+ return ENXIO;
+ }
+
+ return 0;
+}
+
+static int
+ti_mux_attach(device_t dev)
+{
+ struct ti_mux_softc *sc;
+ phandle_t node;
+ int err;
+ cell_t value;
+
+ sc = device_get_softc(dev);
+ sc->sc_dev = dev;
+ node = ofw_bus_get_node(dev);
+
+ /* Grab the content of reg properties */
+ OF_getencprop(node, "reg", &value, sizeof(value));
+ sc->mux_def.offset = value;
+
+ if (OF_hasprop(node, "ti,bit-shift")) {
+ OF_getencprop(node, "ti,bit-shift", &value, sizeof(value));
+ sc->mux_def.shift = value;
+ DPRINTF(sc->sc_dev, "ti,bit-shift => shift %x\n", sc->mux_def.shift);
+ }
+ if (OF_hasprop(node, "ti,index-starts-at-one")) {
+ /* FIXME: Add support in dev/extres/clk */
+ /*sc->mux_def.mux_flags = ... */
+ device_printf(sc->sc_dev, "ti,index-starts-at-one - Not implemented\n");
+ }
+
+ if (OF_hasprop(node, "ti,set-rate-parent"))
+ device_printf(sc->sc_dev, "ti,set-rate-parent - Not implemented\n");
+ if (OF_hasprop(node, "ti,latch-bit"))
+ device_printf(sc->sc_dev, "ti,latch-bit - Not implemented\n");
+
+ read_clock_cells(sc->sc_dev, &sc->clock_cell);
+
+ create_clkdef(sc->sc_dev, &sc->clock_cell, &sc->mux_def.clkdef);
+
+ /* Figure out the width from ti_max_div */
+ if (sc->mux_def.mux_flags)
+ sc->mux_def.width = fls(sc->clock_cell.num_real_clocks-1);
+ else
+ sc->mux_def.width = fls(sc->clock_cell.num_real_clocks);
+
+ DPRINTF(sc->sc_dev, "sc->clock_cell.num_real_clocks %x def.width %x\n",
+ sc->clock_cell.num_real_clocks, sc->mux_def.width);
+
+ err = find_parent_clock_names(sc->sc_dev, &sc->clock_cell, &sc->mux_def.clkdef);
+
+ if (err) {
+ DPRINTF(sc->sc_dev, "find_parent_clock_names failed\n");
+ return (bus_generic_attach(sc->sc_dev));
+ }
+
+ err = register_clk(sc);
+
+ if (err) {
+ DPRINTF(sc->sc_dev, "register_clk failed\n");
+ return (bus_generic_attach(sc->sc_dev));
+ }
+
+ sc->attach_done = true;
+
+ free_clkdef(&sc->mux_def.clkdef);
+
+ return (bus_generic_attach(sc->sc_dev));
+}
+
+static void
+ti_mux_new_pass(device_t dev)
+{
+ struct ti_mux_softc *sc;
+ int err;
+
+ sc = device_get_softc(dev);
+
+ if (sc->attach_done) {
+ return;
+ }
+
+ err = find_parent_clock_names(sc->sc_dev, &sc->clock_cell, &sc->mux_def.clkdef);
+ if (err) {
+ DPRINTF(sc->sc_dev, "ti_mux_new_pass find_parent_clock_names failed\n");
+ return;
+ }
+
+ err = register_clk(sc);
+ if (err) {
+ DPRINTF(sc->sc_dev, "ti_mux_new_pass register_clk failed\n");
+ return;
+ }
+
+ sc->attach_done = true;
+
+ free_clkdef(&sc->mux_def.clkdef);
+}
+
+static int
+ti_mux_detach(device_t dev)
+{
+ return (EBUSY);
+}
+
+static device_method_t ti_mux_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, ti_mux_probe),
+ DEVMETHOD(device_attach, ti_mux_attach),
+ DEVMETHOD(device_detach, ti_mux_detach),
+
+ /* Bus interface */
+ DEVMETHOD(bus_new_pass, ti_mux_new_pass),
+
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_0(ti_mux, ti_mux_driver, ti_mux_methods,
+ sizeof(struct ti_mux_softc));
+
+static devclass_t ti_mux_devclass;
+
+EARLY_DRIVER_MODULE(ti_mux, simplebus, ti_mux_driver,
+ ti_mux_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
+MODULE_VERSION(ti_mux, 1);
Index: sys/arm/ti/cpsw/if_cpsw.c
===================================================================
--- sys/arm/ti/cpsw/if_cpsw.c
+++ sys/arm/ti/cpsw/if_cpsw.c
@@ -74,7 +74,8 @@
#include <net/if_media.h>
#include <net/if_types.h>
-#include <arm/ti/ti_scm.h>
+#include <dev/extres/syscon/syscon.h>
+#include "syscon_if.h"
#include <arm/ti/am335x/am335x_scm.h>
#include <dev/mii/mii.h>
@@ -1004,6 +1005,8 @@
struct cpswp_softc *sc;
uint32_t reg;
uint8_t mac_addr[ETHER_ADDR_LEN];
+ phandle_t opp_table;
+ struct syscon *syscon;
sc = device_get_softc(dev);
sc->dev = dev;
@@ -1047,15 +1050,34 @@
IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen);
IFQ_SET_READY(&ifp->if_snd);
+ /* FIXME: For now; Go and kidnap syscon from opp-table */
+ /* ti,cpsw actually have an optional syscon reference but only for am33xx?? */
+ opp_table = OF_finddevice("/opp-table");
+ if (opp_table == -1) {
+ device_printf(dev, "Cant find /opp-table\n");
+ cpswp_detach(dev);
+ return (ENXIO);
+ }
+ if (!OF_hasprop(opp_table, "syscon")) {
+ device_printf(dev, "/opp-table doesnt have required syscon property\n");
+ cpswp_detach(dev);
+ return (ENXIO);
+ }
+ if (syscon_get_by_ofw_property(dev, opp_table, "syscon", &syscon) != 0) {
+ device_printf(dev, "Failed to get syscon\n");
+ cpswp_detach(dev);
+ return (ENXIO);
+ }
+
/* Get high part of MAC address from control module (mac_id[0|1]_hi) */
- ti_scm_reg_read_4(SCM_MAC_ID0_HI + sc->unit * 8, ®);
+ reg = SYSCON_READ_4(syscon, SCM_MAC_ID0_HI + sc->unit * 8);
mac_addr[0] = reg & 0xFF;
mac_addr[1] = (reg >> 8) & 0xFF;
mac_addr[2] = (reg >> 16) & 0xFF;
mac_addr[3] = (reg >> 24) & 0xFF;
/* Get low part of MAC address from control module (mac_id[0|1]_lo) */
- ti_scm_reg_read_4(SCM_MAC_ID0_LO + sc->unit * 8, ®);
+ reg = SYSCON_READ_4(syscon, SCM_MAC_ID0_LO + sc->unit * 8);
mac_addr[4] = reg & 0xFF;
mac_addr[5] = (reg >> 8) & 0xFF;
Index: sys/arm/ti/files.ti
===================================================================
--- sys/arm/ti/files.ti
+++ sys/arm/ti/files.ti
@@ -1,10 +1,11 @@
#$FreeBSD$
arm/ti/ti_cpuid.c standard
-arm/ti/ti_hwmods.c standard
arm/ti/ti_machdep.c standard
arm/ti/ti_prcm.c standard
+arm/ti/ti_omap4_cm.c standard
arm/ti/ti_scm.c standard
+arm/ti/ti_scm_syscon.c standard
arm/ti/ti_pinmux.c standard
dev/mbox/mbox_if.m optional ti_mbox
arm/ti/ti_mbox.c optional ti_mbox
@@ -17,6 +18,15 @@
arm/ti/ti_sdhci.c optional sdhci
arm/ti/ti_spi.c optional ti_spi
arm/ti/ti_sysc.c standard
+
+arm/ti/clk/clock_common.c standard
+arm/ti/clk/ti_clk_clkctrl.c standard
+arm/ti/clk/ti_clkctrl.c standard
+arm/ti/clk/ti_clk_dpll.c standard
+arm/ti/clk/ti_dpll_clock.c standard
+arm/ti/clk/ti_mux_clock.c standard
+arm/ti/clk/ti_divider_clock.c standard
+arm/ti/clk/ti_gate_clock.c standard
dev/uart/uart_dev_ti8250.c optional uart
dev/uart/uart_dev_ns8250.c optional uart
Index: sys/arm/ti/omap4/files.omap4
===================================================================
--- sys/arm/ti/omap4/files.omap4
+++ sys/arm/ti/omap4/files.omap4
@@ -9,7 +9,7 @@
arm/ti/omap4/omap4_gpio.c optional gpio
arm/ti/omap4/omap4_l2cache.c optional pl310
-arm/ti/omap4/omap4_prcm_clks.c standard
+#arm/ti/omap4/omap4_prcm_clks.c standard
arm/ti/omap4/omap4_scm_padconf.c standard
arm/ti/omap4/omap4_mp.c optional smp
arm/ti/omap4/omap4_wugen.c standard
Index: sys/arm/ti/ti_adc.c
===================================================================
--- sys/arm/ti/ti_adc.c
+++ sys/arm/ti/ti_adc.c
@@ -58,7 +58,7 @@
#include <dev/evdev/evdev.h>
#endif
-#include <arm/ti/ti_prcm.h>
+#include <arm/ti/ti_sysc.h>
#include <arm/ti/ti_adcreg.h>
#include <arm/ti/ti_adcvar.h>
@@ -824,7 +824,7 @@
}
/* Activate the ADC_TSC module. */
- err = ti_prcm_clk_enable(TSC_ADC_CLK);
+ err = ti_sysc_clock_enable(device_get_parent(dev));
if (err)
return (err);
@@ -846,7 +846,7 @@
}
/* Check the ADC revision. */
- rev = ADC_READ4(sc, ADC_REVISION);
+ rev = ADC_READ4(sc, ti_sysc_get_rev_address_offset_host(device_get_parent(dev)));
device_printf(dev,
"scheme: %#x func: %#x rtl: %d rev: %d.%d custom rev: %d\n",
(rev & ADC_REV_SCHEME_MSK) >> ADC_REV_SCHEME_SHIFT,
@@ -964,6 +964,7 @@
DRIVER_MODULE(ti_adc, simplebus, ti_adc_driver, ti_adc_devclass, 0, 0);
MODULE_VERSION(ti_adc, 1);
MODULE_DEPEND(ti_adc, simplebus, 1, 1, 1);
+MODULE_DEPEND(ti_adc, ti_sysc, 1, 1, 1);
#ifdef EVDEV_SUPPORT
MODULE_DEPEND(ti_adc, evdev, 1, 1, 1);
#endif
Index: sys/arm/ti/ti_edma3.c
===================================================================
--- sys/arm/ti/ti_edma3.c
+++ sys/arm/ti/ti_edma3.c
@@ -54,7 +54,7 @@
#include <dev/ofw/ofw_bus_subr.h>
#include <arm/ti/ti_scm.h>
-#include <arm/ti/ti_prcm.h>
+#include <arm/ti/ti_sysc.h>
#include <arm/ti/ti_edma3.h>
@@ -181,8 +181,10 @@
return (ENXIO);
}
+ /* FIXME: Require DTS from Linux kernel 5.7 */
+ /* FIXME: OK to enable clkctrl here? */
/* Enable Channel Controller */
- ti_prcm_clk_enable(EDMA_TPCC_CLK);
+ ti_sysc_clock_enable(device_get_parent(dev));
reg = ti_edma3_cc_rd_4(TI_EDMA3CC_PID);
@@ -218,7 +220,7 @@
static devclass_t ti_edma3_devclass;
DRIVER_MODULE(ti_edma3, simplebus, ti_edma3_driver, ti_edma3_devclass, 0, 0);
-MODULE_DEPEND(ti_edma3, ti_prcm, 1, 1, 1);
+MODULE_DEPEND(ti_edma3, ti_sysc, 1, 1, 1);
static void
ti_edma3_intr_comp(void *arg)
@@ -243,11 +245,6 @@
{
uint32_t reg;
int i;
-
- /* on AM335x Event queue 0 is always mapped to Transfer Controller 0,
- * event queue 1 to TC2, etc. So we are asking PRCM to power on specific
- * TC based on what event queue we need to initialize */
- ti_prcm_clk_enable(EDMA_TPTC0_CLK + eqn);
/* Clear Event Missed Regs */
ti_edma3_cc_wr_4(TI_EDMA3CC_EMCR, 0xFFFFFFFF);
Index: sys/arm/ti/ti_gpio.c
===================================================================
--- sys/arm/ti/ti_gpio.c
+++ sys/arm/ti/ti_gpio.c
@@ -57,8 +57,7 @@
#include <arm/ti/ti_cpuid.h>
#include <arm/ti/ti_gpio.h>
#include <arm/ti/ti_scm.h>
-#include <arm/ti/ti_prcm.h>
-#include <arm/ti/ti_hwmods.h>
+#include <arm/ti/ti_sysc.h>
#include <dev/gpio/gpiobusvar.h>
#include <dev/ofw/openfirm.h>
@@ -117,6 +116,18 @@
#define PINS_PER_BANK 32
#define TI_GPIO_MASK(p) (1U << ((p) % PINS_PER_BANK))
+#define OMAP4_GPIO1_REV 0x00000
+#define OMAP4_GPIO2_REV 0x55000
+#define OMAP4_GPIO3_REV 0x57000
+#define OMAP4_GPIO4_REV 0x59000
+#define OMAP4_GPIO5_REV 0x5b000
+#define OMAP4_GPIO6_REV 0x5d000
+
+#define AM335X_GPIO0_REV 0x07000
+#define AM335X_GPIO1_REV 0x4C000
+#define AM335X_GPIO2_REV 0xAC000
+#define AM335X_GPIO3_REV 0xAE000
+
static int ti_gpio_intr(void *arg);
static int ti_gpio_detach(device_t);
@@ -553,29 +564,72 @@
static int
ti_gpio_bank_init(device_t dev)
{
- int pin;
+ int pin, err;
struct ti_gpio_softc *sc;
uint32_t flags, reg_oe, reg_set, rev;
- clk_ident_t clk;
+ uint64_t rev_address;
sc = device_get_softc(dev);
/* Enable the interface and functional clocks for the module. */
- clk = ti_hwmods_get_clock(dev);
- if (clk == INVALID_CLK_IDENT) {
- device_printf(dev, "failed to get device id based on ti,hwmods\n");
+ rev_address = ti_sysc_get_rev_address(device_get_parent(dev));
+ /* AM335x
+ * sc->sc_bank used in am335x/am335x_gpio.c and omap4/omap4_gpio.c */
+ switch(ti_chip()) {
+#ifdef SOC_OMAP4
+ case CHIP_OMAP_4:
+ switch (rev_address) {
+ case OMAP4_GPIO1_REV:
+ sc->sc_bank = 0;
+ break;
+ case OMAP4_GPIO2_REV:
+ sc->sc_bank = 1;
+ break;
+ case OMAP4_GPIO3_REV:
+ sc->sc_bank = 2;
+ break;
+ case OMAP4_GPIO4_REV:
+ sc->sc_bank = 3;
+ break;
+ case OMAP4_GPIO5_REV:
+ sc->sc_bank = 4;
+ break;
+ case OMAP4_GPIO6_REV:
+ sc->sc_bank = 5;
+ break;
+ }
+#endif
+#ifdef SOC_TI_AM335X
+ case CHIP_AM335X:
+ switch (rev_address) {
+ case AM335X_GPIO0_REV:
+ sc->sc_bank = 0;
+ break;
+ case AM335X_GPIO1_REV:
+ sc->sc_bank = 1;
+ break;
+ case AM335X_GPIO2_REV:
+ sc->sc_bank = 2;
+ break;
+ case AM335X_GPIO3_REV:
+ sc->sc_bank = 3;
+ break;
+ }
+#endif
+ }
+ err = ti_sysc_clock_enable(device_get_parent(dev));
+ if (err) {
+ device_printf(dev, "Failed to enable clock\n");
return (EINVAL);
}
- sc->sc_bank = clk - GPIO1_CLK + ti_first_gpio_bank();
- ti_prcm_clk_enable(clk);
-
/*
* Read the revision number of the module. TI don't publish the
* actual revision numbers, so instead the values have been
* determined by experimentation.
*/
- rev = ti_gpio_read_4(sc, TI_GPIO_REVISION);
+ rev = ti_gpio_read_4(sc,
+ ti_sysc_get_rev_address_offset_host(device_get_parent(dev)));
/* Check the revision. */
if (rev != ti_gpio_rev()) {
Index: sys/arm/ti/ti_hwmods.h
===================================================================
--- sys/arm/ti/ti_hwmods.h
+++ sys/arm/ti/ti_hwmods.h
@@ -1,37 +0,0 @@
-/*-
- * Copyright (c) 2015 Oleksandr Tymoshenko <gonzo@freebsd.org>
- * 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.
- *
- * $FreeBSD$
- */
-#ifndef _TI_HWMODS_H_
-#define _TI_HWMODS_H_
-
-clk_ident_t ti_hwmods_get_clock(device_t dev);
-int ti_hwmods_contains(device_t dev, const char *hwmod);
-
-/* Returns the N from "hwmodN" in the ti,hwmods property; 0 on failure. */
-int ti_hwmods_get_unit(device_t dev, const char *hwmod);
-
-#endif /* _TI_HWMODS_H_ */
Index: sys/arm/ti/ti_hwmods.c
===================================================================
--- sys/arm/ti/ti_hwmods.c
+++ sys/arm/ti/ti_hwmods.c
@@ -1,214 +0,0 @@
-/*-
- * Copyright (c) 2015 Oleksandr Tymoshenko <gonzo@freebsd.org>
- * 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.
- *
- * $FreeBSD$
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/bus.h>
-#include <sys/kernel.h>
-
-#include <dev/ofw/openfirm.h>
-#include <dev/ofw/ofw_bus.h>
-#include <dev/ofw/ofw_bus_subr.h>
-
-#include <machine/bus.h>
-#include <machine/fdt.h>
-
-#include <arm/ti/ti_prcm.h>
-#include <arm/ti/ti_hwmods.h>
-
-struct hwmod {
- const char *name;
- int clock_id;
-};
-
-struct hwmod ti_hwmods[] = {
- {"i2c1", I2C1_CLK},
- {"i2c2", I2C2_CLK},
- {"i2c3", I2C3_CLK},
- {"i2c4", I2C4_CLK},
- {"i2c5", I2C5_CLK},
-
- {"gpio1", GPIO1_CLK},
- {"gpio2", GPIO2_CLK},
- {"gpio3", GPIO3_CLK},
- {"gpio4", GPIO4_CLK},
- {"gpio5", GPIO5_CLK},
- {"gpio6", GPIO6_CLK},
- {"gpio7", GPIO7_CLK},
-
- {"mmc1", MMC1_CLK},
- {"mmc2", MMC2_CLK},
- {"mmc3", MMC3_CLK},
- {"mmc4", MMC4_CLK},
- {"mmc5", MMC5_CLK},
- {"mmc6", MMC6_CLK},
-
- {"epwmss0", PWMSS0_CLK},
- {"epwmss1", PWMSS1_CLK},
- {"epwmss2", PWMSS2_CLK},
-
- {"spi0", SPI0_CLK},
- {"spi1", SPI1_CLK},
-
- {"timer1", TIMER1_CLK},
- {"timer2", TIMER2_CLK},
- {"timer3", TIMER3_CLK},
- {"timer4", TIMER4_CLK},
- {"timer5", TIMER5_CLK},
- {"timer6", TIMER6_CLK},
- {"timer7", TIMER7_CLK},
-
- {"uart1", UART1_CLK},
- {"uart2", UART2_CLK},
- {"uart3", UART3_CLK},
- {"uart4", UART4_CLK},
- {"uart5", UART5_CLK},
- {"uart6", UART6_CLK},
- {"uart7", UART7_CLK},
-
- {NULL, 0}
-};
-
-static inline int
-ti_get_hwmods_prop(phandle_t node, void **name)
-{
- int len;
-
- if ((len = OF_getprop_alloc(node, "ti,hwmods", name)) > 0)
- return (len);
- return (OF_getprop_alloc(OF_parent(node), "ti,hwmods", name));
-}
-
-clk_ident_t
-ti_hwmods_get_clock(device_t dev)
-{
- phandle_t node;
- int len, l;
- char *name;
- char *buf;
- int clk;
- struct hwmod *hw;
-
- if ((node = ofw_bus_get_node(dev)) == 0)
- return (INVALID_CLK_IDENT);
-
- if ((len = ti_get_hwmods_prop(node, (void **)&name)) <= 0)
- return (INVALID_CLK_IDENT);
-
- buf = name;
-
- clk = INVALID_CLK_IDENT;
- while ((len > 0) && (clk == INVALID_CLK_IDENT)) {
- for (hw = ti_hwmods; hw->name != NULL; ++hw) {
- if (strcmp(hw->name, name) == 0) {
- clk = hw->clock_id;
- break;
- }
- }
-
- /* Slide to the next sub-string. */
- l = strlen(name) + 1;
- name += l;
- len -= l;
- }
-
- if (len > 0)
- device_printf(dev, "WARNING: more than one ti,hwmod \n");
-
- OF_prop_free(buf);
- return (clk);
-}
-
-int ti_hwmods_contains(device_t dev, const char *hwmod)
-{
- phandle_t node;
- int len, l;
- char *name;
- char *buf;
- int result;
-
- if ((node = ofw_bus_get_node(dev)) == 0)
- return (0);
-
- if ((len = ti_get_hwmods_prop(node, (void **)&name)) <= 0)
- return (0);
-
- buf = name;
-
- result = 0;
- while (len > 0) {
- if (strcmp(name, hwmod) == 0) {
- result = 1;
- break;
- }
-
- /* Slide to the next sub-string. */
- l = strlen(name) + 1;
- name += l;
- len -= l;
- }
-
- OF_prop_free(buf);
-
- return (result);
-}
-
-int
-ti_hwmods_get_unit(device_t dev, const char *hwmod)
-{
- phandle_t node;
- int l, len, hwmodlen, result;
- char *name;
- char *buf;
-
- if ((node = ofw_bus_get_node(dev)) == 0)
- return (0);
-
- if ((len = ti_get_hwmods_prop(node, (void **)&name)) <= 0)
- return (0);
-
- buf = name;
- hwmodlen = strlen(hwmod);
- result = 0;
- while (len > 0) {
- if (strncmp(name, hwmod, hwmodlen) == 0) {
- result = (int)strtoul(name + hwmodlen, NULL, 10);
- break;
- }
- /* Slide to the next sub-string. */
- l = strlen(name) + 1;
- name += l;
- len -= l;
- }
-
- OF_prop_free(buf);
- return (result);
-}
Index: sys/arm/ti/ti_i2c.c
===================================================================
--- sys/arm/ti/ti_i2c.c
+++ sys/arm/ti/ti_i2c.c
@@ -63,8 +63,7 @@
#include <dev/ofw/ofw_bus_subr.h>
#include <arm/ti/ti_cpuid.h>
-#include <arm/ti/ti_prcm.h>
-#include <arm/ti/ti_hwmods.h>
+#include <arm/ti/ti_sysc.h>
#include <arm/ti/ti_i2c.h>
#include <dev/iicbus/iiconf.h>
@@ -79,7 +78,6 @@
struct ti_i2c_softc
{
device_t sc_dev;
- clk_ident_t clk_id;
struct resource* sc_irq_res;
struct resource* sc_mem_res;
device_t sc_iicbus;
@@ -700,7 +698,7 @@
* 1. Enable the functional and interface clocks (see Section
* 23.1.5.1.1.1.1).
*/
- err = ti_prcm_clk_enable(sc->clk_id);
+ err = ti_sysc_clock_enable(device_get_parent(dev));
if (err)
return (err);
@@ -748,7 +746,7 @@
}
/* Finally disable the functional and interface clocks. */
- ti_prcm_clk_disable(sc->clk_id);
+ ti_sysc_clock_disable(device_get_parent(dev));
}
static int
@@ -818,7 +816,6 @@
ti_i2c_attach(device_t dev)
{
int err, rid;
- phandle_t node;
struct ti_i2c_softc *sc;
struct sysctl_ctx_list *ctx;
struct sysctl_oid_list *tree;
@@ -827,15 +824,6 @@
sc = device_get_softc(dev);
sc->sc_dev = dev;
- /* Get the i2c device id from FDT. */
- node = ofw_bus_get_node(dev);
- /* i2c ti,hwmods bindings is special: it start with index 1 */
- sc->clk_id = ti_hwmods_get_clock(dev);
- if (sc->clk_id == INVALID_CLK_IDENT) {
- device_printf(dev, "failed to get device id using ti,hwmod\n");
- return (ENXIO);
- }
-
/* Get the memory resource for the register mapping. */
rid = 0;
sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
@@ -986,5 +974,5 @@
DRIVER_MODULE(ti_iic, simplebus, ti_i2c_driver, ti_i2c_devclass, 0, 0);
DRIVER_MODULE(iicbus, ti_iic, iicbus_driver, iicbus_devclass, 0, 0);
-MODULE_DEPEND(ti_iic, ti_prcm, 1, 1, 1);
+MODULE_DEPEND(ti_iic, ti_sysc, 1, 1, 1);
MODULE_DEPEND(ti_iic, iicbus, 1, 1, 1);
Index: sys/arm/ti/ti_mbox.c
===================================================================
--- sys/arm/ti/ti_mbox.c
+++ sys/arm/ti/ti_mbox.c
@@ -50,7 +50,7 @@
#include <machine/bus.h>
#include <arm/ti/ti_mbox.h>
-#include <arm/ti/ti_prcm.h>
+#include <arm/ti/ti_sysc.h>
#include "mbox_if.h"
@@ -102,6 +102,7 @@
static devclass_t ti_mbox_devclass;
DRIVER_MODULE(ti_mbox, simplebus, ti_mbox_driver, ti_mbox_devclass, 0, 0);
+MODULE_DEPEND(ti_mbox, ti_sysc, 1, 1, 1);
static __inline uint32_t
ti_mbox_reg_read(struct ti_mbox_softc *sc, uint16_t reg)
@@ -137,10 +138,11 @@
int rid, delay, chan;
uint32_t rev, sysconfig;
- if (ti_prcm_clk_enable(MAILBOX0_CLK) != 0) {
+ if (ti_sysc_clock_enable(device_get_parent(dev)) != 0) {
device_printf(dev, "could not enable MBOX clock\n");
return (ENXIO);
}
+
sc = device_get_softc(dev);
rid = 0;
mtx_init(&sc->sc_mtx, "TI mbox", NULL, MTX_DEF);
@@ -188,7 +190,8 @@
*/
ti_mbox_reg_write(sc, TI_MBOX_SYSCONFIG,
ti_mbox_reg_read(sc, TI_MBOX_SYSCONFIG) | TI_MBOX_SYSCONFIG_SMARTIDLE);
- rev = ti_mbox_reg_read(sc, TI_MBOX_REVISION);
+ rev = ti_mbox_reg_read(sc,
+ ti_sysc_get_rev_address_offset_host(device_get_parent(dev)));
DPRINTF("rev %d\n", rev);
device_printf(dev, "revision %d.%d\n", (rev >> 8) & 0x4, rev & 0x40);
/*
Index: sys/arm/ti/ti_omap4_cm.h
===================================================================
--- sys/arm/ti/ti_omap4_cm.h
+++ sys/arm/ti/ti_omap4_cm.h
@@ -0,0 +1,34 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se>
+ *
+ * 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.
+ *
+ * $FreeBSD$
+ */
+#ifndef __TI_OMAP4_CM__
+#define __TI_OMAP4_CM__
+
+uint64_t ti_omap4_cm_get_simplebus_base_host(device_t dev);
+
+#endif /* __TI_OMAP4_CM__ */
Index: sys/arm/ti/ti_omap4_cm.c
===================================================================
--- sys/arm/ti/ti_omap4_cm.c
+++ sys/arm/ti/ti_omap4_cm.c
@@ -0,0 +1,151 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2019 Emmanuel Vadot <manu@FreeBSD.org>
+ * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se>
+ *
+ * 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.
+ *
+ * Based on sys/arm/ti/ti_sysc.c
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/fbio.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/resource.h>
+#include <machine/bus.h>
+#include <vm/vm.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_kern.h>
+#include <vm/pmap.h>
+
+#include <dev/fdt/simplebus.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <arm/ti/ti_omap4_cm.h>
+
+static struct ofw_compat_data compat_data[] = {
+ { "ti,omap4-cm", 1 },
+ { NULL, 0 }
+};
+
+struct ti_omap4_cm_softc {
+ struct simplebus_softc sc;
+ device_t dev;
+};
+
+uint64_t
+ti_omap4_cm_get_simplebus_base_host(device_t dev) {
+ struct ti_omap4_cm_softc *sc;
+
+ sc = device_get_softc(dev);
+ if (sc->sc.nranges == 0)
+ return (0);
+
+ return (sc->sc.ranges[0].host);
+}
+
+static int ti_omap4_cm_probe(device_t dev);
+static int ti_omap4_cm_attach(device_t dev);
+static int ti_omap4_cm_detach(device_t dev);
+
+static int
+ti_omap4_cm_probe(device_t dev)
+{
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "TI OMAP4-CM");
+ if (!bootverbose)
+ device_quiet(dev);
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+ti_omap4_cm_attach(device_t dev)
+{
+ struct ti_omap4_cm_softc *sc;
+ device_t cdev;
+ phandle_t node, child;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+ node = ofw_bus_get_node(dev);
+
+ simplebus_init(dev, node);
+ if (simplebus_fill_ranges(node, &sc->sc) < 0) {
+ device_printf(dev, "could not get ranges\n");
+ return (ENXIO);
+ }
+
+ bus_generic_probe(sc->dev);
+
+ for (child = OF_child(node); child > 0; child = OF_peer(child)) {
+ cdev = simplebus_add_device(dev, child, 0, NULL, -1, NULL);
+ if (cdev != NULL)
+ device_probe_and_attach(cdev);
+ }
+
+ return (bus_generic_attach(dev));
+}
+
+static int
+ti_omap4_cm_detach(device_t dev)
+{
+ return (EBUSY);
+}
+
+static device_method_t ti_omap4_cm_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, ti_omap4_cm_probe),
+ DEVMETHOD(device_attach, ti_omap4_cm_attach),
+ DEVMETHOD(device_detach, ti_omap4_cm_detach),
+
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_1(ti_omap4_cm, ti_omap4_cm_driver, ti_omap4_cm_methods,
+ sizeof(struct ti_omap4_cm_softc), simplebus_driver);
+
+static devclass_t ti_omap4_cm_devclass;
+
+EARLY_DRIVER_MODULE(ti_omap4_cm, simplebus, ti_omap4_cm_driver,
+ti_omap4_cm_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_FIRST);
+
+EARLY_DRIVER_MODULE(ti_omap4_cm, ofwbus, ti_omap4_cm_driver,
+ti_omap4_cm_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_FIRST);
+
Index: sys/arm/ti/ti_pinmux.c
===================================================================
--- sys/arm/ti/ti_pinmux.c
+++ sys/arm/ti/ti_pinmux.c
@@ -459,3 +459,5 @@
static devclass_t ti_pinmux_devclass;
DRIVER_MODULE(ti_pinmux, simplebus, ti_pinmux_driver, ti_pinmux_devclass, 0, 0);
+MODULE_VERSION(ti_pinmux, 1);
+MODULE_DEPEND(ti_pinmux, ti_scm, 1, 1, 1);
Index: sys/arm/ti/ti_prcm.h
===================================================================
--- sys/arm/ti/ti_prcm.h
+++ sys/arm/ti/ti_prcm.h
@@ -1,209 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-4-Clause
- *
- * Copyright (c) 2010
- * Ben Gray <ben.r.gray@gmail.com>.
- * 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.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Ben Gray.
- * 4. The name of the company nor the name of the author may be used to
- * endorse or promote products derived from this software without specific
- * prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY BEN GRAY ``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 BEN GRAY 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.
- *
- * $FreeBSD$
- */
-
-
-/*
- * Texas Instruments - OMAP3xxx series processors
- *
- * Reference:
- * OMAP35x Applications Processor
- * Technical Reference Manual
- * (omap35xx_techref.pdf)
- */
-#ifndef _TI_PRCM_H_
-#define _TI_PRCM_H_
-
-typedef enum {
-
- INVALID_CLK_IDENT = 0,
-
- /* System clocks, typically you can only call ti_prcm_clk_get_source_freq()
- * on these clocks as they are enabled by default.
- */
- SYS_CLK = 1,
-
- /* The MPU (ARM) core clock */
- MPU_CLK = 20,
-
- /* MMC modules */
- MMC1_CLK = 100,
- MMC2_CLK,
- MMC3_CLK,
- MMC4_CLK,
- MMC5_CLK,
- MMC6_CLK,
-
- /* I2C modules */
- I2C1_CLK = 200,
- I2C2_CLK,
- I2C3_CLK,
- I2C4_CLK,
- I2C5_CLK,
-
- /* USB module(s) */
- USBTLL_CLK = 300,
- USBHSHOST_CLK,
- USBFSHOST_CLK,
- USBP1_PHY_CLK,
- USBP2_PHY_CLK,
- USBP1_UTMI_CLK,
- USBP2_UTMI_CLK,
- USBP1_HSIC_CLK,
- USBP2_HSIC_CLK,
-
- /* UART modules */
- UART1_CLK = 400,
- UART2_CLK,
- UART3_CLK,
- UART4_CLK,
- UART5_CLK,
- UART6_CLK,
- UART7_CLK,
- UART8_CLK,
- UART9_CLK,
-
- /* General purpose timer modules */
- TIMER1_CLK = 500,
- TIMER2_CLK,
- TIMER3_CLK,
- TIMER4_CLK,
- TIMER5_CLK,
- TIMER6_CLK,
- TIMER7_CLK,
- TIMER8_CLK,
- TIMER9_CLK,
- TIMER10_CLK,
- TIMER11_CLK,
- TIMER12_CLK,
-
- /* McBSP module(s) */
- MCBSP1_CLK = 600,
- MCBSP2_CLK,
- MCBSP3_CLK,
- MCBSP4_CLK,
- MCBSP5_CLK,
-
- /* General purpose I/O modules */
- GPIO1_CLK = 700,
- GPIO2_CLK,
- GPIO3_CLK,
- GPIO4_CLK,
- GPIO5_CLK,
- GPIO6_CLK,
- GPIO7_CLK,
-
- /* sDMA module */
- SDMA_CLK = 800,
-
- /* CPSW modules */
- CPSW_CLK = 1000,
-
- /* Mentor USB modules */
- MUSB0_CLK = 1100,
-
- /* EDMA module */
- EDMA_TPCC_CLK = 1200,
- EDMA_TPTC0_CLK,
- EDMA_TPTC1_CLK,
- EDMA_TPTC2_CLK,
-
- /* LCD controller module */
- LCDC_CLK = 1300,
-
- /* PWM modules */
- PWMSS0_CLK = 1400,
- PWMSS1_CLK,
- PWMSS2_CLK,
-
- /* Mailbox modules */
- MAILBOX0_CLK = 1500,
-
- /* Spinlock modules */
- SPINLOCK0_CLK = 1600,
-
- PRUSS_CLK = 1700,
-
- TSC_ADC_CLK = 1800,
-
- /* RTC module */
- RTC_CLK = 1900,
-
- /* McSPI */
- SPI0_CLK = 2000,
- SPI1_CLK,
-} clk_ident_t;
-
-/*
- *
- */
-typedef enum {
- SYSCLK_CLK, /* System clock */
- EXT_CLK,
-
- F32KHZ_CLK, /* 32KHz clock */
- F48MHZ_CLK, /* 48MHz clock */
- F64MHZ_CLK, /* 64MHz clock */
- F96MHZ_CLK, /* 96MHz clock */
-
-} clk_src_t;
-
-struct ti_clock_dev {
- /* The profile of the timer */
- clk_ident_t id;
-
- /* A bunch of callbacks associated with the clock device */
- int (*clk_activate)(struct ti_clock_dev *clkdev);
- int (*clk_deactivate)(struct ti_clock_dev *clkdev);
- int (*clk_set_source)(struct ti_clock_dev *clkdev,
- clk_src_t clksrc);
- int (*clk_accessible)(struct ti_clock_dev *clkdev);
- int (*clk_set_source_freq)(struct ti_clock_dev *clkdev,
- unsigned int freq);
- int (*clk_get_source_freq)(struct ti_clock_dev *clkdev,
- unsigned int *freq);
-};
-
-int ti_prcm_clk_valid(clk_ident_t clk);
-int ti_prcm_clk_enable(clk_ident_t clk);
-int ti_prcm_clk_disable(clk_ident_t clk);
-int ti_prcm_clk_accessible(clk_ident_t clk);
-int ti_prcm_clk_disable_autoidle(clk_ident_t clk);
-int ti_prcm_clk_set_source(clk_ident_t clk, clk_src_t clksrc);
-int ti_prcm_clk_set_source_freq(clk_ident_t clk, unsigned int freq);
-int ti_prcm_clk_get_source_freq(clk_ident_t clk, unsigned int *freq);
-void ti_prcm_reset(void);
-
-#endif /* _TI_PRCM_H_ */
Index: sys/arm/ti/ti_prcm.c
===================================================================
--- sys/arm/ti/ti_prcm.c
+++ sys/arm/ti/ti_prcm.c
@@ -1,10 +1,11 @@
/*-
- * SPDX-License-Identifier: BSD-4-Clause
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
- * Copyright (c) 2010
- * Ben Gray <ben.r.gray@gmail.com>.
+ * Copyright (c) 2012 Damjan Marion <dmarion@Freebsd.org>
* All rights reserved.
*
+ * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se>
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -13,345 +14,335 @@
* 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.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Ben Gray.
- * 4. The name of the company nor the name of the author may be used to
- * endorse or promote products derived from this software without specific
- * prior written permission.
*
- * THIS SOFTWARE IS PROVIDED BY BEN GRAY ``AS IS'' AND ANY EXPRESS OR
+ * 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 BEN GRAY 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.
- */
-
-/**
- * Power, Reset and Clock Management Module
+ * 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.
*
- * This is a very simple driver wrapper around the PRCM set of registers in
- * the OMAP3 chip. It allows you to turn on and off things like the functional
- * and interface clocks to the various on-chip modules.
- *
+ * $FreeBSD$
*/
+
+/* Based on sys/arm/ti/am335x/am335x_prcm.c */
+
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
-#include <sys/bus.h>
-#include <sys/resource.h>
+#include <sys/malloc.h>
#include <sys/rman.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
-
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
#include <machine/bus.h>
-#include <machine/resource.h>
+#include <machine/cpu.h>
#include <machine/intr.h>
#include <arm/ti/ti_cpuid.h>
-#include <arm/ti/ti_prcm.h>
+#include <arm/ti/tivar.h>
-/**
- * ti_*_clk_devmap - Array of clock devices, should be defined one per SoC
- *
- * This array is typically defined in one of the targeted *_prcm_clk.c
- * files and is specific to the given SoC platform. Each entry in the array
- * corresponds to an individual clock device.
- */
-extern struct ti_clock_dev ti_omap4_clk_devmap[];
-extern struct ti_clock_dev ti_am335x_clk_devmap[];
+#include <dev/fdt/simplebus.h>
-/**
- * ti_prcm_clk_dev - returns a pointer to the clock device with given id
- * @clk: the ID of the clock device to get
- *
- * Simply iterates through the clk_devmap global array and returns a pointer
- * to the clock device if found.
- *
- * LOCKING:
- * None
- *
- * RETURNS:
- * The pointer to the clock device on success, on failure NULL is returned.
- */
-static struct ti_clock_dev *
-ti_prcm_clk_dev(clk_ident_t clk)
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include "clkdev_if.h"
+
+#if 0
+#define DPRINTF(dev, msg...) device_printf(dev, msg)
+#else
+#define DPRINTF(dev, msg...)
+#endif
+
+struct ti_prcm_softc {
+ struct simplebus_softc sc_simplebus;
+ device_t dev;
+ struct resource * mem_res;
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+ int attach_done;
+ struct mtx mtx;
+};
+
+static struct ti_prcm_softc *ti_prcm_sc = NULL;
+static void omap4_prcm_reset(void);
+static void am335x_prcm_reset(void);
+static int ti_prcm_write_4(device_t dev, bus_addr_t addr, uint32_t val);
+static int ti_prcm_read_4(device_t dev, bus_addr_t addr, uint32_t *val);
+static void ti_prcm_device_lock(device_t dev);
+static void ti_prcm_device_unlock(device_t dev);
+
+#define TI_AM3_PRCM 18
+#define TI_AM4_PRCM 17
+#define TI_OMAP2_PRCM 16
+#define TI_OMAP3_PRM 15
+#define TI_OMAP3_CM 14
+#define TI_OMAP4_CM1 13
+#define TI_OMAP4_PRM 12
+#define TI_OMAP4_CM2 11
+#define TI_OMAP4_SCRM 10
+#define TI_OMAP5_PRM 9
+#define TI_OMAP5_CM_CORE_AON 8
+#define TI_OMAP5_SCRM 7
+#define TI_OMAP5_CM_CORE 6
+#define TI_DRA7_PRM 5
+#define TI_DRA7_CM_CORE_AON 4
+#define TI_DRA7_CM_CORE 3
+#define TI_DM814_PRCM 2
+#define TI_DM816_PRCM 1
+#define TI_PRCM_END 0
+
+static struct ofw_compat_data compat_data[] = {
+ { "ti,am3-prcm", TI_AM3_PRCM },
+ { "ti,am4-prcm", TI_AM4_PRCM },
+ { "ti,omap2-prcm", TI_OMAP2_PRCM },
+ { "ti,omap3-prm", TI_OMAP3_PRM },
+ { "ti,omap3-cm", TI_OMAP3_CM },
+ { "ti,omap4-cm1", TI_OMAP4_CM1 },
+ { "ti,omap4-prm", TI_OMAP4_PRM },
+ { "ti,omap4-cm2", TI_OMAP4_CM2 },
+ { "ti,omap4-scrm", TI_OMAP4_SCRM },
+ { "ti,omap5-prm", TI_OMAP5_PRM },
+ { "ti,omap5-cm-core-aon", TI_OMAP5_CM_CORE_AON },
+ { "ti,omap5-scrm", TI_OMAP5_SCRM },
+ { "ti,omap5-cm-core", TI_OMAP5_CM_CORE },
+ { "ti,dra7-prm", TI_DRA7_PRM },
+ { "ti,dra7-cm-core-aon", TI_DRA7_CM_CORE_AON },
+ { "ti,dra7-cm-core", TI_DRA7_CM_CORE },
+ { "ti,dm814-prcm", TI_DM814_PRCM },
+ { "ti,dm816-prcm", TI_DM816_PRCM },
+ { NULL, TI_PRCM_END}
+};
+
+static int
+ti_prcm_probe(device_t dev)
{
- struct ti_clock_dev *clk_dev;
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) {
+ return (ENXIO);
+ }
+
+ device_set_desc(dev, "TI Power and Clock Management");
+ return(BUS_PROBE_DEFAULT);
+}
+
+static int
+ti_prcm_attach(device_t dev)
+{
+ struct ti_prcm_softc *sc;
+ phandle_t node, child;
+ int rid;
- /* Find the clock within the devmap - it's a bit inefficent having a for
- * loop for this, but this function should only called when a driver is
- * being activated so IMHO not a big issue.
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ node = ofw_bus_get_node(sc->dev);
+ simplebus_init(sc->dev, node);
+
+ if (simplebus_fill_ranges(node, &sc->sc_simplebus) < 0) {
+ device_printf(sc->dev, "could not get ranges\n");
+ return (ENXIO);
+ }
+ if (sc->sc_simplebus.nranges == 0) {
+ device_printf(sc->dev, "nranges == 0\n");
+ return (ENXIO);
+ }
+
+ sc->mem_res = bus_alloc_resource(sc->dev, SYS_RES_MEMORY, &rid,
+ sc->sc_simplebus.ranges[0].host,
+ (sc->sc_simplebus.ranges[0].host +
+ sc->sc_simplebus.ranges[0].size - 1),
+ sc->sc_simplebus.ranges[0].size,
+ RF_ACTIVE | RF_SHAREABLE);
+
+ if (sc->mem_res == NULL) {
+ return (ENXIO);
+ }
+
+ sc->bst = rman_get_bustag(sc->mem_res);
+ sc->bsh = rman_get_bushandle(sc->mem_res);
+
+ mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF);
+
+ /* Fixme: for xxx_prcm_reset functions.
+ * Get rid of global variables?
*/
- clk_dev = NULL;
+ ti_prcm_sc = sc;
+
switch(ti_chip()) {
#ifdef SOC_OMAP4
case CHIP_OMAP_4:
- clk_dev = &(ti_omap4_clk_devmap[0]);
+ ti_cpu_reset = omap4_prcm_reset;
break;
#endif
#ifdef SOC_TI_AM335X
case CHIP_AM335X:
- clk_dev = &(ti_am335x_clk_devmap[0]);
+ ti_cpu_reset = am335x_prcm_reset;
break;
#endif
}
- if (clk_dev == NULL)
- panic("No clock devmap found");
- while (clk_dev->id != INVALID_CLK_IDENT) {
- if (clk_dev->id == clk) {
- return (clk_dev);
- }
- clk_dev++;
+
+ bus_generic_probe(sc->dev);
+ for (child = OF_child(node); child != 0; child = OF_peer(child)) {
+ simplebus_add_device(dev, child, 0, NULL, -1, NULL);
}
- /* Sanity check we managed to find the clock */
- printf("ti_prcm: Failed to find clock device (%d)\n", clk);
- return (NULL);
+ return (bus_generic_attach(sc->dev));
}
-/**
- * ti_prcm_clk_valid - enables a clock for a particular module
- * @clk: identifier for the module to enable, see ti_prcm.h for a list
- * of possible modules.
- * Example: OMAP3_MODULE_MMC1_ICLK or OMAP3_MODULE_GPTIMER10_FCLK.
- *
- * This function can enable either a functional or interface clock.
- *
- * The real work done to enable the clock is really done in the callback
- * function associated with the clock, this function is simply a wrapper
- * around that.
- *
- * LOCKING:
- * Internally locks the driver context.
- *
- * RETURNS:
- * Returns 0 on success or positive error code on failure.
- */
-int
-ti_prcm_clk_valid(clk_ident_t clk)
+static int
+ti_prcm_write_4(device_t dev, bus_addr_t addr, uint32_t val)
{
- int ret = 0;
+ struct ti_prcm_softc *sc;
- if (ti_prcm_clk_dev(clk) == NULL)
- ret = EINVAL;
-
- return (ret);
+ sc = device_get_softc(dev);
+ DPRINTF(sc->dev, "offset=%lx write %x\n", addr, val);
+ bus_space_write_4(sc->bst, sc->bsh, addr, val);
+ return (0);
}
-
-
-/**
- * ti_prcm_clk_enable - enables a clock for a particular module
- * @clk: identifier for the module to enable, see ti_prcm.h for a list
- * of possible modules.
- * Example: OMAP3_MODULE_MMC1_ICLK or OMAP3_MODULE_GPTIMER10_FCLK.
- *
- * This function can enable either a functional or interface clock.
- *
- * The real work done to enable the clock is really done in the callback
- * function associated with the clock, this function is simply a wrapper
- * around that.
- *
- * LOCKING:
- * Internally locks the driver context.
- *
- * RETURNS:
- * Returns 0 on success or positive error code on failure.
- */
-int
-ti_prcm_clk_enable(clk_ident_t clk)
+static int
+ti_prcm_read_4(device_t dev, bus_addr_t addr, uint32_t *val)
{
- struct ti_clock_dev *clk_dev;
- int ret;
+ struct ti_prcm_softc *sc;
- /* Find the clock within the devmap - it's a bit inefficent having a for
- * loop for this, but this function should only called when a driver is
- * being activated so IMHO not a big issue.
- */
- clk_dev = ti_prcm_clk_dev(clk);
+ sc = device_get_softc(dev);
- /* Sanity check we managed to find the clock */
- if (clk_dev == NULL)
- return (EINVAL);
-
- /* Activate the clock */
- if (clk_dev->clk_activate)
- ret = clk_dev->clk_activate(clk_dev);
- else
- ret = EINVAL;
-
- return (ret);
+ *val = bus_space_read_4(sc->bst, sc->bsh, addr);
+ DPRINTF(sc->dev, "offset=%lx Read %x\n", addr, *val);
+ return (0);
}
-
-/**
- * ti_prcm_clk_disable - disables a clock for a particular module
- * @clk: identifier for the module to enable, see ti_prcm.h for a list
- * of possible modules.
- * Example: OMAP3_MODULE_MMC1_ICLK or OMAP3_MODULE_GPTIMER10_FCLK.
- *
- * This function can enable either a functional or interface clock.
- *
- * The real work done to enable the clock is really done in the callback
- * function associated with the clock, this function is simply a wrapper
- * around that.
- *
- * LOCKING:
- * Internally locks the driver context.
- *
- * RETURNS:
- * Returns 0 on success or positive error code on failure.
- */
-int
-ti_prcm_clk_disable(clk_ident_t clk)
+static int
+ti_prcm_modify_4(device_t dev, bus_addr_t addr, uint32_t clr, uint32_t set)
{
- struct ti_clock_dev *clk_dev;
- int ret;
+ struct ti_prcm_softc *sc;
+ uint32_t reg;
- /* Find the clock within the devmap - it's a bit inefficent having a for
- * loop for this, but this function should only called when a driver is
- * being activated so IMHO not a big issue.
- */
- clk_dev = ti_prcm_clk_dev(clk);
+ sc = device_get_softc(dev);
- /* Sanity check we managed to find the clock */
- if (clk_dev == NULL)
- return (EINVAL);
+ reg = bus_space_read_4(sc->bst, sc->bsh, addr);
+ reg &= ~clr;
+ reg |= set;
+ bus_space_write_4(sc->bst, sc->bsh, addr, reg);
+ DPRINTF(sc->dev, "offset=%lx reg: %x (clr %x set %x)\n", addr, reg, clr, set);
- /* Activate the clock */
- if (clk_dev->clk_deactivate)
- ret = clk_dev->clk_deactivate(clk_dev);
- else
- ret = EINVAL;
-
- return (ret);
+ return (0);
}
-/**
- * ti_prcm_clk_set_source - sets the source
- * @clk: identifier for the module to enable, see ti_prcm.h for a list
- * of possible modules.
- * Example: OMAP3_MODULE_MMC1_ICLK or OMAP3_MODULE_GPTIMER10_FCLK.
- *
- * This function can enable either a functional or interface clock.
- *
- * The real work done to enable the clock is really done in the callback
- * function associated with the clock, this function is simply a wrapper
- * around that.
- *
- * LOCKING:
- * Internally locks the driver context.
- *
- * RETURNS:
- * Returns 0 on success or positive error code on failure.
- */
-int
-ti_prcm_clk_set_source(clk_ident_t clk, clk_src_t clksrc)
+static void
+ti_prcm_device_lock(device_t dev)
{
- struct ti_clock_dev *clk_dev;
- int ret;
+ struct ti_prcm_softc *sc;
+
+ sc = device_get_softc(dev);
+ mtx_lock(&sc->mtx);
+}
+
+static void
+ti_prcm_device_unlock(device_t dev)
+{
+ struct ti_prcm_softc *sc;
+
+ sc = device_get_softc(dev);
+ mtx_unlock(&sc->mtx);
+}
- /* Find the clock within the devmap - it's a bit inefficent having a for
- * loop for this, but this function should only called when a driver is
- * being activated so IMHO not a big issue.
- */
- clk_dev = ti_prcm_clk_dev(clk);
+static device_method_t ti_prcm_methods[] = {
+ DEVMETHOD(device_probe, ti_prcm_probe),
+ DEVMETHOD(device_attach, ti_prcm_attach),
- /* Sanity check we managed to find the clock */
- if (clk_dev == NULL)
- return (EINVAL);
+ /* clkdev interface */
+ DEVMETHOD(clkdev_write_4, ti_prcm_write_4),
+ DEVMETHOD(clkdev_read_4, ti_prcm_read_4),
+ DEVMETHOD(clkdev_modify_4, ti_prcm_modify_4),
+ DEVMETHOD(clkdev_device_lock, ti_prcm_device_lock),
+ DEVMETHOD(clkdev_device_unlock, ti_prcm_device_unlock),
- /* Activate the clock */
- if (clk_dev->clk_set_source)
- ret = clk_dev->clk_set_source(clk_dev, clksrc);
- else
- ret = EINVAL;
+ DEVMETHOD_END
+};
- return (ret);
-}
+DEFINE_CLASS_1(ti_prcm, ti_prcm_driver, ti_prcm_methods,
+ sizeof(struct ti_prcm_softc), simplebus_driver);
+static devclass_t ti_prcm_devclass;
-/**
- * ti_prcm_clk_get_source_freq - gets the source clock frequency
- * @clk: identifier for the module to enable, see ti_prcm.h for a list
- * of possible modules.
- * @freq: pointer to an integer that upon return will contain the src freq
- *
- * This function returns the frequency of the source clock.
- *
- * The real work done to enable the clock is really done in the callback
- * function associated with the clock, this function is simply a wrapper
- * around that.
- *
- * LOCKING:
- * Internally locks the driver context.
- *
- * RETURNS:
- * Returns 0 on success or positive error code on failure.
- */
-int
-ti_prcm_clk_get_source_freq(clk_ident_t clk, unsigned int *freq)
-{
- struct ti_clock_dev *clk_dev;
- int ret;
+EARLY_DRIVER_MODULE(ti_prcm, ofwbus, ti_prcm_driver,
+ ti_prcm_devclass, 0, 0, BUS_PASS_BUS);
+EARLY_DRIVER_MODULE(ti_prcm, simplebus, ti_prcm_driver,
+ ti_prcm_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
+MODULE_VERSION(ti_prcm, 1);
+MODULE_DEPEND(ti_prcm, ti_scm, 1, 1, 1);
- /* Find the clock within the devmap - it's a bit inefficent having a for
- * loop for this, but this function should only called when a driver is
- * being activated so IMHO not a big issue.
- */
- clk_dev = ti_prcm_clk_dev(clk);
- /* Sanity check we managed to find the clock */
- if (clk_dev == NULL)
- return (EINVAL);
+/* From sys/arm/ti/am335x/am335x_prcm.c
+ * Copyright (c) 2012 Damjan Marion <dmarion@Freebsd.org>
+ */
+#define PRM_DEVICE_OFFSET 0xF00
+#define AM335x_PRM_RSTCTRL (PRM_DEVICE_OFFSET + 0x00)
- /* Get the source frequency of the clock */
- if (clk_dev->clk_get_source_freq)
- ret = clk_dev->clk_get_source_freq(clk_dev, freq);
- else
- ret = EINVAL;
-
- return (ret);
+static void
+am335x_prcm_reset(void)
+{
+ ti_prcm_write_4(ti_prcm_sc->dev, AM335x_PRM_RSTCTRL, (1<<1));
}
-/**
- * ti_prcm_clk_set_source_freq - sets the source clock frequency as close to freq as possible
- * @clk: identifier for the module to enable, see ti_prcm.h for a list
- * of possible modules.
- * @freq: requested freq
+/* FIXME: Is this correct - or should the license part be ontop? */
+
+/* From sys/arm/ti/omap4/omap4_prcm_clks.c */
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
*
- * LOCKING:
- * Internally locks the driver context.
+ * Copyright (c) 2011
+ * Ben Gray <ben.r.gray@gmail.com>.
+ * All rights reserved.
*
- * RETURNS:
- * Returns 0 on success or positive error code on failure.
+ * 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.
+ * 3. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BEN GRAY ``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 BEN GRAY 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.
*/
-int
-ti_prcm_clk_set_source_freq(clk_ident_t clk, unsigned int freq)
+#define PRM_RSTCTRL 0x1b00
+#define PRM_RSTCTRL_RESET 0x2
+
+static void
+omap4_prcm_reset(void)
{
- struct ti_clock_dev *clk_dev;
- int ret;
+ uint32_t reg;
- clk_dev = ti_prcm_clk_dev(clk);
-
- /* Sanity check we managed to find the clock */
- if (clk_dev == NULL)
- return (EINVAL);
-
- /* Get the source frequency of the clock */
- if (clk_dev->clk_set_source_freq)
- ret = clk_dev->clk_set_source_freq(clk_dev, freq);
- else
- ret = EINVAL;
-
- return (ret);
+ ti_prcm_read_4(ti_prcm_sc->dev, PRM_RSTCTRL, ®);
+ reg = reg | PRM_RSTCTRL_RESET;
+ ti_prcm_write_4(ti_prcm_sc->dev, PRM_RSTCTRL, reg);
+ ti_prcm_read_4(ti_prcm_sc->dev, PRM_RSTCTRL, ®);
}
Index: sys/arm/ti/ti_pruss.c
===================================================================
--- sys/arm/ti/ti_pruss.c
+++ sys/arm/ti/ti_pruss.c
@@ -57,7 +57,7 @@
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
-#include <arm/ti/ti_prcm.h>
+#include <arm/ti/ti_sysc.h>
#include <arm/ti/ti_pruss.h>
#ifdef DEBUG
@@ -161,7 +161,7 @@
static devclass_t ti_pruss_devclass;
DRIVER_MODULE(ti_pruss, simplebus, ti_pruss_driver, ti_pruss_devclass, 0, 0);
-MODULE_DEPEND(ti_pruss, ti_prcm, 1, 1, 1);
+MODULE_DEPEND(ti_pruss, ti_sysc, 1, 1, 1);
static struct resource_spec ti_pruss_irq_spec[] = {
{ SYS_RES_IRQ, 0, RF_ACTIVE },
@@ -517,10 +517,17 @@
struct ti_pruss_softc *sc;
int rid, i;
- if (ti_prcm_clk_enable(PRUSS_CLK) != 0) {
- device_printf(dev, "could not enable PRUSS clock\n");
+
+ if (ti_sysc_clock_enable(device_get_parent(dev)) != 0) {
+ device_printf(dev, "Could not enable PRUSS clock\n");
return (ENXIO);
}
+
+ /* FIXME: CM_PER_PRU_ICSS_CLKSTCTRL@140 set clkctrctrl = 0x2
+ * wait for the clocks to be active
+ * No way to get to the CM_PER@140 in current devicetree
+ */
+
sc = device_get_softc(dev);
rid = 0;
mtx_init(&sc->sc_mtx, "TI PRUSS", NULL, MTX_DEF);
Index: sys/arm/ti/ti_scm.c
===================================================================
--- sys/arm/ti/ti_scm.c
+++ sys/arm/ti/ti_scm.c
@@ -1,9 +1,7 @@
/*-
- * SPDX-License-Identifier: BSD-4-Clause
+ * Copyright (c) 2019 Emmanuel Vadot <manu@FreeBSD.org>
*
- * Copyright (c) 2010
- * Ben Gray <ben.r.gray@gmail.com>.
- * All rights reserved.
+ * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -13,169 +11,152 @@
* 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.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Ben Gray.
- * 4. The name of the company nor the name of the author may be used to
- * endorse or promote products derived from this software without specific
- * prior written permission.
*
- * THIS SOFTWARE IS PROVIDED BY BEN GRAY ``AS IS'' AND ANY EXPRESS OR
+ * 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 BEN GRAY 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.
- */
-
-/**
- * SCM - System Control Module
+ * 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.
*
- * Hopefully in the end this module will contain a bunch of utility functions
- * for configuring and querying the general system control registers, but for
- * now it only does pin(pad) multiplexing.
- *
- * This is different from the GPIO module in that it is used to configure the
- * pins between modules not just GPIO input/output.
- *
- * This file contains the generic top level driver, however it relies on chip
- * specific settings and therefore expects an array of ti_scm_padconf structs
- * call ti_padconf_devmap to be located somewhere in the kernel.
- *
+ * $FreeBSD$
*/
+
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+
+/* Based on sys/arm/ti/ti_sysc.c */
+
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/fbio.h>
#include <sys/kernel.h>
#include <sys/module.h>
-#include <sys/bus.h>
-#include <sys/resource.h>
#include <sys/rman.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
-
+#include <sys/resource.h>
#include <machine/bus.h>
-#include <machine/resource.h>
+#include <vm/vm.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_kern.h>
+#include <vm/pmap.h>
-#include <dev/ofw/openfirm.h>
+#include <dev/fdt/simplebus.h>
+
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
-#include <dev/fdt/fdt_pinctrl.h>
-#include "ti_scm.h"
-#include "ti_cpuid.h"
+#define TI_AM3_SCM 14
+#define TI_AM4_SCM 13
+#define TI_DM814_SCRM 12
+#define TI_DM816_SCRM 11
+#define TI_OMAP2_SCM 10
+#define TI_OMAP3_SCM 9
+#define TI_OMAP4_SCM_CORE 8
+#define TI_OMAP4_SCM_PADCONF_CORE 7
+#define TI_OMAP4_SCM_WKUP 6
+#define TI_OMAP4_SCM_PADCONF_WKUP 5
+#define TI_OMAP5_SCM_CORE 4
+#define TI_OMAP5_SCM_PADCONF_CORE 3
+#define TI_OMAP5_SCM_WKUP_PAD_CONF 2
+#define TI_DRA7_SCM_CORE 1
+#define TI_SCM_END 0
-static struct resource_spec ti_scm_res_spec[] = {
- { SYS_RES_MEMORY, 0, RF_ACTIVE }, /* Control memory window */
- { -1, 0 }
+static struct ofw_compat_data compat_data[] = {
+ { "ti,am3-scm", TI_AM3_SCM },
+ { "ti,am4-scm", TI_AM4_SCM },
+ { "ti,dm814-scrm", TI_DM814_SCRM },
+ { "ti,dm816-scrm", TI_DM816_SCRM },
+ { "ti,omap2-scm", TI_OMAP2_SCM },
+ { "ti,omap3-scm", TI_OMAP3_SCM },
+ { "ti,omap4-scm-core", TI_OMAP4_SCM_CORE },
+ { "ti,omap4-scm-padconf-core", TI_OMAP4_SCM_PADCONF_CORE },
+ { "ti,omap4-scm-wkup", TI_OMAP4_SCM_WKUP },
+ { "ti,omap4-scm-padconf-wkup", TI_OMAP4_SCM_PADCONF_WKUP },
+ { "ti,omap5-scm-core", TI_OMAP5_SCM_CORE },
+ { "ti,omap5-scm-padconf-core", TI_OMAP5_SCM_PADCONF_CORE },
+ { "ti,omap5-scm-wkup-pad-conf", TI_OMAP5_SCM_WKUP_PAD_CONF },
+ { "ti,dra7-scm-core", TI_DRA7_SCM_CORE },
+ { NULL, TI_SCM_END }
};
-static struct ti_scm_softc *ti_scm_sc;
+struct ti_scm_softc {
+ struct simplebus_softc sc;
+ device_t dev;
+};
-#define ti_scm_read_4(sc, reg) \
- bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
-#define ti_scm_write_4(sc, reg, val) \
- bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
+static int ti_scm_probe(device_t dev);
+static int ti_scm_attach(device_t dev);
+static int ti_scm_detach(device_t dev);
-/*
- * Device part of OMAP SCM driver
- */
static int
ti_scm_probe(device_t dev)
{
-
- if (!ti_soc_is_supported())
- return (ENXIO);
-
if (!ofw_bus_status_okay(dev))
return (ENXIO);
- if (!ofw_bus_is_compatible(dev, "syscon"))
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
return (ENXIO);
- if (ti_scm_sc) {
- return (EEXIST);
- }
+ device_set_desc(dev, "TI OMAP Control Module");
- device_set_desc(dev, "TI Control Module");
return (BUS_PROBE_DEFAULT);
}
-/**
- * ti_scm_attach - attaches the timer to the simplebus
- * @dev: new device
- *
- * Reserves memory and interrupt resources, stores the softc structure
- * globally and registers both the timecount and eventtimer objects.
- *
- * RETURNS
- * Zero on success or ENXIO if an error occuried.
- */
static int
ti_scm_attach(device_t dev)
{
- struct ti_scm_softc *sc = device_get_softc(dev);
+ struct ti_scm_softc *sc;
+ device_t cdev;
+ phandle_t node, child;
- sc->sc_dev = dev;
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+ node = ofw_bus_get_node(dev);
- if (bus_alloc_resources(dev, ti_scm_res_spec, sc->sc_res)) {
- device_printf(dev, "could not allocate resources\n");
+ simplebus_init(dev, node);
+ if (simplebus_fill_ranges(node, &sc->sc) < 0) {
+ device_printf(dev, "could not get ranges\n");
return (ENXIO);
}
- /* Global timer interface */
- sc->sc_bst = rman_get_bustag(sc->sc_res[0]);
- sc->sc_bsh = rman_get_bushandle(sc->sc_res[0]);
+ for (child = OF_child(node); child > 0; child = OF_peer(child)) {
+ cdev = simplebus_add_device(dev, child, 0, NULL, -1, NULL);
+ if (cdev != NULL)
+ device_probe_and_attach(cdev);
+ }
- ti_scm_sc = sc;
-
- /* Attach platform extensions, if any. */
- bus_generic_probe(dev);
-
return (bus_generic_attach(dev));
}
-int
-ti_scm_reg_read_4(uint32_t reg, uint32_t *val)
+static int
+ti_scm_detach(device_t dev)
{
- if (!ti_scm_sc)
- return (ENXIO);
-
- *val = ti_scm_read_4(ti_scm_sc, reg);
- return (0);
+ return (EBUSY);
}
-int
-ti_scm_reg_write_4(uint32_t reg, uint32_t val)
-{
- if (!ti_scm_sc)
- return (ENXIO);
-
- ti_scm_write_4(ti_scm_sc, reg, val);
- return (0);
-}
-
-
static device_method_t ti_scm_methods[] = {
+ /* Device interface */
DEVMETHOD(device_probe, ti_scm_probe),
DEVMETHOD(device_attach, ti_scm_attach),
+ DEVMETHOD(device_detach, ti_scm_detach),
- { 0, 0 }
+ DEVMETHOD_END
};
-static driver_t ti_scm_driver = {
- "ti_scm",
- ti_scm_methods,
- sizeof(struct ti_scm_softc),
-};
+DEFINE_CLASS_1(ti_scm, ti_scm_driver, ti_scm_methods,
+ sizeof(struct ti_scm_softc), simplebus_driver);
static devclass_t ti_scm_devclass;
-EARLY_DRIVER_MODULE(ti_scm, simplebus, ti_scm_driver, ti_scm_devclass, 0, 0,
- BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
+EARLY_DRIVER_MODULE(ti_scm, simplebus, ti_scm_driver,
+ ti_scm_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_FIRST);
+MODULE_VERSION(ti_scm, 1);
+MODULE_DEPEND(ti_scm, ti_sysc, 1, 1, 1);
+
Index: sys/arm/ti/ti_scm_syscon.c
===================================================================
--- sys/arm/ti/ti_scm_syscon.c
+++ sys/arm/ti/ti_scm_syscon.c
@@ -0,0 +1,294 @@
+/*-
+ * Copyright (c) 2019 Emmanuel Vadot <manu@FreeBSD.org>
+ *
+ * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se>
+ *
+ * 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.
+ *
+ * $FreeBSD$
+ */
+/* Based on sys/arm/ti/ti_sysc.c */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <dev/fdt/simplebus.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include "syscon_if.h"
+#include <dev/extres/syscon/syscon.h>
+#include "clkdev_if.h"
+
+#if 0
+#define DPRINTF(dev, msg...) device_printf(dev, msg)
+#else
+#define DPRINTF(dev, msg...)
+#endif
+
+MALLOC_DECLARE(M_SYSCON);
+
+struct ti_scm_syscon_softc {
+ struct simplebus_softc sc_simplebus;
+ device_t dev;
+ struct syscon * syscon;
+ struct resource * res[1];
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+ struct mtx mtx;
+};
+
+static struct resource_spec ti_scm_syscon_res_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE | RF_SHAREABLE },
+ { -1, 0 }
+};
+
+/* Device */
+static struct ofw_compat_data compat_data[] = {
+ { "syscon", 1 },
+ { NULL, 0 }
+};
+
+/* --- dev/extres/syscon syscon_method_t interface --- */
+static int
+ti_scm_syscon_write_4(struct syscon *syscon, bus_size_t offset, uint32_t val)
+{
+ struct ti_scm_syscon_softc *sc;
+
+ sc = device_get_softc(syscon->pdev);
+ DPRINTF(sc->dev, "offset=%lx write %x\n", offset, val);
+ mtx_lock(&sc->mtx);
+ bus_space_write_4(sc->bst, sc->bsh, offset, val);
+ mtx_unlock(&sc->mtx);
+ return (0);
+}
+
+static uint32_t
+ti_scm_syscon_read_4(struct syscon *syscon, bus_size_t offset)
+{
+ struct ti_scm_syscon_softc *sc;
+ uint32_t val;
+
+ sc = device_get_softc(syscon->pdev);
+
+ mtx_lock(&sc->mtx);
+ val = bus_space_read_4(sc->bst, sc->bsh, offset);
+ mtx_unlock(&sc->mtx);
+ DPRINTF(sc->dev, "offset=%lx Read %x\n", offset, val);
+ return (val);
+}
+static int
+ti_scm_syscon_modify_4(struct syscon *syscon, bus_size_t offset, uint32_t clr, uint32_t set)
+{
+ struct ti_scm_syscon_softc *sc;
+ uint32_t reg;
+
+ sc = device_get_softc(syscon->pdev);
+
+ mtx_lock(&sc->mtx);
+ reg = bus_space_read_4(sc->bst, sc->bsh, offset);
+ reg &= ~clr;
+ reg |= set;
+ bus_space_write_4(sc->bst, sc->bsh, offset, reg);
+ mtx_unlock(&sc->mtx);
+ DPRINTF(sc->dev, "offset=%lx reg: %x (clr %x set %x)\n", offset, reg, clr, set);
+
+ return (0);
+}
+
+static syscon_method_t ti_scm_syscon_reg_methods[] = {
+ SYSCONMETHOD(syscon_read_4, ti_scm_syscon_read_4),
+ SYSCONMETHOD(syscon_write_4, ti_scm_syscon_write_4),
+ SYSCONMETHOD(syscon_modify_4, ti_scm_syscon_modify_4),
+
+ SYSCONMETHOD_END
+};
+
+DEFINE_CLASS_1(ti_scm_syscon_reg, ti_scm_syscon_reg_class, ti_scm_syscon_reg_methods,
+ 0, syscon_class);
+
+/* device interface */
+static int
+ti_scm_syscon_probe(device_t dev)
+{
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "TI OMAP Control Module Syscon");
+ return(BUS_PROBE_DEFAULT);
+}
+
+static int
+ti_scm_syscon_attach(device_t dev)
+{
+ struct ti_scm_syscon_softc *sc;
+ phandle_t node, child;
+ int err;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ if (bus_alloc_resources(dev, ti_scm_syscon_res_spec, sc->res)) {
+ device_printf(sc->dev, "Cant allocate resources\n");
+ return (ENXIO);
+ }
+
+ sc->dev = dev;
+ sc->bst = rman_get_bustag(sc->res[0]);
+ sc->bsh = rman_get_bushandle(sc->res[0]);
+
+ mtx_init(&sc->mtx, device_get_nameunit(sc->dev), NULL, MTX_DEF);
+ node = ofw_bus_get_node(sc->dev);
+
+ /* dev/extres/syscon interface */
+ sc->syscon = syscon_create_ofw_node(dev, &ti_scm_syscon_reg_class, node);
+ if (sc->syscon == NULL) {
+ device_printf(dev, "Failed to create/register syscon\n");
+ return (ENXIO);
+ }
+
+ simplebus_init(sc->dev, node);
+
+ err = bus_generic_probe(sc->dev);
+ for (child = OF_child(node); child != 0; child = OF_peer(child)) {
+ simplebus_add_device(sc->dev, child, 0, NULL, -1, NULL);
+ }
+
+ return (bus_generic_attach(sc->dev));
+}
+
+/* syscon interface */
+static int
+ti_scm_syscon_get_handle(device_t dev, struct syscon **syscon)
+{
+ struct ti_scm_syscon_softc *sc;
+
+ sc = device_get_softc(dev);
+ *syscon = sc->syscon;
+ if (*syscon == NULL)
+ return (ENODEV);
+ return (0);
+}
+
+/* clkdev interface */
+static int
+ti_scm_syscon_clk_write_4(device_t dev, bus_addr_t addr, uint32_t val)
+{
+ struct ti_scm_syscon_softc *sc;
+
+ sc = device_get_softc(dev);
+ DPRINTF(sc->dev, "offset=%lx write %x\n", addr, val);
+ bus_space_write_4(sc->bst, sc->bsh, addr, val);
+ return (0);
+}
+
+static int
+ti_scm_syscon_clk_read_4(device_t dev, bus_addr_t addr, uint32_t *val)
+{
+ struct ti_scm_syscon_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ *val = bus_space_read_4(sc->bst, sc->bsh, addr);
+ DPRINTF(sc->dev, "offset=%lx Read %x\n", addr, *val);
+ return (0);
+}
+
+static int
+ti_scm_syscon_clk_modify_4(device_t dev, bus_addr_t addr, uint32_t clr, uint32_t set)
+{
+ struct ti_scm_syscon_softc *sc;
+ uint32_t reg;
+
+ sc = device_get_softc(dev);
+
+ reg = bus_space_read_4(sc->bst, sc->bsh, addr);
+ reg &= ~clr;
+ reg |= set;
+ bus_space_write_4(sc->bst, sc->bsh, addr, reg);
+ DPRINTF(sc->dev, "offset=%lx reg: %x (clr %x set %x)\n", addr, reg, clr, set);
+
+ return (0);
+}
+
+static void
+ti_scm_syscon_clk_device_lock(device_t dev)
+{
+ struct ti_scm_syscon_softc *sc;
+
+ sc = device_get_softc(dev);
+ mtx_lock(&sc->mtx);
+}
+
+static void
+ti_scm_syscon_clk_device_unlock(device_t dev)
+{
+ struct ti_scm_syscon_softc *sc;
+ sc = device_get_softc(dev);
+ mtx_unlock(&sc->mtx);
+}
+
+static device_method_t ti_scm_syscon_methods[] = {
+ DEVMETHOD(device_probe, ti_scm_syscon_probe),
+ DEVMETHOD(device_attach, ti_scm_syscon_attach),
+
+ /* syscon interface */
+ DEVMETHOD(syscon_get_handle, ti_scm_syscon_get_handle),
+
+ /* clkdev interface */
+ DEVMETHOD(clkdev_write_4, ti_scm_syscon_clk_write_4),
+ DEVMETHOD(clkdev_read_4, ti_scm_syscon_clk_read_4),
+ DEVMETHOD(clkdev_modify_4, ti_scm_syscon_clk_modify_4),
+ DEVMETHOD(clkdev_device_lock, ti_scm_syscon_clk_device_lock),
+ DEVMETHOD(clkdev_device_unlock, ti_scm_syscon_clk_device_unlock),
+
+ DEVMETHOD_END
+};
+
+
+DEFINE_CLASS_1(ti_scm_syscon, ti_scm_syscon_driver, ti_scm_syscon_methods,
+ sizeof(struct ti_scm_syscon_softc), simplebus_driver);
+
+static devclass_t ti_scm_syscon_devclass;
+
+EARLY_DRIVER_MODULE(ti_scm_syscon, simplebus, ti_scm_syscon_driver,
+ ti_scm_syscon_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
+MODULE_VERSION(ti_scm_syscon, 1);
+MODULE_DEPEND(ti_scm_syscon, ti_scm, 1, 1, 1);
Index: sys/arm/ti/ti_sdhci.c
===================================================================
--- sys/arm/ti/ti_sdhci.c
+++ sys/arm/ti/ti_sdhci.c
@@ -44,10 +44,11 @@
#include <sys/lock.h>
#include <sys/mutex.h>
-#include <machine/bus.h>
-#include <machine/resource.h>
-#include <machine/intr.h>
+#include <arm/ti/ti_cpuid.h>
+#include <arm/ti/ti_sysc.h>
+#include "gpio_if.h"
+#include <dev/extres/clk/clk.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
@@ -59,11 +60,11 @@
#include <dev/sdhci/sdhci_fdt_gpio.h>
#include "sdhci_if.h"
-#include <arm/ti/ti_cpuid.h>
-#include <arm/ti/ti_prcm.h>
-#include <arm/ti/ti_hwmods.h>
-#include "gpio_if.h"
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <machine/intr.h>
+
#include "opt_mmccam.h"
struct ti_sdhci_softc {
@@ -73,10 +74,9 @@
struct resource * irq_res;
void * intr_cookie;
struct sdhci_slot slot;
- clk_ident_t mmchs_clk_id;
uint32_t mmchs_reg_off;
uint32_t sdhci_reg_off;
- uint32_t baseclk_hz;
+ uint64_t baseclk_hz;
uint32_t cmd_and_mode;
uint32_t sdhci_clkdiv;
boolean_t disable_highspeed;
@@ -414,25 +414,33 @@
return (EBUSY);
}
-static void
+static int
ti_sdhci_hw_init(device_t dev)
{
struct ti_sdhci_softc *sc = device_get_softc(dev);
uint32_t regval;
unsigned long timeout;
+ clk_t mmc_clk;
+ int err;
/* Enable the controller and interface/functional clocks */
- if (ti_prcm_clk_enable(sc->mmchs_clk_id) != 0) {
+ if (ti_sysc_clock_enable(device_get_parent(dev)) != 0) {
device_printf(dev, "Error: failed to enable MMC clock\n");
- return;
+ return (ENXIO);
}
- /* Get the frequency of the source clock */
- if (ti_prcm_clk_get_source_freq(sc->mmchs_clk_id,
- &sc->baseclk_hz) != 0) {
- device_printf(dev, "Error: failed to get source clock freq\n");
- return;
+ /* FIXME: Devicetree dosent have any reference to mmc_clk */
+ err = clk_get_by_name(dev, "mmc_clk", &mmc_clk);
+ if (err) {
+ device_printf(dev, "Can not find mmc_clk\n");
+ return (ENXIO);
}
+ err = clk_get_freq(mmc_clk, &sc->baseclk_hz);
+ if (err) {
+ device_printf(dev, "Cant get mmc_clk frequency\n");
+ /* AM335x TRM 8.1.6.8 table 8-24 96MHz @ OPP100 */
+ sc->baseclk_hz = 96000000;
+ }
/* Issue a softreset to the controller */
ti_mmchs_write_4(sc, MMCHS_SYSCONFIG, MMCHS_SYSCONFIG_RESET);
@@ -499,6 +507,8 @@
/* Set the initial controller configuration. */
ti_mmchs_write_4(sc, MMCHS_CON, MMCHS_CON_DVAL_8_4MS);
+
+ return (0);
}
static int
@@ -512,16 +522,9 @@
sc->dev = dev;
/*
- * Get the MMCHS device id from FDT. If it's not there use the newbus
- * unit number (which will work as long as the devices are in order and
- * none are skipped in the fdt). Note that this is a property we made
- * up and added in freebsd, it doesn't exist in the published bindings.
+ * Get the MMCHS device id from FDT. Use rev address to identify the unit.
*/
node = ofw_bus_get_node(dev);
- sc->mmchs_clk_id = ti_hwmods_get_clock(dev);
- if (sc->mmchs_clk_id == INVALID_CLK_IDENT) {
- device_printf(dev, "failed to get clock based on hwmods property\n");
- }
/*
* The hardware can inherently do dual-voltage (1p8v, 3p0v) on the first
@@ -531,7 +534,8 @@
* that it can set the right values in the CAPA register.
*/
sc->slot.host.caps |= MMC_OCR_LOW_VOLTAGE;
- if (sc->mmchs_clk_id == MMC1_CLK || OF_hasprop(node, "ti,dual-volt")) {
+
+ if (OF_hasprop(node, "ti,dual-volt")) {
sc->slot.host.caps |= MMC_OCR_290_300 | MMC_OCR_300_310;
}
@@ -603,7 +607,11 @@
sc->disable_readonly = true;
/* Initialise the MMCHS hardware. */
- ti_sdhci_hw_init(dev);
+ err = ti_sdhci_hw_init(dev);
+ if (err != 0) {
+ /* err should already contain ENXIO from ti_sdhci_hw_init() */
+ goto fail;
+ }
/*
* The capabilities register can only express base clock frequencies in
@@ -754,6 +762,7 @@
DRIVER_MODULE(sdhci_ti, simplebus, ti_sdhci_driver, ti_sdhci_devclass, NULL,
NULL);
+MODULE_DEPEND(sdhci_ti, ti_sysc, 1, 1, 1);
SDHCI_DEPEND(sdhci_ti);
#ifndef MMCCAM
Index: sys/arm/ti/ti_sdma.c
===================================================================
--- sys/arm/ti/ti_sdma.c
+++ sys/arm/ti/ti_sdma.c
@@ -51,7 +51,7 @@
#include <dev/ofw/ofw_bus_subr.h>
#include <arm/ti/ti_cpuid.h>
-#include <arm/ti/ti_prcm.h>
+#include <arm/ti/ti_sysc.h>
#include <arm/ti/ti_sdma.h>
#include <arm/ti/ti_sdmareg.h>
@@ -1175,10 +1175,11 @@
panic("%s: Cannot map registers", device_get_name(dev));
/* Enable the interface and functional clocks */
- ti_prcm_clk_enable(SDMA_CLK);
+ ti_sysc_clock_enable(device_get_parent(dev));
/* Read the sDMA revision register and sanity check it's known */
- sc->sc_hw_rev = ti_sdma_read_4(sc, DMA4_REVISION);
+ sc->sc_hw_rev = ti_sdma_read_4(sc,
+ ti_sysc_get_rev_address_offset_host(device_get_parent(dev)));
device_printf(dev, "sDMA revision %08x\n", sc->sc_hw_rev);
if (!ti_sdma_is_omap4_rev(sc) && !ti_sdma_is_omap3_rev(sc)) {
@@ -1248,4 +1249,4 @@
static devclass_t ti_sdma_devclass;
DRIVER_MODULE(ti_sdma, simplebus, ti_sdma_driver, ti_sdma_devclass, 0, 0);
-MODULE_DEPEND(ti_sdma, ti_prcm, 1, 1, 1);
+MODULE_DEPEND(ti_sdma, ti_sysc, 1, 1, 1);
Index: sys/arm/ti/ti_spi.c
===================================================================
--- sys/arm/ti/ti_spi.c
+++ sys/arm/ti/ti_spi.c
@@ -48,8 +48,7 @@
#include <dev/spibus/spi.h>
#include <dev/spibus/spibusvar.h>
-#include <arm/ti/ti_prcm.h>
-#include <arm/ti/ti_hwmods.h>
+#include <arm/ti/ti_sysc.h>
#include <arm/ti/ti_spireg.h>
#include <arm/ti/ti_spivar.h>
@@ -166,28 +165,15 @@
static int
ti_spi_attach(device_t dev)
{
- int clk_id, err, i, rid, timeout;
+ int err, i, rid, timeout;
struct ti_spi_softc *sc;
uint32_t rev;
sc = device_get_softc(dev);
sc->sc_dev = dev;
- /*
- * Get the MMCHS device id from FDT. If it's not there use the newbus
- * unit number (which will work as long as the devices are in order and
- * none are skipped in the fdt). Note that this is a property we made
- * up and added in freebsd, it doesn't exist in the published bindings.
- */
- clk_id = ti_hwmods_get_clock(dev);
- if (clk_id == INVALID_CLK_IDENT) {
- device_printf(dev,
- "failed to get clock based on hwmods property\n");
- return (EINVAL);
- }
-
/* Activate the McSPI module. */
- err = ti_prcm_clk_enable(clk_id);
+ err = ti_sysc_clock_enable(device_get_parent(dev));
if (err) {
device_printf(dev, "Error: failed to activate source clock\n");
return (err);
@@ -245,7 +231,8 @@
}
/* Print the McSPI module revision. */
- rev = TI_SPI_READ(sc, MCSPI_REVISION);
+ rev = TI_SPI_READ(sc,
+ ti_sysc_get_rev_address_offset_host(device_get_parent(dev)));
device_printf(dev,
"scheme: %#x func: %#x rtl: %d rev: %d.%d custom rev: %d\n",
(rev >> MCSPI_REVISION_SCHEME_SHIFT) & MCSPI_REVISION_SCHEME_MSK,
@@ -592,3 +579,4 @@
};
DRIVER_MODULE(ti_spi, simplebus, ti_spi_driver, ti_spi_devclass, 0, 0);
+MODULE_DEPEND(ti_spi, ti_sysc, 1, 1, 1);
Index: sys/arm/ti/ti_sysc.h
===================================================================
--- sys/arm/ti/ti_sysc.h
+++ sys/arm/ti/ti_sysc.h
@@ -0,0 +1,44 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se>
+ *
+ * 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.
+ *
+ * $FreeBSD$
+ */
+#ifndef __TI_SYSC__
+#define __TI_SYSC__
+
+uint64_t ti_sysc_get_rev_address(device_t dev);
+uint64_t ti_sysc_get_rev_address_offset_host(device_t dev);
+uint64_t ti_sysc_get_sysc_address(device_t dev);
+uint64_t ti_sysc_get_sysc_address_offset_host(device_t dev);
+uint64_t ti_sysc_get_syss_address(device_t dev);
+uint64_t ti_sysc_get_syss_address_offset_host(device_t dev);
+int ti_sysc_clock_enable(device_t dev);
+int ti_sysc_clock_disable(device_t dev);
+
+uint32_t ti_sysc_get_soft_reset_bit(device_t dev);
+
+#endif /* __TI_SYSC__ */
+
Index: sys/arm/ti/ti_sysc.c
===================================================================
--- sys/arm/ti/ti_sysc.c
+++ sys/arm/ti/ti_sysc.c
@@ -1,6 +1,8 @@
/*-
* Copyright (c) 2019 Emmanuel Vadot <manu@FreeBSD.org>
*
+ * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se>
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -34,6 +36,7 @@
#include <sys/fbio.h>
#include <sys/kernel.h>
#include <sys/module.h>
+#include <sys/queue.h>
#include <sys/rman.h>
#include <sys/resource.h>
#include <machine/bus.h>
@@ -47,21 +50,434 @@
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/extres/clk/clk.h>
+
+#include <arm/ti/ti_sysc.h>
+#include <arm/ti/clk/clock_common.h>
+
+#define DEBUG_SYSC 0
+
+#if DEBUG_SYSC
+#define DPRINTF(dev, msg...) device_printf(dev, msg)
+#else
+#define DPRINTF(dev, msg...)
+#endif
+
+/* Documentation/devicetree/bindings/bus/ti-sysc.txt
+ *
+ * Documentation/devicetree/clock/clock-bindings.txt
+ * Defines phandle + optional pair
+ * Documentation/devicetree/clock/ti-clkctl.txt
+ */
+
+static int ti_sysc_probe(device_t dev);
+static int ti_sysc_attach(device_t dev);
+static int ti_sysc_detach(device_t dev);
+
+#define TI_SYSC_DRA7_MCAN 15
+#define TI_SYSC_USB_HOST_FS 14
+#define TI_SYSC_DRA7_MCASP 13
+#define TI_SYSC_MCASP 12
+#define TI_SYSC_OMAP_AES 11
+#define TI_SYSC_OMAP3_SHAM 10
+#define TI_SYSC_OMAP4_SR 9
+#define TI_SYSC_OMAP3630_SR 8
+#define TI_SYSC_OMAP3430_SR 7
+#define TI_SYSC_OMAP4_TIMER 6
+#define TI_SYSC_OMAP2_TIMER 5
+/* Above needs special workarounds */
+#define TI_SYSC_OMAP4_SIMPLE 4
+#define TI_SYSC_OMAP4 3
+#define TI_SYSC_OMAP2 2
+#define TI_SYSC 1
+#define TI_SYSC_END 0
+
static struct ofw_compat_data compat_data[] = {
- { "ti,sysc", 1 },
- { NULL, 0 }
+ { "ti,sysc-dra7-mcan", TI_SYSC_DRA7_MCAN },
+ { "ti,sysc-usb-host-fs", TI_SYSC_USB_HOST_FS },
+ { "ti,sysc-dra7-mcasp", TI_SYSC_DRA7_MCASP },
+ { "ti,sysc-mcasp", TI_SYSC_MCASP },
+ { "ti,sysc-omap-aes", TI_SYSC_OMAP_AES },
+ { "ti,sysc-omap3-sham", TI_SYSC_OMAP3_SHAM },
+ { "ti,sysc-omap4-sr", TI_SYSC_OMAP4_SR },
+ { "ti,sysc-omap3630-sr", TI_SYSC_OMAP3630_SR },
+ { "ti,sysc-omap3430-sr", TI_SYSC_OMAP3430_SR },
+ { "ti,sysc-omap4-timer", TI_SYSC_OMAP4_TIMER },
+ { "ti,sysc-omap2-timer", TI_SYSC_OMAP2_TIMER },
+ /* Above needs special workarounds */
+ { "ti,sysc-omap4-simple", TI_SYSC_OMAP4_SIMPLE },
+ { "ti,sysc-omap4", TI_SYSC_OMAP4 },
+ { "ti,sysc-omap2", TI_SYSC_OMAP2 },
+ { "ti,sysc", TI_SYSC },
+ { NULL, TI_SYSC_END }
};
+/* reg-names can be "rev", "sysc" and "syss" */
+static const char * reg_names[] = { "rev", "sysc", "syss" };
+#define REG_REV 0
+#define REG_SYSC 1
+#define REG_SYSS 2
+#define REG_MAX 3
+
+/* master idle / slave idle mode defined in 8.1.3.2.1 / 8.1.3.2.2 */
+#include <gnu/dts/include/dt-bindings/bus/ti-sysc.h>
+#define SYSC_IDLE_MAX 4
+
+struct sysc_reg {
+ uint64_t address;
+ uint64_t size;
+};
+
+struct clk_list {
+ TAILQ_ENTRY(clk_list) next;
+ clk_t clk;
+ uint32_t clock_index;
+};
+
struct ti_sysc_softc {
struct simplebus_softc sc;
+ bool attach_done;
+
device_t dev;
+ int device_type;
+
+ struct sysc_reg reg[REG_MAX];
+ /* Offset from host base address */
+ uint64_t offset_reg[REG_MAX];
+
+ uint32_t ti_sysc_mask;
+ int32_t ti_sysc_midle[SYSC_IDLE_MAX];
+ int32_t ti_sysc_sidle[SYSC_IDLE_MAX];
+ uint32_t ti_sysc_delay_us;
+ uint32_t ti_syss_mask;
+
+ int num_clocks;
+ TAILQ_HEAD(, clk_list) clk_list;
+
+ /* deprecated ti_hwmods */
+ bool ti_no_reset_on_init;
+ bool ti_no_idle_on_init;
+ bool ti_no_idle;
};
-static int ti_sysc_probe(device_t dev);
-static int ti_sysc_attach(device_t dev);
-static int ti_sysc_detach(device_t dev);
+/*
+ * All sysc seems to have a reg["rev"] register.
+ * Lets use that for identification of which module the driver are connected to.
+ */
+uint64_t
+ti_sysc_get_rev_address(device_t dev) {
+ struct ti_sysc_softc *sc = device_get_softc(dev);
+ return (sc->reg[REG_REV].address);
+}
+
+uint64_t
+ti_sysc_get_rev_address_offset_host(device_t dev) {
+ struct ti_sysc_softc *sc = device_get_softc(dev);
+
+ return (sc->offset_reg[REG_REV]);
+}
+
+uint64_t
+ti_sysc_get_sysc_address(device_t dev) {
+ struct ti_sysc_softc *sc = device_get_softc(dev);
+
+ return (sc->reg[REG_SYSC].address);
+}
+
+uint64_t
+ti_sysc_get_sysc_address_offset_host(device_t dev) {
+ struct ti_sysc_softc *sc = device_get_softc(dev);
+
+ return (sc->offset_reg[REG_SYSC]);
+}
+
+uint64_t
+ti_sysc_get_syss_address(device_t dev) {
+ struct ti_sysc_softc *sc = device_get_softc(dev);
+
+ return (sc->reg[REG_SYSS].address);
+}
+
+uint64_t
+ti_sysc_get_syss_address_offset_host(device_t dev) {
+ struct ti_sysc_softc *sc = device_get_softc(dev);
+
+ return (sc->offset_reg[REG_SYSS]);
+}
+
+/*
+ * Due no memory region is assigned the sysc driver the children needs to
+ * handle the practical read/writes to the registers.
+ * Check if sysc has reset bit.
+ */
+uint32_t
+ti_sysc_get_soft_reset_bit(device_t dev) {
+ struct ti_sysc_softc *sc = device_get_softc(dev);
+ switch (sc->device_type) {
+ case TI_SYSC_OMAP4_TIMER:
+ case TI_SYSC_OMAP4_SIMPLE:
+ case TI_SYSC_OMAP4:
+ if (sc->ti_sysc_mask & SYSC_OMAP4_SOFTRESET) {
+ return (SYSC_OMAP4_SOFTRESET);
+ }
+ break;
+
+ case TI_SYSC_OMAP2_TIMER:
+ case TI_SYSC_OMAP2:
+ case TI_SYSC:
+ if (sc->ti_sysc_mask & SYSC_OMAP2_SOFTRESET) {
+ return (SYSC_OMAP2_SOFTRESET);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return (0);
+}
+
+int
+ti_sysc_clock_enable(device_t dev) {
+ struct clk_list *clkp, *clkp_tmp;
+ struct ti_sysc_softc *sc = device_get_softc(dev);
+ int err;
+
+ TAILQ_FOREACH_SAFE(clkp, &sc->clk_list, next, clkp_tmp) {
+ if (clkp->clock_index)
+ err = clk_mux(clkp->clk, clkp->clock_index);
+ else
+ err = clk_enable(clkp->clk);
+
+ if (err) {
+ DPRINTF(sc->dev, "clk_enable %s failed %d\n",
+ clk_get_name(clkp->clk), err);
+ break;
+ }
+ }
+ return (err);
+}
+
+int
+ti_sysc_clock_disable(device_t dev) {
+ struct clk_list *clkp, *clkp_tmp;
+ struct ti_sysc_softc *sc = device_get_softc(dev);
+ int err = 0;
+
+ TAILQ_FOREACH_SAFE(clkp, &sc->clk_list, next, clkp_tmp) {
+ if (clkp->clock_index)
+ continue;
+
+ err = clk_disable(clkp->clk);
+
+ if (err) {
+ DPRINTF(sc->dev, "clk_enable %s failed %d\n",
+ clk_get_name(clkp->clk), err);
+ break;
+ }
+ }
+ return (err);
+}
+
static int
+parse_regfields(struct ti_sysc_softc *sc) {
+ phandle_t node;
+ uint32_t parent_address_cells;
+ uint32_t parent_size_cells;
+ cell_t *reg;
+ ssize_t nreg;
+ int err, k, reg_i, prop_idx;
+ uint32_t idx;
+
+ node = ofw_bus_get_node(sc->dev);
+
+ /* Get parents address and size properties */
+ err = OF_searchencprop(OF_parent(node), "#address-cells",
+ &parent_address_cells, sizeof(parent_address_cells));
+ if (err == -1)
+ return (ENXIO);
+ if (!(parent_address_cells == 1 || parent_address_cells == 2)) {
+ DPRINTF(sc->dev, "Expect parent #address-cells=[1||2]\n");
+ return (ENXIO);
+ }
+
+ err = OF_searchencprop(OF_parent(node), "#size-cells",
+ &parent_size_cells, sizeof(parent_size_cells));
+ if (err == -1)
+ return (ENXIO);
+
+ if (!(parent_size_cells == 1 || parent_size_cells == 2)) {
+ DPRINTF(sc->dev, "Expect parent #size-cells = [1||2]\n");
+ return (ENXIO);
+ }
+
+ /* Grab the content of reg properties */
+ nreg = OF_getproplen(node, "reg");
+ reg = malloc(nreg, M_DEVBUF, M_WAITOK);
+ OF_getencprop(node, "reg", reg, nreg);
+
+ /* Make sure address & size are 0 */
+ for (idx = 0; idx < REG_MAX; idx++) {
+ sc->reg[idx].address = 0;
+ sc->reg[idx].size = 0;
+ }
+
+ /* Loop through reg-names and figure out which reg-name corresponds to
+ * index populate the values into the reg array.
+ */
+ for (idx = 0, reg_i = 0; idx < REG_MAX && reg_i < nreg; idx++) {
+ err = ofw_bus_find_string_index(node, "reg-names",
+ reg_names[idx], &prop_idx);
+ if (err != 0)
+ continue;
+
+ for (k = 0; k < parent_address_cells; k++) {
+ sc->reg[prop_idx].address <<= 32;
+ sc->reg[prop_idx].address |= reg[reg_i++];
+ }
+
+ for (k = 0; k < parent_size_cells; k++) {
+ sc->reg[prop_idx].size <<= 32;
+ sc->reg[prop_idx].size |= reg[reg_i++];
+ }
+
+ if (sc->sc.nranges == 0)
+ sc->offset_reg[prop_idx] = sc->reg[prop_idx].address;
+ else
+ sc->offset_reg[prop_idx] = sc->reg[prop_idx].address -
+ sc->sc.ranges[REG_REV].host;
+
+ DPRINTF(sc->dev, "reg[%s] adress %#jx size %#jx\n",
+ reg_names[idx],
+ sc->reg[prop_idx].address,
+ sc->reg[prop_idx].size);
+ }
+ free(reg, M_DEVBUF);
+ return (0);
+}
+
+static void
+parse_idle(struct ti_sysc_softc *sc, const char *name, uint32_t *idle) {
+ phandle_t node;
+ cell_t value[SYSC_IDLE_MAX];
+ int len, no, i;
+
+ node = ofw_bus_get_node(sc->dev);
+
+ if (!OF_hasprop(node, name)) {
+ return;
+ }
+
+ len = OF_getproplen(node, name);
+ no = len / sizeof(cell_t);
+ if (no >= SYSC_IDLE_MAX) {
+ DPRINTF(sc->dev, "Limit %s\n", name);
+ no = SYSC_IDLE_MAX-1;
+ len = no * sizeof(cell_t);
+ }
+
+ OF_getencprop(node, name, value, len);
+ for (i = 0; i < no; i++) {
+ idle[i] = value[i];
+#if DEBUG_SYSC
+ DPRINTF(sc->dev, "%s[%d] = %d ",
+ name, i, value[i]);
+ switch(value[i]) {
+ case SYSC_IDLE_FORCE:
+ DPRINTF(sc->dev, "SYSC_IDLE_FORCE\n");
+ break;
+ case SYSC_IDLE_NO:
+ DPRINTF(sc->dev, "SYSC_IDLE_NO\n");
+ break;
+ case SYSC_IDLE_SMART:
+ DPRINTF(sc->dev, "SYSC_IDLE_SMART\n");
+ break;
+ case SYSC_IDLE_SMART_WKUP:
+ DPRINTF(sc->dev, "SYSC_IDLE_SMART_WKUP\n");
+ break;
+ }
+#endif
+ }
+ for ( ; i < SYSC_IDLE_MAX; i++)
+ idle[i] = -1;
+}
+
+static int
+ti_sysc_attach_clocks(struct ti_sysc_softc *sc) {
+ clk_t *clk;
+ phandle_t parent, *cells;
+ uint32_t *clock_index;
+ int ncells;
+ struct clk_list *clkp;
+ int index, err;
+ phandle_t cnode;
+
+ clk = malloc(sc->num_clocks*sizeof(clk_t), M_DEVBUF, M_WAITOK | M_ZERO);
+ clock_index = malloc(sc->num_clocks*sizeof(uint32_t), M_DEVBUF,
+ M_WAITOK | M_ZERO);
+
+ cnode = ofw_bus_get_node(sc->dev);
+
+ /* Check if all clocks can be found */
+ for (index = 0; index < sc->num_clocks; index++) {
+ err = clk_get_by_ofw_index(sc->dev, 0, index, &clk[index]);
+
+ if (err != 0) {
+ free(clock_index, M_DEVBUF);
+ free(clk, M_DEVBUF);
+ return (1);
+ }
+ err = ofw_bus_parse_xref_list_alloc(cnode, "clocks",
+ "#clock-cells", index,
+ &parent, &ncells, &cells);
+
+ if (err) {
+ free(clock_index, M_DEVBUF);
+ free(clk, M_DEVBUF);
+ return (2);
+ }
+ if (ncells != 2) {
+ OF_prop_free(cells);
+ free(clock_index, M_DEVBUF);
+ free(clk, M_DEVBUF);
+ return (3);
+ }
+ clock_index[index] = cells[1];
+ OF_prop_free(cells);
+ }
+
+ /* All clocks are found, add to list */
+ for (index = 0; index < sc->num_clocks; index++) {
+ clkp = malloc(sizeof(*clkp), M_DEVBUF, M_WAITOK | M_ZERO);
+ clkp->clk = clk[index];
+ clkp->clock_index = clock_index[index];
+ TAILQ_INSERT_TAIL(&sc->clk_list, clkp, next);
+ }
+
+ /* Release the clk array */
+ free(clock_index, M_DEVBUF);
+ free(clk, M_DEVBUF);
+ return (0);
+}
+
+static int
+ti_sysc_simplebus_attach_child(device_t dev) {
+ device_t cdev;
+ phandle_t node, child;
+ struct ti_sysc_softc *sc = device_get_softc(dev);
+
+ node = ofw_bus_get_node(sc->dev);
+
+ for (child = OF_child(node); child > 0; child = OF_peer(child)) {
+ cdev = simplebus_add_device(sc->dev, child, 0, NULL, -1, NULL);
+ if (cdev != NULL)
+ device_probe_and_attach(cdev);
+ }
+ return (0);
+}
+
+/* Device interface */
+static int
ti_sysc_probe(device_t dev)
{
if (!ofw_bus_status_okay(dev))
@@ -71,8 +487,6 @@
return (ENXIO);
device_set_desc(dev, "TI SYSC Interconnect");
- if (!bootverbose)
- device_quiet(dev);
return (BUS_PROBE_DEFAULT);
}
@@ -81,48 +495,160 @@
ti_sysc_attach(device_t dev)
{
struct ti_sysc_softc *sc;
- device_t cdev;
- phandle_t node, child;
+ phandle_t node;
+ int err;
+ cell_t value;
sc = device_get_softc(dev);
sc->dev = dev;
- node = ofw_bus_get_node(dev);
+ sc->device_type = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
- simplebus_init(dev, node);
+ node = ofw_bus_get_node(sc->dev);
+ /* ranges - use simplebus */
+ simplebus_init(sc->dev, node);
if (simplebus_fill_ranges(node, &sc->sc) < 0) {
- device_printf(dev, "could not get ranges\n");
+ DPRINTF(sc->dev, "could not get ranges\n");
return (ENXIO);
}
- for (child = OF_child(node); child > 0; child = OF_peer(child)) {
- cdev = simplebus_add_device(dev, child, 0, NULL, -1, NULL);
- if (cdev != NULL)
- device_probe_and_attach(cdev);
+ if (sc->sc.nranges == 0) {
+ DPRINTF(sc->dev, "nranges == 0\n");
+ return (ENXIO);
}
- return (bus_generic_attach(dev));
+ /* Required field reg & reg-names - assume at least "rev" exists */
+ err = parse_regfields(sc);
+ if (err) {
+ DPRINTF(sc->dev, "parse_regfields failed %d\n", err);
+ return (ENXIO);
+ }
+
+ /* Optional */
+ if (OF_hasprop(node, "ti,sysc-mask")) {
+ OF_getencprop(node, "ti,sysc-mask", &value, sizeof(cell_t));
+ sc->ti_sysc_mask = value;
+ }
+ if (OF_hasprop(node, "ti,syss-mask")) {
+ OF_getencprop(node, "ti,syss-mask", &value, sizeof(cell_t));
+ sc->ti_syss_mask = value;
+ }
+ if (OF_hasprop(node, "ti,sysc-delay-us")) {
+ OF_getencprop(node, "ti,sysc-delay-us", &value, sizeof(cell_t));
+ sc->ti_sysc_delay_us = value;
+ }
+
+ DPRINTF(sc->dev, "sysc_mask %x syss_mask %x delay_us %x\n",
+ sc->ti_sysc_mask, sc->ti_syss_mask, sc->ti_sysc_delay_us);
+
+ parse_idle(sc, "ti,sysc-midle", sc->ti_sysc_midle);
+ parse_idle(sc, "ti,sysc-sidle", sc->ti_sysc_sidle);
+
+ if (OF_hasprop(node, "ti,no-reset-on-init"))
+ sc->ti_no_reset_on_init = true;
+ else
+ sc->ti_no_reset_on_init = false;
+
+ if (OF_hasprop(node, "ti,no-idle-on-init"))
+ sc->ti_no_idle_on_init = true;
+ else
+ sc->ti_no_idle_on_init = false;
+
+ if (OF_hasprop(node, "ti,no-idle"))
+ sc->ti_no_idle = true;
+ else
+ sc->ti_no_idle = false;
+
+ DPRINTF(sc->dev,
+ "no-reset-on-init %d, no-idle-on-init %d, no-idle %d\n",
+ sc->ti_no_reset_on_init,
+ sc->ti_no_idle_on_init,
+ sc->ti_no_idle);
+
+ if (OF_hasprop(node, "clocks")) {
+ struct clock_cell_info cell_info;
+ read_clock_cells(sc->dev, &cell_info);
+ free(cell_info.clock_cells, M_DEVBUF);
+ free(cell_info.clock_cells_ncells, M_DEVBUF);
+
+ sc->num_clocks = cell_info.num_real_clocks;
+ TAILQ_INIT(&sc->clk_list);
+
+ err = ti_sysc_attach_clocks(sc);
+ if (err) {
+ DPRINTF(sc->dev, "Failed to attach clocks\n");
+ return (bus_generic_attach(sc->dev));
+ }
+ }
+
+ err = ti_sysc_simplebus_attach_child(sc->dev);
+ if (err) {
+ DPRINTF(sc->dev, "ti_sysc_simplebus_attach_child %d\n",
+ err);
+ return (err);
+ }
+
+ sc->attach_done = true;
+
+ return (bus_generic_attach(sc->dev));
}
static int
ti_sysc_detach(device_t dev)
{
-
return (EBUSY);
}
+/* Bus interface */
+static void
+ti_sysc_new_pass(device_t dev)
+{
+ struct ti_sysc_softc *sc;
+ int err;
+ phandle_t node;
+
+ sc = device_get_softc(dev);
+
+ if (sc->attach_done) {
+ bus_generic_new_pass(sc->dev);
+ return;
+ }
+
+ node = ofw_bus_get_node(sc->dev);
+ if (OF_hasprop(node, "clocks")) {
+ err = ti_sysc_attach_clocks(sc);
+ if (err) {
+ DPRINTF(sc->dev, "Failed to attach clocks\n");
+ return;
+ }
+ }
+
+ err = ti_sysc_simplebus_attach_child(sc->dev);
+ if (err) {
+ DPRINTF(sc->dev,
+ "ti_sysc_simplebus_attach_child failed %d\n", err);
+ return;
+ }
+ sc->attach_done = true;
+
+ bus_generic_attach(sc->dev);
+}
+
static device_method_t ti_sysc_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, ti_sysc_probe),
DEVMETHOD(device_attach, ti_sysc_attach),
DEVMETHOD(device_detach, ti_sysc_detach),
+ /* Bus interface */
+ DEVMETHOD(bus_new_pass, ti_sysc_new_pass),
+
DEVMETHOD_END
};
DEFINE_CLASS_1(ti_sysc, ti_sysc_driver, ti_sysc_methods,
- sizeof(struct ti_sysc_softc), simplebus_driver);
+ sizeof(struct ti_sysc_softc), simplebus_driver);
static devclass_t ti_sysc_devclass;
EARLY_DRIVER_MODULE(ti_sysc, simplebus, ti_sysc_driver,
-ti_sysc_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_FIRST);
+ ti_sysc_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_FIRST);
Index: sys/arm/ti/ti_wdt.c
===================================================================
--- sys/arm/ti/ti_wdt.c
+++ sys/arm/ti/ti_wdt.c
@@ -49,7 +49,6 @@
#include <machine/bus.h>
-#include <arm/ti/ti_prcm.h>
#include <arm/ti/ti_wdt.h>
#ifdef DEBUG
@@ -93,6 +92,7 @@
static devclass_t ti_wdt_devclass;
DRIVER_MODULE(ti_wdt, simplebus, ti_wdt_driver, ti_wdt_devclass, 0, 0);
+MODULE_DEPEND(ti_wdt, ti_sysc, 1, 1, 1);
static __inline uint32_t
ti_wdt_reg_read(struct ti_wdt_softc *sc, uint32_t reg)
Index: sys/arm/ti/usb/omap_ehci.c
===================================================================
--- sys/arm/ti/usb/omap_ehci.c
+++ sys/arm/ti/usb/omap_ehci.c
@@ -57,7 +57,6 @@
#include <machine/bus.h>
-#include <arm/ti/ti_prcm.h>
#include <arm/ti/usb/omap_usb.h>
#include <arm/ti/omap4/pandaboard/pandaboard.h>
Index: sys/arm/ti/usb/omap_host.c
===================================================================
--- sys/arm/ti/usb/omap_host.c
+++ sys/arm/ti/usb/omap_host.c
@@ -40,7 +40,7 @@
#include <machine/bus.h>
-#include <arm/ti/ti_prcm.h>
+#include <arm/ti/ti_sysc.h>
#include <arm/ti/usb/omap_usb.h>
/*
@@ -139,12 +139,14 @@
int i;
/* Enable Clocks for high speed USBHOST */
- ti_prcm_clk_enable(USBHSHOST_CLK);
+ ti_sysc_clock_enable(device_get_parent(isc->sc_dev));
/* Read the UHH revision */
isc->uhh_rev = omap_uhh_read_4(isc, OMAP_USBHOST_UHH_REVISION);
device_printf(isc->sc_dev, "UHH revision 0x%08x\n", isc->uhh_rev);
+ /* FIXME */
+#if 0
if (isc->uhh_rev == OMAP_UHH_REV2) {
/* For OMAP44xx devices you have to enable the per-port clocks:
* PHY_MODE - External ULPI clock
@@ -200,6 +202,7 @@
device_printf(isc->sc_dev, "unknown port mode %d for port 1\n", isc->port_mode[1]);
}
}
+#endif
/* Put UHH in SmartIdle/SmartStandby mode */
reg = omap_uhh_read_4(isc, OMAP_USBHOST_UHH_SYSCONFIG);
@@ -327,7 +330,7 @@
}
/* Disable functional and interface clocks for the TLL and HOST modules */
- ti_prcm_clk_disable(USBHSHOST_CLK);
+ ti_sysc_clock_disable(device_get_parent(isc->sc_dev));
device_printf(isc->sc_dev, "Clock to USB host has been disabled\n");
}
Index: sys/arm/ti/usb/omap_tll.c
===================================================================
--- sys/arm/ti/usb/omap_tll.c
+++ sys/arm/ti/usb/omap_tll.c
@@ -39,7 +39,7 @@
#include <machine/bus.h>
-#include <arm/ti/ti_prcm.h>
+#include <arm/ti/ti_sysc.h>
#include <arm/ti/usb/omap_usb.h>
/*
@@ -212,7 +212,7 @@
int ret = 0;
/* Enable the USB TLL */
- ti_prcm_clk_enable(USBTLL_CLK);
+ ti_sysc_clock_enable(device_get_parent(sc->sc_dev));
/* Perform TLL soft reset, and wait until reset is complete */
omap_tll_write_4(sc, OMAP_USBTLL_SYSCONFIG, TLL_SYSCONFIG_SOFTRESET);
@@ -248,7 +248,7 @@
err_sys_status:
/* Disable the TLL clocks */
- ti_prcm_clk_disable(USBTLL_CLK);
+ ti_sysc_clock_disable(device_get_parent(sc->sc_dev));
return(ret);
}
@@ -273,7 +273,7 @@
}
/* Disable functional and interface clocks for the TLL and HOST modules */
- ti_prcm_clk_disable(USBTLL_CLK);
+ ti_sysc_clock_disable(device_get_parent(sc->sc_dev));
}
static int
Index: sys/dev/uart/uart_dev_ti8250.c
===================================================================
--- sys/dev/uart/uart_dev_ti8250.c
+++ sys/dev/uart/uart_dev_ti8250.c
@@ -39,9 +39,6 @@
#include <sys/sysctl.h>
#include <machine/bus.h>
-#include <arm/ti/ti_prcm.h>
-#include <arm/ti/ti_hwmods.h>
-
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
@@ -52,6 +49,8 @@
#include <dev/uart/uart_bus.h>
#include <dev/uart/uart_dev_ns8250.h>
+#include <arm/ti/ti_sysc.h>
+
#include "uart_if.h"
/*
@@ -74,16 +73,8 @@
ti8250_bus_probe(struct uart_softc *sc)
{
int status;
- clk_ident_t clkid;
- /* Enable clocks for this device. We can't continue if that fails. */
- clkid = ti_hwmods_get_clock(sc->sc_dev);
- if (clkid == INVALID_CLK_IDENT) {
- device_printf(sc->sc_dev,
- "failed to get clock based on hwmods\n");
- clkid = UART1_CLK + device_get_unit(sc->sc_dev);
- }
- if ((status = ti_prcm_clk_enable(clkid)) != 0)
+ if ((status = ti_sysc_clock_enable(device_get_parent(sc->sc_dev))) != 0)
return (status);
/*
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Nov 28, 11:21 AM (18 h, 41 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
26282319
Default Alt Text
D25118.id72803.diff (224 KB)
Attached To
Mode
D25118: Ti AM335x move to dev/extres/clk framework
Attached
Detach File
Event Timeline
Log In to Comment