Browse Source

Merge branch 'freebsd/current/master' into hardened/current/master

* freebsd/current/master:
  Remove use of intr_config_hook from the am335x_pmic and tda19988 drivers. Long ago this was needed, but now low-level i2c controller drivers cleverly defer attachment of the bus until interrupts are enabled (if they require interrupts to function), so that every i2c slave device doesn't have to.
  The am335x_ehrpwm driver now requires the pwmbus_if interface, add it.
  Allow the sdhci timeout sysctl var to be set as a tunable.  Also, add a missing newline in a warning printf.
  allwinner: Add support to min/max in aw_clk_frac
  Remove some duplicate code that end up in r350844
  allwinner: Add a new clock aw_clk_m
  .gitignore: Add LINT kernel configurations generated into SRCDIR
  allwinner: Rework the BUS_PASS on drivers
  When responding to an interrupt in the am335x_pmic driver, use a taskqueue thread to do the work that involves i2c IO, which sleeps while the IO is in progress.
hardened/current/master
Oliver Pinter + 9 months ago
parent
commit
d51ebbf2e3
32 changed files with 593 additions and 135 deletions
  1. +16
    -0
      .gitignore
  2. +1
    -1
      sys/arm/allwinner/a10_sramc.c
  3. +1
    -1
      sys/arm/allwinner/a20/a20_cpu_cfg.c
  4. +1
    -1
      sys/arm/allwinner/aw_ccu.c
  5. +1
    -1
      sys/arm/allwinner/aw_gmacclk.c
  6. +1
    -1
      sys/arm/allwinner/aw_reset.c
  7. +2
    -2
      sys/arm/allwinner/aw_rsb.c
  8. +1
    -1
      sys/arm/allwinner/aw_rtc.c
  9. +1
    -1
      sys/arm/allwinner/aw_sid.c
  10. +1
    -1
      sys/arm/allwinner/aw_syscon.c
  11. +3
    -0
      sys/arm/allwinner/clkng/aw_ccung.c
  12. +3
    -0
      sys/arm/allwinner/clkng/aw_ccung.h
  13. +30
    -1
      sys/arm/allwinner/clkng/aw_clk.h
  14. +78
    -17
      sys/arm/allwinner/clkng/aw_clk_frac.c
  15. +3
    -0
      sys/arm/allwinner/clkng/aw_clk_frac.h
  16. +290
    -0
      sys/arm/allwinner/clkng/aw_clk_m.c
  17. +48
    -0
      sys/arm/allwinner/clkng/aw_clk_m.h
  18. +5
    -3
      sys/arm/allwinner/clkng/ccu_a10.c
  19. +1
    -1
      sys/arm/allwinner/clkng/ccu_a13.c
  20. +13
    -8
      sys/arm/allwinner/clkng/ccu_a31.c
  21. +45
    -49
      sys/arm/allwinner/clkng/ccu_a64.c
  22. +1
    -1
      sys/arm/allwinner/clkng/ccu_a83t.c
  23. +1
    -1
      sys/arm/allwinner/clkng/ccu_de2.c
  24. +9
    -5
      sys/arm/allwinner/clkng/ccu_h3.c
  25. +2
    -2
      sys/arm/allwinner/clkng/ccu_sun8i_r.c
  26. +1
    -0
      sys/arm/allwinner/files.allwinner
  27. +21
    -18
      sys/arm/ti/am335x/am335x_pmic.c
  28. +1
    -0
      sys/arm/ti/am335x/files.am335x
  29. +8
    -17
      sys/arm/ti/am335x/tda19988.c
  30. +1
    -0
      sys/conf/files.arm64
  31. +1
    -0
      sys/dev/extres/clk/clk.h
  32. +2
    -2
      sys/dev/sdhci/sdhci.c

+ 16
- 0
.gitignore View File

@@ -20,3 +20,19 @@ ID
.tags
cscope.out
?cscope.out
# Ignore LINT generated configs.
/sys/amd64/conf/LINT
/sys/amd64/conf/LINT-NOINET
/sys/amd64/conf/LINT-NOINET6
/sys/amd64/conf/LINT-NOIP
/sys/arm/conf/LINT
/sys/arm/conf/LINT-V5
/sys/arm/conf/LINT-V7
/sys/arm64/conf/LINT
/sys/i386/conf/LINT
/sys/i386/conf/LINT-NOINET
/sys/i386/conf/LINT-NOINET6
/sys/i386/conf/LINT-NOIP
/sys/powerpc/conf/LINT
/sys/powerpc/conf/LINT64
/sys/sparc64/conf/LINT

+ 1
- 1
sys/arm/allwinner/a10_sramc.c View File

@@ -116,7 +116,7 @@ static driver_t a10_sramc_driver = {
static devclass_t a10_sramc_devclass;

EARLY_DRIVER_MODULE(a10_sramc, simplebus, a10_sramc_driver, a10_sramc_devclass,
0, 0, BUS_PASS_RESOURCE + BUS_PASS_ORDER_EARLY);
0, 0, BUS_PASS_SUPPORTDEV + BUS_PASS_ORDER_FIRST);

int
a10_map_to_emac(void)

+ 1
- 1
sys/arm/allwinner/a20/a20_cpu_cfg.c View File

@@ -119,7 +119,7 @@ static driver_t a20_cpu_cfg_driver = {
static devclass_t a20_cpu_cfg_devclass;

EARLY_DRIVER_MODULE(a20_cpu_cfg, simplebus, a20_cpu_cfg_driver, a20_cpu_cfg_devclass, 0, 0,
BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE);
BUS_PASS_CPU + BUS_PASS_ORDER_FIRST);

uint64_t
a20_read_counter64(void)

+ 1
- 1
sys/arm/allwinner/aw_ccu.c View File

