[Differential] D40712: support for rockchip rk3308

"titus_edc.ro (Titus Manea)" <[email protected]>
Newsgroups gmane.os.freebsd.devel.arm
Message-ID <[email protected]>
titus_edc.ro created this revision.
titus_edc.ro added a reviewer: arm64.
Herald added a reviewer: andrew.
Herald added a reviewer: andrew.
Herald added subscribers: andrew, emaste.
Herald added a reviewer: manu.
Herald added a reviewer: manu.
titus_edc.ro requested review of this revision.

REVISION SUMMARY
  rockchip-s is probably the cheapest arm64 board
  usb, sdcard, ethernet, uart work
  most of the changes are ported from linux and openbsd
  the rk3308_cru.c file is basically generated with a set of conversion cpp macros (convert linux macros to freebsd macros)
  the regulator-pwm is crude and only supports continuous mode
  setting cpu frequency works
  temperature reading works
  ethernet media autoselect does not work
  with older u-boot 2017 ethernet does not work (phy regulator seems down)

TEST PLAN
  you need to build u-boot from git with rock-pi-s-rk3308_defconfig + EFI support
  preloader and trust.img are from rockchip (there is no public source code for bl31), then use rk-loaderimage (ports) to convert u-boot-dtb.bin into u-boot.img
  i built a 13.x kernel and it works (all the files in the diff are from -CURRENT but they are mostly the same as 13.2 )
  u-boot binaries available here link <https://drive.google.com/file/d/16jwXtRo7bmHexh-VTz6OdjV2fkH4IHgX/view>
  disk layout is similar to other rockchip sbcs, you need  16MB of empty space before the first/efi partition

REVISION DETAIL
  https://reviews.freebsd.org/D40712

AFFECTED FILES
  sys/arm64/conf/std.rockchip
  sys/arm64/rockchip/clk/rk3308_cru.c
  sys/arm64/rockchip/if_dwc_rk.c
  sys/arm64/rockchip/rk_grf.c
  sys/arm64/rockchip/rk_pinctrl.c
  sys/arm64/rockchip/rk_pwm.c
  sys/arm64/rockchip/rk_spi.c
  sys/arm64/rockchip/rk_tsadc.c
  sys/arm64/rockchip/rk_usb2phy.c
  sys/conf/files
  sys/conf/files.arm64
  sys/dev/extres/regulator/regulator_pwm.c
  sys/dev/extres/regulator/regulator_pwm.h

EMAIL PREFERENCES
  https://reviews.freebsd.org/settings/panel/emailpreferences/

To: titus_edc.ro, #arm64, andrew, manu
Cc: emaste, freebsd-arm-list, andrew
D40712.123644.patch (text/x-patch, 64.6 KB)
diff --git a/sys/dev/extres/regulator/regulator_pwm.h b/sys/dev/extres/regulator/regulator_pwm.h
new file mode 100644
--- /dev/null
+++ b/sys/dev/extres/regulator/regulator_pwm.h
@@ -0,0 +1,16 @@
+#ifndef _DEV_EXTRES_REGULATOR_PWM_H_
+#define _DEV_EXTRES_REGULATOR_PWM_H_
+
+#include <dev/gpio/gpiobusvar.h>
+#include <dev/extres/regulator/regulator.h>
+
+struct regnode_pwm_init_def {
+	struct regnode_init_def	reg_init_def;
+	bool			gpio_open_drain;
+	struct gpiobus_pin	*gpio_pin;
+};
+
+int regnode_pwm_register(device_t dev,
+    struct regnode_pwm_init_def *init_def);
+
+#endif /*_DEV_EXTRES_REGULATOR_PWM_H_*/
diff --git a/sys/dev/extres/regulator/regulator_pwm.c b/sys/dev/extres/regulator/regulator_pwm.c
new file mode 100644
--- /dev/null
+++ b/sys/dev/extres/regulator/regulator_pwm.c
@@ -0,0 +1,560 @@
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_platform.h"
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/gpio.h>
+#include <sys/kernel.h>
+#include <sys/kobj.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+
+#ifdef FDT
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include "pwmbus_if.h"
+#endif
+#include <dev/gpio/gpiobusvar.h>
+#include <dev/pwm/pwmbus.h>
+#include <dev/extres/regulator/regulator_pwm.h>
+
+#include "regdev_if.h"
+
+MALLOC_DEFINE(M_PWMREGULATOR, "pwmregulator", "PWM regulator");
+
+/* GPIO list for shared pins. */
+typedef TAILQ_HEAD(gpio_list, gpio_entry) gpio_list_t;
+struct gpio_entry {
+	TAILQ_ENTRY(gpio_entry)	link;
+	struct gpiobus_pin	gpio_pin;
+	int 			use_cnt;
+	int 			enable_cnt;
+	bool			always_on;
+};
+static gpio_list_t gpio_list = TAILQ_HEAD_INITIALIZER(gpio_list);
+static struct mtx gpio_list_mtx;
+MTX_SYSINIT(gpio_list_lock, &gpio_list_mtx, "Regulator GPIO lock", MTX_DEF);
+
+struct regnode_pwm_sc {
+	struct regnode_std_param *param;
+	bool			gpio_open_drain;
+	struct gpio_entry	*gpio_entry;
+};
+
+static int regnode_pwm_init(struct regnode *regnode);
+static int regnode_pwm_enable(struct regnode *regnode, bool enable,
+    int *udelay);
+static int regnode_pwm_status(struct regnode *regnode, int *status);
+static int regnode_pwm_stop(struct regnode *regnode, int *udelay);
+static int regnode_pwm_get_voltage(struct regnode *regnode, int *uvolt);
+static int regnode_pwm_set_voltage(struct regnode *regnode, int min_uvolt, int max_uvolt,int *udelay);
+
+static regnode_method_t regnode_pwm_methods[] = {
+	/* Regulator interface */
+	REGNODEMETHOD(regnode_init,		regnode_pwm_init),
+	REGNODEMETHOD(regnode_enable,		regnode_pwm_enable),
+	REGNODEMETHOD(regnode_status,		regnode_pwm_status),
+	REGNODEMETHOD(regnode_stop,		regnode_pwm_stop),
+	REGNODEMETHOD(regnode_get_voltage,	regnode_pwm_get_voltage),
+	REGNODEMETHOD(regnode_set_voltage,	regnode_pwm_set_voltage),	
+	REGNODEMETHOD(regnode_check_voltage,	regnode_method_check_voltage),
+	REGNODEMETHOD_END
+};
+DEFINE_CLASS_1(regnode_pwm, regnode_pwm_class, regnode_pwm_methods,
+   sizeof(struct regnode_pwm_sc), regnode_class);
+
+/*
+ * GPIO list functions.
+ * Two or more regulators can share single GPIO pins, so we must track all
+ * GPIOs in gpio_list.
+ * The GPIO pin is registerd and reseved for first consumer, all others share
+ * gpio_entry with it.
+ */
+static struct gpio_entry *
+regnode_get_gpio_entry(struct gpiobus_pin *gpio_pin)
+{
+	struct gpio_entry *entry, *tmp;
+	device_t busdev;
+	int rv;
+
+	busdev = GPIO_GET_BUS(gpio_pin->dev);
+	if (busdev == NULL)
+		return (NULL);
+	entry = malloc(sizeof(struct gpio_entry), M_PWMREGULATOR,
+	    M_WAITOK | M_ZERO);
+
+	mtx_lock(&gpio_list_mtx);
+
+	TAILQ_FOREACH(tmp, &gpio_list, link) {
+		if (tmp->gpio_pin.dev == gpio_pin->dev &&
+		    tmp->gpio_pin.pin == gpio_pin->pin) {
+			tmp->use_cnt++;
+			mtx_unlock(&gpio_list_mtx);
+			free(entry, M_PWMREGULATOR);
+			return (tmp);
+		}
+	}
+
+	/* Reserve pin. */
+	/* XXX Can we call gpiobus_acquire_pin() with gpio_list_mtx held? */
+	rv = gpiobus_acquire_pin(busdev, gpio_pin->pin);
+	if (rv != 0) {
+		mtx_unlock(&gpio_list_mtx);
+		free(entry, M_PWMREGULATOR);
+		return (NULL);
+	}
+	/* Everything is OK, build new entry and insert it to list. */
+	entry->gpio_pin = *gpio_pin;
+	entry->use_cnt = 1;
+	TAILQ_INSERT_TAIL(&gpio_list, entry, link);
+
+	mtx_unlock(&gpio_list_mtx);
+	return (entry);
+}
+
+#ifdef FDT
+#include <dev/pwm/ofw_pwm.h>
+struct  regpwm_softc
+{
+	device_t			dev;
+	bool				attach_done;
+	struct regnode_pwm_init_def	init_def;
+	phandle_t			gpio_prodxref;
+	pcell_t				*gpio_cells;
+	int				gpio_ncells;
+	struct gpiobus_pin		gpio_pin;
+	pwm_channel_t   		channel;
+	uint32_t			sc_dutycycle_unit;
+	uint32_t			sc_dutycycle_range[2];
+};
+#endif
+/*
+ * Regulator class implementation.
+ */
+static int
+regnode_pwm_init(struct regnode *regnode)
+{
+	device_t dev;
+	struct regnode_pwm_sc *sc;
+	struct gpiobus_pin *pin;
+	uint32_t flags;
+	int rv;
+
+	sc = regnode_get_softc(regnode);
+	dev = regnode_get_device(regnode);
+	sc->param = regnode_get_stdparam(regnode);
+	if (sc->gpio_entry == NULL)
+		return (0);
+	pin = &sc->gpio_entry->gpio_pin;
+
+	flags = GPIO_PIN_OUTPUT;
+	if (sc->gpio_open_drain)
+		flags |= GPIO_PIN_OPENDRAIN;
+	if (sc->param->boot_on || sc->param->always_on) {
+		rv = GPIO_PIN_SET(pin->dev, pin->pin, sc->param->enable_active_high);
+		if (rv != 0) {
+			device_printf(dev, "Cannot set GPIO pin: %d\n",
+			    pin->pin);
+			return (rv);
+		}
+	}
+
+	rv = GPIO_PIN_SETFLAGS(pin->dev, pin->pin, flags);
+	if (rv != 0) {
+		device_printf(dev, "Cannot configure GPIO pin: %d\n", pin->pin);
+		return (rv);
+	}
+
+	return (0);
+}
+
+/*
+ * Enable/disable regulator.
+ * Take shared GPIO pins in account
+ */
+static int
+regnode_pwm_enable(struct regnode *regnode, bool enable, int *udelay)
+{
+	device_t dev;
+	struct regnode_pwm_sc *sc;
+	struct gpiobus_pin *pin;
+	int rv;
+
+	sc = regnode_get_softc(regnode);
+	dev = regnode_get_device(regnode);
+
+	*udelay = 0;
+	if (sc->gpio_entry == NULL)
+		return (0);
+	pin = &sc->gpio_entry->gpio_pin;
+	if (enable) {
+		sc->gpio_entry->enable_cnt++;
+		if (sc->gpio_entry->enable_cnt > 1)
+			return (0);
+	} else {
+		KASSERT(sc->gpio_entry->enable_cnt > 0,
+		    ("Invalid enable count"));
+		sc->gpio_entry->enable_cnt--;
+		if (sc->gpio_entry->enable_cnt >= 1)
+			return (0);
+	}
+	if (sc->gpio_entry->always_on && !enable)
+		return (0);
+	if (!sc->param->enable_active_high)
+		enable = !enable;
+	rv = GPIO_PIN_SET(pin->dev, pin->pin, enable);
+	if (rv != 0) {
+		device_printf(dev, "Cannot set GPIO pin: %d\n", pin->pin);
+		return (rv);
+	}
+	*udelay = sc->param->enable_delay;
+	return (0);
+}
+
+/*
+ * Stop (physicaly shutdown) regulator.
+ * Take shared GPIO pins in account
+ */
+static int
+regnode_pwm_stop(struct regnode *regnode, int *udelay)
+{
+	device_t dev;
+	struct regnode_pwm_sc *sc;
+	struct gpiobus_pin *pin;
+	int rv;
+
+	sc = regnode_get_softc(regnode);
+	dev = regnode_get_device(regnode);
+
+	*udelay = 0;
+	if (sc->gpio_entry == NULL)
+		return (0);
+	if (sc->gpio_entry->always_on)
+		return (0);
+	pin = &sc->gpio_entry->gpio_pin;
+	if (sc->gpio_entry->enable_cnt > 0) {
+		/* Other regulator(s) are enabled. */
+		/* XXXX Any diagnostic message? Or error? */
+		return (0);
+	}
+	rv = GPIO_PIN_SET(pin->dev, pin->pin,
+	    sc->param->enable_active_high ? false: true);
+	if (rv != 0) {
+		device_printf(dev, "Cannot set GPIO pin: %d\n", pin->pin);
+		return (rv);
+	}
+	*udelay = sc->param->enable_delay;
+	return (0);
+}
+
+static int
+regnode_pwm_status(struct regnode *regnode, int *status)
+{
+	struct regnode_pwm_sc *sc;
+	struct gpiobus_pin *pin;
+	uint32_t val;
+	int rv;
+
+	sc = regnode_get_softc(regnode);
+
+	*status = 0;
+	if (sc->gpio_entry == NULL) {
+		*status = REGULATOR_STATUS_ENABLED;
+		return (0);
+	}
+	pin = &sc->gpio_entry->gpio_pin;
+
+	rv = GPIO_PIN_GET(pin->dev, pin->pin, &val);
+	if (rv == 0) {
+		if (!sc->param->enable_active_high ^ (val != 0))
+			*status = REGULATOR_STATUS_ENABLED;
+	}
+	return (rv);
+}
+static int 
+regnode_pwm_set_voltage(struct regnode *regnode, int min_uvolt, int max_uvolt, int * udelay) 
+{
+        struct regnode_pwm_sc *sc;
+        struct regpwm_softc *dsc;
+        int32_t x0, x1, y0, y1;
+        int32_t x, y;
+        bool  enabled;
+
+        sc = regnode_get_softc(regnode);
+        dsc = device_get_softc(regnode_get_device(regnode));
+        PWMBUS_CHANNEL_IS_ENABLED(dsc->channel->dev,dsc->channel->channel, &enabled);
+  	if(!enabled) 
+  	  return 0;
+  	  
+  	x0 = sc->param->min_uvolt;
+  	x1 = sc->param->max_uvolt;
+	y0 = dsc->sc_dutycycle_range[0];
+	y1 = dsc->sc_dutycycle_range[1];
+	x = min_uvolt;
+	y = y0 + (x - x0) * (y1 - y0) / (x1 - x0);
+	dsc->channel->duty = (y * dsc->channel->period) / dsc->sc_dutycycle_unit;
+	PWMBUS_CHANNEL_CONFIG(dsc->channel->dev,dsc->channel->channel,
+         dsc->channel->period, dsc->channel->duty);
+        return 0;	
+}
+
+static int
+regnode_pwm_get_voltage(struct regnode *regnode, int *uvolt)
+{
+	struct regnode_pwm_sc *sc;
+	struct regpwm_softc *dsc;
+	int32_t x0, x1, y0, y1;
+	int32_t x, y;
+	bool  enabled;
+	
+	sc = regnode_get_softc(regnode);
+	dsc = device_get_softc(regnode_get_device(regnode));	
+        PWMBUS_CHANNEL_IS_ENABLED(dsc->channel->dev,dsc->channel->channel, &enabled);
+  	if(!enabled) 
+  	  return 0;
+  		 
+	PWMBUS_CHANNEL_GET_CONFIG(dsc->channel->dev,dsc->channel->channel,
+	(u_int *) &dsc->channel->period, (u_int *)&dsc->channel->duty);
+
+	x0 = dsc->sc_dutycycle_range[0];
+	x1 = dsc->sc_dutycycle_range[1];
+	y0 = sc->param->min_uvolt;
+	y1 = sc->param->max_uvolt;
+	x = (dsc->channel->duty * dsc->sc_dutycycle_unit) / dsc->channel->period;
+	y = y0 + (x - x0) * (y1 - y0) / (x1 - x0);
+	
+	*uvolt = y;
+	return (0);
+}
+
+int
+regnode_pwm_register(device_t dev, struct regnode_pwm_init_def *init_def)
+{
+	struct regnode *regnode;
+	struct regnode_pwm_sc *sc;
+
+	regnode = regnode_create(dev, &regnode_pwm_class,
+	    &init_def->reg_init_def);
+	if (regnode == NULL) {
+		device_printf(dev, "Cannot create regulator.\n");
+		return(ENXIO);
+	}
+	sc = regnode_get_softc(regnode);
+	sc->gpio_open_drain = init_def->gpio_open_drain;
+	if (init_def->gpio_pin != NULL) {
+		sc->gpio_entry = regnode_get_gpio_entry(init_def->gpio_pin);
+		if (sc->gpio_entry == NULL)
+			return(ENXIO);
+	}
+	regnode = regnode_register(regnode);
+	if (regnode == NULL) {
+		device_printf(dev, "Cannot register regulator.\n");
+		return(ENXIO);
+	}
+
+	if (sc->gpio_entry != NULL)
+		sc->gpio_entry->always_on |= sc->param->always_on;
+
+	return (0);
+}
+
+/*
+ * OFW Driver implementation.
+ */
+#ifdef FDT
+static struct ofw_compat_data compat_data[] = {
+	{"pwm-regulator",		1},
+	{NULL,				0},
+};
+
+static int
+regpwm_get_gpio(struct regpwm_softc * sc)
+{
+	device_t busdev;
+	phandle_t node;
+
+	int rv;
+
+	if (sc->gpio_prodxref == 0)
+		return (0);
+
+	node = ofw_bus_get_node(sc->dev);
+
+	/* Test if controller exist. */
+	sc->gpio_pin.dev = OF_device_from_xref(sc->gpio_prodxref);
+	if (sc->gpio_pin.dev == NULL)
+		return (ENODEV);
+
+	/* Test if GPIO bus already exist. */
+	busdev = GPIO_GET_BUS(sc->gpio_pin.dev);
+	if (busdev == NULL)
+		return (ENODEV);
+
+	rv = gpio_map_gpios(sc->gpio_pin.dev, node,
+	    OF_node_from_xref(sc->gpio_prodxref), sc->gpio_ncells,
+	    sc->gpio_cells, &(sc->gpio_pin.pin), &(sc->gpio_pin.flags));
+	if (rv != 0) {
+		device_printf(sc->dev, "Cannot map the gpio property.\n");
+		return (ENXIO);
+	}
+	sc->init_def.gpio_pin = &sc->gpio_pin;
+	return (0);
+}
+
+static int
+regpwm_parse_fdt(struct regpwm_softc * sc)
+{
+	phandle_t node;
+	int rv;
+	int len;
+	struct regnode_init_def *init_def;
+
+	node = ofw_bus_get_node(sc->dev);
+	init_def = &sc->init_def.reg_init_def;
+
+	rv = regulator_parse_ofw_stdparam(sc->dev, node, init_def);
+	if (rv != 0) {
+		device_printf(sc->dev, "Cannot parse standard parameters.\n");
+		return(rv);
+	}
+	len = OF_getproplen(node, "pwms");
+	if (len <= 4) {
+		device_printf(sc->dev, ": no pwms property\n");
+		return ENXIO;
+	}
+
+	if (OF_getproplen(node, "voltage-tables") > 0) {
+		device_printf(sc->dev, ": voltage table mode unsupported\n");
+		return ENXIO;
+	}
+
+	if (init_def->std_param.min_uvolt > init_def->std_param.max_uvolt) {
+		device_printf(sc->dev, "min_uvolt > max_uvolt\n");
+		return (ENXIO);
+	}
+	rv = pwm_get_by_ofw_propidx(sc->dev, node, "pwms", 0, &sc->channel);
+        if (rv != 0) {
+                device_printf(sc->dev, "Cannot map pwm channel %d\n", rv);
+                return (ENXIO);
+        }
+
+	rv = OF_getencprop(node, "pwm-dutycycle-unit", &sc->sc_dutycycle_unit,
+	 sizeof(sc->sc_dutycycle_unit));
+	if(rv <= 0) sc->sc_dutycycle_unit = 100; 
+	sc->sc_dutycycle_range[0] = 0;
+	sc->sc_dutycycle_range[1] = 100;
+	rv = OF_getencprop(node, "pwm-dutycycle-range",
+	    sc->sc_dutycycle_range, sizeof(sc->sc_dutycycle_range));
+//	device_printf(sc->dev,"%x %x\n",sc->sc_dutycycle_range[0],sc->sc_dutycycle_range[1]);
+	/* PWM regulator uses 'startup-delay-us' property for enable_delay */
+/*
+	if (!OF_hasprop(node, "gpio"))
+		return (0);
+	rv = ofw_bus_parse_xref_list_alloc(node, "gpio", "#gpio-cells", 0,
+	    &sc->gpio_prodxref, &sc->gpio_ncells, &sc->gpio_cells);
+	if (rv != 0) {
+		sc->gpio_prodxref = 0;
+		device_printf(sc->dev, "Malformed gpio property\n");
+		return (ENXIO);
+	}
+*/	
+	return (0);
+}
+
+static void
+regpwm_new_pass(device_t dev)
+{
+	struct regpwm_softc * sc;
+	int rv;
+
+	sc = device_get_softc(dev);
+	bus_generic_new_pass(dev);
+
+	if (sc->attach_done)
+		return;
+
+	/* Try to get and configure GPIO. */
+	rv = regpwm_get_gpio(sc);
+	if (rv != 0)
+		return;
+
+	/* Register regulator. */
+	regnode_pwm_register(sc->dev, &sc->init_def);
+	sc->attach_done = true;
+}
+
+static int
+regpwm_probe(device_t dev)
+{
+
+	if (!ofw_bus_status_okay(dev))
+		return (ENXIO);
+
+	if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)
+		return (ENXIO);
+
+	device_set_desc(dev, "PWM Regulator");
+	return (BUS_PROBE_DEFAULT);
+}
+
+static int
+regpwm_detach(device_t dev)
+{
+
+	/* This device is always present. */
+	return (EBUSY);
+}
+
+static int
+regpwm_attach(device_t dev)
+{
+	struct regpwm_softc * sc;
+	int rv;
+
+	sc = device_get_softc(dev);
+	sc->dev = dev;
+
+	/* Parse FDT data. */
+	rv = regpwm_parse_fdt(sc);
+	if (rv != 0)
+		return(ENXIO);
+
+	/* Fill reset of init. */
+	sc->init_def.reg_init_def.id = 1;
+	sc->init_def.reg_init_def.flags = REGULATOR_FLAGS_STATIC;
+
+	/* Try to get and configure GPIO. */
+	rv = regpwm_get_gpio(sc);
+	if (rv != 0)
+		return (bus_generic_attach(dev));
+
+	/* Register regulator. */
+	regnode_pwm_register(sc->dev, &sc->init_def);
+	sc->attach_done = true;
+
+	return (bus_generic_attach(dev));
+}
+
+static device_method_t regpwm_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		regpwm_probe),
+	DEVMETHOD(device_attach,	regpwm_attach),
+	DEVMETHOD(device_detach,	regpwm_detach),
+	/* Bus interface */
+	DEVMETHOD(bus_new_pass,		regpwm_new_pass),
+	/* Regdev interface */
+	DEVMETHOD(regdev_map,		regdev_default_ofw_map),
+
+	DEVMETHOD_END
+};
+
+static devclass_t regpwm_devclass;
+DEFINE_CLASS_0(regpwm, regpwm_driver, regpwm_methods,
+    sizeof(struct regpwm_softc));
+EARLY_DRIVER_MODULE(regpwm, simplebus, regpwm_driver,
+   regpwm_devclass, 0, 0, BUS_PASS_BUS);
+
+#endif /* FDT */
diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64
--- a/sys/conf/files.arm64
+++ b/sys/conf/files.arm64
@@ -690,6 +690,7 @@
 arm64/rockchip/clk/rk3399_pmucru.c		optional fdt soc_rockchip_rk3399
 arm64/rockchip/clk/rk3568_cru.c			optional fdt soc_rockchip_rk3568
 arm64/rockchip/clk/rk3568_pmucru.c		optional fdt soc_rockchip_rk3568
