Add the start of support for the Allwinner A31 clocks. It only adds
support for the i2c, mmc, and gmac clocks. Further clocks can be added as needed. Submitted by: Emmanuel Vadot <manu@bidouilliste.com> Reviewed by: jmcneill Differential Revision: https://reviews.freebsd.org/D5339
This commit is contained in:
parent
afc055d90f
commit
461a7671c7
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=296093
@ -48,8 +48,10 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/mmc/mmcreg.h>
|
||||
#include <dev/mmc/mmcbrvar.h>
|
||||
|
||||
#include <arm/allwinner/allwinner_machdep.h>
|
||||
#include <arm/allwinner/a10_clk.h>
|
||||
#include <arm/allwinner/a10_mmc.h>
|
||||
#include <arm/allwinner/a31/a31_clk.h>
|
||||
|
||||
#define A10_MMC_MEMRES 0
|
||||
#define A10_MMC_IRQRES 1
|
||||
@ -144,6 +146,7 @@ a10_mmc_attach(device_t dev)
|
||||
struct a10_mmc_softc *sc;
|
||||
struct sysctl_ctx_list *ctx;
|
||||
struct sysctl_oid_list *tree;
|
||||
int clk;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
sc->a10_dev = dev;
|
||||
@ -168,7 +171,24 @@ a10_mmc_attach(device_t dev)
|
||||
}
|
||||
|
||||
/* Activate the module clock. */
|
||||
if (a10_clk_mmc_activate(sc->a10_id) != 0) {
|
||||
switch (allwinner_soc_type()) {
|
||||
#if defined(SOC_ALLWINNER_A10) || defined(SOC_ALLWINNER_A20)
|
||||
case ALLWINNERSOC_A10:
|
||||
case ALLWINNERSOC_A10S:
|
||||
case ALLWINNERSOC_A20:
|
||||
clk = a10_clk_mmc_activate(sc->a10_id);
|
||||
break;
|
||||
#endif
|
||||
#if defined(SOC_ALLWINNER_A31) || defined(SOC_ALLWINNER_A31S)
|
||||
case ALLWINNERSOC_A31:
|
||||
case ALLWINNERSOC_A31S:
|
||||
clk = a31_clk_mmc_activate(sc->a10_id);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
clk = -1;
|
||||
}
|
||||
if (clk != 0) {
|
||||
bus_teardown_intr(dev, sc->a10_res[A10_MMC_IRQRES],
|
||||
sc->a10_intrhand);
|
||||
bus_release_resources(dev, a10_mmc_res_spec, sc->a10_res);
|
||||
@ -790,7 +810,23 @@ a10_mmc_update_ios(device_t bus, device_t child)
|
||||
return (error);
|
||||
|
||||
/* Set the MMC clock. */
|
||||
error = a10_clk_mmc_cfg(sc->a10_id, ios->clock);
|
||||
switch (allwinner_soc_type()) {
|
||||
#if defined(SOC_ALLWINNER_A10) || defined(SOC_ALLWINNER_A20)
|
||||
case ALLWINNERSOC_A10:
|
||||
case ALLWINNERSOC_A10S:
|
||||
case ALLWINNERSOC_A20:
|
||||
error = a10_clk_mmc_cfg(sc->a10_id, ios->clock);
|
||||
break;
|
||||
#endif
|
||||
#if defined(SOC_ALLWINNER_A31) || defined(SOC_ALLWINNER_A31S)
|
||||
case ALLWINNERSOC_A31:
|
||||
case ALLWINNERSOC_A31S:
|
||||
error = a31_clk_mmc_cfg(sc->a10_id, ios->clock);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
error = ENXIO;
|
||||
}
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
|
@ -40,7 +40,9 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/ofw_bus_subr.h>
|
||||
|
||||
#include <arm/allwinner/allwinner_machdep.h>
|
||||
#include <arm/allwinner/a10_clk.h>
|
||||
#include <arm/allwinner/a31/a31_clk.h>
|
||||
|
||||
#include "if_dwc_if.h"
|
||||
|
||||
@ -60,9 +62,27 @@ a20_if_dwc_probe(device_t dev)
|
||||
static int
|
||||
a20_if_dwc_init(device_t dev)
|
||||
{
|
||||
int clk;
|
||||
|
||||
/* Activate GMAC clock and set the pin mux to rgmii. */
|
||||
if (a10_clk_gmac_activate(ofw_bus_get_node(dev)) != 0) {
|
||||
switch (allwinner_soc_type()) {
|
||||
#if defined(SOC_ALLWINNER_A10) || defined(SOC_ALLWINNER_A20)
|
||||
case ALLWINNERSOC_A10:
|
||||
case ALLWINNERSOC_A10S:
|
||||
case ALLWINNERSOC_A20:
|
||||
clk = a10_clk_gmac_activate(ofw_bus_get_node(dev));
|
||||
break;
|
||||
#endif
|
||||
#if defined(SOC_ALLWINNER_A31) || defined(SOC_ALLWINNER_A31S)
|
||||
case ALLWINNERSOC_A31:
|
||||
case ALLWINNERSOC_A31S:
|
||||
clk = a31_clk_gmac_activate(ofw_bus_get_node(dev));
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
clk = -1;
|
||||
}
|
||||
if (clk != 0) {
|
||||
device_printf(dev, "could not activate gmac module\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
295
sys/arm/allwinner/a31/a31_clk.c
Normal file
295
sys/arm/allwinner/a31/a31_clk.c
Normal file
@ -0,0 +1,295 @@
|
||||
/*-
|
||||
* Copyright (c) 2013 Ganbold Tsagaankhuu <ganbold@freebsd.org>
|
||||
* Copyright (c) 2016 Emmanuel Vadot <manu@bidouilliste.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Simple clock driver for Allwinner A31
|
||||
* Adapted from a10_clk.c
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <dev/ofw/openfirm.h>
|
||||
#include <dev/ofw/ofw_bus_subr.h>
|
||||
|
||||
#include <arm/allwinner/a31/a31_clk.h>
|
||||
|
||||
struct a31_ccm_softc {
|
||||
struct resource *res;
|
||||
int pll6_enabled;
|
||||
};
|
||||
|
||||
static struct a31_ccm_softc *a31_ccm_sc = NULL;
|
||||
|
||||
#define ccm_read_4(sc, reg) \
|
||||
bus_read_4((sc)->res, (reg))
|
||||
#define ccm_write_4(sc, reg, val) \
|
||||
bus_write_4((sc)->res, (reg), (val))
|
||||
|
||||
#define PLL6_TIMEOUT 10
|
||||
|
||||
static int
|
||||
a31_ccm_probe(device_t dev)
|
||||
{
|
||||
|
||||
if (!ofw_bus_status_okay(dev))
|
||||
return (ENXIO);
|
||||
|
||||
if (ofw_bus_is_compatible(dev, "allwinner,sun6i-a31-ccm")) {
|
||||
device_set_desc(dev, "Allwinner Clock Control Module");
|
||||
return(BUS_PROBE_DEFAULT);
|
||||
}
|
||||
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
static int
|
||||
a31_ccm_attach(device_t dev)
|
||||
{
|
||||
struct a31_ccm_softc *sc = device_get_softc(dev);
|
||||
int rid = 0;
|
||||
|
||||
if (a31_ccm_sc)
|
||||
return (ENXIO);
|
||||
|
||||
sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
|
||||
if (!sc->res) {
|
||||
device_printf(dev, "could not allocate resource\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
a31_ccm_sc = sc;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static device_method_t a31_ccm_methods[] = {
|
||||
DEVMETHOD(device_probe, a31_ccm_probe),
|
||||
DEVMETHOD(device_attach, a31_ccm_attach),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t a31_ccm_driver = {
|
||||
"a31_ccm",
|
||||
a31_ccm_methods,
|
||||
sizeof(struct a31_ccm_softc),
|
||||
};
|
||||
|
||||
static devclass_t a31_ccm_devclass;
|
||||
|
||||
EARLY_DRIVER_MODULE(a31_ccm, simplebus, a31_ccm_driver, a31_ccm_devclass, 0, 0,
|
||||
BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE);
|
||||
|
||||
static int
|
||||
a31_clk_pll6_enable(void)
|
||||
{
|
||||
struct a31_ccm_softc *sc;
|
||||
uint32_t reg_value;
|
||||
int i;
|
||||
|
||||
/* Datasheet recommand to use the default 600Mhz value */
|
||||
sc = a31_ccm_sc;
|
||||
if (sc->pll6_enabled)
|
||||
return (0);
|
||||
reg_value = ccm_read_4(sc, A31_CCM_PLL6_CFG);
|
||||
reg_value |= A31_CCM_PLL_CFG_ENABLE;
|
||||
ccm_write_4(sc, A31_CCM_PLL6_CFG, reg_value);
|
||||
|
||||
/* Wait for PLL to be stable */
|
||||
for (i = 0; i < PLL6_TIMEOUT; i++)
|
||||
if (!(ccm_read_4(sc, A31_CCM_PLL6_CFG) &
|
||||
A31_CCM_PLL6_CFG_REG_LOCK))
|
||||
break;
|
||||
if (i == PLL6_TIMEOUT)
|
||||
return (ENXIO);
|
||||
sc->pll6_enabled = 1;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
a31_clk_pll6_get_rate(void)
|
||||
{
|
||||
struct a31_ccm_softc *sc;
|
||||
uint32_t k, n, reg_value;
|
||||
|
||||
sc = a31_ccm_sc;
|
||||
reg_value = ccm_read_4(sc, A31_CCM_PLL6_CFG);
|
||||
n = ((reg_value & A31_CCM_PLL_CFG_FACTOR_N) >>
|
||||
A31_CCM_PLL_CFG_FACTOR_N_SHIFT);
|
||||
k = ((reg_value & A31_CCM_PLL_CFG_FACTOR_K) >>
|
||||
A31_CCM_PLL_CFG_FACTOR_K_SHIFT) + 1;
|
||||
|
||||
return ((A31_CCM_CLK_REF_FREQ * n * k) / 2);
|
||||
}
|
||||
|
||||
int
|
||||
a31_clk_gmac_activate(phandle_t node)
|
||||
{
|
||||
char *phy_type;
|
||||
struct a31_ccm_softc *sc;
|
||||
uint32_t reg_value;
|
||||
|
||||
sc = a31_ccm_sc;
|
||||
if (sc == NULL)
|
||||
return (ENXIO);
|
||||
|
||||
if (a31_clk_pll6_enable())
|
||||
return (ENXIO);
|
||||
|
||||
/* Gating AHB clock for GMAC */
|
||||
reg_value = ccm_read_4(sc, A31_CCM_AHB_GATING0);
|
||||
reg_value |= A31_CCM_AHB_GATING_GMAC;
|
||||
ccm_write_4(sc, A31_CCM_AHB_GATING0, reg_value);
|
||||
|
||||
/* Set GMAC mode. */
|
||||
reg_value = A31_CCM_GMAC_CLK_MII;
|
||||
if (OF_getprop_alloc(node, "phy-mode", 1, (void **)&phy_type) > 0) {
|
||||
if (strcasecmp(phy_type, "rgmii") == 0)
|
||||
reg_value = A31_CCM_GMAC_CLK_RGMII |
|
||||
A31_CCM_GMAC_MODE_RGMII;
|
||||
free(phy_type, M_OFWPROP);
|
||||
}
|
||||
ccm_write_4(sc, A31_CCM_GMAC_CLK, reg_value);
|
||||
|
||||
/* Reset gmac */
|
||||
reg_value = ccm_read_4(sc, A31_CCM_AHB1_RST_REG0);
|
||||
reg_value |= A31_CCM_AHB1_RST_REG0_GMAC;
|
||||
ccm_write_4(sc, A31_CCM_AHB1_RST_REG0, reg_value);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
a31_clk_mmc_activate(int devid)
|
||||
{
|
||||
struct a31_ccm_softc *sc;
|
||||
uint32_t reg_value;
|
||||
|
||||
sc = a31_ccm_sc;
|
||||
if (sc == NULL)
|
||||
return (ENXIO);
|
||||
|
||||
if (a31_clk_pll6_enable())
|
||||
return (ENXIO);
|
||||
|
||||
/* Gating AHB clock for SD/MMC */
|
||||
reg_value = ccm_read_4(sc, A31_CCM_AHB_GATING0);
|
||||
reg_value |= A31_CCM_AHB_GATING_SDMMC0 << devid;
|
||||
ccm_write_4(sc, A31_CCM_AHB_GATING0, reg_value);
|
||||
|
||||
/* Soft reset */
|
||||
reg_value = ccm_read_4(sc, A31_CCM_AHB1_RST_REG0);
|
||||
reg_value |= A31_CCM_AHB1_RST_REG0_SDMMC << devid;
|
||||
ccm_write_4(sc, A31_CCM_AHB1_RST_REG0, reg_value);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
a31_clk_mmc_cfg(int devid, int freq)
|
||||
{
|
||||
struct a31_ccm_softc *sc;
|
||||
uint32_t clksrc, m, n, ophase, phase, reg_value;
|
||||
unsigned int pll_freq;
|
||||
|
||||
sc = a31_ccm_sc;
|
||||
if (sc == NULL)
|
||||
return (ENXIO);
|
||||
|
||||
freq /= 1000;
|
||||
if (freq <= 400) {
|
||||
pll_freq = A31_CCM_CLK_REF_FREQ / 1000;
|
||||
clksrc = A31_CCM_SD_CLK_SRC_SEL_OSC24M;
|
||||
ophase = 0;
|
||||
phase = 0;
|
||||
n = 2;
|
||||
} else if (freq <= 25000) {
|
||||
pll_freq = a31_clk_pll6_get_rate() / 1000;
|
||||
clksrc = A31_CCM_SD_CLK_SRC_SEL_PLL6;
|
||||
ophase = 0;
|
||||
phase = 5;
|
||||
n = 2;
|
||||
} else if (freq <= 50000) {
|
||||
pll_freq = a31_clk_pll6_get_rate() / 1000;
|
||||
clksrc = A31_CCM_SD_CLK_SRC_SEL_PLL6;
|
||||
ophase = 3;
|
||||
phase = 5;
|
||||
n = 0;
|
||||
} else
|
||||
return (EINVAL);
|
||||
m = ((pll_freq / (1 << n)) / (freq)) - 1;
|
||||
reg_value = ccm_read_4(sc, A31_CCM_MMC0_SCLK_CFG + (devid * 4));
|
||||
reg_value &= ~A31_CCM_SD_CLK_SRC_SEL;
|
||||
reg_value |= (clksrc << A31_CCM_SD_CLK_SRC_SEL_SHIFT);
|
||||
reg_value &= ~A31_CCM_SD_CLK_PHASE_CTR;
|
||||
reg_value |= (phase << A31_CCM_SD_CLK_PHASE_CTR_SHIFT);
|
||||
reg_value &= ~A31_CCM_SD_CLK_DIV_RATIO_N;
|
||||
reg_value |= (n << A31_CCM_SD_CLK_DIV_RATIO_N_SHIFT);
|
||||
reg_value &= ~A31_CCM_SD_CLK_OPHASE_CTR;
|
||||
reg_value |= (ophase << A31_CCM_SD_CLK_OPHASE_CTR_SHIFT);
|
||||
reg_value &= ~A31_CCM_SD_CLK_DIV_RATIO_M;
|
||||
reg_value |= m;
|
||||
reg_value |= A31_CCM_PLL_CFG_ENABLE;
|
||||
ccm_write_4(sc, A31_CCM_MMC0_SCLK_CFG + (devid * 4), reg_value);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
a31_clk_i2c_activate(int devid)
|
||||
{
|
||||
struct a31_ccm_softc *sc;
|
||||
uint32_t reg_value;
|
||||
|
||||
sc = a31_ccm_sc;
|
||||
if (sc == NULL)
|
||||
return (ENXIO);
|
||||
|
||||
if (a31_clk_pll6_enable())
|
||||
return (ENXIO);
|
||||
|
||||
/* Gating APB clock for I2C/TWI */
|
||||
reg_value = ccm_read_4(sc, A31_CCM_APB2_GATING);
|
||||
reg_value |= A31_CCM_APB2_GATING_TWI << devid;
|
||||
ccm_write_4(sc, A31_CCM_APB2_GATING, reg_value);
|
||||
|
||||
/* Soft reset */
|
||||
reg_value = ccm_read_4(sc, A31_CCM_APB2_RST);
|
||||
reg_value |= A31_CCM_APB2_RST_TWI << devid;
|
||||
ccm_write_4(sc, A31_CCM_APB2_RST, reg_value);
|
||||
|
||||
return (0);
|
||||
}
|
189
sys/arm/allwinner/a31/a31_clk.h
Normal file
189
sys/arm/allwinner/a31/a31_clk.h
Normal file
@ -0,0 +1,189 @@
|
||||
/*-
|
||||
* Copyright (c) 2013 Ganbold Tsagaankhuu <ganbold@freebsd.org>
|
||||
* Copyright (c) 2016 Emmanuel Vadot <manu@bidouilliste.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _A31_CLK_H_
|
||||
#define _A31_CLK_H_
|
||||
|
||||
#define A31_CCM_PLL1_CFG 0x0000
|
||||
#define A31_CCM_PLL2_CFG 0x0008
|
||||
#define A31_CCM_PLL3_CFG 0x0010
|
||||
#define A31_CCM_PLL4_CFG 0x0018
|
||||
#define A31_CCM_PLL5_CFG 0x0020
|
||||
#define A31_CCM_PLL6_CFG 0x0028
|
||||
#define A31_CCM_PLL7_CFG 0x0030
|
||||
#define A31_CCM_PLL8_CFG 0x0038
|
||||
#define A31_CCM_MIPI_PLL_CFG 0x0040
|
||||
#define A31_CCM_PLL9_CFG 0x0044
|
||||
#define A31_CCM_PLL10_CFG 0x0048
|
||||
#define A31_CCM_AXI_CFG_REG 0x0050
|
||||
#define A31_CCM_AHB1_APB1_CFG 0x0054
|
||||
#define A31_CCM_APB2_CLK_DIV 0x0058
|
||||
#define A31_CCM_AHB_GATING0 0x0060
|
||||
#define A31_CCM_AHB_GATING1 0x0064
|
||||
#define A31_CCM_APB1_GATING 0x0068
|
||||
#define A31_CCM_APB2_GATING 0x006c
|
||||
#define A31_CCM_NAND0_SCLK_CFG 0x0080
|
||||
#define A31_CCM_NAND1_SCLK_CFG 0x0084
|
||||
#define A31_CCM_MMC0_SCLK_CFG 0x0088
|
||||
#define A31_CCM_MMC1_SCLK_CFG 0x008c
|
||||
#define A31_CCM_MMC2_SCLK_CFG 0x0090
|
||||
#define A31_CCM_MMC3_SCLK_CFG 0x0094
|
||||
#define A31_CCM_TS_CLK 0x0098
|
||||
#define A31_CCM_SS_CLK 0x009c
|
||||
#define A31_CCM_SPI0_CLK 0x00a0
|
||||
#define A31_CCM_SPI1_CLK 0x00a4
|
||||
#define A31_CCM_SPI2_CLK 0x00a8
|
||||
#define A31_CCM_SPI3_CLK 0x00ac
|
||||
#define A31_CCM_DAUDIO0_CLK 0x00b0
|
||||
#define A31_CCM_DAUDIO1_CLK 0x00b4
|
||||
#define A31_CCM_USBPHY_CLK 0x00cc
|
||||
#define A31_CCM_GMAC_CLK 0x00d0
|
||||
#define A31_CCM_MDFS_CLK 0x00f0
|
||||
#define A31_CCM_DRAM_CLK 0x00f4
|
||||
#define A31_CCM_DRAM_GATING 0x0100
|
||||
#define A31_CCM_BE0_SCLK 0x0104
|
||||
#define A31_CCM_BE1_SCLK 0x0108
|
||||
#define A31_CCM_FE0_CLK 0x010c
|
||||
#define A31_CCM_FE1_CLK 0x0110
|
||||
#define A31_CCM_MP_CLK 0x0114
|
||||
#define A31_CCM_LCD0_CH0_CLK 0x0118
|
||||
#define A31_CCM_LCD1_CH0_CLK 0x011c
|
||||
#define A31_CCM_LCD0_CH1_CLK 0x012c
|
||||
#define A31_CCM_LCD1_CH1_CLK 0x0130
|
||||
#define A31_CCM_CSI0_CLK 0x0134
|
||||
#define A31_CCM_CSI1_CLK 0x0138
|
||||
#define A31_CCM_VE_CLK 0x013c
|
||||
#define A31_CCM_AUDIO_CODEC_CLK 0x0140
|
||||
#define A31_CCM_AVS_CLK 0x0144
|
||||
#define A31_CCM_DIGITAL_MIC_CLK 0x0148
|
||||
#define A31_CCM_HDMI_CLK 0x0150
|
||||
#define A31_CCM_PS_CLK 0x0154
|
||||
#define A31_CCM_MBUS_SCLK_CFG0 0x015c
|
||||
#define A31_CCM_MBUS_SCLK_CFG1 0x0160
|
||||
#define A31_CCM_MIPI_DSI_CLK 0x0168
|
||||
#define A31_CCM_MIPI_CSI0_CLK 0x016c
|
||||
#define A31_CCM_DRC0_SCLK_CFG 0x0180
|
||||
#define A31_CCM_DRC1_SCLK_CFG 0x0184
|
||||
#define A31_CCM_DEU0_SCLK_CFG 0x0188
|
||||
#define A31_CCM_DEU1_SCLK_CFG 0x018c
|
||||
#define A31_CCM_GPU_CORE_CLK 0x01a0
|
||||
#define A31_CCM_GPU_MEM_CLK 0x01a4
|
||||
#define A31_CCM_GPU_HYD_CLK 0x01a8
|
||||
#define A31_CCM_ATS_CLK 0x01b0
|
||||
#define A31_CCM_TRACE_CLK 0x01b4
|
||||
#define A31_CCM_PLL_LOCK_CFG 0x0200
|
||||
#define A31_CCM_PLL1_LOCK_CFG 0x0204
|
||||
#define A31_CCM_PLL1_BIAS 0x0220
|
||||
#define A31_CCM_PLL2_BIAS 0x0224
|
||||
#define A31_CCM_PLL3_BIAS 0x0228
|
||||
#define A31_CCM_PLL4_BIAS 0x022c
|
||||
#define A31_CCM_PLL5_BIAS 0x0230
|
||||
#define A31_CCM_PLL6_BIAS 0x0234
|
||||
#define A31_CCM_PLL7_BIAS 0x0238
|
||||
#define A31_CCM_PLL8_BIAS 0x023c
|
||||
#define A31_CCM_PLL9_BIAS 0x0240
|
||||
#define A31_CCM_MIPI_PLL_BIAS 0x0244
|
||||
#define A31_CCM_PLL10_BIAS 0x0248
|
||||
#define A31_CCM_PLL1_PAT_CFG 0x0280
|
||||
#define A31_CCM_PLL2_PAT_CFG 0x0284
|
||||
#define A31_CCM_PLL3_PAT_CFG 0x0288
|
||||
#define A31_CCM_PLL4_PAT_CFG 0x028c
|
||||
#define A31_CCM_PLL5_PAT_CFG 0x0290
|
||||
#define A31_CCM_PLL6_PAT_CFG 0x0294
|
||||
#define A31_CCM_PLL7_PAT_CFG 0x0298
|
||||
#define A31_CCM_PLL8_PAT_CFG 0x029c
|
||||
#define A31_CCM_MIPI_PLL_PAT_CFG 0x02a0
|
||||
#define A31_CCM_PLL9_PAT_CFG 0x02a4
|
||||
#define A31_CCM_PLL10_PAT_CFG 0x02a8
|
||||
#define A31_CCM_AHB1_RST_REG0 0x02c0
|
||||
#define A31_CCM_AHB1_RST_REG1 0x02c4
|
||||
#define A31_CCM_AHB1_RST_REG2 0x02c8
|
||||
#define A31_CCM_APB1_RST 0x02d0
|
||||
#define A31_CCM_APB2_RST 0x02d8
|
||||
#define A31_CCM_CLK_OUTA 0x0300
|
||||
#define A31_CCM_CLK_OUTB 0x0304
|
||||
#define A31_CCM_CLK_OUTC 0x0308
|
||||
|
||||
/* PLL6_CFG_REG */
|
||||
#define A31_CCM_PLL6_CFG_REG_LOCK (1 << 28)
|
||||
|
||||
/* AHB_GATING_REG0 */
|
||||
#define A31_CCM_AHB_GATING_SDMMC0 (1 << 8)
|
||||
#define A31_CCM_AHB_GATING_GMAC (1 << 17)
|
||||
|
||||
#define A31_CCM_PLL_CFG_ENABLE (1U << 31)
|
||||
#define A31_CCM_PLL_CFG_BYPASS (1U << 30)
|
||||
#define A31_CCM_PLL_CFG_PLL5 (1U << 25)
|
||||
#define A31_CCM_PLL_CFG_PLL6 (1U << 24)
|
||||
#define A31_CCM_PLL_CFG_FACTOR_N 0x1f00
|
||||
#define A31_CCM_PLL_CFG_FACTOR_N_SHIFT 8
|
||||
#define A31_CCM_PLL_CFG_FACTOR_K 0x30
|
||||
#define A31_CCM_PLL_CFG_FACTOR_K_SHIFT 4
|
||||
#define A31_CCM_PLL_CFG_FACTOR_M 0x3
|
||||
|
||||
/* APB2_GATING */
|
||||
#define A31_CCM_APB2_GATING_TWI (1 << 0)
|
||||
|
||||
/* AHB1_RST_REG0 */
|
||||
#define A31_CCM_AHB1_RST_REG0_GMAC (1 << 17)
|
||||
#define A31_CCM_AHB1_RST_REG0_SDMMC (1 << 8)
|
||||
|
||||
/* APB2_RST_REG */
|
||||
#define A31_CCM_APB2_RST_TWI (1 << 0)
|
||||
|
||||
|
||||
/* GMAC */
|
||||
#define A31_CCM_GMAC_CLK_DELAY_SHIFT 10
|
||||
#define A31_CCM_GMAC_CLK_MODE_MASK 0x7
|
||||
#define A31_CCM_GMAC_MODE_RGMII (1 << 2)
|
||||
#define A31_CCM_GMAC_CLK_MII 0x0
|
||||
#define A31_CCM_GMAC_CLK_EXT_RGMII 0x1
|
||||
#define A31_CCM_GMAC_CLK_RGMII 0x2
|
||||
|
||||
/* SD/MMC */
|
||||
#define A31_CCM_SD_CLK_SRC_SEL 0x3000000
|
||||
#define A31_CCM_SD_CLK_SRC_SEL_SHIFT 24
|
||||
#define A31_CCM_SD_CLK_SRC_SEL_OSC24M 0
|
||||
#define A31_CCM_SD_CLK_SRC_SEL_PLL6 1
|
||||
#define A31_CCM_SD_CLK_PHASE_CTR 0x700000
|
||||
#define A31_CCM_SD_CLK_PHASE_CTR_SHIFT 20
|
||||
#define A31_CCM_SD_CLK_DIV_RATIO_N 0x30000
|
||||
#define A31_CCM_SD_CLK_DIV_RATIO_N_SHIFT 16
|
||||
#define A31_CCM_SD_CLK_OPHASE_CTR 0x700
|
||||
#define A31_CCM_SD_CLK_OPHASE_CTR_SHIFT 8
|
||||
#define A31_CCM_SD_CLK_DIV_RATIO_M 0xf
|
||||
|
||||
#define A31_CCM_CLK_REF_FREQ 24000000U
|
||||
|
||||
int a31_clk_gmac_activate(phandle_t);
|
||||
int a31_clk_mmc_activate(int);
|
||||
int a31_clk_mmc_cfg(int, int);
|
||||
int a31_clk_i2c_activate(int);
|
||||
|
||||
#endif /* _A31_CLK_H_ */
|
@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/ofw/ofw_bus_subr.h>
|
||||
|
||||
#include <arm/allwinner/a10_clk.h>
|
||||
#include <arm/allwinner/a31/a31_clk.h>
|
||||
|
||||
#include "iicbus_if.h"
|
||||
|
||||
@ -62,6 +63,15 @@ __FBSDID("$FreeBSD$");
|
||||
#define TWI_EFR 0x1C
|
||||
#define TWI_LCR 0x20
|
||||
|
||||
#define A10_I2C 1
|
||||
#define A31_I2C 2
|
||||
|
||||
static struct ofw_compat_data compat_data[] = {
|
||||
{"allwinner,sun4i-a10-i2c", A10_I2C},
|
||||
{"allwinner,sun6i-a31-i2c", A31_I2C},
|
||||
{NULL, 0},
|
||||
};
|
||||
|
||||
static int
|
||||
a10_twsi_probe(device_t dev)
|
||||
{
|
||||
@ -71,7 +81,7 @@ a10_twsi_probe(device_t dev)
|
||||
if (!ofw_bus_status_okay(dev))
|
||||
return (ENXIO);
|
||||
|
||||
if (!ofw_bus_is_compatible(dev, "allwinner,sun4i-a10-i2c"))
|
||||
if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
|
||||
return (ENXIO);
|
||||
|
||||
device_set_desc(dev, "Allwinner Integrated I2C Bus Controller");
|
||||
@ -82,11 +92,30 @@ static int
|
||||
a10_twsi_attach(device_t dev)
|
||||
{
|
||||
struct twsi_softc *sc;
|
||||
int clk;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
/* Activate clock */
|
||||
a10_clk_i2c_activate(device_get_unit(dev));
|
||||
switch (ofw_bus_search_compatible(dev, compat_data)->ocd_data) {
|
||||
#if defined(SOC_ALLWINNER_A10) || defined(SOC_ALLWINNER_A20)
|
||||
case A10_I2C:
|
||||
clk = a10_clk_i2c_activate(device_get_unit(dev));
|
||||
break;
|
||||
#endif
|
||||
#if defined(SOC_ALLWINNER_A31) || defined(SOC_ALLWINNER_A31S)
|
||||
case A31_I2C:
|
||||
clk = a31_clk_i2c_activate(device_get_unit(dev));
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
clk = -1;
|
||||
}
|
||||
|
||||
if (clk != 0) {
|
||||
device_printf(dev, "could not activate i2c clock\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
sc->reg_data = TWI_DATA;
|
||||
sc->reg_slave_addr = TWI_ADDR;
|
||||
|
Loading…
Reference in New Issue
Block a user