@@ -250,6 +250,6 @@ DEFINE_CLASS_1(aw_ccu, aw_ccu_driver, aw_ccu_methods,
static devclass_t aw_ccu_devclass;

EARLY_DRIVER_MODULE(aw_ccu, simplebus, aw_ccu_driver, aw_ccu_devclass,
0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
0, 0, BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE);

MODULE_VERSION(aw_ccu, 1);

+ 1
- 1
sys/arm/allwinner/aw_gmacclk.c View File

@@ -277,4 +277,4 @@ static driver_t aw_gmacclk_driver = {
static devclass_t aw_gmacclk_devclass;

EARLY_DRIVER_MODULE(aw_gmacclk, simplebus, aw_gmacclk_driver,
aw_gmacclk_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
aw_gmacclk_devclass, 0, 0, BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE);

+ 1
- 1
sys/arm/allwinner/aw_reset.c View File

@@ -162,5 +162,5 @@ static driver_t aw_reset_driver = {
static devclass_t aw_reset_devclass;

EARLY_DRIVER_MODULE(aw_reset, simplebus, aw_reset_driver, aw_reset_devclass,
0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
0, 0, BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE);
MODULE_VERSION(aw_reset, 1);

+ 2
- 2
sys/arm/allwinner/aw_rsb.c View File

@@ -494,9 +494,9 @@ static driver_t rsb_driver = {
static devclass_t rsb_devclass;

EARLY_DRIVER_MODULE(iicbus, rsb, iicbus_driver, iicbus_devclass, 0, 0,
BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE);
BUS_PASS_SUPPORTDEV + BUS_PASS_ORDER_MIDDLE);
EARLY_DRIVER_MODULE(rsb, simplebus, rsb_driver, rsb_devclass, 0, 0,
BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE);
BUS_PASS_SUPPORTDEV + BUS_PASS_ORDER_MIDDLE);
MODULE_VERSION(rsb, 1);
MODULE_DEPEND(rsb, iicbus, 1, 1, 1);
SIMPLEBUS_PNP_INFO(compat_data);

+ 1
- 1
sys/arm/allwinner/aw_rtc.c View File

@@ -185,7 +185,7 @@ static driver_t aw_rtc_driver = {
static devclass_t aw_rtc_devclass;

EARLY_DRIVER_MODULE(aw_rtc, simplebus, aw_rtc_driver, aw_rtc_devclass, 0, 0,
BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
BUS_PASS_RESOURCE + BUS_PASS_ORDER_FIRST);
MODULE_VERSION(aw_rtc, 1);
SIMPLEBUS_PNP_INFO(compat_data);


+ 1
- 1
sys/arm/allwinner/aw_sid.c View File

@@ -412,6 +412,6 @@ static driver_t aw_sid_driver = {
static devclass_t aw_sid_devclass;

EARLY_DRIVER_MODULE(aw_sid, simplebus, aw_sid_driver, aw_sid_devclass, 0, 0,
BUS_PASS_RESOURCE + BUS_PASS_ORDER_FIRST);
BUS_PASS_SUPPORTDEV + BUS_PASS_ORDER_FIRST);
MODULE_VERSION(aw_sid, 1);
SIMPLEBUS_PNP_INFO(compat_data);

+ 1
- 1
sys/arm/allwinner/aw_syscon.c View File

@@ -82,5 +82,5 @@ DEFINE_CLASS_1(aw_syscon, aw_syscon_driver, aw_syscon_methods,
static devclass_t aw_syscon_devclass;
/* aw_syscon needs to attach prior to if_awg */
EARLY_DRIVER_MODULE(aw_syscon, simplebus, aw_syscon_driver, aw_syscon_devclass,
0, 0, BUS_PASS_SUPPORTDEV + BUS_PASS_ORDER_MIDDLE);
0, 0, BUS_PASS_SCHEDULER + BUS_PASS_ORDER_LAST);
MODULE_VERSION(aw_syscon, 1);

+ 3
- 0
sys/arm/allwinner/clkng/aw_ccung.c View File

@@ -301,6 +301,9 @@ aw_ccung_attach(device_t dev)
case AW_CLK_NM:
aw_clk_nm_register(sc->clkdom, sc->clks[i].clk.nm);
break;
case AW_CLK_M:
aw_clk_m_register(sc->clkdom, sc->clks[i].clk.m);
break;
case AW_CLK_PREDIV_MUX:
aw_clk_prediv_mux_register(sc->clkdom,
sc->clks[i].clk.prediv_mux);

+ 3
- 0
sys/arm/allwinner/clkng/aw_ccung.h View File

@@ -31,6 +31,7 @@
#define __CCU_NG_H__

#include <arm/allwinner/clkng/aw_clk.h>
#include <arm/allwinner/clkng/aw_clk_m.h>
#include <arm/allwinner/clkng/aw_clk_nkmp.h>
#include <arm/allwinner/clkng/aw_clk_nm.h>
#include <arm/allwinner/clkng/aw_clk_prediv_mux.h>
@@ -48,6 +49,7 @@ enum aw_ccung_clk_type {
AW_CLK_NM,
AW_CLK_PREDIV_MUX,
AW_CLK_FRAC,
AW_CLK_M,
};

struct aw_ccung_clk {
@@ -60,6 +62,7 @@ struct aw_ccung_clk {
struct aw_clk_nm_def *nm;
struct aw_clk_prediv_mux_def *prediv_mux;
struct aw_clk_frac_def *frac;
struct aw_clk_m_def *m;
} clk;
};


+ 30
- 1
sys/arm/allwinner/clkng/aw_clk.h View File

@@ -66,6 +66,7 @@ struct aw_clk_init {
#define AW_CLK_SCALE_CHANGE 0x0010
#define AW_CLK_HAS_UPDATE 0x0040
#define AW_CLK_HAS_PREDIV 0x0080
#define AW_CLK_SET_PARENT 0x0100

#define AW_CLK_FACTOR_POWER_OF_TWO 0x0001
#define AW_CLK_FACTOR_ZERO_BASED 0x0002
@@ -313,13 +314,15 @@ aw_clk_factor_get_value(struct aw_clk_factor *factor, uint32_t raw)
_nshift, _nwidth, _nvalue, _nflags, \
_mshift, _mwidth, _mvalue, _mflags, \
_gate_shift, _lock_shift,_lock_retries, \
_flags, _freq0, _freq1, _mode_sel, _freq_sel) \
_flags, _freq0, _freq1, _mode_sel, _freq_sel, \
_min_freq, _max_freq) \
static struct aw_clk_frac_def _clkname = { \
.clkdef = { \
.id = _id, \
.name = _name, \
.parent_names = _pnames, \
.parent_cnt = nitems(_pnames), \
.flags = CLK_NODE_GLITCH_FREE, \
}, \
.offset = _offset, \
.n.shift = _nshift, \
@@ -338,6 +341,32 @@ aw_clk_factor_get_value(struct aw_clk_factor *factor, uint32_t raw)
.frac.freq1 = _freq1, \
.frac.mode_sel = _mode_sel, \
.frac.freq_sel = _freq_sel, \
.min_freq = _min_freq, \
.max_freq = _max_freq, \
}

#define M_CLK(_clkname, _id, _name, _pnames, \
_offset, \
_mshift, _mwidth, _mvalue, _mflags, \
_mux_shift, _mux_width, \
_gate_shift, \
_flags) \
static struct aw_clk_m_def _clkname = { \
.clkdef = { \
.id = _id, \
.name = _name, \
.parent_names = _pnames, \
.parent_cnt = nitems(_pnames), \
}, \
.offset = _offset, \
.mux_shift = _mux_shift, \
.m.shift = _mshift, \
.m.width = _mwidth, \
.m.value = _mvalue, \
.m.flags = _mflags, \
.mux_width = _mux_width, \
.gate_shift = _gate_shift, \
.flags = _flags, \
}

#define NM_CLK(_clkname, _id, _name, _pnames, \

+ 78
- 17
sys/arm/allwinner/clkng/aw_clk_frac.c View File

@@ -39,6 +39,9 @@ __FBSDID("$FreeBSD$");

#include "clkdev_if.h"

/* #define dprintf(format, arg...) printf("%s:(%s)" format, __func__, clknode_get_name(clk), arg) */
#define dprintf(format, arg...)

/*
* clknode for clocks matching the formula :
*
@@ -54,6 +57,9 @@ struct aw_clk_frac_sc {
struct aw_clk_factor n;
struct aw_clk_frac frac;

uint64_t min_freq;
uint64_t max_freq;

uint32_t mux_shift;
uint32_t mux_mask;
uint32_t gate_shift;
@@ -89,6 +95,7 @@ aw_clk_frac_init(struct clknode *clk, device_t dev)
idx = (val & sc->mux_mask) >> sc->mux_shift;
}

dprintf("init parent idx %d\n", idx);
clknode_init_parent_idx(clk, idx);
return (0);
}
@@ -104,6 +111,7 @@ aw_clk_frac_set_gate(struct clknode *clk, bool enable)
if ((sc->flags & AW_CLK_HAS_GATE) == 0)
return (0);

dprintf("%sabling gate\n", enable ? "En" : "Dis");
DEVICE_LOCK(clk);
READ4(clk, sc->offset, &val);
if (enable)
@@ -127,6 +135,7 @@ aw_clk_frac_set_mux(struct clknode *clk, int index)
if ((sc->flags & AW_CLK_HAS_MUX) == 0)
return (0);

dprintf("Set mux to %d\n", index);
DEVICE_LOCK(clk);
READ4(clk, sc->offset, &val);
val &= ~sc->mux_mask;
@@ -138,7 +147,7 @@ aw_clk_frac_set_mux(struct clknode *clk, int index)
}

static uint64_t
aw_clk_frac_find_best(struct aw_clk_frac_sc *sc, uint64_t fparent, uint64_t *fout,
aw_clk_frac_find_best(struct aw_clk_frac_sc *sc, uint64_t fparent, uint64_t fout,
uint32_t *factor_n, uint32_t *factor_m)
{
uint64_t cur, best;
@@ -150,18 +159,27 @@ aw_clk_frac_find_best(struct aw_clk_frac_sc *sc, uint64_t fparent, uint64_t *fou
max_m = aw_clk_factor_get_max(&sc->m);
max_n = aw_clk_factor_get_max(&sc->n);
min_m = aw_clk_factor_get_min(&sc->m);
min_n = aw_clk_factor_get_min(&sc->n);
min_n = sc->min_freq / fparent;

for (n = min_n; n <= max_n; n++) {
for (m = min_m; m <= max_m; m++) {
cur = fparent * n / m;
if ((*fout - cur) < (*fout - best)) {
if (cur < sc->min_freq) {
continue;
}
if (cur > sc->max_freq) {
continue;
}
if (cur == fout) {
*factor_n = n;
*factor_m = m;
return (cur);
}
if (abs((fout - cur)) < abs((fout - best))) {
best = cur;
*factor_n = n;
*factor_m = m;
}
if (best == *fout)
return (best);
}
}

@@ -175,32 +193,73 @@ aw_clk_frac_set_freq(struct clknode *clk, uint64_t fparent, uint64_t *fout,
struct aw_clk_frac_sc *sc;
uint64_t cur, best, best_frac;
uint32_t val, m, n, best_m, best_n;
int retry;
int retry, multiple, max_mult, best_mult;

sc = clknode_get_softc(clk);

best = best_frac = cur = 0;
best_mult = 0;
max_mult = 1;

dprintf("Trying to find freq %ju with parent %ju\n", *fout, fparent);
if ((flags & CLK_SET_ROUND_MULTIPLE) != 0)
max_mult = 10;
for (multiple = 1; multiple <= max_mult; multiple++) {
/* First test the fractional frequencies */
dprintf("Testing with multiple %d\n", multiple);
if (*fout * multiple == sc->frac.freq0) {
best = best_frac = sc->frac.freq0;
best_mult = multiple;
dprintf("Found with using frac.freq0 and multiple %d\n", multiple);
break;
}
else if (*fout * multiple == sc->frac.freq1) {
best = best_frac = sc->frac.freq1;
best_mult = multiple;
dprintf("Found with using frac.freq1 and multiple %d\n", multiple);
break;
}
else {
cur = aw_clk_frac_find_best(sc, fparent, *fout * multiple,
&n, &m);
dprintf("Got %ju with n=%d, m=%d\n", cur, n, m);
if (cur == (*fout * multiple)) {
best = cur;
best_mult = multiple;
best_n = n;
best_m = m;
dprintf("This is the one: n=%d m=%d mult=%d\n", best_n, best_m, best_mult);
break;
}
if (abs(((*fout * multiple) - cur)) < abs(((*fout * multiple) - best))) {
best = cur;
best_mult = multiple;
best_n = n;
best_m = m;
dprintf("This is the best for now: n=%d m=%d mult=%d\n", best_n, best_m, best_mult);
}
}
}