+arm64/rockchip/clk/rk3308_cru.c                 optional fdt soc_rockchip_rk3308
 
 # Xilinx
 arm/xilinx/uart_dev_cdnc.c			optional uart soc_xilinx_zynq fdt
diff --git a/sys/conf/files b/sys/conf/files
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -1709,6 +1709,7 @@
 dev/extres/regulator/regulator.c	optional regulator
 dev/extres/regulator/regulator_bus.c	optional regulator fdt
 dev/extres/regulator/regulator_fixed.c	optional regulator
+dev/extres/regulator/regulator_pwm.c	optional regulator fdt
 dev/extres/syscon/syscon.c		optional syscon
 dev/extres/syscon/syscon_generic.c	optional syscon fdt
 dev/extres/syscon/syscon_if.m		optional syscon
diff --git a/sys/arm64/rockchip/rk_usb2phy.c b/sys/arm64/rockchip/rk_usb2phy.c
--- a/sys/arm64/rockchip/rk_usb2phy.c
+++ b/sys/arm64/rockchip/rk_usb2phy.c
@@ -81,10 +81,19 @@
 		.disable_mask = 0x100010,
 	}
 };
+struct rk_usb2phy_regs rk3308_regs = {
+	.clk_ctl = {
+		.offset = 0x0108,
+		.enable_mask = 0x100000,
+		/* bit 4 put pll in suspend */
+		.disable_mask = 0x100010,
+	}	
+};
 
 static struct ofw_compat_data compat_data[] = {
 	{ "rockchip,rk3399-usb2phy",	(uintptr_t)&rk3399_regs },
 	{ "rockchip,rk3568-usb2phy",	(uintptr_t)&rk3568_regs },
+	{ "rockchip,rk3308-usb2phy",	(uintptr_t)&rk3308_regs },	
 	{ NULL,				0 }
 };
 
diff --git a/sys/arm64/rockchip/rk_tsadc.c b/sys/arm64/rockchip/rk_tsadc.c
--- a/sys/arm64/rockchip/rk_tsadc.c
+++ b/sys/arm64/rockchip/rk_tsadc.c
@@ -262,6 +262,7 @@
 	}
 };
 
+
 static struct rk_calib_entry rk3399_calib_data[] = {
 	{402, -40000},
 	{410, -35000},
@@ -375,11 +376,33 @@
 	}
 };
 
+static struct tsensor rk3308_tsensors[] = {
+	{ .channel = 0, .id = 0, .name = "CPU"},
+	{ .channel = 1, .id = 1, .name = "GPU"},
+};
+
+static struct tsadc_conf rk3308_tsadc_conf = {
+	.version =		TSADC_V2,
+	.q_sel_ntc =		1,
+	.shutdown_temp =	95000,
+	.shutdown_mode =	0, /* CRU */
+	.shutdown_pol =		0, /* Low  */
+	.tsensors = 		rk3308_tsensors,
+	.ntsensors = 		nitems(rk3308_tsensors),
+	.calib_info = 	{
+			.table = rk3328_calib_data,
+			.nentries = nitems(rk3328_calib_data),
+	}
+};
+
+
 static struct ofw_compat_data compat_data[] = {
 	{"rockchip,rk3288-tsadc",	(uintptr_t)&rk3288_tsadc_conf},
 	{"rockchip,rk3328-tsadc",	(uintptr_t)&rk3328_tsadc_conf},
+	{"rockchip,rk3308-tsadc",	(uintptr_t)&rk3328_tsadc_conf},	
 	{"rockchip,rk3399-tsadc",	(uintptr_t)&rk3399_tsadc_conf},
 	{"rockchip,rk3568-tsadc",	(uintptr_t)&rk3568_tsadc_conf},
+	{"rockchip,rk3308-tsadc",       (uintptr_t)&rk3308_tsadc_conf},
 	{NULL,		0}
 };
 
