svn commit: r296093 - in head/sys: arm/allwinner arm/allwinner/a20 arm/allwinner/a31 dev/iicbus/twsi
Andrew Turner
andrew at FreeBSD.org
Fri Feb 26 13:53:11 UTC 2016
Author: andrew
Date: Fri Feb 26 13:53:09 2016
New Revision: 296093
URL: https://svnweb.freebsd.org/changeset/base/296093
Log:
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 at bidouilliste.com>
Reviewed by: jmcneill
Differential Revision: https://reviews.freebsd.org/D5339
Added:
head/sys/arm/allwinner/a31/a31_clk.c (contents, props changed)
head/sys/arm/allwinner/a31/a31_clk.h (contents, props changed)
Modified:
head/sys/arm/allwinner/a10_mmc.c
head/sys/arm/allwinner/a20/a20_if_dwc.c
head/sys/dev/iicbus/twsi/a10_twsi.c
Modified: head/sys/arm/allwinner/a10_mmc.c
==============================================================================
--- head/sys/arm/allwinner/a10_mmc.c Fri Feb 26 12:46:34 2016 (r296092)
+++ head/sys/arm/allwinner/a10_mmc.c Fri Feb 26 13:53:09 2016 (r296093)
@@ -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_
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);
Modified: head/sys/arm/allwinner/a20/a20_if_dwc.c
==============================================================================
--- head/sys/arm/allwinner/a20/a20_if_dwc.c Fri Feb 26 12:46:34 2016 (r296092)
+++ head/sys/arm/allwinner/a20/a20_if_dwc.c Fri Feb 26 13:53:09 2016 (r296093)
@@ -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);
}
Added: head/sys/arm/allwinner/a31/a31_clk.c
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ head/sys/arm/allwinner/a31/a31_clk.c Fri Feb 26 13:53:09 2016 (r296093)
@@ -0,0 +1,295 @@
+/*-
+ * Copyright (c) 2013 Ganbold Tsagaankhuu <ganbold at freebsd.org>
+ * Copyright (c) 2016 Emmanuel Vadot <manu at 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);
+}
Added: head/sys/arm/allwinner/a31/a31_clk.h
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ head/sys/arm/allwinner/a31/a31_clk.h Fri Feb 26 13:53:09 2016 (r296093)
@@ -0,0 +1,189 @@
+/*-
+ * Copyright (c) 2013 Ganbold Tsagaankhuu <ganbold at freebsd.org>
+ * Copyright (c) 2016 Emmanuel Vadot <manu at 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_ */
Modified: head/sys/dev/iicbus/twsi/a10_twsi.c
==============================================================================
--- head/sys/dev/iicbus/twsi/a10_twsi.c Fri Feb 26 12:46:34 2016 (r296092)
+++ head/sys/dev/iicbus/twsi/a10_twsi.c Fri Feb 26 13:53:09 2016 (r296093)
@@ -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;
More information about the svn-src-head
mailing list