Date: Thu, 15 May 2014 22:50:06 +0000 (UTC) From: Ian Lepore <ian@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r266201 - in stable/10/sys: arm/arm arm/conf arm/freescale/imx arm/freescale/vybrid arm/include boot/fdt/dts Message-ID: <201405152250.s4FMo6tG051305@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: ian Date: Thu May 15 22:50:06 2014 New Revision: 266201 URL: http://svnweb.freebsd.org/changeset/base/266201 Log: MFC r261982, r261987, r262123, r262244, r262278, r262280, r262353, r262354, r262355, r262419, Add Vybrid driver for Synchronous Audio Interface (SAI). Decrease SAI buffer size. Handle eDMA interrupt on running channel only. Give the physmem fdt helper routines static linkage since no global definition of them is provided anywhere. Add imx6 early printf support, wrapped in #if 0 because it's rarely needed. Add basic cpu frequency control and temperature monitoring to imx6_anatop. Add the FREEBSD_BOOT_LOADER option so that a loaded DTB passed in from ubldr will actually get used. Create a generic IMX6 kernel config, then fix it to have an ident line. Don't force imx6 bootverbose on anymore, it can be set from ubldr now. Added: stable/10/sys/arm/conf/IMX6 - copied, changed from r262354, head/sys/arm/conf/IMX6 stable/10/sys/arm/freescale/vybrid/vf_sai.c - copied, changed from r261982, head/sys/arm/freescale/vybrid/vf_sai.c Modified: stable/10/sys/arm/arm/machdep.c stable/10/sys/arm/conf/WANDBOARD.common stable/10/sys/arm/freescale/imx/imx6_anatop.c stable/10/sys/arm/freescale/imx/imx6_anatopreg.h stable/10/sys/arm/freescale/imx/imx6_anatopvar.h stable/10/sys/arm/freescale/imx/imx6_machdep.c stable/10/sys/arm/freescale/vybrid/files.vybrid stable/10/sys/arm/include/physmem.h stable/10/sys/boot/fdt/dts/imx6.dtsi stable/10/sys/boot/fdt/dts/vybrid.dtsi Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/arm/arm/machdep.c ============================================================================== --- stable/10/sys/arm/arm/machdep.c Thu May 15 22:35:04 2014 (r266200) +++ stable/10/sys/arm/arm/machdep.c Thu May 15 22:50:06 2014 (r266201) @@ -1167,7 +1167,6 @@ initarm(struct arm_boot_params *abp) (((uint32_t)(lastaddr) - KERNVIRTADDR) + PAGE_MASK) & ~PAGE_MASK, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); - /* Map L1 directory and allocated L2 page tables */ pmap_map_chunk(l1pagetable, kernel_l1pt.pv_va, kernel_l1pt.pv_pa, L1_TABLE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE); Copied and modified: stable/10/sys/arm/conf/IMX6 (from r262354, head/sys/arm/conf/IMX6) ============================================================================== --- head/sys/arm/conf/IMX6 Sun Feb 23 01:48:07 2014 (r262354, copy source) +++ stable/10/sys/arm/conf/IMX6 Thu May 15 22:50:06 2014 (r266201) @@ -17,6 +17,7 @@ # # $FreeBSD$ +ident IMX6 include "../freescale/imx/std.imx6" options HZ=250 # Scheduling quantum is 4 milliseconds. Modified: stable/10/sys/arm/conf/WANDBOARD.common ============================================================================== --- stable/10/sys/arm/conf/WANDBOARD.common Thu May 15 22:35:04 2014 (r266200) +++ stable/10/sys/arm/conf/WANDBOARD.common Thu May 15 22:50:06 2014 (r266201) @@ -153,3 +153,5 @@ device mmcsd # SDCard disk device device ffec # Freescale Fast Ethernet Controller +options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8) + Modified: stable/10/sys/arm/freescale/imx/imx6_anatop.c ============================================================================== --- stable/10/sys/arm/freescale/imx/imx6_anatop.c Thu May 15 22:35:04 2014 (r266200) +++ stable/10/sys/arm/freescale/imx/imx6_anatop.c Thu May 15 22:50:06 2014 (r266201) @@ -1,5 +1,6 @@ /*- * Copyright (c) 2013 Ian Lepore <ian@freebsd.org> + * Copyright (c) 2014 Steven Lawrance <stl@koffein.net> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,6 +30,8 @@ __FBSDID("$FreeBSD$"); /* * Analog PLL and power regulator driver for Freescale i.MX6 family of SoCs. + * Also, temperature montoring and cpu frequency control. It was Freescale who + * kitchen-sinked this device, not us. :) * * We don't really do anything with analog PLLs, but the registers for * controlling them belong to the same block as the power regulator registers. @@ -42,11 +45,19 @@ __FBSDID("$FreeBSD$"); * I have no idea where the "anatop" name comes from. It's in the standard DTS * source describing i.MX6 SoCs, and in the linux and u-boot code which comes * from Freescale, but it's not in the SoC manual. + * + * Note that temperature values throughout this code are handled in two types of + * units. Items with '_cnt' in the name use the hardware temperature count + * units (higher counts are lower temperatures). Items with '_val' in the name + * are deci-Celcius, which are converted to/from deci-Kelvins in the sysctl + * handlers (dK is the standard unit for temperature in sysctl). */ #include <sys/param.h> #include <sys/systm.h> +#include <sys/callout.h> #include <sys/kernel.h> +#include <sys/sysctl.h> #include <sys/module.h> #include <sys/bus.h> #include <sys/rman.h> @@ -56,68 +67,410 @@ __FBSDID("$FreeBSD$"); #include <machine/bus.h> +#include <arm/freescale/fsl_ocotpreg.h> +#include <arm/freescale/fsl_ocotpvar.h> #include <arm/freescale/imx/imx6_anatopreg.h> #include <arm/freescale/imx/imx6_anatopvar.h> +static struct resource_spec imx6_anatop_spec[] = { + { SYS_RES_MEMORY, 0, RF_ACTIVE }, + { SYS_RES_IRQ, 0, RF_ACTIVE }, + { -1, 0 } +}; +#define MEMRES 0 +#define IRQRES 1 + struct imx6_anatop_softc { device_t dev; - struct resource *mem_res; + struct resource *res[2]; + uint32_t cpu_curhz; + uint32_t cpu_curmhz; + uint32_t cpu_minhz; + uint32_t cpu_maxhz; + uint32_t refosc_hz; + void *temp_intrhand; + uint32_t temp_high_val; + uint32_t temp_high_cnt; + uint32_t temp_last_cnt; + uint32_t temp_room_cnt; + struct callout temp_throttle_callout; + sbintime_t temp_throttle_delay; + uint32_t temp_throttle_reset_cnt; + uint32_t temp_throttle_trigger_cnt; + uint32_t temp_throttle_val; }; static struct imx6_anatop_softc *imx6_anatop_sc; +/* + * Table of CPU max frequencies. This is indexed by the max frequency value + * (0-3) from the ocotp CFG3 register. + */ +static uint32_t imx6_cpu_maxhz_tab[] = { + 792000000, 852000000, 996000000, 1200000000 +}; + +#define TZ_ZEROC 2732 /* deci-Kelvin <-> deci-Celcius offset. */ + uint32_t imx6_anatop_read_4(bus_size_t offset) { - return (bus_read_4(imx6_anatop_sc->mem_res, offset)); + KASSERT(imx6_anatop_sc != NULL, ("imx6_anatop_read_4 sc NULL")); + + return (bus_read_4(imx6_anatop_sc->res[MEMRES], offset)); } void imx6_anatop_write_4(bus_size_t offset, uint32_t value) { - bus_write_4(imx6_anatop_sc->mem_res, offset, value); + KASSERT(imx6_anatop_sc != NULL, ("imx6_anatop_write_4 sc NULL")); + + bus_write_4(imx6_anatop_sc->res[MEMRES], offset, value); +} + +static inline uint32_t +cpufreq_hz_from_div(struct imx6_anatop_softc *sc, uint32_t div) +{ + + return (sc->refosc_hz * (div / 2)); +} + +static inline uint32_t +cpufreq_hz_to_div(struct imx6_anatop_softc *sc, uint32_t cpu_hz) +{ + + return (cpu_hz / (sc->refosc_hz / 2)); +} + +static inline uint32_t +cpufreq_actual_hz(struct imx6_anatop_softc *sc, uint32_t cpu_hz) +{ + + return (cpufreq_hz_from_div(sc, cpufreq_hz_to_div(sc, cpu_hz))); +} + +static void +cpufreq_set_clock(struct imx6_anatop_softc * sc, uint32_t cpu_newhz) +{ + uint32_t div, timeout, wrk32; + const uint32_t mindiv = 54; + const uint32_t maxdiv = 108; + + /* + * Clip the requested frequency to the configured max, then clip the + * resulting divisor to the documented min/max values. + */ + cpu_newhz = min(cpu_newhz, sc->cpu_maxhz); + div = cpufreq_hz_to_div(sc, cpu_newhz); + if (div < mindiv) + div = mindiv; + else if (div > maxdiv) + div = maxdiv; + sc->cpu_curhz = cpufreq_hz_from_div(sc, div); + sc->cpu_curmhz = sc->cpu_curhz / 1000000; + + /* + * I can't find a documented procedure for changing the ARM PLL divisor, + * but some trial and error came up with this: + * - Set the bypass clock source to REF_CLK_24M (source #0). + * - Set the PLL into bypass mode; cpu should now be running at 24mhz. + * - Change the divisor. + * - Wait for the LOCK bit to come on; it takes ~50 loop iterations. + * - Turn off bypass mode; cpu should now be running at cpu_newhz. + */ + imx6_anatop_write_4(IMX6_ANALOG_CCM_PLL_ARM_CLR, + IMX6_ANALOG_CCM_PLL_ARM_CLK_SRC_MASK); + imx6_anatop_write_4(IMX6_ANALOG_CCM_PLL_ARM_SET, + IMX6_ANALOG_CCM_PLL_ARM_BYPASS); + + wrk32 = imx6_anatop_read_4(IMX6_ANALOG_CCM_PLL_ARM); + wrk32 &= ~IMX6_ANALOG_CCM_PLL_ARM_DIV_MASK; + wrk32 |= div; + imx6_anatop_write_4(IMX6_ANALOG_CCM_PLL_ARM, wrk32); + + timeout = 10000; + while ((imx6_anatop_read_4(IMX6_ANALOG_CCM_PLL_ARM) & + IMX6_ANALOG_CCM_PLL_ARM_LOCK) == 0) + if (--timeout == 0) + panic("imx6_set_cpu_clock(): PLL never locked"); + + imx6_anatop_write_4(IMX6_ANALOG_CCM_PLL_ARM_CLR, + IMX6_ANALOG_CCM_PLL_ARM_BYPASS); +} + +static void +cpufreq_initialize(struct imx6_anatop_softc *sc) +{ + uint32_t cfg3speed; + struct sysctl_ctx_list *ctx; + + ctx = device_get_sysctl_ctx(sc->dev); + SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), + OID_AUTO, "cpu_mhz", CTLFLAG_RD, &sc->cpu_curmhz, 0, + "CPU frequency in MHz"); + + /* + * XXX 24mhz shouldn't be hard-coded, should get this from imx6_ccm + * (even though in the real world it will always be 24mhz). Oh wait a + * sec, I never wrote imx6_ccm. + */ + sc->refosc_hz = 24000000; + + /* + * Get the maximum speed this cpu can be set to. The values in the + * OCOTP CFG3 register are not documented in the reference manual. + * The following info was in an archived email found via web search: + * - 2b'11: 1200000000Hz; + * - 2b'10: 996000000Hz; + * - 2b'01: 852000000Hz; -- i.MX6Q Only, exclusive with 996MHz. + * - 2b'00: 792000000Hz; + */ + cfg3speed = (fsl_ocotp_read_4(FSL_OCOTP_CFG3) & + FSL_OCOTP_CFG3_SPEED_MASK) >> FSL_OCOTP_CFG3_SPEED_SHIFT; + + sc->cpu_minhz = cpufreq_actual_hz(sc, imx6_cpu_maxhz_tab[0]); + sc->cpu_maxhz = cpufreq_actual_hz(sc, imx6_cpu_maxhz_tab[cfg3speed]); + + /* + * Set the CPU to maximum speed. + * + * We won't have thermal throttling until interrupts are enabled, but we + * want to run at full speed through all the device init stuff. This + * basically assumes that a single core can't overheat before interrupts + * are enabled; empirical testing shows that to be a safe assumption. + */ + cpufreq_set_clock(sc, sc->cpu_maxhz); + device_printf(sc->dev, "CPU frequency %uMHz\n", sc->cpu_curmhz); +} + +static inline uint32_t +temp_from_count(struct imx6_anatop_softc *sc, uint32_t count) +{ + + return (((sc->temp_high_val - (count - sc->temp_high_cnt) * + (sc->temp_high_val - 250) / + (sc->temp_room_cnt - sc->temp_high_cnt)))); +} + +static inline uint32_t +temp_to_count(struct imx6_anatop_softc *sc, uint32_t temp) +{ + + return ((sc->temp_room_cnt - sc->temp_high_cnt) * + (sc->temp_high_val - temp) / (sc->temp_high_val - 250) + + sc->temp_high_cnt); +} + +static void +temp_update_count(struct imx6_anatop_softc *sc) +{ + uint32_t val; + + val = imx6_anatop_read_4(IMX6_ANALOG_TEMPMON_TEMPSENSE0); + if (!(val & IMX6_ANALOG_TEMPMON_TEMPSENSE0_VALID)) + return; + sc->temp_last_cnt = + (val & IMX6_ANALOG_TEMPMON_TEMPSENSE0_TEMP_CNT_MASK) >> + IMX6_ANALOG_TEMPMON_TEMPSENSE0_TEMP_CNT_SHIFT; } static int -imx6_anatop_detach(device_t dev) +temp_sysctl_handler(SYSCTL_HANDLER_ARGS) { - struct imx6_anatop_softc *sc; + struct imx6_anatop_softc *sc = arg1; + uint32_t t; - sc = device_get_softc(dev); + temp_update_count(sc); - if (sc->mem_res != NULL) - bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res); + t = temp_from_count(sc, sc->temp_last_cnt) + TZ_ZEROC; - return (0); + return (sysctl_handle_int(oidp, &t, 0, req)); +} + +static int +temp_throttle_sysctl_handler(SYSCTL_HANDLER_ARGS) +{ + struct imx6_anatop_softc *sc = arg1; + int err; + uint32_t temp; + + temp = sc->temp_throttle_val + TZ_ZEROC; + err = sysctl_handle_int(oidp, &temp, 0, req); + if (temp < TZ_ZEROC) + return (ERANGE); + temp -= TZ_ZEROC; + if (err != 0 || req->newptr == NULL || temp == sc->temp_throttle_val) + return (err); + + /* Value changed, update counts in softc and hardware. */ + sc->temp_throttle_val = temp; + sc->temp_throttle_trigger_cnt = temp_to_count(sc, sc->temp_throttle_val); + sc->temp_throttle_reset_cnt = temp_to_count(sc, sc->temp_throttle_val - 100); + imx6_anatop_write_4(IMX6_ANALOG_TEMPMON_TEMPSENSE0_CLR, + IMX6_ANALOG_TEMPMON_TEMPSENSE0_ALARM_MASK); + imx6_anatop_write_4(IMX6_ANALOG_TEMPMON_TEMPSENSE0_SET, + (sc->temp_throttle_trigger_cnt << + IMX6_ANALOG_TEMPMON_TEMPSENSE0_ALARM_SHIFT)); + return (err); +} + +static void +tempmon_gofast(struct imx6_anatop_softc *sc) +{ + + if (sc->cpu_curhz < sc->cpu_maxhz) { + cpufreq_set_clock(sc, sc->cpu_maxhz); + } +} + +static void +tempmon_goslow(struct imx6_anatop_softc *sc) +{ + + if (sc->cpu_curhz > sc->cpu_minhz) { + cpufreq_set_clock(sc, sc->cpu_minhz); + } +} + +static int +tempmon_intr(void *arg) +{ + struct imx6_anatop_softc *sc = arg; + + /* + * XXX Note that this code doesn't currently run (for some mysterious + * reason we just never get an interrupt), so the real monitoring is + * done by tempmon_throttle_check(). + */ + tempmon_goslow(sc); + /* XXX Schedule callout to speed back up eventually. */ + return (FILTER_HANDLED); +} + +static void +tempmon_throttle_check(void *arg) +{ + struct imx6_anatop_softc *sc = arg; + + /* Lower counts are higher temperatures. */ + if (sc->temp_last_cnt < sc->temp_throttle_trigger_cnt) + tempmon_goslow(sc); + else if (sc->temp_last_cnt > (sc->temp_throttle_reset_cnt)) + tempmon_gofast(sc); + + callout_reset_sbt(&sc->temp_throttle_callout, sc->temp_throttle_delay, + 0, tempmon_throttle_check, sc, 0); + +} + +static void +initialize_tempmon(struct imx6_anatop_softc *sc) +{ + uint32_t cal; + struct sysctl_ctx_list *ctx; + + /* + * Fetch calibration data: a sensor count at room temperature (25C), + * a sensor count at a high temperature, and that temperature + */ + cal = fsl_ocotp_read_4(FSL_OCOTP_ANA1); + sc->temp_room_cnt = (cal & 0xFFF00000) >> 20; + sc->temp_high_cnt = (cal & 0x000FFF00) >> 8; + sc->temp_high_val = (cal & 0x000000FF) * 10; + + /* + * Throttle to a lower cpu freq at 10C below the "hot" temperature, and + * reset back to max cpu freq at 5C below the trigger. + */ + sc->temp_throttle_val = sc->temp_high_val - 100; + sc->temp_throttle_trigger_cnt = + temp_to_count(sc, sc->temp_throttle_val); + sc->temp_throttle_reset_cnt = + temp_to_count(sc, sc->temp_throttle_val - 50); + + /* + * Set the sensor to sample automatically at 16Hz (32.768KHz/0x800), set + * the throttle count, and begin making measurements. + */ + imx6_anatop_write_4(IMX6_ANALOG_TEMPMON_TEMPSENSE1, 0x0800); + imx6_anatop_write_4(IMX6_ANALOG_TEMPMON_TEMPSENSE0, + (sc->temp_throttle_trigger_cnt << + IMX6_ANALOG_TEMPMON_TEMPSENSE0_ALARM_SHIFT) | + IMX6_ANALOG_TEMPMON_TEMPSENSE0_MEASURE); + + /* + * XXX Note that the alarm-interrupt feature isn't working yet, so + * we'll use a callout handler to check at 10Hz. Make sure we have an + * initial temperature reading before starting up the callouts so we + * don't get a bogus reading of zero. + */ + while (sc->temp_last_cnt == 0) + temp_update_count(sc); + sc->temp_throttle_delay = 100 * SBT_1MS; + callout_init(&sc->temp_throttle_callout, 0); + callout_reset_sbt(&sc->temp_throttle_callout, sc->temp_throttle_delay, + 0, tempmon_throttle_check, sc, 0); + + ctx = device_get_sysctl_ctx(sc->dev); + SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), + OID_AUTO, "temperature", CTLTYPE_INT | CTLFLAG_RD, sc, 0, + temp_sysctl_handler, "IK", "Current die temperature"); + SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), + OID_AUTO, "throttle_temperature", CTLTYPE_INT | CTLFLAG_RW, sc, + 0, temp_throttle_sysctl_handler, "IK", + "Throttle CPU when exceeding this temperature"); +} + +static int +imx6_anatop_detach(device_t dev) +{ + + return (EBUSY); } static int imx6_anatop_attach(device_t dev) { struct imx6_anatop_softc *sc; - int err, rid; + int err; sc = device_get_softc(dev); + sc->dev = dev; /* Allocate bus_space resources. */ - rid = 0; - sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, - RF_ACTIVE); - if (sc->mem_res == NULL) { - device_printf(dev, "Cannot allocate memory resources\n"); + if (bus_alloc_resources(dev, imx6_anatop_spec, sc->res)) { + device_printf(dev, "Cannot allocate resources\n"); err = ENXIO; goto out; } + err = bus_setup_intr(dev, sc->res[IRQRES], INTR_TYPE_MISC | INTR_MPSAFE, + tempmon_intr, NULL, sc, &sc->temp_intrhand); + if (err != 0) + goto out; + imx6_anatop_sc = sc; + + /* + * Other code seen on the net sets this SELFBIASOFF flag around the same + * time the temperature sensor is set up, although it's unclear how the + * two are related (if at all). + */ + imx6_anatop_write_4(IMX6_ANALOG_PMU_MISC0_SET, + IMX6_ANALOG_PMU_MISC0_SELFBIASOFF); + + cpufreq_initialize(sc); + initialize_tempmon(sc); + err = 0; out: - if (err != 0) - imx6_anatop_detach(dev); + if (err != 0) { + bus_release_resources(dev, imx6_anatop_spec, sc->res); + } return (err); } @@ -129,7 +482,7 @@ imx6_anatop_probe(device_t dev) if (!ofw_bus_status_okay(dev)) return (ENXIO); - if (ofw_bus_is_compatible(dev, "fsl,imx6q-anatop") == 0) + if (ofw_bus_is_compatible(dev, "fsl,imx6q-anatop") == 0) return (ENXIO); device_set_desc(dev, "Freescale i.MX6 Analog PLLs and Power"); @@ -137,6 +490,16 @@ imx6_anatop_probe(device_t dev) return (BUS_PROBE_DEFAULT); } +uint32_t +imx6_get_cpu_clock() +{ + uint32_t div; + + div = imx6_anatop_read_4(IMX6_ANALOG_CCM_PLL_ARM) & + IMX6_ANALOG_CCM_PLL_ARM_DIV_MASK; + return (cpufreq_hz_from_div(imx6_anatop_sc, div)); +} + static device_method_t imx6_anatop_methods[] = { /* Device interface */ DEVMETHOD(device_probe, imx6_anatop_probe), Modified: stable/10/sys/arm/freescale/imx/imx6_anatopreg.h ============================================================================== --- stable/10/sys/arm/freescale/imx/imx6_anatopreg.h Thu May 15 22:35:04 2014 (r266200) +++ stable/10/sys/arm/freescale/imx/imx6_anatopreg.h Thu May 15 22:50:06 2014 (r266201) @@ -33,6 +33,10 @@ #define IMX6_ANALOG_CCM_PLL_ARM_SET 0x004 #define IMX6_ANALOG_CCM_PLL_ARM_CLR 0x008 #define IMX6_ANALOG_CCM_PLL_ARM_TOG 0x00C +#define IMX6_ANALOG_CCM_PLL_ARM_DIV_MASK 0x7F +#define IMX6_ANALOG_CCM_PLL_ARM_LOCK (1U << 31) +#define IMX6_ANALOG_CCM_PLL_ARM_BYPASS (1 << 16) +#define IMX6_ANALOG_CCM_PLL_ARM_CLK_SRC_MASK (0x03 << 16) #define IMX6_ANALOG_CCM_PLL_USB1 0x010 #define IMX6_ANALOG_CCM_PLL_USB1_SET 0x014 #define IMX6_ANALOG_CCM_PLL_USB1_CLR 0x018 @@ -81,6 +85,7 @@ #define IMX6_ANALOG_CCM_PFD_528_SET 0x104 #define IMX6_ANALOG_CCM_PFD_528_CLR 0x108 #define IMX6_ANALOG_CCM_PFD_528_TOG 0x10C + #define IMX6_ANALOG_PMU_REG_CORE 0x140 #define IMX6_ANALOG_PMU_REG2_TARG_SHIFT 18 #define IMX6_ANALOG_PMU_REG2_TARG_MASK \ @@ -92,14 +97,56 @@ #define IMX6_ANALOG_PMU_REG0_TARG_MASK \ (0x1f << IMX6_ANALOG_PMU_REG0_TARG_SHIFT) -#define IMX6_ANALOG_CCM_MISC0 0x150 -#define IMX6_ANALOG_CCM_MISC0_SET 0x154 -#define IMX6_ANALOG_CCM_MISC0_CLR 0x158 -#define IMX6_ANALOG_CCM_MISC0_TOG 0x15C -#define IMX6_ANALOG_CCM_MISC2 0x170 -#define IMX6_ANALOG_CCM_MISC2_SET 0x174 -#define IMX6_ANALOG_CCM_MISC2_CLR 0x178 -#define IMX6_ANALOG_CCM_MISC2_TOG 0x17C +#define IMX6_ANALOG_PMU_MISC0 0x150 +#define IMX6_ANALOG_PMU_MISC0_SET 0x154 +#define IMX6_ANALOG_PMU_MISC0_CLR 0x158 +#define IMX6_ANALOG_PMU_MISC0_TOG 0x15C +#define IMX6_ANALOG_PMU_MISC0_SELFBIASOFF (1 << 3) + +#define IMX6_ANALOG_PMU_MISC1 0x160 +#define IMX6_ANALOG_PMU_MISC1_SET 0x164 +#define IMX6_ANALOG_PMU_MISC1_CLR 0x168 +#define IMX6_ANALOG_PMU_MISC1_TOG 0x16C +#define IMX6_ANALOG_PMU_MISC1_IRQ_TEMPSENSE (1 << 29) + +#define IMX6_ANALOG_PMU_MISC2 0x170 +#define IMX6_ANALOG_PMU_MISC2_SET 0x174 +#define IMX6_ANALOG_PMU_MISC2_CLR 0x178 +#define IMX6_ANALOG_PMU_MISC2_TOG 0x17C + +/* + * Note that the ANALOG_CCM_MISCn registers are the same as the PMU_MISCn + * registers; some bits conceptually belong to the PMU and some to the CCM. + */ +#define IMX6_ANALOG_CCM_MISC0 IMX6_ANALOG_PMU_MISC0 +#define IMX6_ANALOG_CCM_MISC0_SET IMX6_ANALOG_PMU_MISC0_SET +#define IMX6_ANALOG_CCM_MISC0_CLR IMX6_ANALOG_PMU_MISC0_CLR +#define IMX6_ANALOG_CCM_MISC0_TOG IMX6_ANALOG_PMU_MISC0_TOG + +#define IMX6_ANALOG_CCM_MISC2 IMX6_ANALOG_PMU_MISC2 +#define IMX6_ANALOG_CCM_MISC2_SET IMX6_ANALOG_PMU_MISC2_SET +#define IMX6_ANALOG_CCM_MISC2_CLR IMX6_ANALOG_PMU_MISC2_CLR +#define IMX6_ANALOG_CCM_MISC2_TOG IMX6_ANALOG_PMU_MISC2_TOG + +#define IMX6_ANALOG_TEMPMON_TEMPSENSE0 0x180 +#define IMX6_ANALOG_TEMPMON_TEMPSENSE0_SET 0x184 +#define IMX6_ANALOG_TEMPMON_TEMPSENSE0_CLR 0x188 +#define IMX6_ANALOG_TEMPMON_TEMPSENSE0_TOG 0x18C +#define IMX6_ANALOG_TEMPMON_TEMPSENSE0_TOG 0x18C +#define IMX6_ANALOG_TEMPMON_TEMPSENSE0_ALARM_SHIFT 20 +#define IMX6_ANALOG_TEMPMON_TEMPSENSE0_ALARM_MASK \ + (0xfff << IMX6_ANALOG_TEMPMON_TEMPSENSE0_ALARM_SHIFT) +#define IMX6_ANALOG_TEMPMON_TEMPSENSE0_TEMP_CNT_SHIFT 8 +#define IMX6_ANALOG_TEMPMON_TEMPSENSE0_TEMP_CNT_MASK \ + (0xfff << IMX6_ANALOG_TEMPMON_TEMPSENSE0_TEMP_CNT_SHIFT) +#define IMX6_ANALOG_TEMPMON_TEMPSENSE0_VALID 0x4 +#define IMX6_ANALOG_TEMPMON_TEMPSENSE0_MEASURE 0x2 +#define IMX6_ANALOG_TEMPMON_TEMPSENSE0_POWER_DOWN 0x1 + +#define IMX6_ANALOG_TEMPMON_TEMPSENSE1 0x190 +#define IMX6_ANALOG_TEMPMON_TEMPSENSE1_SET 0x194 +#define IMX6_ANALOG_TEMPMON_TEMPSENSE1_CLR 0x198 +#define IMX6_ANALOG_TEMPMON_TEMPSENSE1_TOG 0x19C #define IMX6_ANALOG_USB1_VBUS_DETECT 0x1A0 #define IMX6_ANALOG_USB1_VBUS_DETECT_SET 0x1A4 Modified: stable/10/sys/arm/freescale/imx/imx6_anatopvar.h ============================================================================== --- stable/10/sys/arm/freescale/imx/imx6_anatopvar.h Thu May 15 22:35:04 2014 (r266200) +++ stable/10/sys/arm/freescale/imx/imx6_anatopvar.h Thu May 15 22:50:06 2014 (r266201) @@ -40,4 +40,6 @@ uint32_t imx6_anatop_read_4(bus_size_t _offset); void imx6_anatop_write_4(bus_size_t _offset, uint32_t _value); +uint32_t imx6_get_cpu_clock(void); + #endif Modified: stable/10/sys/arm/freescale/imx/imx6_machdep.c ============================================================================== --- stable/10/sys/arm/freescale/imx/imx6_machdep.c Thu May 15 22:35:04 2014 (r266200) +++ stable/10/sys/arm/freescale/imx/imx6_machdep.c Thu May 15 22:50:06 2014 (r266201) @@ -55,9 +55,6 @@ void initarm_early_init(void) { - /* XXX - Get rid of this stuff soon. */ - boothowto |= RB_VERBOSE|RB_MULTIPLE; - bootverbose = 1; } void @@ -190,3 +187,27 @@ u_int imx_soc_type() return (IMXSOC_6Q); } +/* + * Early putc routine for EARLY_PRINTF support. To use, add to kernel config: + * option SOCDEV_PA=0x02000000 + * option SOCDEV_VA=0x02000000 + * option EARLY_PRINTF + * Resist the temptation to change the #if 0 to #ifdef EARLY_PRINTF here. It + * makes sense now, but if multiple SOCs do that it will make early_putc another + * duplicate symbol to be eliminated on the path to a generic kernel. + */ +#if 0 +static void +imx6_early_putc(int c) +{ + volatile uint32_t * UART_STAT_REG = (uint32_t *)0x02020098; + volatile uint32_t * UART_TX_REG = (uint32_t *)0x02020040; + const uint32_t UART_TXRDY = (1 << 3); + + while ((*UART_STAT_REG & UART_TXRDY) == 0) + continue; + *UART_TX_REG = c; +} +early_putc_t *early_putc = imx6_early_putc; +#endif + Modified: stable/10/sys/arm/freescale/vybrid/files.vybrid ============================================================================== --- stable/10/sys/arm/freescale/vybrid/files.vybrid Thu May 15 22:35:04 2014 (r266200) +++ stable/10/sys/arm/freescale/vybrid/files.vybrid Thu May 15 22:50:06 2014 (r266201) @@ -29,4 +29,5 @@ arm/freescale/vybrid/vf_nfc.c optional arm/freescale/vybrid/vf_ehci.c optional ehci arm/freescale/vybrid/vf_gpio.c optional gpio arm/freescale/vybrid/vf_uart.c optional uart +arm/freescale/vybrid/vf_sai.c optional sound dev/ffec/if_ffec.c optional ffec Copied and modified: stable/10/sys/arm/freescale/vybrid/vf_sai.c (from r261982, head/sys/arm/freescale/vybrid/vf_sai.c) ============================================================================== --- head/sys/arm/freescale/vybrid/vf_sai.c Sun Feb 16 16:49:54 2014 (r261982, copy source) +++ stable/10/sys/arm/freescale/vybrid/vf_sai.c Thu May 15 22:50:06 2014 (r266201) @@ -396,7 +396,8 @@ sai_dma_intr(void *arg, int chn) if (sc->pos >= sc->dma_size) sc->pos -= sc->dma_size; - chn_intr(ch->channel); + if (ch->run) + chn_intr(ch->channel); return (0); } @@ -492,7 +493,7 @@ setup_dma(struct sc_pcminfo *scp) tcd->nbytes = 64; tcd->nmajor = 512; - tcd->smod = 18; /* dma_size range */ + tcd->smod = 17; /* dma_size range */ tcd->dmod = 0; tcd->esg = 0; tcd->soff = 0x4; @@ -523,6 +524,7 @@ saichan_trigger(kobj_t obj, void *data, #if 0 device_printf(scp->dev, "trigger start\n"); #endif + ch->run = 1; break; case PCMTRIG_STOP: @@ -530,6 +532,7 @@ saichan_trigger(kobj_t obj, void *data, #if 0 device_printf(scp->dev, "trigger stop or abort\n"); #endif + ch->run = 0; break; } @@ -720,7 +723,7 @@ sai_attach(device_t dev) scp->dev = dev; /* DMA */ - sc->dma_size = 262144; + sc->dma_size = 131072; /* * Must use dma_size boundary as modulo feature required. Modified: stable/10/sys/arm/include/physmem.h ============================================================================== --- stable/10/sys/arm/include/physmem.h Thu May 15 22:35:04 2014 (r266200) +++ stable/10/sys/arm/include/physmem.h Thu May 15 22:50:06 2014 (r266201) @@ -65,7 +65,7 @@ void arm_physmem_print_tables(void); #include <machine/ofw_machdep.h> -inline void +static inline void arm_physmem_hardware_regions(struct mem_region * mrptr, int mrcount) { while (mrcount--) { @@ -74,7 +74,7 @@ arm_physmem_hardware_regions(struct mem_ } } -inline void +static inline void arm_physmem_exclude_regions(struct mem_region * mrptr, int mrcount, uint32_t exflags) { Modified: stable/10/sys/boot/fdt/dts/imx6.dtsi ============================================================================== --- stable/10/sys/boot/fdt/dts/imx6.dtsi Thu May 15 22:35:04 2014 (r266200) +++ stable/10/sys/boot/fdt/dts/imx6.dtsi Thu May 15 22:50:06 2014 (r266201) @@ -97,6 +97,8 @@ anatop: anatop@020c8000 { compatible = "fsl,imx6q-anatop"; reg = <0x020c8000 0x1000>; + interrupt-parent = <&gic>; + interrupts = <49>; } gpt: timer@02098000 { Modified: stable/10/sys/boot/fdt/dts/vybrid.dtsi ============================================================================== --- stable/10/sys/boot/fdt/dts/vybrid.dtsi Thu May 15 22:35:04 2014 (r266200) +++ stable/10/sys/boot/fdt/dts/vybrid.dtsi Thu May 15 22:50:06 2014 (r266201) @@ -311,6 +311,9 @@ interrupt-parent = <&GIC>; status = "disabled"; edma-controller = <&edma1>; + edma-src-receive = < 8 >; + edma-src-transmit = < 9 >; + edma-mux-group = < 1 >; clock_names = "sai3", "cko1"; iomux_config = < 16 0x2 19 0x2
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201405152250.s4FMo6tG051305>