diff --git a/sys/arm64/rockchip/rk_spi.c b/sys/arm64/rockchip/rk_spi.c
--- a/sys/arm64/rockchip/rk_spi.c
+++ b/sys/arm64/rockchip/rk_spi.c
@@ -1,5 +1,5 @@
 /*-
- * SPDX-License-Identifier: BSD-2-Clause
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
  *
  * Copyright (c) 2019 Oleksandr Tymoshenko <[email protected]>
  *
@@ -92,7 +92,7 @@
 static struct ofw_compat_data compat_data[] = {
 	{ "rockchip,rk3328-spi",		1 },
 	{ "rockchip,rk3399-spi",		1 },
-	{ "rockchip,rk3568-spi",		1 },
+	{ "rockchip,rk3308-spi",		1 },	
 	{ NULL,					0 }
 };
 
@@ -475,7 +475,9 @@
 	sizeof(struct rk_spi_softc),
 };
 
-DRIVER_MODULE(rk_spi, simplebus, rk_spi_driver, 0, 0);
-DRIVER_MODULE(ofw_spibus, rk_spi, ofw_spibus_driver, 0, 0);
+static devclass_t rk_spi_devclass;
+
+DRIVER_MODULE(rk_spi, simplebus, rk_spi_driver, rk_spi_devclass, 0, 0);
+DRIVER_MODULE(ofw_spibus, rk_spi, ofw_spibus_driver, ofw_spibus_devclass, 0, 0);
 MODULE_DEPEND(rk_spi, ofw_spibus, 1, 1, 1);
 OFWBUS_PNP_INFO(compat_data);
diff --git a/sys/arm64/rockchip/rk_pwm.c b/sys/arm64/rockchip/rk_pwm.c
--- a/sys/arm64/rockchip/rk_pwm.c
+++ b/sys/arm64/rockchip/rk_pwm.c
@@ -1,5 +1,5 @@
 /*-
- * SPDX-License-Identifier: BSD-2-Clause
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
  *
  * Copyright (c) 2018 Emmanuel Vadot <[email protected]>
  * Copyright (c) 2019 Brandon Bergren <[email protected]>
@@ -100,6 +100,7 @@
 
 static struct ofw_compat_data compat_data[] = {
 	{ "rockchip,rk3288-pwm",		1 },
+	{ "rockchip,rk3328-pwm",		1 },	
 	{ "rockchip,rk3399-pwm",		1 },
 	{ NULL,					0 }
 };
@@ -398,5 +399,7 @@
 	sizeof(struct rk_pwm_softc),
 };
 
-DRIVER_MODULE(rk_pwm, simplebus, rk_pwm_driver, 0, 0);
+static devclass_t rk_pwm_devclass;
+
+EARLY_DRIVER_MODULE(rk_pwm, simplebus, rk_pwm_driver, rk_pwm_devclass, 0, 0,BUS_PASS_BUS + BUS_PASS_ORDER_LATE);
 SIMPLEBUS_PNP_INFO(compat_data);
diff --git a/sys/arm64/rockchip/rk_pinctrl.c b/sys/arm64/rockchip/rk_pinctrl.c
--- a/sys/arm64/rockchip/rk_pinctrl.c
+++ b/sys/arm64/rockchip/rk_pinctrl.c
@@ -1004,11 +1004,195 @@
 	.get_bias_value = rk3568_get_bias_value,
 };
 
+static struct rk_pinctrl_gpio rk3308_gpio_bank[] = {
+        RK_GPIO(0, "gpio0"),
+        RK_GPIO(1, "gpio1"),
+        RK_GPIO(2, "gpio2"),
+        RK_GPIO(3, "gpio3"),
+        RK_GPIO(4, "gpio4"),        
+
+};
+
+static struct rk_pinctrl_bank rk3308_iomux_bank[] = {
+        /*    bank sub offs nbits */
+        RK_IOMUX(0, 0, 0x0000, 2),
+        RK_IOMUX(0, 1, 0x0004, 2),
+        RK_IOMUX(0, 2, 0x0008, 2),
+        RK_IOMUX(0, 3, 0x000C, 2),
+        RK_IOMUX(1, 0, 0x0010, 2),
+        RK_IOMUX(1, 1, 0x0014, 2),
+        RK_IOMUX(1, 2, 0x0018, 2),
+        RK_IOMUX(1, 3, 0x001C, 2),
+        RK_IOMUX(2, 0, 0x0020, 2),
+        RK_IOMUX(2, 1, 0x0024, 2),
+        RK_IOMUX(2, 2, 0x0028, 2),
+        RK_IOMUX(2, 3, 0x002C, 2),
+        RK_IOMUX(3, 0, 0x0030, 2),
+        RK_IOMUX(3, 1, 0x0034, 2),
+        RK_IOMUX(3, 2, 0x0038, 2),
+        RK_IOMUX(3, 3, 0x003C, 2),
+        RK_IOMUX(4, 0, 0x0040, 2),
+        RK_IOMUX(4, 1, 0x0044, 2),
+        RK_IOMUX(4, 2, 0x0048, 2),
+        RK_IOMUX(4, 3, 0x004C, 2),        
+};
+#define RK_PINFIX_MS(bank,pin,reg,bit,mask) RK_PINFIX(bank,pin,reg,bit,(mask << bit))
+static struct rk_pinctrl_pin_fixup rk3308_pin_fixup[] = {
+	/*      bank  pin reg  bit  mask */
+          RK_PINFIX_MS(1, 14, 0x28, 12, 0xf),
+          RK_PINFIX_MS(1, 15, 0x2c, 0, 0x3),
+          RK_PINFIX_MS(1, 18, 0x30, 4, 0xf),
+          RK_PINFIX_MS(1, 19, 0x30, 8, 0xf),
+          RK_PINFIX_MS(1, 20, 0x30, 12, 0xf),
+          RK_PINFIX_MS(1, 21, 0x34, 0, 0xf),
+          RK_PINFIX_MS(1, 22, 0x34, 4, 0xf),
+          RK_PINFIX_MS(1, 23, 0x34, 8, 0xf),
+          RK_PINFIX_MS(2, 2, 0x40, 4, 0x3),
+          RK_PINFIX_MS(2, 3, 0x40, 6, 0x3),
+          RK_PINFIX_MS(2, 16, 0x50, 0, 0x3),
+          RK_PINFIX_MS(3, 10, 0x68, 4, 0x3),
+          RK_PINFIX_MS(3, 11, 0x68, 6, 0x3),
+          RK_PINFIX_MS(3, 12, 0x68, 8, 0xf),
+          RK_PINFIX_MS(3, 13, 0x68, 12, 0xf),
+};
+static struct rk_pinctrl_pin_drive rk3308_pin_drive[] = {
+	/*       bank sub  offs val ma */
+	RK_PINDRIVE(0, 0, 0x100, 0, 2),
+	RK_PINDRIVE(0, 0, 0x100, 1, 4),
+	RK_PINDRIVE(0, 0, 0x100, 2, 8),
+	RK_PINDRIVE(0, 0, 0x100, 3, 12),
+
+	RK_PINDRIVE(0, 1, 0x104, 0, 2),
+	RK_PINDRIVE(0, 1, 0x104, 1, 4),
+	RK_PINDRIVE(0, 1, 0x104, 2, 8),
+	RK_PINDRIVE(0, 1, 0x104, 3, 12),
+
+	RK_PINDRIVE(0, 2, 0x108, 0, 2),
+	RK_PINDRIVE(0, 2, 0x108, 1, 4),
+	RK_PINDRIVE(0, 2, 0x108, 2, 8),
+	RK_PINDRIVE(0, 2, 0x108, 3, 12),
+
+	RK_PINDRIVE(0, 3, 0x10C, 0, 2),
+	RK_PINDRIVE(0, 3, 0x10C, 1, 4),
+	RK_PINDRIVE(0, 3, 0x10C, 2, 8),
+	RK_PINDRIVE(0, 3, 0x10C, 3, 12),
+
+	RK_PINDRIVE(1, 0, 0x110, 0, 2),
+	RK_PINDRIVE(1, 0, 0x110, 1, 4),
+	RK_PINDRIVE(1, 0, 0x110, 2, 8),
+	RK_PINDRIVE(1, 0, 0x110, 3, 12),
+
+	RK_PINDRIVE(1, 1, 0x114, 0, 2),
+	RK_PINDRIVE(1, 1, 0x114, 1, 4),
+	RK_PINDRIVE(1, 1, 0x114, 2, 8),
+	RK_PINDRIVE(1, 1, 0x114, 3, 12),
+
+	RK_PINDRIVE(1, 2, 0x118, 0, 2),
+	RK_PINDRIVE(1, 2, 0x118, 1, 4),
+	RK_PINDRIVE(1, 2, 0x118, 2, 8),
+	RK_PINDRIVE(1, 2, 0x118, 3, 12),
+
+	RK_PINDRIVE(1, 3, 0x11C, 0, 2),
+	RK_PINDRIVE(1, 3, 0x11C, 1, 4),
+	RK_PINDRIVE(1, 3, 0x11C, 2, 8),
+	RK_PINDRIVE(1, 3, 0x11C, 3, 12),
+
+	RK_PINDRIVE(2, 0, 0x120, 0, 2),
+	RK_PINDRIVE(2, 0, 0x120, 1, 4),
+	RK_PINDRIVE(2, 0, 0x120, 2, 8),
+	RK_PINDRIVE(2, 0, 0x120, 3, 12),
+
+	RK_PINDRIVE(2, 1, 0x124, 0, 2),
+	RK_PINDRIVE(2, 1, 0x124, 1, 4),
+	RK_PINDRIVE(2, 1, 0x124, 2, 8),
+	RK_PINDRIVE(2, 1, 0x124, 3, 12),
+
+	RK_PINDRIVE(2, 2, 0x128, 0, 2),
+	RK_PINDRIVE(2, 2, 0x128, 1, 4),
+	RK_PINDRIVE(2, 2, 0x128, 2, 8),
+	RK_PINDRIVE(2, 2, 0x128, 3, 12),
+
+	RK_PINDRIVE(2, 3, 0x12C, 0, 2),
+	RK_PINDRIVE(2, 3, 0x12C, 1, 4),
+	RK_PINDRIVE(2, 3, 0x12C, 2, 8),
+	RK_PINDRIVE(2, 3, 0x12C, 3, 12),
+
+	RK_PINDRIVE(3, 0, 0x130, 0, 2),
+	RK_PINDRIVE(3, 0, 0x130, 1, 4),
+	RK_PINDRIVE(3, 0, 0x130, 2, 8),
+	RK_PINDRIVE(3, 0, 0x130, 3, 12),
+
+	RK_PINDRIVE(3, 1, 0x134, 0, 2),
+	RK_PINDRIVE(3, 1, 0x134, 1, 4),
+	RK_PINDRIVE(3, 1, 0x134, 2, 8),
+	RK_PINDRIVE(3, 1, 0x134, 3, 12),
+
+	RK_PINDRIVE(3, 2, 0x138, 0, 2),
+	RK_PINDRIVE(3, 2, 0x138, 1, 4),
+	RK_PINDRIVE(3, 2, 0x138, 2, 8),
+	RK_PINDRIVE(3, 2, 0x138, 3, 12),
+
+	RK_PINDRIVE(3, 3, 0x13C, 0, 2),
+	RK_PINDRIVE(3, 3, 0x13C, 1, 4),
+	RK_PINDRIVE(3, 3, 0x13C, 2, 8),
+	RK_PINDRIVE(3, 3, 0x13C, 3, 12),
+
+	RK_PINDRIVE(4, 0, 0x140, 0, 2),
+	RK_PINDRIVE(4, 0, 0x140, 1, 4),
+	RK_PINDRIVE(4, 0, 0x140, 2, 8),
+	RK_PINDRIVE(4, 0, 0x140, 4, 12),
+
+	RK_PINDRIVE(4, 1, 0x144, 0, 2),
+	RK_PINDRIVE(4, 1, 0x144, 1, 4),
+	RK_PINDRIVE(4, 1, 0x144, 2, 8),
+	RK_PINDRIVE(4, 1, 0x144, 4, 12),
+
+	RK_PINDRIVE(4, 2, 0x148, 0, 2),
+	RK_PINDRIVE(4, 2, 0x148, 1, 4),
+	RK_PINDRIVE(4, 2, 0x148, 2, 8),
+	RK_PINDRIVE(4, 2, 0x148, 4, 12),
+
+	RK_PINDRIVE(4, 4, 0x14C, 0, 2),
+	RK_PINDRIVE(4, 4, 0x14C, 1, 4),
+	RK_PINDRIVE(4, 4, 0x14C, 2, 8),
+	RK_PINDRIVE(4, 4, 0x14C, 4, 12),
+	
+};
+
+static uint32_t
+rk3308_get_pd_offset(struct rk_pinctrl_softc *sc, uint32_t bank)
+{
+	return (0xA0);
+}
+
+static struct syscon *
+rk3308_get_syscon(struct rk_pinctrl_softc *sc, uint32_t bank)
+{
+	return (sc->grf);
+}
+
+struct rk_pinctrl_conf rk3308_conf = {
+	.iomux_conf = rk3308_iomux_bank,
+	.iomux_nbanks = nitems(rk3308_iomux_bank),
+	.pin_fixup = rk3308_pin_fixup,
+	.npin_fixup = nitems(rk3308_pin_fixup),
+	.pin_drive = rk3308_pin_drive,
+	.npin_drive = nitems(rk3308_pin_drive),
+	.gpio_bank = rk3308_gpio_bank,
+	.ngpio_bank = nitems(rk3308_gpio_bank),
+	.get_pd_offset = rk3308_get_pd_offset,
+	.get_syscon = rk3308_get_syscon,
+	.parse_bias = rk3288_parse_bias,
+	.resolv_bias_value = rk3288_resolv_bias_value,
+	.get_bias_value = rk3288_get_bias_value,
+};
+
 static struct ofw_compat_data compat_data[] = {
 	{"rockchip,rk3288-pinctrl", (uintptr_t)&rk3288_conf},
 	{"rockchip,rk3328-pinctrl", (uintptr_t)&rk3328_conf},
 	{"rockchip,rk3399-pinctrl", (uintptr_t)&rk3399_conf},
 	{"rockchip,rk3568-pinctrl", (uintptr_t)&rk3568_conf},
+	{"rockchip,rk3308-pinctrl", (uintptr_t)&rk3308_conf},	
 	{NULL,             0}
 };
 