if (*fout == sc->frac.freq0)
best = best_frac = sc->frac.freq0;
else if (*fout == sc->frac.freq1)
best = best_frac = sc->frac.freq1;
else
best = aw_clk_frac_find_best(sc, fparent, fout,
&best_n, &best_m);

if (best < sc->min_freq ||
best > sc->max_freq) {
printf("%s: Cannot set %ju for %s (min=%ju max=%ju)\n",
__func__, best, clknode_get_name(clk),
sc->min_freq, sc->max_freq);
return (ERANGE);
}
if ((flags & CLK_SET_DRYRUN) != 0) {
*fout = best;
*stop = 1;
return (0);
}

if ((best < *fout) &&
if ((best < (*fout * best_mult)) &&
((flags & CLK_SET_ROUND_DOWN) == 0)) {
*stop = 1;
return (ERANGE);
}
if ((best > *fout) &&
if ((best > *fout * best_mult) &&
((flags & CLK_SET_ROUND_UP) == 0)) {
*stop = 1;
return (ERANGE);
@@ -271,7 +330,6 @@ aw_clk_frac_recalc(struct clknode *clk, uint64_t *freq)
} else {
m = aw_clk_get_factor(val, &sc->m);
n = aw_clk_get_factor(val, &sc->n);

*freq = *freq * n / m;
}

@@ -322,6 +380,9 @@ aw_clk_frac_register(struct clkdom *clkdom, struct aw_clk_frac_def *clkdef)
sc->frac.mode_sel = 1 << clkdef->frac.mode_sel;
sc->frac.freq_sel = 1 << clkdef->frac.freq_sel;

sc->min_freq = clkdef->min_freq;
sc->max_freq = clkdef->max_freq;

sc->mux_shift = clkdef->mux_shift;
sc->mux_mask = ((1 << clkdef->mux_width) - 1) << sc->mux_shift;


+ 3
- 0
sys/arm/allwinner/clkng/aw_clk_frac.h View File

@@ -38,6 +38,9 @@ struct aw_clk_frac_def {
struct aw_clk_factor n;
struct aw_clk_frac frac;

uint64_t min_freq;
uint64_t max_freq;

uint32_t mux_shift;
uint32_t mux_width;
uint32_t gate_shift;

+ 290
- 0
sys/arm/allwinner/clkng/aw_clk_m.c View File

@@ -0,0 +1,290 @@
/*-
* Copyright (c) 2019 Emmanuel Vadot <manu@freebsd.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/

#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>

#include <dev/extres/clk/clk.h>

#include <arm/allwinner/clkng/aw_clk.h>
#include <arm/allwinner/clkng/aw_clk_m.h>

#include "clkdev_if.h"

/*
* clknode for clocks matching the formula :
*
* clk = clkin / m
* And that needs to potentially :
* 1) Set the parent freq
* 2) Support Setting the parent to a multiple
*
*/

struct aw_clk_m_sc {
uint32_t offset;

struct aw_clk_factor m;

uint32_t mux_shift;
uint32_t mux_mask;
uint32_t gate_shift;

uint32_t flags;
};

#define WRITE4(_clk, off, val) \
CLKDEV_WRITE_4(clknode_get_device(_clk), off, val)
#define READ4(_clk, off, val) \
CLKDEV_READ_4(clknode_get_device(_clk), off, val)
#define DEVICE_LOCK(_clk) \
CLKDEV_DEVICE_LOCK(clknode_get_device(_clk))
#define DEVICE_UNLOCK(_clk) \
CLKDEV_DEVICE_UNLOCK(clknode_get_device(_clk))

static int
aw_clk_m_init(struct clknode *clk, device_t dev)
{
struct aw_clk_m_sc *sc;
uint32_t val, idx;

sc = clknode_get_softc(clk);

idx = 0;
if ((sc->flags & AW_CLK_HAS_MUX) != 0) {
DEVICE_LOCK(clk);
READ4(clk, sc->offset, &val);
DEVICE_UNLOCK(clk);

idx = (val & sc->mux_mask) >> sc->mux_shift;
}

clknode_init_parent_idx(clk, idx);
return (0);
}

static int
aw_clk_m_set_gate(struct clknode *clk, bool enable)
{
struct aw_clk_m_sc *sc;
uint32_t val;

sc = clknode_get_softc(clk);

if ((sc->flags & AW_CLK_HAS_GATE) == 0)
return (0);

DEVICE_LOCK(clk);
READ4(clk, sc->offset, &val);
if (enable)
val |= (1 << sc->gate_shift);
else
val &= ~(1 << sc->gate_shift);
WRITE4(clk, sc->offset, val);
DEVICE_UNLOCK(clk);

return (0);
}

static int
aw_clk_m_set_mux(struct clknode *clk, int index)
{
struct aw_clk_m_sc *sc;
uint32_t val;

sc = clknode_get_softc(clk);

if ((sc->flags & AW_CLK_HAS_MUX) == 0)
return (0);

DEVICE_LOCK(clk);
READ4(clk, sc->offset, &val);
val &= ~sc->mux_mask;
val |= index << sc->mux_shift;
WRITE4(clk, sc->offset, val);
DEVICE_UNLOCK(clk);

return (0);
}

static uint64_t
aw_clk_m_find_best(struct aw_clk_m_sc *sc, uint64_t fparent, uint64_t *fout,
uint32_t *factor_m)
{
uint64_t cur, best;
uint32_t m, max_m, min_m;

*factor_m = 0;

max_m = aw_clk_factor_get_max(&sc->m);
min_m = aw_clk_factor_get_min(&sc->m);

for (m = min_m; m <= max_m; ) {
cur = fparent / m;
if (abs(*fout - cur) < abs(*fout - best)) {
best = cur;
*factor_m = m;
}
if ((sc->m.flags & AW_CLK_FACTOR_POWER_OF_TWO) != 0)
m <<= 1;
else
m++;
}

return (best);
}

static int
aw_clk_m_set_freq(struct clknode *clk, uint64_t fparent, uint64_t *fout,
int flags, int *stop)
{
struct aw_clk_m_sc *sc;
struct clknode *p_clk;
uint64_t cur, best;
uint32_t val, m, best_m;

sc = clknode_get_softc(clk);

best = cur = 0;

if ((sc->flags & AW_CLK_SET_PARENT) != 0) {
p_clk = clknode_get_parent(clk);
if (p_clk == NULL) {
printf("%s: Cannot get parent for clock %s\n",
__func__,
clknode_get_name(clk));
return (ENXIO);
}
clknode_set_freq(p_clk, *fout, CLK_SET_ROUND_MULTIPLE, 0);
clknode_get_freq(p_clk, &fparent);
best = aw_clk_m_find_best(sc, fparent, fout,
&best_m);
} else {
best = aw_clk_m_find_best(sc, fparent, fout,
&best_m);
}

if ((flags & CLK_SET_DRYRUN) != 0) {
*fout = best;
*stop = 1;
return (0);
}

if ((best < *fout) &&
((flags & CLK_SET_ROUND_DOWN) == 0)) {
*stop = 1;
return (ERANGE);
}
if ((best > *fout) &&
((flags & CLK_SET_ROUND_UP) == 0)) {
*stop = 1;
return (ERANGE);
}

DEVICE_LOCK(clk);
READ4(clk, sc->offset, &val);

m = aw_clk_factor_get_value(&sc->m, best_m);
val &= ~sc->m.mask;
val |= m << sc->m.shift;

WRITE4(clk, sc->offset, val);
DEVICE_UNLOCK(clk);

*fout = best;
*stop = 1;

return (0);
}

static int
aw_clk_m_recalc(struct clknode *clk, uint64_t *freq)
{
struct aw_clk_m_sc *sc;
uint32_t val, m;

sc = clknode_get_softc(clk);

DEVICE_LOCK(clk);
READ4(clk, sc->offset, &val);
DEVICE_UNLOCK(clk);

m = aw_clk_get_factor(val, &sc->m);

*freq = *freq / m;

return (0);
}

static clknode_method_t aw_m_clknode_methods[] = {
/* Device interface */
CLKNODEMETHOD(clknode_init, aw_clk_m_init),
CLKNODEMETHOD(clknode_set_gate, aw_clk_m_set_gate),
CLKNODEMETHOD(clknode_set_mux, aw_clk_m_set_mux),
CLKNODEMETHOD(clknode_recalc_freq, aw_clk_m_recalc),
CLKNODEMETHOD(clknode_set_freq, aw_clk_m_set_freq),
CLKNODEMETHOD_END
};

DEFINE_CLASS_1(aw_m_clknode, aw_m_clknode_class, aw_m_clknode_methods,
sizeof(struct aw_clk_m_sc), clknode_class);

int
aw_clk_m_register(struct clkdom *clkdom, struct aw_clk_m_def *clkdef)
{
struct clknode *clk;
struct aw_clk_m_sc *sc;

clk = clknode_create(clkdom, &aw_m_clknode_class, &clkdef->clkdef);
if (clk == NULL)
return (1);

sc = clknode_get_softc(clk);

sc->offset = clkdef->offset;

sc->m.shift = clkdef->m.shift;
sc->m.width = clkdef->m.width;
sc->m.mask = ((1 << sc->m.width) - 1) << sc->m.shift;
sc->m.value = clkdef->m.value;
sc->m.flags = clkdef->m.flags;

sc->mux_shift = clkdef->mux_shift;
sc->mux_mask = ((1 << clkdef->mux_width) - 1) << sc->mux_shift;

sc->gate_shift = clkdef->gate_shift;

sc->flags = clkdef->flags;

clknode_register(clkdom, clk);

return (0);
}

+ 48
- 0
sys/arm/allwinner/clkng/aw_clk_m.h View File

@@ -0,0 +1,48 @@
/*-
* Copyright (c) 2019 Emmanuel Vadot <manu@freebsd.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/

#ifndef __AW_CLK_M_H__
#define __AW_CLK_M_H__

#include <dev/extres/clk/clk.h>

struct aw_clk_m_def {
struct clknode_init_def clkdef;
uint32_t offset;

struct aw_clk_factor m;

uint32_t mux_shift;
uint32_t mux_width;
uint32_t gate_shift;

uint32_t flags;
};

int aw_clk_m_register(struct clkdom *clkdom, struct aw_clk_m_def *clkdef);

#endif /* __AW_CLK_M_H__ */

+ 5
- 3
sys/arm/allwinner/clkng/ccu_a10.c View File

@@ -221,7 +221,8 @@ FRAC_CLK(pll_video0_clk,
31, 0, 0, /* gate, lock, lock retries */
AW_CLK_HAS_GATE, /* flags */
270000000, 297000000, /* freq0, freq1 */
15, 14); /* mode sel, freq sel */
15, 14, /* mode sel, freq sel */
27000000, 381000000); /* min freq, max freq */
static const char *pll_video0_2x_parents[] = {"pll_video0"};
FIXED_CLK(pll_video0_2x_clk,
CLK_PLL_VIDEO0_2X, /* id */
@@ -240,7 +241,8 @@ FRAC_CLK(pll_video1_clk,
31, 0, 0, /* gate, lock, lock retries */
AW_CLK_HAS_GATE, /* flags */
270000000, 297000000, /* freq0, freq1 */
15, 14); /* mode sel, freq sel */
15, 14, /* mode sel, freq sel */
27000000, 381000000); /* min freq, max freq */
static const char *pll_video1_2x_parents[] = {"pll_video1"};
FIXED_CLK(pll_video1_2x_clk,
CLK_PLL_VIDEO1_2X, /* id */
@@ -621,4 +623,4 @@ DEFINE_CLASS_1(ccu_a10ng, ccu_a10ng_driver, ccu_a10ng_methods,
sizeof(struct aw_ccung_softc), aw_ccung_driver);

EARLY_DRIVER_MODULE(ccu_a10ng, simplebus, ccu_a10ng_driver,
ccu_a10ng_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
ccu_a10ng_devclass, 0, 0, BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE);

+ 1
- 1
sys/arm/allwinner/clkng/ccu_a13.c View File

@@ -568,4 +568,4 @@ DEFINE_CLASS_1(ccu_a13ng, ccu_a13ng_driver, ccu_a13ng_methods,
sizeof(struct aw_ccung_softc), aw_ccung_driver);

EARLY_DRIVER_MODULE(ccu_a13ng, simplebus, ccu_a13ng_driver,
ccu_a13ng_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
ccu_a13ng_devclass, 0, 0, BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE);

+ 13
- 8
sys/arm/allwinner/clkng/ccu_a31.c View File

@@ -302,8 +302,8 @@ FRAC_CLK(pll_video0_clk,
31, 28, 1000, /* gate, lock, lock retries */
AW_CLK_HAS_LOCK, /* flags */
270000000, 297000000, /* freq0, freq1 */
24, 25); /* mode sel, freq sel */
24, 25, /* mode sel, freq sel */
30000000, 600000000); /* min freq, max freq */
static const char *pll_video0_2x_parents[] = {"pll_video0"};
FIXED_CLK(pll_video0_2x_clk,
CLK_PLL_VIDEO0_2X, /* id */
@@ -323,7 +323,8 @@ FRAC_CLK(pll_ve_clk,
31, 28, 1000, /* gate, lock, lock retries */
AW_CLK_HAS_LOCK, /* flags */
270000000, 297000000, /* freq0, freq1 */
24, 25); /* mode sel, freq sel */
24, 25, /* mode sel, freq sel */
30000000, 600000000); /* min freq, max freq */

NKMP_CLK_WITH_UPDATE(pll_ddr_clk,
CLK_PLL_DDR, /* id */
@@ -369,7 +370,8 @@ FRAC_CLK(pll_video1_clk,
31, 28, 1000, /* gate, lock, lock retries */
AW_CLK_HAS_LOCK, /* flags */
270000000, 297000000, /* freq0, freq1 */
24, 25); /* mode sel, freq sel */
24, 25, /* mode sel, freq sel */
30000000, 600000000); /* min freq, max freq */

static const char *pll_video1_2x_parents[] = {"pll_video1"};
FIXED_CLK(pll_video1_2x_clk,
@@ -390,7 +392,8 @@ FRAC_CLK(pll_gpu_clk,
31, 28, 1000, /* gate, lock, lock retries */
AW_CLK_HAS_LOCK, /* flags */
270000000, 297000000, /* freq0, freq1 */
24, 25); /* mode sel, freq sel */
24, 25, /* mode sel, freq sel */
30000000, 600000000); /* min freq, max freq */

static const char *pll_mipi_parents[] = {"pll_video0", "pll_video1"};
NKMP_CLK(pll_mipi_clk,
@@ -414,7 +417,8 @@ FRAC_CLK(pll9_clk,
31, 28, 1000, /* gate, lock, lock retries */
AW_CLK_HAS_LOCK, /* flags */
270000000, 297000000, /* freq0, freq1 */
24, 25); /* mode sel, freq sel */
24, 25, /* mode sel, freq sel */
30000000, 600000000); /* min freq, max freq */

FRAC_CLK(pll10_clk,
CLK_PLL10, /* id */
@@ -425,7 +429,8 @@ FRAC_CLK(pll10_clk,
31, 28, 1000, /* gate, lock, lock retries */
AW_CLK_HAS_LOCK, /* flags */
270000000, 297000000, /* freq0, freq1 */
24, 25); /* mode sel, freq sel */
24, 25, /* mode sel, freq sel */
30000000, 600000000); /* min freq, max freq */

static struct clk_div_table axi_div_table[] = {
{ .value = 0, .divider = 1, },
@@ -973,4 +978,4 @@ DEFINE_CLASS_1(ccu_a31ng, ccu_a31ng_driver, ccu_a31ng_methods,
sizeof(struct aw_ccung_softc), aw_ccung_driver);

EARLY_DRIVER_MODULE(ccu_a31ng, simplebus, ccu_a31ng_driver,
ccu_a31ng_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_LAST);
ccu_a31ng_devclass, 0, 0, BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE);

+ 45
- 49
sys/arm/allwinner/clkng/ccu_a64.c View File

@@ -288,7 +288,8 @@ FRAC_CLK(pll_video0_clk,
31, 28, 1000, /* gate, lock, lock retries */
AW_CLK_HAS_LOCK, /* flags */
270000000, 297000000, /* freq0, freq1 */
24, 25); /* mode sel, freq sel */
24, 25, /* mode sel, freq sel */
192000000, 600000000); /* min freq, max freq */
static const char *pll_video0_2x_parents[] = {"pll_video0"};
FIXED_CLK(pll_video0_2x_clk,
CLK_PLL_VIDEO0_2X, /* id */
@@ -309,7 +310,8 @@ FRAC_CLK(pll_ve_clk,
31, 28, 1000, /* gate, lock, lock retries */
AW_CLK_HAS_LOCK, /* flags */
270000000, 297000000, /* freq0, freq1 */
24, 25); /* mode sel, freq sel */
24, 25, /* mode sel, freq sel */
192000000, 600000000); /* min freq, max freq */

static const char *pll_ddr0_parents[] = {"osc24M"};
NKMP_CLK_WITH_UPDATE(pll_ddr0_clk,
@@ -379,7 +381,8 @@ FRAC_CLK(pll_video1_clk,
31, 28, 1000, /* gate, lock, lock retries */
AW_CLK_HAS_LOCK, /* flags */
270000000, 297000000, /* freq0, freq1 */
24, 25); /* mode sel, freq sel */
24, 25, /* mode sel, freq sel */
192000000, 600000000); /* min freq, max freq */

static const char *pll_gpu_parents[] = {"osc24M"};
FRAC_CLK(pll_gpu_clk,
@@ -391,7 +394,8 @@ FRAC_CLK(pll_gpu_clk,
31, 28, 1000, /* gate, lock, lock retries */
AW_CLK_HAS_LOCK, /* flags */
270000000, 297000000, /* freq0, freq1 */
24, 25); /* mode sel, freq sel */
24, 25, /* mode sel, freq sel */
192000000, 600000000); /* min freq, max freq */

/* PLL MIPI is missing */

@@ -405,7 +409,8 @@ FRAC_CLK(pll_hsic_clk,
31, 28, 1000, /* gate, lock, lock retries */
AW_CLK_HAS_LOCK, /* flags */
270000000, 297000000, /* freq0, freq1 */
24, 25); /* mode sel, freq sel */
24, 25, /* mode sel, freq sel */
192000000, 600000000); /* min freq, max freq */

