Path: blob/main/sys/arm/ti/am335x/am335x_dmtpps.c
101200 views
/*-1* Copyright (c) 2015 Ian lepore <[email protected]>2* All rights reserved.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9* 2. Redistributions in binary form must reproduce the above copyright10* notice, this list of conditions and the following disclaimer in the11* documentation and/or other materials provided with the distribution.12*13* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND14* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE15* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE16* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE17* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL18* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS19* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)20* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT21* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY22* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF23* SUCH DAMAGE.24*/2526/*27* AM335x PPS driver using DMTimer capture.28*29* Note that this PPS driver does not use an interrupt. Instead it uses the30* hardware's ability to latch the timer's count register in response to a31* signal on an IO pin. Each of timers 4-7 have an associated pin, and this32* code allows any one of those to be used.33*34* The timecounter routines in kern_tc.c call the pps poll routine periodically35* to see if a new counter value has been latched. When a new value has been36* latched, the only processing done in the poll routine is to capture the37* current set of timecounter timehands (done with pps_capture()) and the38* latched value from the timer. The remaining work (done by pps_event() while39* holding a mutex) is scheduled to be done later in a non-interrupt context.40*/4142#include <sys/cdefs.h>43#include "opt_platform.h"4445#include <sys/param.h>46#include <sys/systm.h>47#include <sys/bus.h>48#include <sys/conf.h>49#include <sys/kernel.h>50#include <sys/lock.h>51#include <sys/module.h>52#include <sys/malloc.h>53#include <sys/mutex.h>54#include <sys/rman.h>55#include <sys/timepps.h>56#include <sys/timetc.h>57#include <machine/bus.h>5859#include <dev/ofw/openfirm.h>60#include <dev/ofw/ofw_bus.h>61#include <dev/ofw/ofw_bus_subr.h>62#include <dev/clk/clk.h>6364#include <arm/ti/ti_sysc.h>65#include <arm/ti/ti_pinmux.h>66#include <arm/ti/am335x/am335x_scm_padconf.h>6768#include "am335x_dmtreg.h"6970#define PPS_CDEV_NAME "dmtpps"7172struct dmtpps_softc {73device_t dev;74int mem_rid;75struct resource * mem_res;76int tmr_num; /* N from hwmod str "timerN" */77char tmr_name[12]; /* "DMTimerN" */78uint32_t tclr; /* Cached TCLR register. */79struct timecounter tc;80int pps_curmode; /* Edge mode now set in hw. */81struct cdev * pps_cdev;82struct pps_state pps_state;83struct mtx pps_mtx;84clk_t clk_fck;85uint64_t sysclk_freq;86};8788static int dmtpps_tmr_num; /* Set by probe() */8990/* List of compatible strings for FDT tree */91static struct ofw_compat_data compat_data[] = {92{"ti,am335x-timer", 1},93{"ti,am335x-timer-1ms", 1},94{NULL, 0},95};96SIMPLEBUS_PNP_INFO(compat_data);9798/*99* A table relating pad names to the hardware timer number they can be mux'd to.100*/101struct padinfo {102char * ballname;103int tmr_num;104};105static struct padinfo dmtpps_padinfo[] = {106{"GPMC_ADVn_ALE", 4},107{"I2C0_SDA", 4},108{"MII1_TX_EN", 4},109{"XDMA_EVENT_INTR0", 4},110{"GPMC_BEn0_CLE", 5},111{"MDC", 5},112{"MMC0_DAT3", 5},113{"UART1_RTSn", 5},114{"GPMC_WEn", 6},115{"MDIO", 6},116{"MMC0_DAT2", 6},117{"UART1_CTSn", 6},118{"GPMC_OEn_REn", 7},119{"I2C0_SCL", 7},120{"UART0_CTSn", 7},121{"XDMA_EVENT_INTR1", 7},122{NULL, 0}123};124125/*126* This is either brilliantly user-friendly, or utterly lame...127*128* The am335x chip is used on the popular Beaglebone boards. Those boards have129* pins for all four capture-capable timers available on the P8 header. Allow130* users to configure the input pin by giving the name of the header pin.131*/132struct nicknames {133const char * nick;134const char * name;135};136static struct nicknames dmtpps_pin_nicks[] = {137{"P8-7", "GPMC_ADVn_ALE"},138{"P8-9", "GPMC_BEn0_CLE"},139{"P8-10", "GPMC_WEn"},140{"P8-8", "GPMC_OEn_REn",},141{NULL, NULL}142};143144#define DMTIMER_READ4(sc, reg) bus_read_4((sc)->mem_res, (reg))145#define DMTIMER_WRITE4(sc, reg, val) bus_write_4((sc)->mem_res, (reg), (val))146147/*148* Translate a short friendly case-insensitive name to its canonical name.149*/150static const char *151dmtpps_translate_nickname(const char *nick)152{153struct nicknames *nn;154155for (nn = dmtpps_pin_nicks; nn->nick != NULL; nn++)156if (strcasecmp(nick, nn->nick) == 0)157return nn->name;158return (nick);159}160161/*162* See if our tunable is set to the name of the input pin. If not, that's NOT163* an error, return 0. If so, try to configure that pin as a timer capture164* input pin, and if that works, then we have our timer unit number and if it165* fails that IS an error, return -1.166*/167static int168dmtpps_find_tmr_num_by_tunable(void)169{170struct padinfo *pi;171char iname[20];172char muxmode[12];173const char * ballname;174int err;175176if (!TUNABLE_STR_FETCH("hw.am335x_dmtpps.input", iname, sizeof(iname)))177return (0);178ballname = dmtpps_translate_nickname(iname);179for (pi = dmtpps_padinfo; pi->ballname != NULL; pi++) {180if (strcmp(ballname, pi->ballname) != 0)181continue;182snprintf(muxmode, sizeof(muxmode), "timer%d", pi->tmr_num);183err = ti_pinmux_padconf_set(pi->ballname, muxmode,184PADCONF_INPUT);185if (err != 0) {186printf("am335x_dmtpps: unable to configure capture pin "187"for %s to input mode\n", muxmode);188return (-1);189} else if (bootverbose) {190printf("am335x_dmtpps: configured pin %s as input "191"for %s\n", iname, muxmode);192}193return (pi->tmr_num);194}195196/* Invalid name in the tunable, that's an error. */197printf("am335x_dmtpps: unknown pin name '%s'\n", iname);198return (-1);199}200201/*202* Ask the pinmux driver whether any pin has been configured as a TIMER4..TIMER7203* input pin. If so, return the timer number, if not return 0.204*/205static int206dmtpps_find_tmr_num_by_padconf(void)207{208int err;209unsigned int padstate;210const char * padmux;211struct padinfo *pi;212char muxmode[12];213214for (pi = dmtpps_padinfo; pi->ballname != NULL; pi++) {215err = ti_pinmux_padconf_get(pi->ballname, &padmux, &padstate);216snprintf(muxmode, sizeof(muxmode), "timer%d", pi->tmr_num);217if (err == 0 && (padstate & RXACTIVE) != 0 &&218strcmp(muxmode, padmux) == 0)219return (pi->tmr_num);220}221/* Nothing found, not an error. */222return (0);223}224225/*226* Figure out which hardware timer number to use based on input pin227* configuration. This is done just once, the first time probe() runs.228*/229static int230dmtpps_find_tmr_num(void)231{232int tmr_num;233234if ((tmr_num = dmtpps_find_tmr_num_by_tunable()) == 0)235tmr_num = dmtpps_find_tmr_num_by_padconf();236237if (tmr_num <= 0) {238printf("am335x_dmtpps: PPS driver not enabled: unable to find "239"or configure a capture input pin\n");240tmr_num = -1; /* Must return non-zero to prevent re-probing. */241}242return (tmr_num);243}244245static void246dmtpps_set_hw_capture(struct dmtpps_softc *sc, bool force_off)247{248int newmode;249250if (force_off)251newmode = 0;252else253newmode = sc->pps_state.ppsparam.mode & PPS_CAPTUREASSERT;254255if (newmode == sc->pps_curmode)256return;257sc->pps_curmode = newmode;258259if (newmode == PPS_CAPTUREASSERT)260sc->tclr |= DMT_TCLR_CAPTRAN_LOHI;261else262sc->tclr &= ~DMT_TCLR_CAPTRAN_MASK;263DMTIMER_WRITE4(sc, DMT_TCLR, sc->tclr);264}265266static unsigned267dmtpps_get_timecount(struct timecounter *tc)268{269struct dmtpps_softc *sc;270271sc = tc->tc_priv;272273return (DMTIMER_READ4(sc, DMT_TCRR));274}275276static void277dmtpps_poll(struct timecounter *tc)278{279struct dmtpps_softc *sc;280281sc = tc->tc_priv;282283/*284* If a new value has been latched we've got a PPS event. Capture the285* timecounter data, then override the capcount field (pps_capture()286* populates it from the current DMT_TCRR register) with the latched287* value from the TCAR1 register.288*289* Note that we don't have the TCAR interrupt enabled, but the hardware290* still provides the status bits in the "RAW" status register even when291* they're masked from generating an irq. However, when clearing the292* TCAR status to re-arm the capture for the next second, we have to293* write to the IRQ status register, not the RAW register. Quirky.294*295* We do not need to hold a lock while capturing the pps data, because296* it is captured into an area of the pps_state struct which is read297* only by pps_event(). We do need to hold a lock while calling298* pps_event(), because it manipulates data which is also accessed from299* the ioctl(2) context by userland processes.300*/301if (DMTIMER_READ4(sc, DMT_IRQSTATUS_RAW) & DMT_IRQ_TCAR) {302pps_capture(&sc->pps_state);303sc->pps_state.capcount = DMTIMER_READ4(sc, DMT_TCAR1);304DMTIMER_WRITE4(sc, DMT_IRQSTATUS, DMT_IRQ_TCAR);305306mtx_lock_spin(&sc->pps_mtx);307pps_event(&sc->pps_state, PPS_CAPTUREASSERT);308mtx_unlock_spin(&sc->pps_mtx);309}310}311312static int313dmtpps_open(struct cdev *dev, int flags, int fmt,314struct thread *td)315{316struct dmtpps_softc *sc;317318sc = dev->si_drv1;319320/*321* Begin polling for pps and enable capture in the hardware whenever the322* device is open. Doing this stuff again is harmless if this isn't the323* first open.324*/325sc->tc.tc_poll_pps = dmtpps_poll;326dmtpps_set_hw_capture(sc, false);327328return 0;329}330331static int332dmtpps_close(struct cdev *dev, int flags, int fmt,333struct thread *td)334{335struct dmtpps_softc *sc;336337sc = dev->si_drv1;338339/*340* Stop polling and disable capture on last close. Use the force-off341* flag to override the configured mode and turn off the hardware.342*/343sc->tc.tc_poll_pps = NULL;344dmtpps_set_hw_capture(sc, true);345346return 0;347}348349static int350dmtpps_ioctl(struct cdev *dev, u_long cmd, caddr_t data,351int flags, struct thread *td)352{353struct dmtpps_softc *sc;354int err;355356sc = dev->si_drv1;357358/* Let the kernel do the heavy lifting for ioctl. */359mtx_lock_spin(&sc->pps_mtx);360err = pps_ioctl(cmd, data, &sc->pps_state);361mtx_unlock_spin(&sc->pps_mtx);362if (err != 0)363return (err);364365/*366* The capture mode could have changed, set the hardware to whatever367* mode is now current. Effectively a no-op if nothing changed.368*/369dmtpps_set_hw_capture(sc, false);370371return (err);372}373374static struct cdevsw dmtpps_cdevsw = {375.d_version = D_VERSION,376.d_open = dmtpps_open,377.d_close = dmtpps_close,378.d_ioctl = dmtpps_ioctl,379.d_name = PPS_CDEV_NAME,380};381382static int383dmtpps_probe(device_t dev)384{385int tmr_num;386uint64_t rev_address;387388if (!ofw_bus_status_okay(dev))389return (ENXIO);390391if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)392return (ENXIO);393394/*395* If we haven't chosen which hardware timer to use yet, go do that now.396* We need to know that to decide whether to return success for this397* hardware timer instance or not.398*/399if (dmtpps_tmr_num == 0)400dmtpps_tmr_num = dmtpps_find_tmr_num();401402/*403* Figure out which hardware timer is being probed and see if it matches404* the configured timer number determined earlier.405*/406rev_address = ti_sysc_get_rev_address(device_get_parent(dev));407switch (rev_address) {408case DMTIMER1_1MS_REV:409tmr_num = 1;410break;411case DMTIMER2_REV:412tmr_num = 2;413break;414case DMTIMER3_REV:415tmr_num = 3;416break;417case DMTIMER4_REV:418tmr_num = 4;419break;420case DMTIMER5_REV:421tmr_num = 5;422break;423case DMTIMER6_REV:424tmr_num = 6;425break;426case DMTIMER7_REV:427tmr_num = 7;428break;429default:430return (ENXIO);431}432433if (dmtpps_tmr_num != tmr_num)434return (ENXIO);435436device_set_descf(dev, "AM335x PPS-Capture DMTimer%d", tmr_num);437438return(BUS_PROBE_DEFAULT);439}440441static int442dmtpps_attach(device_t dev)443{444struct dmtpps_softc *sc;445struct make_dev_args mda;446int err;447clk_t sys_clkin;448uint64_t rev_address;449450sc = device_get_softc(dev);451sc->dev = dev;452453/* Figure out which hardware timer this is and set the name string. */454rev_address = ti_sysc_get_rev_address(device_get_parent(dev));455switch (rev_address) {456case DMTIMER1_1MS_REV:457sc->tmr_num = 1;458break;459case DMTIMER2_REV:460sc->tmr_num = 2;461break;462case DMTIMER3_REV:463sc->tmr_num = 3;464break;465case DMTIMER4_REV:466sc->tmr_num = 4;467break;468case DMTIMER5_REV:469sc->tmr_num = 5;470break;471case DMTIMER6_REV:472sc->tmr_num = 6;473break;474case DMTIMER7_REV:475sc->tmr_num = 7;476break;477}478snprintf(sc->tmr_name, sizeof(sc->tmr_name), "DMTimer%d", sc->tmr_num);479480/* expect one clock */481err = clk_get_by_ofw_index(dev, 0, 0, &sc->clk_fck);482if (err != 0) {483device_printf(dev, "Cant find clock index 0. err: %d\n", err);484return (ENXIO);485}486487err = clk_get_by_name(dev, "sys_clkin_ck@40", &sys_clkin);488if (err != 0) {489device_printf(dev, "Cant find sys_clkin_ck@40 err: %d\n", err);490return (ENXIO);491}492493/* Select M_OSC as DPLL parent */494err = clk_set_parent_by_clk(sc->clk_fck, sys_clkin);495if (err != 0) {496device_printf(dev, "Cant set mux to CLK_M_OSC\n");497return (ENXIO);498}499500/* Enable clocks and power on the device. */501err = ti_sysc_clock_enable(device_get_parent(dev));502if (err != 0) {503device_printf(dev, "Cant enable sysc clkctrl, err %d\n", err);504return (ENXIO);505}506507/* Get the base clock frequency. */508err = clk_get_freq(sc->clk_fck, &sc->sysclk_freq);509if (err != 0) {510device_printf(dev, "Cant get sysclk frequency, err %d\n", err);511return (ENXIO);512}513/* Request the memory resources. */514sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,515&sc->mem_rid, RF_ACTIVE);516if (sc->mem_res == NULL) {517return (ENXIO);518}519520/*521* Configure the timer pulse/capture pin to input/capture mode. This is522* required in addition to configuring the pin as input with the pinmux523* controller (which was done via fdt data or tunable at probe time).524*/525sc->tclr = DMT_TCLR_GPO_CFG;526DMTIMER_WRITE4(sc, DMT_TCLR, sc->tclr);527528/* Set up timecounter hardware, start it. */529DMTIMER_WRITE4(sc, DMT_TSICR, DMT_TSICR_RESET);530while (DMTIMER_READ4(sc, DMT_TIOCP_CFG) & DMT_TIOCP_RESET)531continue;532533sc->tclr |= DMT_TCLR_START | DMT_TCLR_AUTOLOAD;534DMTIMER_WRITE4(sc, DMT_TLDR, 0);535DMTIMER_WRITE4(sc, DMT_TCRR, 0);536DMTIMER_WRITE4(sc, DMT_TCLR, sc->tclr);537538/* Register the timecounter. */539sc->tc.tc_name = sc->tmr_name;540sc->tc.tc_get_timecount = dmtpps_get_timecount;541sc->tc.tc_counter_mask = ~0u;542sc->tc.tc_frequency = sc->sysclk_freq;543sc->tc.tc_quality = 1000;544sc->tc.tc_priv = sc;545546tc_init(&sc->tc);547548/*549* Indicate our PPS capabilities. Have the kernel init its part of the550* pps_state struct and add its capabilities.551*552* While the hardware has a mode to capture each edge, it's not clear we553* can use it that way, because there's only a single interrupt/status554* bit to say something was captured, but not which edge it was. For555* now, just say we can only capture assert events (the positive-going556* edge of the pulse).557*/558mtx_init(&sc->pps_mtx, "dmtpps", NULL, MTX_SPIN);559sc->pps_state.flags = PPSFLAG_MTX_SPIN;560sc->pps_state.ppscap = PPS_CAPTUREASSERT;561sc->pps_state.driver_abi = PPS_ABI_VERSION;562sc->pps_state.driver_mtx = &sc->pps_mtx;563pps_init_abi(&sc->pps_state);564565/* Create the PPS cdev. */566make_dev_args_init(&mda);567mda.mda_flags = MAKEDEV_WAITOK;568mda.mda_devsw = &dmtpps_cdevsw;569mda.mda_cr = NULL;570mda.mda_uid = UID_ROOT;571mda.mda_gid = GID_WHEEL;572mda.mda_mode = 0600;573mda.mda_unit = device_get_unit(dev);574mda.mda_si_drv1 = sc;575if ((err = make_dev_s(&mda, &sc->pps_cdev, PPS_CDEV_NAME)) != 0) {576device_printf(dev, "Failed to create cdev %s\n", PPS_CDEV_NAME);577return (err);578}579580if (bootverbose)581device_printf(sc->dev, "Using %s for PPS device /dev/%s\n",582sc->tmr_name, PPS_CDEV_NAME);583584return (0);585}586587static int588dmtpps_detach(device_t dev)589{590591/*592* There is no way to remove a timecounter once it has been registered,593* even if it's not in use, so we can never detach. If we were594* dynamically loaded as a module this will prevent unloading.595*/596return (EBUSY);597}598599static device_method_t dmtpps_methods[] = {600DEVMETHOD(device_probe, dmtpps_probe),601DEVMETHOD(device_attach, dmtpps_attach),602DEVMETHOD(device_detach, dmtpps_detach),603{ 0, 0 }604};605606static driver_t dmtpps_driver = {607"am335x_dmtpps",608dmtpps_methods,609sizeof(struct dmtpps_softc),610};611612DRIVER_MODULE(am335x_dmtpps, simplebus, dmtpps_driver, 0, 0);613MODULE_DEPEND(am335x_dmtpps, ti_sysc, 1, 1, 1);614615616