diff --git a/sys/arm64/rockchip/rk_grf.c b/sys/arm64/rockchip/rk_grf.c
--- a/sys/arm64/rockchip/rk_grf.c
+++ b/sys/arm64/rockchip/rk_grf.c
@@ -55,6 +55,7 @@
 	{"rockchip,rk3568-pipe-grf", 1},
 	{"rockchip,rk3568-pipe-phy-grf", 1},
 	{"rockchip,rk3568-pcie3-phy-grf", 1},
+	{"rockchip,rk3308-grf", 1},	
 	{NULL,             0}
 };
 
diff --git a/sys/arm64/rockchip/if_dwc_rk.c b/sys/arm64/rockchip/if_dwc_rk.c
--- a/sys/arm64/rockchip/if_dwc_rk.c
+++ b/sys/arm64/rockchip/if_dwc_rk.c
@@ -1,5 +1,5 @@
 /*-
- * SPDX-License-Identifier: BSD-2-Clause
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
  *
  * Copyright (c) 2018 Emmanuel Vadot <[email protected]>
  *
@@ -103,6 +103,13 @@
 #define	 SOC_CON6_GMAC_RXCLK_DLY_ENA		(1 << 15)
 #define	 SOC_CON6_RX_DL_CFG_SHIFT		8
 
+/* RK3308 registers */
+#define RK3308_GRF_MAC_CON0	0x04a0
+#define RK3308_MAC_SPEED_100M	((0x1 << 0) << 16 | (0x1 << 0))
+#define RK3308_MAC_SPEED_10M	((0x1 << 0) << 16 | (0x0 << 0))
+#define RK3308_INTF_SEL_RMII	((0x1 << 4) << 16 | (0x1 << 4))
+
+
 struct if_dwc_rk_softc;
 
 typedef void (*if_dwc_rk_set_delaysfn_t)(struct if_dwc_rk_softc *);
@@ -147,9 +154,13 @@
 static void rk3399_set_delays(struct if_dwc_rk_softc *sc);
 static int rk3399_set_speed(struct if_dwc_rk_softc *sc, int speed);
 
+static int rk3308_set_speed(struct if_dwc_rk_softc *sc, int speed);
+static void rk3308_set_phy_mode(struct if_dwc_rk_softc *sc);
+
 static struct if_dwc_rk_ops rk3288_ops = {
 };
 
+
 static struct if_dwc_rk_ops rk3328_ops = {
 	.set_delays = rk3328_set_delays,
 	.set_speed = rk3328_set_speed,
@@ -162,10 +173,17 @@
 	.set_speed = rk3399_set_speed,
 };
 
+static struct if_dwc_rk_ops rk3308_ops = {
+	.set_speed = rk3308_set_speed,
+	.set_phy_mode = rk3308_set_phy_mode,
+};
+
 static struct ofw_compat_data compat_data[] = {
 	{"rockchip,rk3288-gmac", (uintptr_t)&rk3288_ops},
 	{"rockchip,rk3328-gmac", (uintptr_t)&rk3328_ops},
 	{"rockchip,rk3399-gmac", (uintptr_t)&rk3399_ops},
+	{"rockchip,rk3308-gmac", (uintptr_t)&rk3308_ops},	
+	{"rockchip,rk3308-mac", (uintptr_t)&rk3308_ops},		
 	{NULL,			 0}
 };
 
@@ -337,6 +355,46 @@
 	    ((SOC_CON5_GMAC_CLK_SEL_MASK << 16) | reg));
 	return (0);
 }
+static int
+rk3308_set_speed(struct if_dwc_rk_softc *sc, int speed)
+{
+	uint32_t reg;
+
+	switch (sc->base.phy_mode) {
+	case PHY_MODE_RGMII:
+		break;
+	case PHY_MODE_RMII:
+		switch (speed) {
+		case IFM_100_TX:
+			reg = RK3308_INTF_SEL_RMII | RK3308_MAC_SPEED_100M;
+			break;
+		case IFM_10_T:
+			 reg = RK3308_INTF_SEL_RMII | RK3308_MAC_SPEED_10M;
+			break;
+		default:
+			device_printf(sc->base.dev, "unsupported RMII media %u\n", speed);
+			return (-1);
+		}
+
+		SYSCON_WRITE_4(sc->grf, RK3308_GRF_MAC_CON0, reg);
+		break;
+	}
+
+	return (0);
+}
+
+static void
+rk3308_set_phy_mode(struct if_dwc_rk_softc *sc)
+{
+	switch (sc->base.phy_mode) {
+	case PHY_MODE_RGMII:
+		break;
+	case PHY_MODE_RMII:
+		SYSCON_WRITE_4(sc->grf, RK3308_GRF_MAC_CON0,RK3308_INTF_SEL_RMII);
+
+		break;
+	}
+}
 
 static int
 if_dwc_rk_sysctl_delays(SYSCTL_HANDLER_ARGS)
@@ -407,6 +465,8 @@
 	if (error != 0) {
 		device_printf(dev, "could not find clock stmmaceth\n");
 		return (error);
+	} else {
+//	clk_set_freq(sc->clk_stmmaceth, 50000000, 0);
 	}
 
 	if (clk_get_by_ofw_name(dev, 0, "mac_clk_rx", &sc->mac_clk_rx) != 0) {
@@ -440,7 +500,6 @@
 				device_printf(sc->base.dev, "could not get clk_mac_refout clock\n");
 				sc->clk_mac_refout = NULL;
 			}
-
 			clk_set_freq(sc->clk_stmmaceth, 50000000, 0);
 		}
 	}
@@ -464,8 +523,9 @@
 		if (sc->clk_mac_refout)
 			clk_enable(sc->clk_mac_refout);
 	}
-	if (sc->clk_phy)
+	if (sc->clk_phy) {
 		clk_enable(sc->clk_phy);
+		}
 	if (sc->aclk_mac)
 		clk_enable(sc->aclk_mac);
 	if (sc->pclk_mac)
@@ -615,9 +675,11 @@
 	DEVMETHOD_END
 };
 
+static devclass_t dwc_rk_devclass;
+
 extern driver_t dwc_driver;
 
 DEFINE_CLASS_1(dwc, dwc_rk_driver, if_dwc_rk_methods,
     sizeof(struct if_dwc_rk_softc), dwc_driver);
-DRIVER_MODULE(dwc_rk, simplebus, dwc_rk_driver, 0, 0);
+DRIVER_MODULE(dwc_rk, simplebus, dwc_rk_driver, dwc_rk_devclass, 0, 0);
 MODULE_DEPEND(dwc_rk, dwc, 1, 1, 1);
