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 <m...@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 <ganb...@freebsd.org>
+ * Copyright (c) 2016 Emmanuel Vadot <m...@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 <ganb...@freebsd.org>
+ * Copyright (c) 2016 Emmanuel Vadot <m...@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;
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to