static const char *pll_de_parents[] = {"osc24M"};
FRAC_CLK(pll_de_clk,
@@ -417,7 +422,8 @@ FRAC_CLK(pll_de_clk,
31, 28, 1000, /* gate, lock, lock retries */
AW_CLK_HAS_LOCK, /* flags */
270000000, 297000000, /* freq0, freq1 */
24, 25); /* mode sel, freq sel */
24, 25, /* mode sel, freq sel */
192000000, 600000000); /* min freq, max freq */

static const char *pll_ddr1_parents[] = {"osc24M"};
NKMP_CLK_WITH_UPDATE(pll_ddr1_clk,
@@ -607,10 +613,9 @@ MUX_CLK(i2s2mux_clk,
0xb8, 16, 2); /* offset, mux shift, mux width */

static const char *spdif_parents[] = {"pll_audio"};
NM_CLK(spdif_clk,
M_CLK(spdif_clk,
CLK_SPDIF, "spdif", spdif_parents, /* id, name, parents */
0xC0, /* offset */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake); */
0, 4, 0, 0, /* m factor */
0, 0, /* mux */
31, /* gate */
@@ -620,20 +625,18 @@ NM_CLK(spdif_clk,

/* DRAM needs update bit */
static const char *dram_parents[] = {"pll_ddr0", "pll_ddr1"};
NM_CLK(dram_clk,
M_CLK(dram_clk,
CLK_DRAM, "dram", dram_parents, /* id, name, parents */
0xF4, /* offset */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
0, 2, 0, 0, /* m factor */
20, 2, /* mux */
0, /* gate */
AW_CLK_HAS_MUX); /* flags */

static const char *de_parents[] = {"pll_periph0_2x", "pll_de"};
NM_CLK(de_clk,
M_CLK(de_clk,
CLK_DE, "de", de_parents, /* id, name, parents */
0x104, /* offset */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
0, 4, 0, 0, /* m factor */
24, 2, /* mux */
31, /* gate */
@@ -641,81 +644,74 @@ NM_CLK(de_clk,

/* TCON0/1 Needs mux table */
static const char *tcon1_parents[] = {"pll_video0", "pll_video0", "pll_video1"};
NM_CLK(tcon1_clk,
CLK_TCON1, "tcon1", tcon1_parents,
0x11C,
0, 0, 1, AW_CLK_FACTOR_FIXED,
0, 4, 0, 0,
24, 2,
31,
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE);
M_CLK(tcon1_clk,
CLK_TCON1, "tcon1", tcon1_parents, /* id, name, parents */
0x11C, /* offset */
0, 5, 0, 0, /* m factor */
24, 2, /* mux */
31, /* gate */
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE |
AW_CLK_SET_PARENT); /* flags */

static const char *deinterlace_parents[] = {"pll_periph0", "pll_periph1"};
NM_CLK(deinterlace_clk,
M_CLK(deinterlace_clk,
CLK_DEINTERLACE, "deinterlace", deinterlace_parents, /* id, name, parents */
0x124, /* offset */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
0, 4, 0, 0, /* m factor */
24, 2, /* mux */
31, /* gate */
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */

static const char *csi_sclk_parents[] = {"pll_periph0", "pll_periph1"};
NM_CLK(csi_sclk_clk,
M_CLK(csi_sclk_clk,
CLK_CSI_SCLK, "csi-sclk", csi_sclk_parents, /* id, name, parents */
0x134, /* offset */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
16, 4, 0, 0, /* m factor */
24, 2, /* mux */
31, /* gate */
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */

static const char *csi_mclk_parents[] = {"osc24M", "pll_video0", "pll_periph1"};
NM_CLK(csi_mclk_clk,
M_CLK(csi_mclk_clk,
CLK_CSI_MCLK, "csi-mclk", csi_mclk_parents, /* id, name, parents */
0x134, /* offset */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
0, 4, 0, 0, /* m factor */
8, 2, /* mux */
15, /* gate */
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */

static const char *ve_parents[] = {"pll_ve"};
NM_CLK(ve_clk,
M_CLK(ve_clk,
CLK_VE, "ve", ve_parents, /* id, name, parents */
0x13C, /* offset */
16, 3, 0, 0, /* n factor */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* m factor (fake) */
16, 3, 0, 0, /* m factor */
0, 0, /* mux */
31, /* gate */
AW_CLK_HAS_GATE); /* flags */

static const char *hdmi_parents[] = {"pll_video0"};
NM_CLK(hdmi_clk,
M_CLK(hdmi_clk,
CLK_HDMI, "hdmi", hdmi_parents, /* id, name, parents */
0x150, /* offset */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
0, 4, 0, 0, /* m factor */
24, 2, /* mux */
31, /* gate */
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE | AW_CLK_SET_PARENT); /* flags */

static const char *mbus_parents[] = {"osc24M", "pll_periph0_2x", "pll_ddr0"};
NM_CLK(mbus_clk,
M_CLK(mbus_clk,
CLK_MBUS, "mbus", mbus_parents, /* id, name, parents */
0x15C, /* offset */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
0, 3, 0, 0, /* m factor */
24, 2, /* mux */
31, /* gate */
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */

static const char *gpu_parents[] = {"pll_gpu"};
NM_CLK(gpu_clk,
M_CLK(gpu_clk,
CLK_GPU, "gpu", gpu_parents, /* id, name, parents */
0x1A0, /* offset */
0, 2, 0, 0, /* n factor */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* m factor (fake) */
0, 2, 0, 0, /* m factor */
0, 0, /* mux */
31, /* gate */
AW_CLK_HAS_GATE); /* flags */
@@ -744,17 +740,17 @@ static struct aw_ccung_clk a64_ccu_clks[] = {
{ .type = AW_CLK_NM, .clk.nm = &ce_clk},
{ .type = AW_CLK_NM, .clk.nm = &spi0_clk},
{ .type = AW_CLK_NM, .clk.nm = &spi1_clk},
{ .type = AW_CLK_NM, .clk.nm = &spdif_clk},
{ .type = AW_CLK_NM, .clk.nm = &dram_clk},
{ .type = AW_CLK_NM, .clk.nm = &de_clk},
{ .type = AW_CLK_NM, .clk.nm = &tcon1_clk},
{ .type = AW_CLK_NM, .clk.nm = &deinterlace_clk},
{ .type = AW_CLK_NM, .clk.nm = &csi_sclk_clk},
{ .type = AW_CLK_NM, .clk.nm = &csi_mclk_clk},
{ .type = AW_CLK_NM, .clk.nm = &ve_clk},
{ .type = AW_CLK_NM, .clk.nm = &hdmi_clk},
{ .type = AW_CLK_NM, .clk.nm = &mbus_clk},
{ .type = AW_CLK_NM, .clk.nm = &gpu_clk},
{ .type = AW_CLK_M, .clk.m = &spdif_clk},
{ .type = AW_CLK_M, .clk.m = &dram_clk},
{ .type = AW_CLK_M, .clk.m = &de_clk},
{ .type = AW_CLK_M, .clk.m = &tcon1_clk},
{ .type = AW_CLK_M, .clk.m = &deinterlace_clk},
{ .type = AW_CLK_M, .clk.m = &csi_sclk_clk},
{ .type = AW_CLK_M, .clk.m = &csi_mclk_clk},
{ .type = AW_CLK_M, .clk.m = &ve_clk},
{ .type = AW_CLK_M, .clk.m = &hdmi_clk},
{ .type = AW_CLK_M, .clk.m = &mbus_clk},
{ .type = AW_CLK_M, .clk.m = &gpu_clk},
{ .type = AW_CLK_PREDIV_MUX, .clk.prediv_mux = &ahb1_clk},
{ .type = AW_CLK_PREDIV_MUX, .clk.prediv_mux = &ahb2_clk},
{ .type = AW_CLK_MUX, .clk.mux = &cpux_clk},
@@ -827,4 +823,4 @@ DEFINE_CLASS_1(ccu_a64ng, ccu_a64ng_driver, ccu_a64ng_methods,
sizeof(struct aw_ccung_softc), aw_ccung_driver);

EARLY_DRIVER_MODULE(ccu_a64ng, simplebus, ccu_a64ng_driver,
ccu_a64ng_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_LAST);
ccu_a64ng_devclass, 0, 0, BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE);

+ 1
- 1
sys/arm/allwinner/clkng/ccu_a83t.c View File

@@ -786,4 +786,4 @@ DEFINE_CLASS_1(ccu_a83tng, ccu_a83tng_driver, ccu_a83tng_methods,
sizeof(struct aw_ccung_softc), aw_ccung_driver);

EARLY_DRIVER_MODULE(ccu_a83tng, simplebus, ccu_a83tng_driver,
ccu_a83tng_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_LAST);
ccu_a83tng_devclass, 0, 0, BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE);

+ 1
- 1
sys/arm/allwinner/clkng/ccu_de2.c View File

@@ -163,4 +163,4 @@ DEFINE_CLASS_1(ccu_de2, ccu_de2_driver, ccu_de2_methods,
sizeof(struct aw_ccung_softc), aw_ccung_driver);

EARLY_DRIVER_MODULE(ccu_de2, simplebus, ccu_de2_driver,
ccu_de2ng_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_LAST);
ccu_de2ng_devclass, 0, 0, BUS_PASS_RESOURCE + BUS_PASS_ORDER_LAST);

+ 9
- 5
sys/arm/allwinner/clkng/ccu_h3.c View File

@@ -306,7 +306,8 @@ FRAC_CLK(pll_video_clk,
31, 28, 1000, /* gate, lock, lock retries */
AW_CLK_HAS_LOCK, /* flags */
270000000, 297000000, /* freq0, freq1 */
24, 25); /* mode sel, freq sel */
24, 25, /* mode sel, freq sel */
192000000, 600000000); /* min freq, max freq */

static const char *pll_ve_parents[] = {"osc24M"};
FRAC_CLK(pll_ve_clk,
@@ -318,7 +319,8 @@ FRAC_CLK(pll_ve_clk,
31, 28, 1000, /* gate, lock, lock retries */
AW_CLK_HAS_LOCK, /* flags */
270000000, 297000000, /* freq0, freq1 */
24, 25); /* mode sel, freq sel */
24, 25, /* mode sel, freq sel */
192000000, 600000000); /* min freq, max freq */

static const char *pll_ddr_parents[] = {"osc24M"};
NKMP_CLK_WITH_UPDATE(pll_ddr_clk,
@@ -366,7 +368,8 @@ FRAC_CLK(pll_gpu_clk,
31, 28, 1000, /* gate, lock, lock retries */
AW_CLK_HAS_LOCK, /* flags */
270000000, 297000000, /* freq0, freq1 */
24, 25); /* mode sel, freq sel */
24, 25, /* mode sel, freq sel */
192000000, 600000000); /* min freq, max freq */

static const char *pll_periph1_parents[] = {"osc24M"};
NKMP_CLK(pll_periph1_clk,
@@ -391,7 +394,8 @@ FRAC_CLK(pll_de_clk,
31, 28, 1000, /* gate, lock, lock retries */
AW_CLK_HAS_LOCK, /* flags */
270000000, 297000000, /* freq0, freq1 */
24, 25); /* mode sel, freq sel */
24, 25, /* mode sel, freq sel */
192000000, 600000000); /* min freq, max freq */

static const char *cpux_parents[] = {"osc32k", "osc24M", "pll_cpux", "pll_cpux"};
MUX_CLK(cpux_clk,
@@ -787,4 +791,4 @@ DEFINE_CLASS_1(ccu_h3ng, ccu_h3ng_driver, ccu_h3ng_methods,
sizeof(struct aw_ccung_softc), aw_ccung_driver);

EARLY_DRIVER_MODULE(ccu_h3ng, simplebus, ccu_h3ng_driver,
ccu_h3ng_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_LAST);
ccu_h3ng_devclass, 0, 0, BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE);

+ 2
- 2
sys/arm/allwinner/clkng/ccu_sun8i_r.c View File

@@ -215,7 +215,7 @@ DEFINE_CLASS_1(ccu_sun8i_r, ccu_sun8i_r_driver, ccu_sun8i_r_methods,
sizeof(struct aw_ccung_softc), aw_ccung_driver);

EARLY_DRIVER_MODULE(ccu_sun8i_r, simplebus, ccu_sun8i_r_driver,
ccu_sun8i_r_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_LAST);
ccu_sun8i_r_devclass, 0, 0, BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE);

static int
ccu_a83t_r_probe(device_t dev)
@@ -262,4 +262,4 @@ DEFINE_CLASS_1(ccu_a83t_r, ccu_a83t_r_driver, ccu_a83t_r_methods,
sizeof(struct aw_ccung_softc), aw_ccung_driver);

EARLY_DRIVER_MODULE(ccu_a83t_r, simplebus, ccu_a83t_r_driver,
ccu_a83t_r_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_LAST);
ccu_a83t_r_devclass, 0, 0, BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE);

+ 1
- 0
sys/arm/allwinner/files.allwinner View File

@@ -36,6 +36,7 @@ arm/allwinner/aw_gmacclk.c standard

arm/allwinner/clkng/aw_ccung.c standard
arm/allwinner/clkng/aw_clk_frac.c standard
arm/allwinner/clkng/aw_clk_m.c standard
arm/allwinner/clkng/aw_clk_nkmp.c standard
arm/allwinner/clkng/aw_clk_nm.c standard
arm/allwinner/clkng/aw_clk_prediv_mux.c standard

+ 21
- 18
sys/arm/ti/am335x/am335x_pmic.c View File

@@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$");
#include <sys/reboot.h>
#include <sys/resource.h>
#include <sys/rman.h>
#include <sys/taskqueue.h>

#include <dev/iicbus/iicbus.h>
#include <dev/iicbus/iiconf.h>
@@ -59,9 +60,9 @@ __FBSDID("$FreeBSD$");
struct am335x_pmic_softc {
device_t sc_dev;
uint32_t sc_addr;
struct intr_config_hook enum_hook;
struct resource *sc_irq_res;
void *sc_intrhand;
struct task intr_task;
};

static const char *tps65217_voreg_c[4] = {"4.10V", "4.15V", "4.20V", "4.25V"};
@@ -86,7 +87,7 @@ am335x_pmic_write(device_t dev, uint8_t address, uint8_t *data, uint8_t size)
}

static void
am335x_pmic_intr(void *arg)
am335x_pmic_intrtask(void *arg, int pending)
{
struct am335x_pmic_softc *sc = (struct am335x_pmic_softc *)arg;
struct tps65217_status_reg status_reg;
@@ -94,20 +95,16 @@ am335x_pmic_intr(void *arg)
int rv;
char notify_buf[16];

THREAD_SLEEPING_OK();
rv = am335x_pmic_read(sc->sc_dev, TPS65217_INT_REG, (uint8_t *)&int_reg, 1);
if (rv != 0) {
device_printf(sc->sc_dev, "Cannot read interrupt register\n");
THREAD_NO_SLEEPING();
return;
}
rv = am335x_pmic_read(sc->sc_dev, TPS65217_STATUS_REG, (uint8_t *)&status_reg, 1);
if (rv != 0) {
device_printf(sc->sc_dev, "Cannot read status register\n");
THREAD_NO_SLEEPING();
return;
}
THREAD_NO_SLEEPING();

if (int_reg.pbi && status_reg.pb)
shutdown_nice(RB_POWEROFF);
@@ -118,6 +115,18 @@ am335x_pmic_intr(void *arg)
}
}

static void
am335x_pmic_intr(void *arg)
{
struct am335x_pmic_softc *sc = arg;

/*
* Handling the interrupt requires doing i2c IO, which sleeps while the
* IO is in progress, so do the processing on a taskqueue thread.
*/
taskqueue_enqueue(taskqueue_thread, &sc->intr_task);
}

static int
am335x_pmic_probe(device_t dev)
{
@@ -200,10 +209,9 @@ am335x_pmic_setvo(device_t dev, uint8_t vo)
}

static void
am335x_pmic_start(void *xdev)
am335x_pmic_start(struct am335x_pmic_softc *sc)
{
struct am335x_pmic_softc *sc;
device_t dev = (device_t)xdev;
device_t dev;
struct tps65217_status_reg status_reg;
struct tps65217_chipid_reg chipid_reg;
uint8_t reg, vo;
@@ -211,8 +219,7 @@ am335x_pmic_start(void *xdev)
char pwr[4][11] = {"Battery", "USB", "AC", "USB and AC"};
int rv;

sc = device_get_softc(dev);

dev = sc->sc_dev;
am335x_pmic_read(dev, TPS65217_CHIPID_REG, (uint8_t *)&chipid_reg, 1);
switch (chipid_reg.chip) {
case TPS65217A:
@@ -255,8 +262,6 @@ am335x_pmic_start(void *xdev)
EVENTHANDLER_REGISTER(shutdown_final, am335x_pmic_shutdown, dev,
SHUTDOWN_PRI_LAST);

config_intrhook_disestablish(&sc->enum_hook);

/* Unmask all interrupts and clear pending status */
reg = 0;
am335x_pmic_write(dev, TPS65217_INT_REG, &reg, 1);
@@ -280,6 +285,8 @@ am335x_pmic_attach(device_t dev)

sc = device_get_softc(dev);

TASK_INIT(&sc->intr_task, 0, am335x_pmic_intrtask, sc);

rid = 0;
sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
RF_ACTIVE);
@@ -288,11 +295,7 @@ am335x_pmic_attach(device_t dev)
/* return (ENXIO); */
}

sc->enum_hook.ich_func = am335x_pmic_start;
sc->enum_hook.ich_arg = dev;

if (config_intrhook_establish(&sc->enum_hook) != 0)
return (ENOMEM);
am335x_pmic_start(sc);

return (0);
}

+ 1
- 0
sys/arm/ti/am335x/files.am335x View File

@@ -10,6 +10,7 @@ arm/ti/am335x/am335x_lcd_syscons.c optional sc
arm/ti/am335x/am335x_pmic.c optional am335x_pmic
arm/ti/am335x/am335x_prcm.c standard
arm/ti/am335x/am335x_pwmss.c standard
dev/pwm/pwmbus_if.m standard
arm/ti/am335x/am335x_ehrpwm.c standard
arm/ti/am335x/am335x_ecap.c standard
arm/ti/am335x/am335x_rtc.c optional am335x_rtc

+ 8
- 17
sys/arm/ti/am335x/tda19988.c View File

@@ -243,7 +243,6 @@ struct tda19988_softc {
uint32_t sc_addr;
uint32_t sc_cec_addr;
uint16_t sc_version;
struct intr_config_hook enum_hook;
int sc_current_page;
uint8_t *sc_edid;
uint32_t sc_edid_len;
@@ -645,15 +644,14 @@ done:
}

static void
tda19988_start(void *xdev)
tda19988_start(struct tda19988_softc *sc)
{
struct tda19988_softc *sc;
device_t dev = (device_t)xdev;
device_t dev;
uint8_t data;
uint16_t version;

sc = device_get_softc(dev);
dev = sc->sc_dev;
tda19988_cec_write(sc, TDA_CEC_ENAMODS, ENAMODS_RXSENS | ENAMODS_HDMI);
DELAY(1000);
tda19988_cec_read(sc, 0xfe, &data);
@@ -699,7 +697,7 @@ tda19988_start(void *xdev)
break;
default:
device_printf(dev, "Unknown device: %04x\n", sc->sc_version);
goto done;
return;
}

tda19988_reg_write(sc, TDA_DDC_CTRL, DDC_ENABLE);
@@ -710,16 +708,13 @@ tda19988_start(void *xdev)

if (tda19988_read_edid(sc) < 0) {
device_printf(dev, "failed to read EDID\n");
goto done;
return;
}

/* Default values for RGB 4:4:4 mapping */
tda19988_reg_write(sc, TDA_VIP_CNTRL_0, 0x23);
tda19988_reg_write(sc, TDA_VIP_CNTRL_1, 0x01);
tda19988_reg_write(sc, TDA_VIP_CNTRL_2, 0x45);

done:
config_intrhook_disestablish(&sc->enum_hook);
}

static int
@@ -738,15 +733,11 @@ tda19988_attach(device_t dev)

device_set_desc(dev, "NXP TDA19988 HDMI transmitter");

sc->enum_hook.ich_func = tda19988_start;
sc->enum_hook.ich_arg = dev;

if (config_intrhook_establish(&sc->enum_hook) != 0)
return (ENOMEM);

node = ofw_bus_get_node(dev);
OF_device_register_xref(OF_xref_from_node(node), dev);

tda19988_start(sc);

return (0);
}


+ 1
- 0
sys/conf/files.arm64 View File

@@ -50,6 +50,7 @@ arm/allwinner/if_awg.c optional awg ext_resources syscon aw_sid nvmem fdt
# Allwinner clock driver
arm/allwinner/clkng/aw_ccung.c optional aw_ccu fdt
arm/allwinner/clkng/aw_clk_frac.c optional aw_ccu fdt
arm/allwinner/clkng/aw_clk_m.c optional aw_ccu fdt
arm/allwinner/clkng/aw_clk_nkmp.c optional aw_ccu fdt
arm/allwinner/clkng/aw_clk_nm.c optional aw_ccu fdt
arm/allwinner/clkng/aw_clk_prediv_mux.c optional aw_ccu fdt

+ 1
- 0
sys/dev/extres/clk/clk.h View File

@@ -48,6 +48,7 @@
#define CLK_SET_ROUND_EXACT 0
#define CLK_SET_ROUND_UP 0x00000001
#define CLK_SET_ROUND_DOWN 0x00000002
#define CLK_SET_ROUND_MULTIPLE 0x00000004
#define CLK_SET_ROUND_ANY (CLK_SET_ROUND_UP | CLK_SET_ROUND_DOWN)

#define CLK_SET_USER_MASK 0x0000FFFF

+ 2
- 2
sys/dev/sdhci/sdhci.c View File

@@ -481,7 +481,7 @@ sdhci_set_power(struct sdhci_slot *slot, u_char power)
DELAY(100);
}
if (!(RD1(slot, SDHCI_POWER_CONTROL) & SDHCI_POWER_ON))
slot_printf(slot, "Bus power failed to enable");
slot_printf(slot, "Bus power failed to enable\n");

if (slot->quirks & SDHCI_QUIRK_INTEL_POWER_UP_RESET) {
WR1(slot, SDHCI_POWER_CONTROL, pwr | 0x10);
@@ -1128,7 +1128,7 @@ no_tuning:
slot->timeout = 10;
SYSCTL_ADD_INT(device_get_sysctl_ctx(slot->bus),
SYSCTL_CHILDREN(device_get_sysctl_tree(slot->bus)), OID_AUTO,
"timeout", CTLFLAG_RW, &slot->timeout, 0,
"timeout", CTLFLAG_RWTUN, &slot->timeout, 0,
"Maximum timeout for SDHCI transfers (in secs)");
TASK_INIT(&slot->card_task, 0, sdhci_card_task, slot);
TIMEOUT_TASK_INIT(taskqueue_swi_giant, &slot->card_delayed_task, 0,

Loading…
Cancel
Save