diff --git a/sys/arm64/rockchip/clk/rk3308_cru.c b/sys/arm64/rockchip/clk/rk3308_cru.c
new file mode 100644
--- /dev/null
+++ b/sys/arm64/rockchip/clk/rk3308_cru.c
@@ -0,0 +1,722 @@
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <machine/bus.h>
+
+#include <dev/fdt/simplebus.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/extres/clk/clk_div.h>
+#include <dev/extres/clk/clk_fixed.h>
+#include <dev/extres/clk/clk_mux.h>
+
+#include <arm64/rockchip/clk/rk_cru.h>
+#include <contrib/device-tree/include/dt-bindings/clock/rk3308-cru.h>
+
+
+#define RK3308_PLLSEL_CON(x) 		((x) * 0x20)
+#define RK3308_CLKSEL_CON(x)		((x) * 0x4 + 0x100)
+#define RK3308_CLKGATE_CON(x)		((x) * 0x4 + 0x300)
+#define RK3308_GLB_SRST_FST		0xb8
+#define RK3308_SOFTRST_CON(x)		((x) * 0x4 + 0x400)
+#define RK3308_MODE_CON			0xa0
+#define RK3308_SDMMC_CON0		0x480
+#define RK3308_SDMMC_CON1		0x484
+#define RK3308_SDIO_CON0		0x488
+#define RK3308_SDIO_CON1		0x48c
+#define RK3308_EMMC_CON0		0x490
+#define RK3308_EMMC_CON1		0x494
+
+
+#define	PNAME(_name) static const char *_name[]
+
+
+#define	RK_PLLRATE(_hz, _ref, _fb, _post1, _post2, _dspd)		\
+{									\
+	.freq = _hz,							\
+	.refdiv = _ref,							\
+	.fbdiv = _fb,							\
+	.postdiv1 = _post1,						\
+	.postdiv2 = _post2,						\
+	.dsmpd = _dspd,							\
+}
+
+/* PLL clock */
+#define	RK_PLL(_id, _name, _pnames, _off, _shift)			\
+{									\
+	.type = RK3328_CLK_PLL,						\
+	.clk.pll = &(struct rk_clk_pll_def) {				\
+		.clkdef.id = _id,					\
+		.clkdef.name = _name,					\
+		.clkdef.parent_names = _pnames,				\
+		.clkdef.parent_cnt = nitems(_pnames),			\
+		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
+		.base_offset = RK3308_PLLSEL_CON(_off),			\
+		.mode_reg = 0xc0,					\
+		.mode_shift = _shift,					\
+		.rates = rk3308_pll_rates,				\
+	},								\
+}
+
+/* Clock for ARM core(s) */
+#define	RK_ARMDIV(_id, _nm, _pn, _r, _off, _ds, _dw, _ms, _mw, _mp, _ap)\
+{									\
+	.type = RK_CLK_ARMCLK,						\
+	.clk.armclk = &(struct rk_clk_armclk_def) {			\
+		.clkdef.id = _id,					\
+		.clkdef.name = _nm,					\
+		.clkdef.parent_names = _pn,				\
+		.clkdef.parent_cnt = nitems(_pn),			\
+		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
+		.muxdiv_offset = RK3308_CLKSEL_CON(_off),		\
+		.mux_shift = _ms,					\
+		.mux_width = _mw,					\
+		.div_shift = _ds,					\
+		.div_width = _dw,					\
+		.main_parent = _mp,					\
+		.alt_parent = _ap,					\
+		.rates = _r,						\
+		.nrates = nitems(_r),					\
+	},								\
+}
+
+/* Composite */
+#define	RK_COMPOSITE(_id, _name, _pnames, _o, _ms, _mw, _ds, _dw, _go, _gw,_f)\
+{									\
+	.type = RK_CLK_COMPOSITE,					\
+	.clk.composite = &(struct rk_clk_composite_def) {		\
+		.clkdef.id = _id,					\
+		.clkdef.name = _name,					\
+		.clkdef.parent_names = _pnames,				\
+		.clkdef.parent_cnt = nitems(_pnames),			\
+		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
+		.muxdiv_offset = RK3308_CLKSEL_CON(_o),			\
+		.mux_shift = _ms,					\
+		.mux_width = _mw,					\
+		.div_shift = _ds,					\
+		.div_width = _dw,					\
+		.gate_offset = RK3308_CLKGATE_CON(_go),			\
+		.gate_shift = _gw,					\
+		.flags = RK_CLK_COMPOSITE_HAVE_MUX |			\
+			 RK_CLK_COMPOSITE_HAVE_GATE | _f,		\
+	},								\
+}
+
+/* Composite no mux */
+#define	RK_COMPNOMUX(_id, _name, _pname, _o, _ds, _dw, _go, _gw, _f)	\
+{									\
+	.type = RK_CLK_COMPOSITE,					\
+	.clk.composite = &(struct rk_clk_composite_def) {		\
+		.clkdef.id = _id,					\
+		.clkdef.name = _name,					\
+		.clkdef.parent_names = (const char *[]){_pname},	\
+		.clkdef.parent_cnt = 1,					\
+		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
+		.muxdiv_offset = RK3308_CLKSEL_CON(_o),			\
+		.div_shift = _ds,					\
+		.div_width = _dw,					\
+		.gate_offset = RK3308_CLKGATE_CON(_go),			\
+		.gate_shift = _gw,					\
+		.flags = RK_CLK_COMPOSITE_HAVE_GATE | _f,		\
+	},								\
+}
+
+/* Composite no div */
+#define	RK_COMPNODIV(_id, _name, _pnames, _o, _ms, _mw, _go, _gw, _f)	\
+{									\
+	.type = RK_CLK_COMPOSITE,					\
+	.clk.composite = &(struct rk_clk_composite_def) {		\
+		.clkdef.id = _id,					\
+		.clkdef.name = _name,					\
+		.clkdef.parent_names = _pnames,				\
+		.clkdef.parent_cnt =  nitems(_pnames),			\
+		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
+		.muxdiv_offset = RK3308_CLKSEL_CON(_o),			\
+		.mux_shift = _ms,					\
+		.mux_width = _mw,					\
+		.gate_offset = RK3308_CLKGATE_CON(_go),			\
+		.gate_shift = _gw,					\
+		.flags = RK_CLK_COMPOSITE_HAVE_MUX |			\
+			 RK_CLK_COMPOSITE_HAVE_GATE | _f,		\
+	},								\
+}
+
+/* Composite div only */
+#define	RK_COMPDIV(_id, _name, _pname, _o, _ds, _dw, _f)		\
+{									\
+	.type = RK_CLK_COMPOSITE,					\
+	.clk.composite = &(struct rk_clk_composite_def) {		\
+		.clkdef.id = _id,					\
+		.clkdef.name = _name,					\
+		.clkdef.parent_names = (const char *[]){_pname},	\
+		.clkdef.parent_cnt = 1,					\
+		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
+		.muxdiv_offset = RK3308_CLKSEL_CON(_o),			\
+		.div_shift = _ds,					\
+		.div_width = _dw,					\
+		.flags =  _f,						\
+	},								\
+}
+
+
+/* Fixed factor mux/div */
+#define	RK_FACTOR(_id, _name, _pname, _mult, _div)			\
+{									\
+	.type = RK_CLK_FIXED,						\
+	.clk.fixed = &(struct clk_fixed_def) {				\
+		.clkdef.id = _id,					\
+		.clkdef.name = _name,					\
+		.clkdef.parent_names = (const char *[]){_pname},	\
+		.clkdef.parent_cnt = 1,					\
+		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
+		.mult = _mult,						\
+		.div = _div,						\
+	},								\
+}
+
+
+#define RK_FACTOR_GATE(_id, cname, pname,f,  fm, fd, go, gb, gf)	\
+	{							\
+	.type = RK_CLK_COMPOSITE,						\
+	.clk.composite = &(struct rk_clk_composite_def) {				\
+		.clkdef.id = _id,					\
+		.clkdef.name = cname,					\
+		.clkdef.parent_names = (const char *[]){ pname },	\
+		.clkdef.parent_cnt = 1,					\
+		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
+		.div_shift	= fm,				\
+		.div_width	= fd,				\
+		.gate_offset	= go,				\
+		.gate_shift	= gb,				\
+		.flags	= RK_CLK_FRACT_HAVE_GATE | gf,				\
+	},	\
+}
+/* Fractional */
+#define	RK_FRACTION(_id, _name, _pname, _o, _go, _gw, _f)		\
+{									\
+	.type = RK_CLK_FRACT,						\
+	.clk.fract = &(struct rk_clk_fract_def) {			\
+		.clkdef.id = _id,					\
+		.clkdef.name = _name,					\
+		.clkdef.parent_names = (const char *[]){_pname},	\
+		.clkdef.parent_cnt = 1,					\
+		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
+		.offset = RK3308_CLKSEL_CON(_o),			\
+		.gate_offset = RK3308_CLKGATE_CON(_go),			\
+		.gate_shift = _gw,					\
+		.flags = RK_CLK_FRACT_HAVE_GATE | _f,			\
+	},								\
+}
+
+/* Multiplexer */
+#define	RK_MUX(_id, _name, _pnames, _o, _ms, _mw, _f)			\
+{									\
+	.type = RK_CLK_MUX,						\
+	.clk.mux = &(struct rk_clk_mux_def) {				\
+		.clkdef.id = _id,					\
+		.clkdef.name = _name,					\
+		.clkdef.parent_names = _pnames,				\
+		.clkdef.parent_cnt = nitems(_pnames),			\
+		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
+		.offset = RK3308_CLKSEL_CON(_o),			\
+		.shift = _ms,						\
+		.width = _mw,						\
+		.mux_flags = _f,					\
+	},								\
+}
+
+#define	RK_GATE(_id, _name, _pname, _o, _s)				\
+{									\
+	.id = _id,							\
+	.name = _name,							\
+	.parent_name = _pname,						\
+	.offset = RK3308_CLKGATE_CON(_o),				\
+	.shift = _s,							\
+}
+#define	RK_MMC(_id, _name, _pname, _o, _ds)		\
+{									\
+	.type = RK_CLK_COMPOSITE,					\
+	.clk.composite = &(struct rk_clk_composite_def) {		\
+		.clkdef.id = _id,					\
+		.clkdef.name = _name,					\
+		.clkdef.parent_names = (const char *[]){_pname},	\
+		.clkdef.parent_cnt = 1,					\
+		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
+		.muxdiv_offset = RK3308_CLKSEL_CON(_o),			\
+		.div_shift = _ds,					\
+	},								\
+}
+
+struct rk_clk_pll_rate rk3308_pll_rates[] = {
+	/* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd */
+	RK_PLLRATE(1608000000, 1, 67, 1, 1, 1),
+	RK_PLLRATE(1584000000, 1, 66, 1, 1, 1),
+	RK_PLLRATE(1560000000, 1, 65, 1, 1, 1),
+	RK_PLLRATE(1536000000, 1, 64, 1, 1, 1),
+	RK_PLLRATE(1512000000, 1, 63, 1, 1, 1),
+	RK_PLLRATE(1488000000, 1, 62, 1, 1, 1),
+	RK_PLLRATE(1464000000, 1, 61, 1, 1, 1),
+	RK_PLLRATE(1440000000, 1, 60, 1, 1, 1),
+	RK_PLLRATE(1416000000, 1, 59, 1, 1, 1),
+	RK_PLLRATE(1392000000, 1, 58, 1, 1, 1),
+	RK_PLLRATE(1368000000, 1, 57, 1, 1, 1),
+	RK_PLLRATE(1344000000, 1, 56, 1, 1, 1),
+	RK_PLLRATE(1320000000, 1, 55, 1, 1, 1),
+	RK_PLLRATE(1296000000, 1, 54, 1, 1, 1),
+	RK_PLLRATE(1272000000, 1, 53, 1, 1, 1),
+	RK_PLLRATE(1248000000, 1, 52, 1, 1, 1),
+	RK_PLLRATE(1200000000, 1, 50, 1, 1, 1),
+	RK_PLLRATE(1188000000, 2, 99, 1, 1, 1),
+	RK_PLLRATE(1104000000, 1, 46, 1, 1, 1),
+	RK_PLLRATE(1100000000, 12, 550, 1, 1, 1),
+	RK_PLLRATE(1008000000, 1, 84, 2, 1, 1),
+	RK_PLLRATE(1000000000, 6, 500, 2, 1, 1),
+	RK_PLLRATE(984000000, 1, 82, 2, 1, 1),
+	RK_PLLRATE(960000000, 1, 80, 2, 1, 1),
+	RK_PLLRATE(936000000, 1, 78, 2, 1, 1),
+	RK_PLLRATE(912000000, 1, 76, 2, 1, 1),
+	RK_PLLRATE(900000000, 4, 300, 2, 1, 1),
+	RK_PLLRATE(888000000, 1, 74, 2, 1, 1),
+	RK_PLLRATE(864000000, 1, 72, 2, 1, 1),
+	RK_PLLRATE(840000000, 1, 70, 2, 1, 1),
+	RK_PLLRATE(816000000, 1, 68, 2, 1, 1),
+	RK_PLLRATE(800000000, 6, 400, 2, 1, 1),
+	RK_PLLRATE(700000000, 6, 350, 2, 1, 1),
+	RK_PLLRATE(696000000, 1, 58, 2, 1, 1),
+	RK_PLLRATE(624000000, 1, 52, 2, 1, 1),
+	RK_PLLRATE(600000000, 1, 75, 3, 1, 1),
+	RK_PLLRATE(594000000, 2, 99, 2, 1, 1),
+	RK_PLLRATE(504000000, 1, 63, 3, 1, 1),
+	RK_PLLRATE(500000000, 6, 250, 2, 1, 1),
+	RK_PLLRATE(408000000, 1, 68, 2, 2, 1),
+	RK_PLLRATE(312000000, 1, 52, 2, 2, 1),
+	RK_PLLRATE(216000000, 1, 72, 4, 2, 1),
+	RK_PLLRATE(96000000, 1, 64, 4, 4, 1),
+	{ /* sentinel */ },
+};
+
+static struct rk_clk_armclk_rates rk3308_armclk_rates[] = {
+	{1608000000, 1},
+        {1512000000, 1},
+        {1488000000, 1},
+        {1416000000, 1},
+        {1392000000, 1},
+        {1296000000, 1},
+        {1200000000, 1},
+        {1104000000, 1},
+        {1008000000, 1},
+        {912000000, 1},
+        {816000000, 1},
+        {696000000, 1},
+        {600000000, 1},
+        {408000000, 1},
+        {312000000, 1},
+        {216000000,  1},
+        {96000000, 1},
+	{},
+};
+
+/* Parent clock defines */
+PNAME(mux_pll_p)		= { "xin24m" };
+PNAME(mux_usb480m_p)		= { "xin24m", "usb480m_phy", "clk_rtc32k" };
+PNAME(mux_armclk_p)		= { "apll_core", "vpll0_core", "vpll1_core" };
+PNAME(mux_dpll_vpll0_p)		= { "dpll", "vpll0" };
+PNAME(mux_dpll_vpll0_xin24m_p)	= { "dpll", "vpll0", "xin24m" };
+PNAME(mux_dpll_vpll0_vpll1_p)	= { "dpll", "vpll0", "vpll1" };
+PNAME(mux_dpll_vpll0_vpll1_xin24m_p)	= { "dpll", "vpll0", "vpll1", "xin24m" };
+PNAME(mux_dpll_vpll0_vpll1_usb480m_xin24m_p)	= { "dpll", "vpll0", "vpll1", "usb480m", "xin24m" };
+PNAME(mux_vpll0_vpll1_p)	= { "vpll0", "vpll1" };
+PNAME(mux_vpll0_vpll1_xin24m_p)	= { "vpll0", "vpll1", "xin24m" };
+PNAME(mux_uart0_p)		= { "clk_uart0_src", "dummy", "clk_uart0_frac" };
+PNAME(mux_uart1_p)		= { "clk_uart1_src", "dummy", "clk_uart1_frac" };
+PNAME(mux_uart2_p)		= { "clk_uart2_src", "dummy", "clk_uart2_frac" };
+PNAME(mux_uart3_p)		= { "clk_uart3_src", "dummy", "clk_uart3_frac" };
+PNAME(mux_uart4_p)		= { "clk_uart4_src", "dummy", "clk_uart4_frac" };
+PNAME(mux_dclk_vop_p)		= { "dclk_vop_src", "dclk_vop_frac", "xin24m" };
+PNAME(mux_nandc_p)		= { "clk_nandc_div", "clk_nandc_div50" };
+PNAME(mux_sdmmc_p)		= { "clk_sdmmc_div", "clk_sdmmc_div50" };
+PNAME(mux_sdio_p)		= { "clk_sdio_div", "clk_sdio_div50" };
+PNAME(mux_emmc_p)		= { "clk_emmc_div", "clk_emmc_div50" };
+PNAME(mux_mac_p)		= { "clk_mac_src", "mac_clkin" };
+PNAME(mux_mac_rmii_sel_p)	= { "clk_mac_rx_tx_div20", "clk_mac_rx_tx_div2" };
+PNAME(mux_ddrstdby_p)		= { "clk_ddrphy1x_out", "clk_ddr_stdby_div4" };
+PNAME(mux_rtc32k_p)		= { "xin32k", "clk_pvtm_32k", "clk_rtc32k_frac", "clk_rtc32k_div" };
+PNAME(mux_usbphy_ref_p)		= { "xin24m", "clk_usbphy_ref_src" };
+PNAME(mux_wifi_src_p)		= { "clk_wifi_dpll", "clk_wifi_vpll0" };
+PNAME(mux_wifi_p)		= { "clk_wifi_osc", "clk_wifi_src" };
+PNAME(mux_pdm_p)		= { "clk_pdm_src", "clk_pdm_frac" };
+PNAME(mux_i2s0_8ch_tx_p)	= { "clk_i2s0_8ch_tx_src", "clk_i2s0_8ch_tx_frac", "mclk_i2s0_8ch_in" };
+PNAME(mux_i2s0_8ch_tx_rx_p)	= { "clk_i2s0_8ch_tx_mux", "clk_i2s0_8ch_rx_mux"};
+PNAME(mux_i2s0_8ch_tx_out_p)	= { "clk_i2s0_8ch_tx", "xin12m" };
+PNAME(mux_i2s0_8ch_rx_p)	= { "clk_i2s0_8ch_rx_src", "clk_i2s0_8ch_rx_frac", "mclk_i2s0_8ch_in" };
+PNAME(mux_i2s0_8ch_rx_tx_p)	= { "clk_i2s0_8ch_rx_mux", "clk_i2s0_8ch_tx_mux"};
+PNAME(mux_i2s1_8ch_tx_p)	= { "clk_i2s1_8ch_tx_src", "clk_i2s1_8ch_tx_frac", "mclk_i2s1_8ch_in" };
+PNAME(mux_i2s1_8ch_tx_rx_p)	= { "clk_i2s1_8ch_tx_mux", "clk_i2s1_8ch_rx_mux"};
+PNAME(mux_i2s1_8ch_tx_out_p)	= { "clk_i2s1_8ch_tx", "xin12m" };
+PNAME(mux_i2s1_8ch_rx_p)	= { "clk_i2s1_8ch_rx_src", "clk_i2s1_8ch_rx_frac", "mclk_i2s1_8ch_in" };
+PNAME(mux_i2s1_8ch_rx_tx_p)	= { "clk_i2s1_8ch_rx_mux", "clk_i2s1_8ch_tx_mux"};
+PNAME(mux_i2s2_8ch_tx_p)	= { "clk_i2s2_8ch_tx_src", "clk_i2s2_8ch_tx_frac", "mclk_i2s2_8ch_in" };
+PNAME(mux_i2s2_8ch_tx_rx_p)	= { "clk_i2s2_8ch_tx_mux", "clk_i2s2_8ch_rx_mux"};
+PNAME(mux_i2s2_8ch_tx_out_p)	= { "clk_i2s2_8ch_tx", "xin12m" };
+PNAME(mux_i2s2_8ch_rx_p)	= { "clk_i2s2_8ch_rx_src", "clk_i2s2_8ch_rx_frac", "mclk_i2s2_8ch_in" };
+PNAME(mux_i2s2_8ch_rx_tx_p)	= { "clk_i2s2_8ch_rx_mux", "clk_i2s2_8ch_tx_mux"};
+PNAME(mux_i2s3_8ch_tx_p)	= { "clk_i2s3_8ch_tx_src", "clk_i2s3_8ch_tx_frac", "mclk_i2s3_8ch_in" };
+PNAME(mux_i2s3_8ch_tx_rx_p)	= { "clk_i2s3_8ch_tx_mux", "clk_i2s3_8ch_rx_mux"};
+PNAME(mux_i2s3_8ch_tx_out_p)	= { "clk_i2s3_8ch_tx", "xin12m" };
+PNAME(mux_i2s3_8ch_rx_p)	= { "clk_i2s3_8ch_rx_src", "clk_i2s3_8ch_rx_frac", "mclk_i2s3_8ch_in" };
+PNAME(mux_i2s3_8ch_rx_tx_p)	= { "clk_i2s3_8ch_rx_mux", "clk_i2s3_8ch_tx_mux"};
+PNAME(mux_i2s0_2ch_p)		= { "clk_i2s0_2ch_src", "clk_i2s0_2ch_frac", "mclk_i2s0_2ch_in" };
+PNAME(mux_i2s0_2ch_out_p)	= { "clk_i2s0_2ch", "xin12m" };
+PNAME(mux_i2s1_2ch_p)		= { "clk_i2s1_2ch_src", "clk_i2s1_2ch_frac", "mclk_i2s1_2ch_in"};
+PNAME(mux_i2s1_2ch_out_p)	= { "clk_i2s1_2ch", "xin12m" };
+PNAME(mux_spdif_tx_src_p)	= { "clk_spdif_tx_div", "clk_spdif_tx_div50" };
+PNAME(mux_spdif_tx_p)		= { "clk_spdif_tx_src", "clk_spdif_tx_frac", "mclk_i2s0_2ch_in" };
+PNAME(mux_spdif_rx_src_p)	= { "clk_spdif_rx_div", "clk_spdif_rx_div50" };
+PNAME(mux_spdif_rx_p)		= { "clk_spdif_rx_src", "clk_spdif_rx_frac" };
+/* CLOCKS */
+static struct rk_clk rk3308_clks[] = {
+	/* External clocks */
+ 	 LINK("xin24m"),
+	 LINK("clk_rtc_32k"),
+  	 LINK("usb480m_phy"),
+//  	 LINK("jtag_clkin"),
+  	 LINK("clk_ddrphy1x_out"),
+  	 LINK("clk_pvtm_32k"),
+  	 LINK("xin32k"),
+	 LINK("mclk_i2s0_8ch_in"),
+	 LINK("mclk_i2s1_8ch_in"),	// SOS SCRU
+	 LINK("mclk_i2s2_8ch_in"),
+	 LINK("mclk_i2s3_8ch_in"),
+	 LINK("mclk_i2s0_2ch_in"),
+	 LINK("mclk_i2s1_2ch_in"),
+	 LINK("mac_clkin"),
+	 LINK("dummy"),
+	/* PLL's */
+ 	 RK_PLL(PLL_APLL, "apll", mux_pll_p, 0, 0),
+	 RK_PLL(PLL_DPLL, "dpll", mux_pll_p, 1, 2),
+	 RK_PLL(PLL_VPLL0, "vpll0", mux_pll_p, 2, 4),
+	 RK_PLL(PLL_VPLL1, "vpll1", mux_pll_p, 3, 6),
+	 RK_ARMDIV(ARMCLK, "armclk", mux_armclk_p, rk3308_armclk_rates, 0, 0, 5,6, 1, 0, 1),
+	 RK_MUX(USB480M, "usb480m", mux_usb480m_p, RK3308_MODE_CON, 8, 2, 0),
+	 RK_FACTOR(0, "xin12m", "xin24m", 1, 2),
+	 RK_COMPNOMUX(0, "pclk_core_dbg", "armclk", 0, 8, 4, 0, 2, 0),
+	 RK_COMPNOMUX(0, "aclk_core", "armclk", 0, 12, 3, 0, 1, 0),
+	 RK_COMPNODIV(ACLK_BUS_SRC, "clk_bus_src", mux_dpll_vpll0_vpll1_p, 5, 6, 2, 1, 0, 0),
+	 RK_COMPNOMUX(PCLK_BUS, "pclk_bus", "clk_bus_src", 6, 8, 5, 1, 3, 0),
+	 RK_COMPNOMUX(HCLK_BUS, "hclk_bus", "clk_bus_src", 6, 0, 5, 1, 2, 0),
+	 RK_COMPNOMUX(ACLK_BUS, "aclk_bus", "clk_bus_src", 5, 0, 5, 1, 1, 0),
+	 RK_COMPOSITE(0, "clk_uart0_src", mux_dpll_vpll0_vpll1_usb480m_xin24m_p, 10, 13, 3, 0, 5, 1, 9, 0),
+	 RK_FRACTION(0, "clk_uart0_frac", "clk_uart0_src", 12, 1, 11, 0),
+	 RK_MUX(0, "clk_uart0_mux", mux_uart0_p, 11, 14, 2, 0),
+	 RK_COMPOSITE(0, "clk_uart1_src", mux_dpll_vpll0_vpll1_usb480m_xin24m_p, 13, 13, 3, 0, 5, 1, 13, 0),
+	 RK_FRACTION(0, "clk_uart1_frac", "clk_uart1_src", 15, 1, 15, 0),
+	 RK_MUX(0, "clk_uart1_mux", mux_uart1_p, 14, 14, 2, 0),
+	 RK_COMPOSITE(0, "clk_uart2_src", mux_dpll_vpll0_vpll1_usb480m_xin24m_p, 16, 13, 3, 0, 5, 2, 1, 0),
+	 RK_FRACTION(0, "clk_uart2_frac", "clk_uart2_src", 18, 2, 3, 0),
+	 RK_MUX(0, "clk_uart2_mux", mux_uart2_p, 17, 14, 2, 0),
+	 RK_COMPOSITE(0, "clk_uart3_src", mux_dpll_vpll0_vpll1_usb480m_xin24m_p, 19, 13, 3, 0, 5, 2, 5, 0),
+	 RK_FRACTION(0, "clk_uart3_frac", "clk_uart3_src", 21, 2, 7, 0),
+	 RK_MUX(0, "clk_uart3_mux", mux_uart3_p, 20, 14, 2, 0),
+	 RK_COMPOSITE(0, "clk_uart4_src", mux_dpll_vpll0_vpll1_usb480m_xin24m_p, 22, 13, 3, 0, 5, 2, 9, 0),
+	 RK_FRACTION(0, "clk_uart4_frac", "clk_uart4_src", 24, 2, 11, 0),
+	 RK_MUX(0, "clk_uart4_mux", mux_uart4_p, 23, 14, 2, 0),
+	 RK_COMPOSITE(SCLK_I2C0, "clk_i2c0", mux_dpll_vpll0_xin24m_p, 25, 14, 2, 0, 7, 2, 13, 0),
+	 RK_COMPOSITE(SCLK_I2C1, "clk_i2c1", mux_dpll_vpll0_xin24m_p, 26, 14, 2, 0, 7, 2, 14, 0),
+	 RK_COMPOSITE(SCLK_I2C2, "clk_i2c2", mux_dpll_vpll0_xin24m_p, 27, 14, 2, 0, 7, 2, 15, 0),
+	 RK_COMPOSITE(SCLK_I2C3, "clk_i2c3", mux_dpll_vpll0_xin24m_p, 28, 14, 2, 0, 7, 3, 0, 0),
+	 RK_COMPOSITE(SCLK_PWM0, "clk_pwm0", mux_dpll_vpll0_xin24m_p, 29, 14, 2, 0, 7, 3, 1, 0),
+	 RK_COMPOSITE(SCLK_PWM1, "clk_pwm1", mux_dpll_vpll0_xin24m_p, 74, 14, 2, 0, 7, 15, 0, 0),
+	 RK_COMPOSITE(SCLK_PWM2, "clk_pwm2", mux_dpll_vpll0_xin24m_p, 75, 14, 2, 0, 7, 15, 1, 0),
+	 RK_COMPOSITE(SCLK_SPI0, "clk_spi0", mux_dpll_vpll0_xin24m_p, 30, 14, 2, 0, 7, 3, 2, 0),
+	 RK_COMPOSITE(SCLK_SPI1, "clk_spi1", mux_dpll_vpll0_xin24m_p, 31, 14, 2, 0, 7, 3, 3, 0),
+	 RK_COMPOSITE(SCLK_SPI2, "clk_spi2", mux_dpll_vpll0_xin24m_p, 32, 14, 2, 0, 7, 3, 4, 0),
+	 RK_COMPNOMUX(SCLK_TSADC, "clk_tsadc", "xin24m", 33, 0, 11, 3, 5, 0),
+	 RK_COMPNOMUX(SCLK_SARADC, "clk_saradc", "xin24m", 34, 0, 11, 3, 6, 0),
+	 RK_COMPNOMUX(SCLK_OTP, "clk_otp", "xin24m", 35, 0, 4, 3, 7, 0),
+	 RK_COMPNOMUX(SCLK_OTP_USR, "clk_otp_usr", "clk_otp", 35, 4, 2, 3, 8, 0),
+	 RK_COMPOSITE(SCLK_CRYPTO, "clk_crypto", mux_dpll_vpll0_vpll1_p, 7, 6, 2, 0, 5, 1, 4, 0),
+	 RK_COMPOSITE(SCLK_CRYPTO_APK, "clk_crypto_apk", mux_dpll_vpll0_vpll1_p, 7, 14, 2, 8, 5, 1, 5, 0),
+	 RK_COMPOSITE(0, "dclk_vop_src", mux_dpll_vpll0_vpll1_p, 8, 10, 2, 0, 8, 1, 6, 0),
+	 RK_FRACTION(0, "dclk_vop_frac", "dclk_vop_src", 9, 1, 7, 0),
+ 	 RK_MUX(0, "dclk_vop_mux", mux_dclk_vop_p, 8, 14, 2, 0),
+	 RK_COMPNODIV(ACLK_PERI_SRC, "clk_peri_src", mux_dpll_vpll0_vpll1_p, 36, 6, 2, 8, 0, 0),
+	 RK_COMPNOMUX(ACLK_PERI, "aclk_peri", "clk_peri_src", 36, 0, 5, 8, 1, 0),
+	 RK_COMPNOMUX(HCLK_PERI, "hclk_peri", "clk_peri_src", 37, 0, 5, 8, 2, 0),
+	 RK_COMPNOMUX(PCLK_PERI, "pclk_peri", "clk_peri_src", 37, 8, 5, 8, 3, 0),
+	 RK_COMPOSITE(SCLK_NANDC_DIV, "clk_nandc_div", mux_dpll_vpll0_vpll1_p, 38, 6, 2, 0, 5, 8, 4, 0),
+	 RK_COMPOSITE(SCLK_NANDC_DIV50, "clk_nandc_div50", mux_dpll_vpll0_vpll1_p, 38, 6, 2, 0, 5, 8, 4, 0),
+	 RK_COMPNODIV(SCLK_NANDC, "clk_nandc", mux_nandc_p, 38, 15, 1, 8, 5, 0),
+	 RK_COMPOSITE(SCLK_SDMMC_DIV, "clk_sdmmc_div", mux_dpll_vpll0_vpll1_xin24m_p, 39, 8, 2, 0, 8, 8, 6, 0),
+	 RK_COMPOSITE(SCLK_SDMMC_DIV50, "clk_sdmmc_div50", mux_dpll_vpll0_vpll1_xin24m_p, 39, 8, 2, 0, 8, 8, 6, 0),
+	 RK_COMPNODIV(SCLK_SDMMC, "clk_sdmmc", mux_sdmmc_p, 39, 15, 1, 8, 7, 0),
+//	 RK_MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "clk_sdmmc", RK3308_SDMMC_CON0, 1),
+//	 RK_MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "clk_sdmmc", RK3308_SDMMC_CON1, 1),
+	 RK_COMPOSITE(SCLK_SDIO_DIV, "clk_sdio_div", mux_dpll_vpll0_vpll1_xin24m_p, 40, 8, 2, 0, 8, 8, 8, 0),
+	 RK_COMPOSITE(SCLK_SDIO_DIV50, "clk_sdio_div50", mux_dpll_vpll0_vpll1_xin24m_p, 40, 8, 2, 0, 8, 8, 8, 0),
+	 RK_COMPNODIV(SCLK_SDIO, "clk_sdio", mux_sdio_p, 40, 15, 1, 8, 9, 0),
+//	 RK_MMC(SCLK_SDIO_DRV, "sdio_drv", "clk_sdio", RK3308_SDIO_CON0, 1),
+//	 RK_MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "clk_sdio", RK3308_SDIO_CON1, 1),
+	 RK_COMPOSITE(SCLK_EMMC_DIV, "clk_emmc_div", mux_dpll_vpll0_vpll1_xin24m_p, 41, 8, 2, 0, 8, 8, 10, 0),
+	 RK_COMPOSITE(SCLK_EMMC_DIV50, "clk_emmc_div50", mux_dpll_vpll0_vpll1_xin24m_p, 41, 8, 2, 0, 8, 8, 10, 0),
+	 RK_COMPNODIV(SCLK_EMMC, "clk_emmc", mux_emmc_p, 41, 15, 1, 8, 11, 0),
+//	 RK_MMC(SCLK_EMMC_DRV, "emmc_drv", "clk_emmc", RK3308_EMMC_CON0, 1),
+//	 RK_MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "clk_emmc", RK3308_EMMC_CON1, 1),
+	 RK_COMPOSITE(SCLK_SFC, "clk_sfc", mux_dpll_vpll0_vpll1_p, 42, 14, 2, 0, 7, 8, 12, 0),
+	 RK_MUX(SCLK_RTC32K, "clk_rtc32k", mux_rtc32k_p, 2, 8, 2, 0),
+	 RK_COMPOSITE(SCLK_MAC_SRC, "clk_mac_src", mux_dpll_vpll0_vpll1_p, 43, 6, 2, 0, 5, 8, 14, 0),
+	 RK_MUX(SCLK_MAC, "clk_mac", mux_mac_p, 43, 14, 1, 0),
+	 RK_FACTOR(0, "clk_mac_rx_tx_div2", "clk_mac_rx_tx", 1, 2),
+	 RK_FACTOR(0, "clk_mac_rx_tx_div20", "clk_mac_rx_tx", 1, 20),
+	 RK_MUX(SCLK_MAC_RMII, "clk_mac_rmii_sel", mux_mac_rmii_sel_p, 43, 15, 1, 0),
+	 RK_COMPOSITE(SCLK_OWIRE, "clk_owire", mux_dpll_vpll0_xin24m_p, 44, 14, 2, 8, 6, 8, 15, 0),
+	 RK_COMPOSITE(SCLK_DDRCLK, "clk_ddrphy4x_src", mux_dpll_vpll0_vpll1_p, 1, 6, 2, 0, 3, 0, 10, 0),
+	 RK_FACTOR_GATE(0, "clk_ddr_stdby_div4", "clk_ddrphy4x",0,1, 4, 0, 13,0),
+	 RK_COMPNODIV(0, "clk_ddrstdby", mux_ddrstdby_p, 1, 8, 1, 4, 14, 0),
+	 RK_FRACTION(0, "clk_rtc32k_frac", "xin24m", 3, 4, 3, 0),
+	 RK_MUX(0, "clk_rtc32k_div_src", mux_vpll0_vpll1_p, 2, 10, 1, 0),
+	 RK_COMPNOMUX(0, "clk_rtc32k_div", "clk_rtc32k_div_src", 4, 0, 16, 4, 2, 0),
+	 RK_COMPOSITE(0, "clk_usbphy_ref_src", mux_dpll_vpll0_p, 72, 6, 1, 0, 6, 4, 7, 0),
+	 RK_COMPNODIV(SCLK_USBPHY_REF, "clk_usbphy_ref", mux_usbphy_ref_p, 72, 7, 1, 4, 8, 0),
+	 RK_COMPOSITE(0, "clk_wifi_src", mux_wifi_src_p, 44, 6, 1, 0, 6, 4, 0, 0),
+	 RK_COMPNODIV(SCLK_WIFI, "clk_wifi", mux_wifi_p, 44, 7, 1, 4, 1, 0),
+	 RK_COMPNODIV(0, "clk_audio_src", mux_vpll0_vpll1_xin24m_p, 45, 6, 2, 10, 0, 0),
+	 RK_COMPNOMUX(HCLK_AUDIO, "hclk_audio", "clk_audio_src", 45, 0, 5, 10, 1, 0),
+	 RK_COMPNOMUX(PCLK_AUDIO, "pclk_audio", "clk_audio_src", 45, 8, 5, 10, 2, 0),
+	 RK_COMPOSITE(0, "clk_pdm_src", mux_vpll0_vpll1_xin24m_p, 46, 8, 2, 0, 7, 10, 3, 0),
+	 RK_FRACTION(0, "clk_pdm_frac", "clk_pdm_src", 47, 10, 4, 0),
+	 RK_MUX(0, "clk_pdm_mux", mux_pdm_p, 46, 15, 1, 0),
+	 RK_COMPOSITE(SCLK_I2S0_8CH_TX_SRC, "clk_i2s0_8ch_tx_src", mux_vpll0_vpll1_xin24m_p, 52, 8, 2, 0, 7, 10, 12, 0),
+	 RK_FRACTION(0, "clk_i2s0_8ch_tx_frac", "clk_i2s0_8ch_tx_src", 53, 10, 13, 0),
+	 RK_COMPNODIV(SCLK_I2S0_8CH_TX, "clk_i2s0_8ch_tx", mux_i2s0_8ch_tx_rx_p, 52, 12, 1, 10, 14, 0),
+	 RK_COMPNODIV(SCLK_I2S0_8CH_TX_OUT, "clk_i2s0_8ch_tx_out", mux_i2s0_8ch_tx_out_p, 52, 15, 1, 10, 15, 0),
+	 RK_COMPOSITE(SCLK_I2S0_8CH_RX_SRC, "clk_i2s0_8ch_rx_src", mux_vpll0_vpll1_xin24m_p, 54, 8, 2, 0, 7, 11, 0, 0),
+	 RK_FRACTION(0, "clk_i2s0_8ch_rx_frac", "clk_i2s0_8ch_rx_src", 55, 11, 1, 0),
+	 RK_COMPNODIV(SCLK_I2S0_8CH_RX, "clk_i2s0_8ch_rx", mux_i2s0_8ch_rx_tx_p, 54, 12, 1, 11, 2, 0),
+	 RK_COMPOSITE(SCLK_I2S1_8CH_TX_SRC, "clk_i2s1_8ch_tx_src", mux_vpll0_vpll1_xin24m_p, 56, 8, 2, 0, 7, 11, 4, 0),
+	 RK_FRACTION(0, "clk_i2s1_8ch_tx_frac", "clk_i2s1_8ch_tx_src", 57, 11, 5, 0),
+	 RK_COMPNODIV(SCLK_I2S1_8CH_TX, "clk_i2s1_8ch_tx", mux_i2s1_8ch_tx_rx_p, 56, 12, 1, 11, 6, 0),
+	 RK_COMPNODIV(SCLK_I2S1_8CH_TX_OUT, "clk_i2s1_8ch_tx_out", mux_i2s1_8ch_tx_out_p, 56, 15, 1, 11, 7, 0),
+	 RK_COMPOSITE(SCLK_I2S1_8CH_RX_SRC, "clk_i2s1_8ch_rx_src", mux_vpll0_vpll1_xin24m_p, 58, 8, 2, 0, 7, 11, 8, 0),
+	 RK_FRACTION(0, "clk_i2s1_8ch_rx_frac", "clk_i2s1_8ch_rx_src", 59, 11, 9, 0),
+	 RK_COMPNODIV(SCLK_I2S1_8CH_RX, "clk_i2s1_8ch_rx", mux_i2s1_8ch_rx_tx_p, 58, 12, 1, 11, 10, 0),
+	 RK_COMPOSITE(SCLK_I2S2_8CH_TX_SRC, "clk_i2s2_8ch_tx_src", mux_vpll0_vpll1_xin24m_p, 60, 8, 2, 0, 7, 11, 12, 0),
+	 RK_FRACTION(0, "clk_i2s2_8ch_tx_frac", "clk_i2s2_8ch_tx_src", 61, 11, 13, 0),
+	 RK_COMPNODIV(SCLK_I2S2_8CH_TX, "clk_i2s2_8ch_tx", mux_i2s2_8ch_tx_rx_p, 60, 12, 1, 11, 14, 0),
+	 RK_COMPNODIV(SCLK_I2S2_8CH_TX_OUT, "clk_i2s2_8ch_tx_out", mux_i2s2_8ch_tx_out_p, 60, 15, 1, 11, 15, 0),
+	 RK_COMPOSITE(SCLK_I2S2_8CH_RX_SRC, "clk_i2s2_8ch_rx_src", mux_vpll0_vpll1_xin24m_p, 62, 8, 2, 0, 7, 12, 0, 0),
+	 RK_FRACTION(0, "clk_i2s2_8ch_rx_frac", "clk_i2s2_8ch_rx_src", 63, 12, 1, 0),
+	 RK_COMPNODIV(SCLK_I2S2_8CH_RX, "clk_i2s2_8ch_rx", mux_i2s2_8ch_rx_tx_p, 62, 12, 1, 12, 2, 0),
+	 RK_COMPOSITE(SCLK_I2S3_8CH_TX_SRC, "clk_i2s3_8ch_tx_src", mux_vpll0_vpll1_xin24m_p, 64, 8, 2, 0, 7, 12, 4, 0),
+	 RK_FRACTION(0, "clk_i2s3_8ch_tx_frac", "clk_i2s3_8ch_tx_src", 65, 12, 5, 0),
+	 RK_COMPNODIV(SCLK_I2S3_8CH_TX, "clk_i2s3_8ch_tx", mux_i2s3_8ch_tx_rx_p, 64, 12, 1, 12, 6, 0),
+	 RK_COMPNODIV(SCLK_I2S3_8CH_TX_OUT, "clk_i2s3_8ch_tx_out", mux_i2s3_8ch_tx_out_p, 64, 15, 1, 12, 7, 0),
+	 RK_COMPOSITE(SCLK_I2S3_8CH_RX_SRC, "clk_i2s3_8ch_rx_src", mux_vpll0_vpll1_xin24m_p, 66, 8, 2, 0, 7, 12, 8, 0),
+	 RK_FRACTION(0, "clk_i2s3_8ch_rx_frac", "clk_i2s3_8ch_rx_src", 67, 12, 9, 0),
+	 RK_COMPNODIV(SCLK_I2S3_8CH_RX, "clk_i2s3_8ch_rx", mux_i2s3_8ch_rx_tx_p, 66, 12, 1, 12, 10, 0),
+	 RK_COMPOSITE(SCLK_I2S0_2CH_SRC, "clk_i2s0_2ch_src", mux_vpll0_vpll1_xin24m_p, 68, 8, 2, 0, 7, 12, 12, 0),
+	 RK_FRACTION(0, "clk_i2s0_2ch_frac", "clk_i2s0_2ch_src", 69, 12, 13, 0),
+	 RK_COMPNODIV(SCLK_I2S0_2CH_OUT, "clk_i2s0_2ch_out", mux_i2s0_2ch_out_p, 68, 15, 1, 12, 15, 0),
+	 RK_COMPOSITE(SCLK_I2S1_2CH_SRC, "clk_i2s1_2ch_src", mux_vpll0_vpll1_xin24m_p, 70, 8, 2, 0, 7, 13, 0, 0),
+	 RK_FRACTION(0, "clk_i2s1_2ch_frac", "clk_i2s1_2ch_src", 71, 13, 1, 0),
+	 RK_COMPNODIV(SCLK_I2S1_2CH_OUT, "clk_i2s1_2ch_out", mux_i2s1_2ch_out_p, 70, 15, 1, 13, 3, 0),
+	 RK_COMPOSITE(SCLK_SPDIF_TX_DIV, "clk_spdif_tx_div", mux_vpll0_vpll1_xin24m_p, 48, 8, 2, 0, 7, 10, 6, 0),
+	 RK_COMPOSITE(SCLK_SPDIF_TX_DIV50, "clk_spdif_tx_div50", mux_vpll0_vpll1_xin24m_p, 48, 8, 2, 0, 7, 10, 6, 0),
+	 RK_MUX(0, "clk_spdif_tx_src", mux_spdif_tx_src_p, 48, 12, 1, 0),
+	 RK_FRACTION(0, "clk_spdif_tx_frac", "clk_spdif_tx_src", 49, 10, 7, 0),
+	 RK_COMPOSITE(SCLK_SPDIF_RX_DIV, "clk_spdif_rx_div", mux_vpll0_vpll1_xin24m_p, 50, 8, 2, 0, 7, 10, 9, 0),
+	 RK_COMPOSITE(SCLK_SPDIF_RX_DIV50, "clk_spdif_rx_div50", mux_vpll0_vpll1_xin24m_p, 50, 8, 2, 0, 7, 10, 9, 0),
+	 RK_MUX(0, "clk_spdif_rx_src", mux_spdif_rx_src_p, 50, 14, 1, 0),
+	 RK_FRACTION(0, "clk_spdif_rx_frac", "clk_spdif_rx_src", 51, 10, 10, 0),
+	 RK_FACTOR(ACLK_DMAC0, "aclk_dmac0", "aclk_bus", 1, 1),
+	 RK_FACTOR(ACLK_DMAC1, "aclk_dmac1", "aclk_bus", 1, 1),
+	 RK_FACTOR(PCLK_WDT, "pclk_wdt", "pclk_bus", 1, 1),
+	 RK_MUX(SCLK_I2S0_8CH_TX_MUX, "clk_i2s0_8ch_tx_mux", mux_i2s0_8ch_tx_p, 52, 10, 2, 0),
+	 RK_MUX(SCLK_I2S0_8CH_RX_MUX, "clk_i2s0_8ch_rx_mux", mux_i2s0_8ch_rx_p, 54, 10, 2, 0),
+	 RK_MUX(SCLK_I2S1_8CH_TX_MUX, "clk_i2s1_8ch_tx_mux", mux_i2s1_8ch_tx_p, 56, 10, 2, 0),
+	 RK_MUX(SCLK_I2S1_8CH_RX_MUX, "clk_i2s1_8ch_rx_mux", mux_i2s1_8ch_rx_p, 58, 10, 2, 0),
+	 RK_MUX(SCLK_I2S2_8CH_TX_MUX, "clk_i2s2_8ch_tx_mux", mux_i2s2_8ch_tx_p, 60, 10, 2, 0),
+	 RK_MUX(SCLK_I2S2_8CH_RX_MUX, "clk_i2s2_8ch_rx_mux", mux_i2s2_8ch_rx_p, 62, 10, 2, 0),
+	 RK_MUX(SCLK_I2S3_8CH_TX_MUX, "clk_i2s3_8ch_tx_mux", mux_i2s3_8ch_tx_p, 64, 10, 2, 0),
+	 RK_MUX(SCLK_I2S3_8CH_RX_MUX, "clk_i2s3_8ch_rx_mux", mux_i2s3_8ch_rx_p, 66, 10, 2, 0),
+	 RK_MUX(0, "clk_i2s0_2ch_mux", mux_i2s0_2ch_p, 68, 10, 2, 0),
+	 RK_MUX(0, "clk_i2s1_2ch_mux", mux_i2s1_2ch_p, 70, 10, 2, 0),
+	 RK_MUX(0, "clk_spdif_tx_mux", mux_spdif_tx_p, 48, 14, 2, 0),
+	 RK_MUX(0, "clk_spdif_rx_mux", mux_spdif_rx_p, 50, 15, 1, 0),
+};
+
+/* GATES */
+static struct rk_cru_gate rk3308_gates[] = {
+ RK_GATE(0, "apll_core", "apll", 0, 0),
+ RK_GATE(0, "vpll0_core", "vpll0", 0, 0),
+ RK_GATE(0, "vpll1_core", "vpll1", 0, 0),
+// RK_GATE(0, "clk_jtag", "jtag_clkin", 0, 3),
+ RK_GATE(SCLK_PVTM_CORE, "clk_pvtm_core", "xin24m", 0, 4),
+ RK_GATE(PCLK_DDR, "pclk_ddr", "pclk_bus", 4, 15),
+ RK_GATE(SCLK_UART0, "clk_uart0", "clk_uart0_mux", 1, 12),
+ RK_GATE(SCLK_UART1, "clk_uart1", "clk_uart1_mux", 2, 0),
+ RK_GATE(SCLK_UART2, "clk_uart2", "clk_uart2_mux", 2, 4),
+ RK_GATE(SCLK_UART3, "clk_uart3", "clk_uart3_mux", 2, 8),
+ RK_GATE(SCLK_UART4, "clk_uart4", "clk_uart4_mux", 2, 12),
+ RK_GATE(SCLK_TIMER0, "sclk_timer0", "xin24m", 3, 10),
+ RK_GATE(SCLK_TIMER1, "sclk_timer1", "xin24m", 3, 11),
+ RK_GATE(SCLK_TIMER2, "sclk_timer2", "xin24m", 3, 12),
+ RK_GATE(SCLK_TIMER3, "sclk_timer3", "xin24m", 3, 13),
+ RK_GATE(SCLK_TIMER4, "sclk_timer4", "xin24m", 3, 14),
+ RK_GATE(SCLK_TIMER5, "sclk_timer5", "xin24m", 3, 15),
+ RK_GATE(SCLK_CPU_BOOST, "clk_cpu_boost", "xin24m", 3, 9),
+ RK_GATE(DCLK_VOP, "dclk_vop", "dclk_vop_mux", 1, 8),
+ RK_GATE(SCLK_OTG_ADP, "clk_otg_adp", "clk_rtc32k", 8, 13),
+ RK_GATE(SCLK_MAC_REF, "clk_mac_ref", "clk_mac", 9, 1),
+ RK_GATE(SCLK_MAC_RX_TX, "clk_mac_rx_tx", "clk_mac", 9, 0),
+ RK_GATE(0, "clk_ddr_mon_timer", "xin24m", 0, 12),
+ RK_GATE(0, "clk_ddr_mon", "clk_ddrphy1x_out", 4, 10),
+ RK_GATE(0, "clk_ddr_upctrl", "clk_ddrphy1x_out", 4, 11),
+ RK_GATE(0, "clk_ddr_msch", "clk_ddrphy1x_out", 4, 12),
+ RK_GATE(0, "clk_ddr_msch_peribus", "clk_ddrphy1x_out", 4, 13),
+ RK_GATE(0, "clk_ddrphy4x", "clk_ddrphy4x_src", 0, 11),
+ RK_GATE(PCLK_PMU, "pclk_pmu", "pclk_bus", 4, 5),
+ RK_GATE(SCLK_PMU, "clk_pmu", "pclk_bus", 4, 6),
+ RK_GATE(0, "clk_wifi_dpll", "dpll", 15, 2),
+ RK_GATE(0, "clk_wifi_vpll0", "vpll0", 15, 3),
+ RK_GATE(0, "clk_wifi_osc", "xin24m", 15, 4),
+ RK_GATE(SCLK_PVTM_PMU, "clk_pvtm_pmu", "xin24m", 4, 4),
+ RK_GATE(SCLK_PDM, "clk_pdm", "clk_pdm_mux", 10, 5),
+ RK_GATE(SCLK_I2S0_8CH_RX_OUT, "clk_i2s0_8ch_rx_out", "clk_i2s0_8ch_rx", 11, 3),
+ RK_GATE(SCLK_I2S1_8CH_RX_OUT, "clk_i2s1_8ch_rx_out", "clk_i2s1_8ch_rx", 11, 11),
+ RK_GATE(SCLK_I2S2_8CH_RX_OUT, "clk_i2s2_8ch_rx_out", "clk_i2s2_8ch_rx", 12, 3),
+ RK_GATE(SCLK_I2S3_8CH_RX_OUT, "clk_i2s3_8ch_rx_out", "clk_i2s3_8ch_rx", 12, 11),
+ RK_GATE(SCLK_I2S0_2CH, "clk_i2s0_2ch", "clk_i2s0_2ch_mux", 12, 14),
+ RK_GATE(SCLK_I2S1_2CH, "clk_i2s1_2ch", "clk_i2s1_2ch_mux", 13, 2),
+ RK_GATE(SCLK_SPDIF_TX, "clk_spdif_tx", "clk_spdif_tx_mux", 10, 8),
+ RK_GATE(SCLK_SPDIF_RX, "clk_spdif_rx", "clk_spdif_rx_mux", 10, 11),
+ RK_GATE(0, "aclk_core_niu", "aclk_core", 0, 5),
+ RK_GATE(0, "pclk_core_dbg_niu", "aclk_core", 0, 6),
+ RK_GATE(0, "pclk_core_dbg_daplite", "pclk_core_dbg", 0, 7),
+ RK_GATE(0, "aclk_core_perf", "pclk_core_dbg", 0, 8),
+ RK_GATE(0, "pclk_core_grf", "pclk_core_dbg", 0, 9),
+ RK_GATE(0, "aclk_peri_niu", "aclk_peri", 9, 2),
+ RK_GATE(0, "aclk_peribus_niu", "aclk_peri", 9, 3),
+ RK_GATE(ACLK_MAC, "aclk_mac", "aclk_peri", 9, 4),
+ RK_GATE(0, "hclk_peri_niu", "hclk_peri", 9, 5),
+ RK_GATE(HCLK_NANDC, "hclk_nandc", "hclk_peri", 9, 6),
+ RK_GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_peri", 9, 7),
+ RK_GATE(HCLK_SDIO, "hclk_sdio", "hclk_peri", 9, 8),
+ RK_GATE(HCLK_EMMC, "hclk_emmc", "hclk_peri", 9, 9),
+ RK_GATE(HCLK_SFC, "hclk_sfc", "hclk_peri", 9, 10),
+ RK_GATE(HCLK_OTG, "hclk_otg", "hclk_peri", 9, 11),
+ RK_GATE(HCLK_HOST, "hclk_host", "hclk_peri", 9, 12),
+ RK_GATE(HCLK_HOST_ARB, "hclk_host_arb", "hclk_peri", 9, 13),
+ RK_GATE(0, "pclk_peri_niu", "pclk_peri", 9, 14),
+ RK_GATE(PCLK_MAC, "pclk_mac", "pclk_peri", 9, 15),
+ RK_GATE(0, "hclk_audio_niu", "hclk_audio", 14, 0),
+ RK_GATE(HCLK_PDM, "hclk_pdm", "hclk_audio", 14, 1),
+ RK_GATE(HCLK_SPDIFTX, "hclk_spdiftx", "hclk_audio", 14, 2),
+ RK_GATE(HCLK_SPDIFRX, "hclk_spdifrx", "hclk_audio", 14, 3),
+ RK_GATE(HCLK_I2S0_8CH, "hclk_i2s0_8ch", "hclk_audio", 14, 4),
+ RK_GATE(HCLK_I2S1_8CH, "hclk_i2s1_8ch", "hclk_audio", 14, 5),
+ RK_GATE(HCLK_I2S2_8CH, "hclk_i2s2_8ch", "hclk_audio", 14, 6),
+ RK_GATE(HCLK_I2S3_8CH, "hclk_i2s3_8ch", "hclk_audio", 14, 7),
+ RK_GATE(HCLK_I2S0_2CH, "hclk_i2s0_2ch", "hclk_audio", 14, 8),
+ RK_GATE(HCLK_I2S1_2CH, "hclk_i2s1_2ch", "hclk_audio", 14, 9),
+ RK_GATE(HCLK_VAD, "hclk_vad", "hclk_audio", 14, 10),
+ RK_GATE(0, "pclk_audio_niu", "pclk_audio", 14, 11),
+ RK_GATE(PCLK_ACODEC, "pclk_acodec", "pclk_audio", 14, 12),
+ RK_GATE(0, "aclk_bus_niu", "aclk_bus", 5, 0),
+ RK_GATE(0, "aclk_intmem", "aclk_bus", 5, 1),
+ RK_GATE(ACLK_CRYPTO, "aclk_crypto", "aclk_bus", 5, 2),
+ RK_GATE(ACLK_VOP, "aclk_vop", "aclk_bus", 5, 3),
+ RK_GATE(0, "aclk_gic", "aclk_bus", 5, 4),
+ RK_GATE(0, "hclk_bus_niu", "hclk_bus", 5, 5),
+ RK_GATE(0, "hclk_rom", "hclk_bus", 5, 6),
+ RK_GATE(HCLK_CRYPTO, "hclk_crypto", "hclk_bus", 5, 7),
+ RK_GATE(HCLK_VOP, "hclk_vop", "hclk_bus", 5, 8),
+ RK_GATE(0, "pclk_bus_niu", "pclk_bus", 5, 9),
+ RK_GATE(PCLK_UART0, "pclk_uart0", "pclk_bus", 5, 10),
+ RK_GATE(PCLK_UART1, "pclk_uart1", "pclk_bus", 5, 11),
+ RK_GATE(PCLK_UART2, "pclk_uart2", "pclk_bus", 5, 12),
+ RK_GATE(PCLK_UART3, "pclk_uart3", "pclk_bus", 5, 13),
+ RK_GATE(PCLK_UART4, "pclk_uart4", "pclk_bus", 5, 14),
+ RK_GATE(PCLK_I2C0, "pclk_i2c0", "pclk_bus", 5, 15),
+ RK_GATE(PCLK_I2C1, "pclk_i2c1", "pclk_bus", 6, 0),
+ RK_GATE(PCLK_I2C2, "pclk_i2c2", "pclk_bus", 6, 1),
+ RK_GATE(PCLK_I2C3, "pclk_i2c3", "pclk_bus", 6, 2),
+ RK_GATE(PCLK_PWM0, "pclk_pwm0", "pclk_bus", 6, 3),
+ RK_GATE(PCLK_SPI0, "pclk_spi0", "pclk_bus", 6, 4),
+ RK_GATE(PCLK_SPI1, "pclk_spi1", "pclk_bus", 6, 5),
+ RK_GATE(PCLK_SPI2, "pclk_spi2", "pclk_bus", 6, 6),
+ RK_GATE(PCLK_SARADC, "pclk_saradc", "pclk_bus", 6, 7),
+ RK_GATE(PCLK_TSADC, "pclk_tsadc", "pclk_bus", 6, 8),
+ RK_GATE(PCLK_TIMER, "pclk_timer", "pclk_bus", 6, 9),
+ RK_GATE(PCLK_OTP_NS, "pclk_otp_ns", "pclk_bus", 6, 10),
+ RK_GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_bus", 6, 12),
+ RK_GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_bus", 6, 13),
+ RK_GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_bus", 6, 14),
+ RK_GATE(PCLK_GPIO3, "pclk_gpio3", "pclk_bus", 6, 15),
+ RK_GATE(PCLK_GPIO4, "pclk_gpio4", "pclk_bus", 7, 0),
+ RK_GATE(PCLK_SGRF, "pclk_sgrf", "pclk_bus", 7, 1),
+ RK_GATE(PCLK_GRF, "pclk_grf", "pclk_bus", 7, 2),
+ RK_GATE(PCLK_USBSD_DET, "pclk_usbsd_det", "pclk_bus", 7, 3),
+ RK_GATE(PCLK_DDR_UPCTL, "pclk_ddr_upctl", "pclk_bus", 7, 4),
+ RK_GATE(PCLK_DDR_MON, "pclk_ddr_mon", "pclk_bus", 7, 5),
+ RK_GATE(PCLK_DDRPHY, "pclk_ddrphy", "pclk_bus", 7, 6),
+ RK_GATE(PCLK_DDR_STDBY, "pclk_ddr_stdby", "pclk_bus", 7, 7),
+ RK_GATE(PCLK_USB_GRF, "pclk_usb_grf", "pclk_bus", 7, 8),
+ RK_GATE(PCLK_CRU, "pclk_cru", "pclk_bus", 7, 9),
+ RK_GATE(PCLK_OTP_PHY, "pclk_otp_phy", "pclk_bus", 7, 10),
+ RK_GATE(PCLK_CPU_BOOST, "pclk_cpu_boost", "pclk_bus", 7, 11),
+ RK_GATE(PCLK_PWM1, "pclk_pwm1", "pclk_bus", 7, 12),
+ RK_GATE(PCLK_PWM2, "pclk_pwm2", "pclk_bus", 7, 13),
+ RK_GATE(PCLK_CAN, "pclk_can", "pclk_bus", 7, 14),
+ RK_GATE(PCLK_OWIRE, "pclk_owire", "pclk_bus", 7, 15),
+};
+
+
+static int
+rk3308_cru_probe(device_t dev)
+{
+
+	if (!ofw_bus_status_okay(dev))
+		return (ENXIO);
+
+	if (ofw_bus_is_compatible(dev, "rockchip,rk3308-cru")) {
+		device_set_desc(dev, "Rockchip RK3308 Clock & Reset Unit");
+		return (BUS_PROBE_DEFAULT);
+	}
+	return (ENXIO);
+}
+
+static int
+rk3308_cru_attach(device_t dev)
+{
+	struct rk_cru_softc *sc;
+
+	sc = device_get_softc(dev);
+	sc->dev = dev;
+	sc->clks = rk3308_clks;
+	sc->nclks = nitems(rk3308_clks);
+	sc->gates = rk3308_gates;
+	sc->ngates = nitems(rk3308_gates);
+	sc->reset_offset = 0x400;
+	sc->reset_num = 478;
+
+	return (rk_cru_attach(dev));
+}
+
+static device_method_t methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		rk3308_cru_probe),
+	DEVMETHOD(device_attach,	rk3308_cru_attach),
+
+	DEVMETHOD_END
+};
+
+DEFINE_CLASS_1(rk3308_cru, rk3308_cru_driver, methods,
+    sizeof(struct rk_cru_softc), rk_cru_driver);
+
+EARLY_DRIVER_MODULE(rk3308_cru, simplebus, rk3308_cru_driver,
+    0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
diff --git a/sys/arm64/conf/std.rockchip b/sys/arm64/conf/std.rockchip
--- a/sys/arm64/conf/std.rockchip
+++ b/sys/arm64/conf/std.rockchip
@@ -6,6 +6,8 @@
 options 	SOC_ROCKCHIP_RK3328
 options 	SOC_ROCKCHIP_RK3399
 options 	SOC_ROCKCHIP_RK3568
+options         SOC_ROCKCHIP_RK3308
+
 
 # GPIO / PINCTRL
 device		dwgpio			# Synopsys DesignWare APB GPIO Controller
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.